1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
import logging
import random
from datetime import datetime
from typing import Optional
import discord
from discord.ext import commands
from discord.ext.commands.cooldowns import BucketType
from bot.constants import NEGATIVE_REPLIES
from bot.exts.utils.extensions import invoke_help_command
log = logging.getLogger(__name__)
GITHUB_API_URL = "https://api.github.com"
class GithubInfo(commands.Cog):
"""Fetches info from GitHub."""
def __init__(self, bot: commands.Bot):
self.bot = bot
async def fetch_data(self, url: str) -> dict:
"""Retrieve data as a dictionary."""
async with self.bot.http_session.get(url) as r:
return await r.json()
@commands.group(name='github', aliases=('gh', 'git'))
@commands.cooldown(1, 10, BucketType.user)
async def github_group(self, ctx: commands.Context) -> None:
"""Commands for finding info related to Github."""
if ctx.invoked_subcommand is None:
await invoke_help_command(ctx)
@github_group.command(name='user', aliases=('userinfo',))
async def github_user_info(self, ctx: commands.Context, username: Optional[str]) -> None:
"""
Fetches a user's GitHub information.
Username is optional and sends the help command if not specified.
"""
if username is None:
await invoke_help_command(ctx)
ctx.command.reset_cooldown(ctx)
return
async with ctx.typing():
user_data = await self.fetch_data(f"{GITHUB_API_URL}/users/{username}")
# User_data will not have a message key if the user exists
if user_data.get('message') is not None:
await ctx.send(embed=discord.Embed(title=random.choice(NEGATIVE_REPLIES),
description=f"The profile for `{username}` was not found.",
colour=discord.Colour.red()))
return
org_data = await self.fetch_data(user_data['organizations_url'])
orgs = [f"[{org['login']}](https://github.com/{org['login']})" for org in org_data]
orgs_to_add = ' | '.join(orgs)
gists = user_data['public_gists']
# Forming blog link
if user_data['blog'].startswith("http"): # Blog link is complete
blog = user_data['blog']
elif user_data['blog']: # Blog exists but the link is not complete
blog = f"https://{user_data['blog']}"
else:
blog = "No website link available"
embed = discord.Embed(
title=f"`{user_data['login']}`'s GitHub profile info",
description=f"```{user_data['bio']}```\n" if user_data['bio'] is not None else "",
colour=0x7289da,
url=user_data['html_url'],
timestamp=datetime.strptime(user_data['created_at'], "%Y-%m-%dT%H:%M:%SZ")
)
embed.set_thumbnail(url=user_data['avatar_url'])
embed.set_footer(text="Account created at")
if user_data['type'] == "User":
embed.add_field(name="Followers",
value=f"[{user_data['followers']}]({user_data['html_url']}?tab=followers)")
embed.add_field(name="Following",
value=f"[{user_data['following']}]({user_data['html_url']}?tab=following)")
embed.add_field(name="Public repos",
value=f"[{user_data['public_repos']}]({user_data['html_url']}?tab=repositories)")
if user_data['type'] == "User":
embed.add_field(name="Gists", value=f"[{gists}](https://gist.github.com/{username})")
embed.add_field(name=f"Organization{'s' if len(orgs)!=1 else ''}",
value=orgs_to_add if orgs else "No organizations")
embed.add_field(name="Website", value=blog)
await ctx.send(embed=embed)
@github_group.command(name='repository', aliases=('repo',))
async def github_repo_info(self, ctx: commands.Context, repo: str) -> None:
"""
Fetches a repositories' GitHub information. The repository should look like `user/reponame`.
Repository is optional and sends the help command if not specified.
"""
async with ctx.typing():
repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{repo}")
# There won't be a message key if this repo exists
if repo_data.get('message') is not None:
embed = discord.Embed(
title=random.choice(NEGATIVE_REPLIES),
description="The requested repository was not found.",
colour=discord.Colour.red()
)
await ctx.send(embed=embed)
return
repo_owner = repo_data['owner']
parent = repo_data.get('parent')
embed = discord.Embed(
title=f"{repo_data['name']}",
description=repo_data["description"],
colour=0x7289da,
url=repo_data['html_url'],
timestamp=datetime.strptime(repo_data['pushed_at'], "%Y-%m-%dT%H:%M:%SZ")
)
# If it's a fork, then it will have a parent key
if parent:
embed.description += f"\n\nForked from [{parent['full_name']}]({parent['html_url']})"
embed.set_author(
name=repo_owner["login"],
url=repo_owner["html_url"],
icon_url=repo_owner["avatar_url"]
)
repo_created_at = datetime.strptime(repo_data['created_at'], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y")
embed.set_footer(
text=(
f"{repo_data['forks_count']} ⑂ "
f"• {repo_data['stargazers_count']} ⭐ "
f"• Created At {repo_created_at} "
f"• Last commit "
)
)
await ctx.send(embed=embed)
def setup(bot: commands.Bot) -> None:
"""Adding the cog to the bot."""
bot.add_cog(GithubInfo(bot))
|