diff options
| author | 2021-09-06 13:11:27 +0100 | |
|---|---|---|
| committer | 2021-09-06 13:11:27 +0100 | |
| commit | 5e136d9aadcdb334f502cebb6e85981394802324 (patch) | |
| tree | 58abafa6a5acd9938fd291947c7c9ce8bd949938 /bot/exts/utilities/githubinfo.py | |
| parent | Set logging level for async-rediscache to warning (diff) | |
| parent | Merge pull request #853 from python-discord/post-restructure-fix (diff) | |
Merge branch 'main' into async-redisache-logs
Diffstat (limited to 'bot/exts/utilities/githubinfo.py')
| -rw-r--r-- | bot/exts/utilities/githubinfo.py | 178 | 
1 files changed, 178 insertions, 0 deletions
| diff --git a/bot/exts/utilities/githubinfo.py b/bot/exts/utilities/githubinfo.py new file mode 100644 index 00000000..d00b408d --- /dev/null +++ b/bot/exts/utilities/githubinfo.py @@ -0,0 +1,178 @@ +import logging +import random +from datetime import datetime +from urllib.parse import quote, quote_plus + +import discord +from discord.ext import commands + +from bot.bot import Bot +from bot.constants import Colours, NEGATIVE_REPLIES +from bot.exts.core.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: 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, commands.BucketType.user) +    async def github_group(self, ctx: commands.Context) -> None: +        """Commands for finding information 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: str) -> None: +        """Fetches a user's GitHub information.""" +        async with ctx.typing(): +            user_data = await self.fetch_data(f"{GITHUB_API_URL}/users/{quote_plus(username)}") + +            # User_data will not have a message key if the user exists +            if "message" in user_data: +                embed = discord.Embed( +                    title=random.choice(NEGATIVE_REPLIES), +                    description=f"The profile for `{username}` was not found.", +                    colour=Colours.soft_red +                ) + +                await ctx.send(embed=embed) +                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"```\n{user_data['bio']}\n```\n" if user_data["bio"] else "", +                colour=discord.Colour.blurple(), +                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/{quote_plus(username, safe='')})" +                ) + +                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` or `user reponame`. +        """ +        repo = "/".join(repo) +        if repo.count("/") != 1: +            embed = discord.Embed( +                title=random.choice(NEGATIVE_REPLIES), +                description="The repository should look like `user/reponame` or `user reponame`.", +                colour=Colours.soft_red +            ) + +            await ctx.send(embed=embed) +            return + +        async with ctx.typing(): +            repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{quote(repo)}") + +            # There won't be a message key if this repo exists +            if "message" in repo_data: +                embed = discord.Embed( +                    title=random.choice(NEGATIVE_REPLIES), +                    description="The requested repository was not found.", +                    colour=Colours.soft_red +                ) + +                await ctx.send(embed=embed) +                return + +        embed = discord.Embed( +            title=repo_data["name"], +            description=repo_data["description"], +            colour=discord.Colour.blurple(), +            url=repo_data["html_url"] +        ) + +        # If it's a fork, then it will have a parent key +        try: +            parent = repo_data["parent"] +            embed.description += f"\n\nForked from [{parent['full_name']}]({parent['html_url']})" +        except KeyError: +            log.debug("Repository is not a fork.") + +        repo_owner = repo_data["owner"] + +        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") +        last_pushed = datetime.strptime(repo_data["pushed_at"], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y at %H:%M") + +        embed.set_footer( +            text=( +                f"{repo_data['forks_count']} ⑂ " +                f"• {repo_data['stargazers_count']} ⭐ " +                f"• Created At {repo_created_at} " +                f"• Last Commit {last_pushed}" +            ) +        ) + +        await ctx.send(embed=embed) + + +def setup(bot: Bot) -> None: +    """Load the GithubInfo cog.""" +    bot.add_cog(GithubInfo(bot)) | 
