Skip to content

Commit bb59375

Browse files
committed
feat: Add Discord bot for GitHub info retrieval
- Implement !repo and !issue commands for GitHub info. - Extract and display repo and issue details from links.
1 parent 0363566 commit bb59375

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ venv/
127127
ENV/
128128
env.bak/
129129
venv.bak/
130+
Pipfile
131+
Pipfile.lock
130132

131133
# Spyder project settings
132134
.spyderproject

requirements.txt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
aiohttp==3.8.5
2+
aiosignal==1.3.1
3+
async-timeout==4.0.3
4+
attrs==23.1.0
5+
certifi==2023.7.22
6+
charset-normalizer==3.2.0
7+
discord.py==2.3.2
8+
frozenlist==1.4.0
9+
idna==3.4
10+
multidict==6.0.4
11+
python-dotenv==1.0.0
12+
requests==2.31.0
13+
urllib3==2.0.5
14+
yarl==1.9.2

scripts/gbot

+124
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,126 @@
11
#!/usr/bin/env python3
2+
import re
3+
import os
4+
import discord
5+
import requests
6+
from dotenv import load_dotenv
7+
from discord.ext import commands
28

9+
load_dotenv()
10+
11+
TOKEN = os.getenv('DISCORD_BOT_TOKEN')
12+
13+
14+
# Bot's intents
15+
intents = discord.Intents.default()
16+
intents.typing = False
17+
intents.presences = False
18+
intents.message_content = True
19+
20+
# Bot instance
21+
bot = commands.Bot(command_prefix='!', intents=intents, disable_auto_responses=True)
22+
23+
@bot.event
24+
async def on_ready():
25+
print(f'Logged in as {bot.user.name}')
26+
27+
def get_repository_info(username, repo_name):
28+
url = f'https://api.github.com/repos/{username}/{repo_name}'
29+
response = requests.get(url)
30+
return response.json() if response.status_code == 200 else None
31+
32+
def get_issue_info(username, repo_name, issue_number):
33+
url = f'https://api.github.com/repos/{username}/{repo_name}/issues/{issue_number}'
34+
response = requests.get(url)
35+
return response.json() if response.status_code == 200 else None
36+
37+
def get_repo_issues(username, repo_name):
38+
url = f'https://api.github.com/repos/{username}/{repo_name}/issues'
39+
response = requests.get(url)
40+
if response.status_code == 200:
41+
issues = response.json()
42+
total_issues = len(issues)
43+
good_first_issue_count = sum(1 for issue in issues if 'good first issue' in issue.get('title', '').lower())
44+
return total_issues, good_first_issue_count
45+
return None, None
46+
47+
@bot.command()
48+
async def repo(ctx, repo_link):
49+
# Extract the GitHub username and repository name from the link
50+
match = re.match(r'https://github.com/([^/]+)/([^/]+)', repo_link)
51+
if not match:
52+
await ctx.send('Invalid GitHub repo link format. Please provide a valid link.')
53+
return
54+
55+
username, repo_name = match.group(1), match.group(2)
56+
57+
repo_data = get_repository_info(username, repo_name)
58+
59+
if repo_data:
60+
total_issues, good_first_issue_count = get_repo_issues(username, repo_name)
61+
await ctx.send(format_github_info(repo_data, total_issues, good_first_issue_count))
62+
else:
63+
await ctx.send('Repository not found or an error occurred.')
64+
65+
@bot.command()
66+
async def issue(ctx, issue_link):
67+
# Use Regex to extract the GitHub username, repository name, and issue number from the link
68+
match = re.match(r'https://github.com/([^/]+)/([^/]+)/issues/(\d+)', issue_link)
69+
if not match:
70+
await ctx.send('Invalid GitHub issue link format. Please provide a valid link.')
71+
return
72+
73+
username, repo_name, issue_number = match.group(1), match.group(2), match.group(3)
74+
75+
repo_data = get_repository_info(username, repo_name)
76+
issue_data = get_issue_info(username, repo_name, issue_number)
77+
78+
if repo_data and issue_data:
79+
await ctx.send(format_github_info(repo_data, None, None, issue_data))
80+
else:
81+
await ctx.send('Issue or repository not found or an error occurred.')
82+
83+
def format_github_info(repo_data, total_issues=None, good_first_issue_count=None, issue_data=None):
84+
description = repo_data['description'] or '*No description*'
85+
stars = repo_data['stargazers_count']
86+
forks = repo_data['forks_count']
87+
url = repo_data['html_url']
88+
89+
formatted_info = (
90+
f"__**Repository Info**__\n"
91+
f"**Repository Name:** {repo_data['name']}\n"
92+
f"**Description:** {description}\n"
93+
f"**Stars:** {stars}\n"
94+
f"**Forks:** {forks}\n"
95+
f"**URL:** {url}\n"
96+
)
97+
98+
if total_issues is not None:
99+
formatted_info += (
100+
f"**Total Issues:** {total_issues}\n"
101+
f"**Good First Issues:** {good_first_issue_count}\n"
102+
)
103+
104+
if issue_data:
105+
title = issue_data['title']
106+
number = issue_data['number']
107+
created_by = issue_data['user']['login']
108+
state = 'Open' if issue_data['state'] == 'open' else 'Closed'
109+
assigned = issue_data['assignee']['login'] if issue_data['assignee'] else '*Not assigned*'
110+
description = re.sub(r'(https?://[^\s]+)', r'`\1`', issue_data['body'][:1000])
111+
112+
formatted_info += (
113+
f"\n__**Issue Info**__\n"
114+
f"**Issue Title:** {title}\n"
115+
f"**Issue Number:** {number}\n"
116+
f"**Created By:** {created_by}\n"
117+
f"**Status:** {state}\n"
118+
f"**Assigned:** {assigned}\n"
119+
f"\n__**Description (Partial)**__\n{description}\n"
120+
f"\nFor the full description, please view the issue on GitHub."
121+
)
122+
123+
return formatted_info
124+
125+
# Run the bot with your token
126+
bot.run(TOKEN)

0 commit comments

Comments
 (0)