Whitepaper
Docs
Sign In
Tool
Tool
v0.1.0
Github Toolkit
Tool ID
github_toolkit
Creator
@momia
Downloads
133+
A tool for interacting with GitHub - manage PRs, reviews, and comments.
Get
README
No README available
Tool Code
Show
""" title: Github Toolkit author: Otron.io - Mo Mia author_url: https://otron.io description: A tool for interacting with GitHub - manage PRs, reviews, and comments. Insert your PAT on line 19. version: 0.1.0 requirements: PyGithub """ import os from github import Github from typing import Literal import base64 class Tools: def __init__(self): """Initialize with default settings""" self.api_key = os.getenv('GITHUB_TOKEN', 'YOUR_PAT') self.github = Github(self.api_key) def get_repo_info(self, owner: str, repo: str) -> str: """ Get basic info about a repository :param owner: Repository owner :param repo: Repository name :return: Repository info as a string """ try: repository = self.github.get_repo(f"{owner}/{repo}") return f"""Repository: {repository.full_name} Description: {repository.description or 'No description'} Stars: {repository.stargazers_count} Language: {repository.language or 'Not specified'} URL: {repository.html_url}""" except Exception as e: return f"Error getting repository info: {str(e)}" def get_pr(self, owner: str, repo: str, pr_number: int) -> str: """ Get basic info about a pull request :param owner: Repository owner :param repo: Repository name :param pr_number: PR number :return: PR info as a string """ try: repository = self.github.get_repo(f"{owner}/{repo}") pr = repository.get_pull(pr_number) return f"""PR #{pr.number}: {pr.title} Status: {pr.state} Created by: {pr.user.login} Base branch: {pr.base.ref} Head branch: {pr.head.ref} URL: {pr.html_url}""" except Exception as e: return f"Error getting PR info: {str(e)}" def add_comment(self, owner: str, repo: str, pr_number: int, body: str) -> str: """ Add a regular comment to a PR :param owner: Repository owner :param repo: Repository name :param pr_number: PR number :param body: Comment text :return: URL of the created comment """ try: repository = self.github.get_repo(f"{owner}/{repo}") pr = repository.get_pull(pr_number) comment = pr.create_issue_comment(body) return f"Added comment: {comment.html_url}" except Exception as e: return f"Error adding comment: {str(e)}" def add_review_comment(self, owner: str, repo: str, pr_number: int, body: str, path: str, line: int) -> str: """ Add a review comment to a specific line in a PR :param owner: Repository owner :param repo: Repository name :param pr_number: PR number :param body: Comment text :param path: File path to comment on :param line: Line number in the file to comment on :return: URL of the created review comment """ try: repository = self.github.get_repo(f"{owner}/{repo}") pr = repository.get_pull(pr_number) commit = pr.get_commits().get_page(0)[0] # Get latest commit comment = pr.create_review_comment( body=body, commit=commit, path=path, line=line ) return f"Added review comment: {comment.html_url}" except Exception as e: return f"Error adding review comment: {str(e)}" def submit_review(self, owner: str, repo: str, pr_number: int, event: Literal["APPROVE", "REQUEST_CHANGES", "COMMENT"], body: str) -> str: """ Submit a PR review :param owner: Repository owner :param repo: Repository name :param pr_number: PR number :param event: Review type (APPROVE, REQUEST_CHANGES, COMMENT) :param body: Review comment :return: URL of the submitted review """ try: repository = self.github.get_repo(f"{owner}/{repo}") pr = repository.get_pull(pr_number) review = pr.create_review(event=event, body=body) return f"Submitted {event.lower()} review: {review.html_url}" except Exception as e: return f"Error submitting review: {str(e)}" def get_repo_content(self, owner: str, repo: str, path: str = "") -> str: """ Get contents of a repository or specific path :param owner: Repository owner :param repo: Repository name :param path: Path within repository :return: Directory listing or file content """ try: repository = self.github.get_repo(f"{owner}/{repo}") contents = repository.get_contents(path) if isinstance(contents, list): # Directory listing output = [f"Contents of {owner}/{repo}/{path}:"] for item in contents: item_type = "📁" if item.type == "dir" else "📄" output.append(f"{item_type} {item.path}") return "\n".join(output) else: # Single file if contents.encoding == "base64": content = base64.b64decode(contents.content).decode('utf-8') return f"File: {contents.path}\n\n{content}" return f"File {contents.path} has unsupported encoding: {contents.encoding}" except Exception as e: return f"Error getting repository content: {str(e)}" def search_code(self, query: str, owner: str, repo: str) -> str: """ Search for code in a specific repository :param query: Search query :param owner: Repository owner (required) :param repo: Repository name (required) :return: Search results """ try: # Build repo-specific query search_query = f"{query} repo:{owner}/{repo}" # Search and format results results = self.github.search_code(query=search_query) output = [f"Found code in {owner}/{repo} matching '{query}':"] for i, item in enumerate(results[:5], 1): # Limit to 5 results output.extend([ f"\n{i}. {item.path}", f" URL: {item.html_url}", " Preview:", " ```" ]) try: content = base64.b64decode(item.content).decode('utf-8') preview_lines = content.split('\n')[:3] # Show first 3 lines output.extend(f" {line}" for line in preview_lines) except: output.append(" (Preview not available)") output.append(" ```") if len(output) == 1: return f"No code found in {owner}/{repo} matching '{query}'" return "\n".join(output) except Exception as e: return f"Error searching code: {str(e)}" def get_diff(self, owner: str, repo: str, pr_number: int, file_path: str) -> str: """ Get the diff from a PR, either full diff or for a specific file :param owner: Repository owner :param repo: Repository name :param pr_number: PR number :param file_path: Optional specific file path to get diff for :return: Diff output as a string """ try: repository = self.github.get_repo(f"{owner}/{repo}") pr = repository.get_pull(pr_number) files = pr.get_files() if file_path: # Find specific file for file in files: if file.filename == file_path: return f"""File: {file.filename} Status: {file.status} Changes: +{file.additions} -{file.deletions} Diff: {file.patch or '(No changes)'}""" return f"File {file_path} not found in PR #{pr_number}" # Full PR diff output = [f"Changes in PR #{pr_number}:"] for file in files: output.extend([ f"\nFile: {file.filename}", f"Status: {file.status}", f"Changes: +{file.additions} -{file.deletions}", "Diff:", file.patch or "(No changes)" ]) if len(output) == 1: return f"No changes found in PR #{pr_number}" return "\n".join(output) except Exception as e: return f"Error getting diff: {str(e)}"