Skip to content

Instantly share code, notes, and snippets.

@ncoop57
Last active December 12, 2025 15:23
Show Gist options
  • Select an option

  • Save ncoop57/9b063060087c4ae090606d1ad18a59a8 to your computer and use it in GitHub Desktop.

Select an option

Save ncoop57/9b063060087c4ae090606d1ad18a59a8 to your computer and use it in GitHub Desktop.
GitHub API tools for solveit
from ghapi.all import GhApi
from datetime import datetime, timedelta
__all__ = ['get_prs', 'get_pr', 'get_issues', 'get_issue', 'get_notifications', 'ghapi_tools']
api = GhApi()
def issue_to_xml(issue, comments=None):
"Convert a GitHub issue/PR to XML format"
labels = ','.join(l['name'] for l in issue.get('labels', []))
is_pr = 'pull_request' in issue or 'diff_url' in issue
typ = 'pr' if is_pr else 'issue'
parts = [f'<{typ} number="{issue["number"]}" state="{issue["state"]}">',
f' <title>{issue["title"]}</title>',
f' <author>{issue["user"]["login"]}</author>',
f' <created>{issue["created_at"]}</created>',
f' <url>{issue["html_url"]}</url>',
f' <labels>{labels}</labels>',
f' <body>{issue.get("body") or ""}</body>']
if comments:
parts.append(' <comments>')
for c in comments:
parts.append(f' <comment author="{c["user"]["login"]}" created="{c["created_at"]}">{c["body"]}</comment>')
parts.append(' </comments>')
parts.append(f'</{typ}>')
return '\n'.join(parts)
def get_prs(owner:str, # owner of the repo
repo:str): # name of the repo
'Get a list of all the PRs currently open'
prs = api.pulls.list(owner, repo)
return '\n'.join(f'- #{pr.number}: {pr.title}' for pr in prs)
def get_pr(owner:str, # owner of the repo
repo:str, # name of the repo
num:int): # num for the pr
'Get the details of the given PR'
pr = api.pulls.get(owner, repo, pull_number=num)
comments = api.issues.list_comments(owner, repo, issue_number=num)
return issue_to_xml(pr, comments)
def get_issues(owner:str, # owner of the repo
repo:str): # name of the repo
'Get a list of all the issues currently open (excludes PRs)'
issues = api.issues.list_for_repo(owner, repo)
issues = [i for i in issues if 'pull_request' not in i]
return '\n'.join(f'- #{i.number}: {i.title}' for i in issues)
def get_issue(owner:str, # owner of the repo
repo:str, # name of the repo
num:int): # issue number
'Get the details of the given issue'
issue = api.issues.get(owner, repo, issue_number=num)
comments = api.issues.list_comments(owner, repo, issue_number=num)
return issue_to_xml(issue, comments)
def get_notifications():
"Get unread notifications for open PRs/Issues from the last 7 days"
since = (datetime.now() - timedelta(days=7)).isoformat() + 'Z'
ns = api.activity.list_notifications_for_authenticated_user(since=since)
results = []
for n in ns:
if not n.unread: continue
repo = n.repository.full_name
owner, repo_name = repo.split('/')
subj = n.subject
# Extract number from URL (e.g., .../pulls/1199 -> 1199)
num = int(subj.url.split('/')[-1])
# Fetch current state
if subj.type == 'PullRequest':
item = api.pulls.get(owner, repo_name, num)
if item.state != 'open' or item.merged_at: continue
url = f'https://github.com/{repo}/pull/{num}'
elif subj.type == 'Issue':
item = api.issues.get(owner, repo_name, num)
if item.state != 'open': continue
url = f'https://github.com/{repo}/issues/{num}'
else: continue
results.append(f'- [{subj.type}] {repo}#{num}: {subj.title} ({n.reason})\n {url}')
return '\n'.join(results) if results else 'No unread notifications for open items!'
def ghapi_tools():
"Add a note describing available ghapi tools"
from dialoghelper.core import add_msg
content = """Tools available from `ghapi_tools` (gist `9b063060087c4ae090606d1ad18a59a8`):
- &`get_prs`: Get a list of all the PRs currently open for a repo.
- &`get_pr`: Get the details of a specific PR including comments, formatted as XML.
- &`get_issues`: Get a list of all open issues (excludes PRs) for a repo.
- &`get_issue`: Get the details of a specific issue including comments, formatted as XML.
- &`get_notifications`: Get unread notifications for open PRs/Issues from the last 7 days."""
add_msg(content, msg_type='note')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment