We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Aliasing for !resources command.
Currently the !resources command links to both the [PyDis resource](https://pythondiscord.com/pages/resources/
) page, and the [PyDis tools](https://pythondiscord.com/pages/tools/) page.

I feel that the alias of !tools should be added to the command, or the links should be separated into two commands, to both make it easier for users to access the tools page, but also increase awareness of the page.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `bot/cogs/site.py`
Content:
```
1 import logging
2 
3 from discord import Colour, Embed
4 from discord.ext.commands import Bot, Cog, Context, group
5 
6 from bot.constants import Channels, STAFF_ROLES, URLs
7 from bot.decorators import redirect_output
8 from bot.pagination import LinePaginator
9 
10 log = logging.getLogger(__name__)
11 
12 PAGES_URL = f"{URLs.site_schema}{URLs.site}/pages"
13 
14 
15 class Site(Cog):
16     """Commands for linking to different parts of the site."""
17 
18     def __init__(self, bot: Bot):
19         self.bot = bot
20 
21     @group(name="site", aliases=("s",), invoke_without_command=True)
22     async def site_group(self, ctx: Context) -> None:
23         """Commands for getting info about our website."""
24         await ctx.invoke(self.bot.get_command("help"), "site")
25 
26     @site_group.command(name="home", aliases=("about",))
27     async def site_main(self, ctx: Context) -> None:
28         """Info about the website itself."""
29         url = f"{URLs.site_schema}{URLs.site}/"
30 
31         embed = Embed(title="Python Discord website")
32         embed.set_footer(text=url)
33         embed.colour = Colour.blurple()
34         embed.description = (
35             f"[Our official website]({url}) is an open-source community project "
36             "created with Python and Flask. It contains information about the server "
37             "itself, lets you sign up for upcoming events, has its own wiki, contains "
38             "a list of valuable learning resources, and much more."
39         )
40 
41         await ctx.send(embed=embed)
42 
43     @site_group.command(name="resources")
44     async def site_resources(self, ctx: Context) -> None:
45         """Info about the site's Resources page."""
46         learning_url = f"{PAGES_URL}/resources"
47         tools_url = f"{PAGES_URL}/tools"
48 
49         embed = Embed(title="Resources & Tools")
50         embed.set_footer(text=f"{learning_url} | {tools_url}")
51         embed.colour = Colour.blurple()
52         embed.description = (
53             f"The [Resources page]({learning_url}) on our website contains a "
54             "list of hand-selected goodies that we regularly recommend "
55             f"to both beginners and experts. The [Tools page]({tools_url}) "
56             "contains a couple of the most popular tools for programming in "
57             "Python."
58         )
59 
60         await ctx.send(embed=embed)
61 
62     @site_group.command(name="help")
63     async def site_help(self, ctx: Context) -> None:
64         """Info about the site's Getting Help page."""
65         url = f"{PAGES_URL}/asking-good-questions"
66 
67         embed = Embed(title="Asking Good Questions")
68         embed.set_footer(text=url)
69         embed.colour = Colour.blurple()
70         embed.description = (
71             "Asking the right question about something that's new to you can sometimes be tricky. "
72             f"To help with this, we've created a [guide to asking good questions]({url}) on our website. "
73             "It contains everything you need to get the very best help from our community."
74         )
75 
76         await ctx.send(embed=embed)
77 
78     @site_group.command(name="faq")
79     async def site_faq(self, ctx: Context) -> None:
80         """Info about the site's FAQ page."""
81         url = f"{PAGES_URL}/frequently-asked-questions"
82 
83         embed = Embed(title="FAQ")
84         embed.set_footer(text=url)
85         embed.colour = Colour.blurple()
86         embed.description = (
87             "As the largest Python community on Discord, we get hundreds of questions every day. "
88             "Many of these questions have been asked before. We've compiled a list of the most "
89             "frequently asked questions along with their answers, which can be found on "
90             f"our [FAQ page]({url})."
91         )
92 
93         await ctx.send(embed=embed)
94 
95     @site_group.command(aliases=['r', 'rule'], name='rules')
96     @redirect_output(destination_channel=Channels.bot, bypass_roles=STAFF_ROLES)
97     async def site_rules(self, ctx: Context, *rules: int) -> None:
98         """Provides a link to all rules or, if specified, displays specific rule(s)."""
99         rules_embed = Embed(title='Rules', color=Colour.blurple())
100         rules_embed.url = f"{PAGES_URL}/rules"
101 
102         if not rules:
103             # Rules were not submitted. Return the default description.
104             rules_embed.description = (
105                 "The rules and guidelines that apply to this community can be found on"
106                 f" our [rules page]({PAGES_URL}/rules). We expect"
107                 " all members of the community to have read and understood these."
108             )
109 
110             await ctx.send(embed=rules_embed)
111             return
112 
113         full_rules = await self.bot.api_client.get('rules', params={'link_format': 'md'})
114         invalid_indices = tuple(
115             pick
116             for pick in rules
117             if pick < 0 or pick >= len(full_rules)
118         )
119 
120         if invalid_indices:
121             indices = ', '.join(map(str, invalid_indices))
122             await ctx.send(f":x: Invalid rule indices {indices}")
123             return
124 
125         final_rules = tuple(f"**{pick}.** {full_rules[pick]}" for pick in rules)
126 
127         await LinePaginator.paginate(final_rules, ctx, rules_embed, max_lines=3)
128 
129 
130 def setup(bot: Bot) -> None:
131     """Site cog load."""
132     bot.add_cog(Site(bot))
133     log.info("Cog loaded: Site")
134
```

Path: `bot/cogs/alias.py`
Content:
```
1 import inspect
2 import logging
3 from typing import Union
4 
5 from discord import Colour, Embed, Member, User
6 from discord.ext.commands import Bot, Cog, Command, Context, clean_content, command, group
7 
8 from bot.cogs.watchchannels.watchchannel import proxy_user
9 from bot.converters import TagNameConverter
10 from bot.pagination import LinePaginator
11 
12 log = logging.getLogger(__name__)
13 
14 
15 class Alias (Cog):
16     """Aliases for commonly used commands."""
17 
18     def __init__(self, bot: Bot):
19         self.bot = bot
20 
21     async def invoke(self, ctx: Context, cmd_name: str, *args, **kwargs) -> None:
22         """Invokes a command with args and kwargs."""
23         log.debug(f"{cmd_name} was invoked through an alias")
24         cmd = self.bot.get_command(cmd_name)
25         if not cmd:
26             return log.warning(f'Did not find command "{cmd_name}" to invoke.')
27         elif not await cmd.can_run(ctx):
28             return log.warning(
29                 f'{str(ctx.author)} tried to run the command "{cmd_name}"'
30             )
31 
32         await ctx.invoke(cmd, *args, **kwargs)
33 
34     @command(name='aliases')
35     async def aliases_command(self, ctx: Context) -> None:
36         """Show configured aliases on the bot."""
37         embed = Embed(
38             title='Configured aliases',
39             colour=Colour.blue()
40         )
41         await LinePaginator.paginate(
42             (
43                 f"• `{ctx.prefix}{value.name}` "
44                 f"=> `{ctx.prefix}{name[:-len('_alias')].replace('_', ' ')}`"
45                 for name, value in inspect.getmembers(self)
46                 if isinstance(value, Command) and name.endswith('_alias')
47             ),
48             ctx, embed, empty=False, max_lines=20
49         )
50 
51     @command(name="resources", aliases=("resource",), hidden=True)
52     async def site_resources_alias(self, ctx: Context) -> None:
53         """Alias for invoking <prefix>site resources."""
54         await self.invoke(ctx, "site resources")
55 
56     @command(name="watch", hidden=True)
57     async def bigbrother_watch_alias(self, ctx: Context, user: Union[Member, User, proxy_user], *, reason: str) -> None:
58         """Alias for invoking <prefix>bigbrother watch [user] [reason]."""
59         await self.invoke(ctx, "bigbrother watch", user, reason=reason)
60 
61     @command(name="unwatch", hidden=True)
62     async def bigbrother_unwatch_alias(self, ctx: Context, user: Union[User, proxy_user], *, reason: str) -> None:
63         """Alias for invoking <prefix>bigbrother unwatch [user] [reason]."""
64         await self.invoke(ctx, "bigbrother unwatch", user, reason=reason)
65 
66     @command(name="home", hidden=True)
67     async def site_home_alias(self, ctx: Context) -> None:
68         """Alias for invoking <prefix>site home."""
69         await self.invoke(ctx, "site home")
70 
71     @command(name="faq", hidden=True)
72     async def site_faq_alias(self, ctx: Context) -> None:
73         """Alias for invoking <prefix>site faq."""
74         await self.invoke(ctx, "site faq")
75 
76     @command(name="rules", hidden=True)
77     async def site_rules_alias(self, ctx: Context) -> None:
78         """Alias for invoking <prefix>site rules."""
79         await self.invoke(ctx, "site rules")
80 
81     @command(name="reload", hidden=True)
82     async def cogs_reload_alias(self, ctx: Context, *, cog_name: str) -> None:
83         """Alias for invoking <prefix>cogs reload [cog_name]."""
84         await self.invoke(ctx, "cogs reload", cog_name)
85 
86     @command(name="defon", hidden=True)
87     async def defcon_enable_alias(self, ctx: Context) -> None:
88         """Alias for invoking <prefix>defcon enable."""
89         await self.invoke(ctx, "defcon enable")
90 
91     @command(name="defoff", hidden=True)
92     async def defcon_disable_alias(self, ctx: Context) -> None:
93         """Alias for invoking <prefix>defcon disable."""
94         await self.invoke(ctx, "defcon disable")
95 
96     @command(name="exception", hidden=True)
97     async def tags_get_traceback_alias(self, ctx: Context) -> None:
98         """Alias for invoking <prefix>tags get traceback."""
99         await self.invoke(ctx, "tags get", tag_name="traceback")
100 
101     @group(name="get",
102            aliases=("show", "g"),
103            hidden=True,
104            invoke_without_command=True)
105     async def get_group_alias(self, ctx: Context) -> None:
106         """Group for reverse aliases for commands like `tags get`, allowing for `get tags` or `get docs`."""
107         pass
108 
109     @get_group_alias.command(name="tags", aliases=("tag", "t"), hidden=True)
110     async def tags_get_alias(
111             self, ctx: Context, *, tag_name: TagNameConverter = None
112     ) -> None:
113         """
114         Alias for invoking <prefix>tags get [tag_name].
115 
116         tag_name: str - tag to be viewed.
117         """
118         await self.invoke(ctx, "tags get", tag_name=tag_name)
119 
120     @get_group_alias.command(name="docs", aliases=("doc", "d"), hidden=True)
121     async def docs_get_alias(
122             self, ctx: Context, symbol: clean_content = None
123     ) -> None:
124         """Alias for invoking <prefix>docs get [symbol]."""
125         await self.invoke(ctx, "docs get", symbol)
126 
127     @command(name="nominate", hidden=True)
128     async def nomination_add_alias(self, ctx: Context, user: Union[Member, User, proxy_user], *, reason: str) -> None:
129         """Alias for invoking <prefix>talentpool add [user] [reason]."""
130         await self.invoke(ctx, "talentpool add", user, reason=reason)
131 
132     @command(name="unnominate", hidden=True)
133     async def nomination_end_alias(self, ctx: Context, user: Union[User, proxy_user], *, reason: str) -> None:
134         """Alias for invoking <prefix>nomination end [user] [reason]."""
135         await self.invoke(ctx, "nomination end", user, reason=reason)
136 
137     @command(name="nominees", hidden=True)
138     async def nominees_alias(self, ctx: Context) -> None:
139         """Alias for invoking <prefix>tp watched."""
140         await self.invoke(ctx, "talentpool watched")
141 
142 
143 def setup(bot: Bot) -> None:
144     """Alias cog load."""
145     bot.add_cog(Alias(bot))
146     log.info("Cog loaded: Alias")
147
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/bot/cogs/alias.py b/bot/cogs/alias.py
--- a/bot/cogs/alias.py
+++ b/bot/cogs/alias.py
@@ -53,6 +53,11 @@
         """Alias for invoking <prefix>site resources."""
         await self.invoke(ctx, "site resources")
 
+    @command(name="tools", hidden=True)
+    async def site_tools_alias(self, ctx: Context) -> None:
+        """Alias for invoking <prefix>site tools."""
+        await self.invoke(ctx, "site tools")
+
     @command(name="watch", hidden=True)
     async def bigbrother_watch_alias(self, ctx: Context, user: Union[Member, User, proxy_user], *, reason: str) -> None:
         """Alias for invoking <prefix>bigbrother watch [user] [reason]."""
diff --git a/bot/cogs/site.py b/bot/cogs/site.py
--- a/bot/cogs/site.py
+++ b/bot/cogs/site.py
@@ -44,17 +44,29 @@
     async def site_resources(self, ctx: Context) -> None:
         """Info about the site's Resources page."""
         learning_url = f"{PAGES_URL}/resources"
-        tools_url = f"{PAGES_URL}/tools"
 
-        embed = Embed(title="Resources & Tools")
-        embed.set_footer(text=f"{learning_url} | {tools_url}")
+        embed = Embed(title="Resources")
+        embed.set_footer(text=f"{learning_url}")
         embed.colour = Colour.blurple()
         embed.description = (
             f"The [Resources page]({learning_url}) on our website contains a "
-            "list of hand-selected goodies that we regularly recommend "
-            f"to both beginners and experts. The [Tools page]({tools_url}) "
-            "contains a couple of the most popular tools for programming in "
-            "Python."
+            "list of hand-selected learning resources that we regularly recommend "
+            f"to both beginners and experts."
+        )
+
+        await ctx.send(embed=embed)
+
+    @site_group.command(name="tools")
+    async def site_tools(self, ctx: Context) -> None:
+        """Info about the site's Tools page."""
+        tools_url = f"{PAGES_URL}/tools"
+
+        embed = Embed(title="Tools")
+        embed.set_footer(text=f"{tools_url}")
+        embed.colour = Colour.blurple()
+        embed.description = (
+            f"The [Tools page]({tools_url}) on our website contains a "
+            f"couple of the most popular tools for programming in Python."
         )
 
         await ctx.send(embed=embed)

{"golden_diff": "diff --git a/bot/cogs/alias.py b/bot/cogs/alias.py\n--- a/bot/cogs/alias.py\n+++ b/bot/cogs/alias.py\n@@ -53,6 +53,11 @@\n         \"\"\"Alias for invoking <prefix>site resources.\"\"\"\n         await self.invoke(ctx, \"site resources\")\n \n+    @command(name=\"tools\", hidden=True)\n+    async def site_tools_alias(self, ctx: Context) -> None:\n+        \"\"\"Alias for invoking <prefix>site tools.\"\"\"\n+        await self.invoke(ctx, \"site tools\")\n+\n     @command(name=\"watch\", hidden=True)\n     async def bigbrother_watch_alias(self, ctx: Context, user: Union[Member, User, proxy_user], *, reason: str) -> None:\n         \"\"\"Alias for invoking <prefix>bigbrother watch [user] [reason].\"\"\"\ndiff --git a/bot/cogs/site.py b/bot/cogs/site.py\n--- a/bot/cogs/site.py\n+++ b/bot/cogs/site.py\n@@ -44,17 +44,29 @@\n     async def site_resources(self, ctx: Context) -> None:\n         \"\"\"Info about the site's Resources page.\"\"\"\n         learning_url = f\"{PAGES_URL}/resources\"\n-        tools_url = f\"{PAGES_URL}/tools\"\n \n-        embed = Embed(title=\"Resources & Tools\")\n-        embed.set_footer(text=f\"{learning_url} | {tools_url}\")\n+        embed = Embed(title=\"Resources\")\n+        embed.set_footer(text=f\"{learning_url}\")\n         embed.colour = Colour.blurple()\n         embed.description = (\n             f\"The [Resources page]({learning_url}) on our website contains a \"\n-            \"list of hand-selected goodies that we regularly recommend \"\n-            f\"to both beginners and experts. The [Tools page]({tools_url}) \"\n-            \"contains a couple of the most popular tools for programming in \"\n-            \"Python.\"\n+            \"list of hand-selected learning resources that we regularly recommend \"\n+            f\"to both beginners and experts.\"\n+        )\n+\n+        await ctx.send(embed=embed)\n+\n+    @site_group.command(name=\"tools\")\n+    async def site_tools(self, ctx: Context) -> None:\n+        \"\"\"Info about the site's Tools page.\"\"\"\n+        tools_url = f\"{PAGES_URL}/tools\"\n+\n+        embed = Embed(title=\"Tools\")\n+        embed.set_footer(text=f\"{tools_url}\")\n+        embed.colour = Colour.blurple()\n+        embed.description = (\n+            f\"The [Tools page]({tools_url}) on our website contains a \"\n+            f\"couple of the most popular tools for programming in Python.\"\n         )\n \n         await ctx.send(embed=embed)\n", "issue": "Aliasing for !resources command.\nCurrently the !resources command links to both the [PyDis resource](https://pythondiscord.com/pages/resources/\r\n) page, and the [PyDis tools](https://pythondiscord.com/pages/tools/) page.\r\n\r\nI feel that the alias of !tools should be added to the command, or the links should be separated into two commands, to both make it easier for users to access the tools page, but also increase awareness of the page.\n", "before_files": [{"content": "import logging\n\nfrom discord import Colour, Embed\nfrom discord.ext.commands import Bot, Cog, Context, group\n\nfrom bot.constants import Channels, STAFF_ROLES, URLs\nfrom bot.decorators import redirect_output\nfrom bot.pagination import LinePaginator\n\nlog = logging.getLogger(__name__)\n\nPAGES_URL = f\"{URLs.site_schema}{URLs.site}/pages\"\n\n\nclass Site(Cog):\n    \"\"\"Commands for linking to different parts of the site.\"\"\"\n\n    def __init__(self, bot: Bot):\n        self.bot = bot\n\n    @group(name=\"site\", aliases=(\"s\",), invoke_without_command=True)\n    async def site_group(self, ctx: Context) -> None:\n        \"\"\"Commands for getting info about our website.\"\"\"\n        await ctx.invoke(self.bot.get_command(\"help\"), \"site\")\n\n    @site_group.command(name=\"home\", aliases=(\"about\",))\n    async def site_main(self, ctx: Context) -> None:\n        \"\"\"Info about the website itself.\"\"\"\n        url = f\"{URLs.site_schema}{URLs.site}/\"\n\n        embed = Embed(title=\"Python Discord website\")\n        embed.set_footer(text=url)\n        embed.colour = Colour.blurple()\n        embed.description = (\n            f\"[Our official website]({url}) is an open-source community project \"\n            \"created with Python and Flask. It contains information about the server \"\n            \"itself, lets you sign up for upcoming events, has its own wiki, contains \"\n            \"a list of valuable learning resources, and much more.\"\n        )\n\n        await ctx.send(embed=embed)\n\n    @site_group.command(name=\"resources\")\n    async def site_resources(self, ctx: Context) -> None:\n        \"\"\"Info about the site's Resources page.\"\"\"\n        learning_url = f\"{PAGES_URL}/resources\"\n        tools_url = f\"{PAGES_URL}/tools\"\n\n        embed = Embed(title=\"Resources & Tools\")\n        embed.set_footer(text=f\"{learning_url} | {tools_url}\")\n        embed.colour = Colour.blurple()\n        embed.description = (\n            f\"The [Resources page]({learning_url}) on our website contains a \"\n            \"list of hand-selected goodies that we regularly recommend \"\n            f\"to both beginners and experts. The [Tools page]({tools_url}) \"\n            \"contains a couple of the most popular tools for programming in \"\n            \"Python.\"\n        )\n\n        await ctx.send(embed=embed)\n\n    @site_group.command(name=\"help\")\n    async def site_help(self, ctx: Context) -> None:\n        \"\"\"Info about the site's Getting Help page.\"\"\"\n        url = f\"{PAGES_URL}/asking-good-questions\"\n\n        embed = Embed(title=\"Asking Good Questions\")\n        embed.set_footer(text=url)\n        embed.colour = Colour.blurple()\n        embed.description = (\n            \"Asking the right question about something that's new to you can sometimes be tricky. \"\n            f\"To help with this, we've created a [guide to asking good questions]({url}) on our website. \"\n            \"It contains everything you need to get the very best help from our community.\"\n        )\n\n        await ctx.send(embed=embed)\n\n    @site_group.command(name=\"faq\")\n    async def site_faq(self, ctx: Context) -> None:\n        \"\"\"Info about the site's FAQ page.\"\"\"\n        url = f\"{PAGES_URL}/frequently-asked-questions\"\n\n        embed = Embed(title=\"FAQ\")\n        embed.set_footer(text=url)\n        embed.colour = Colour.blurple()\n        embed.description = (\n            \"As the largest Python community on Discord, we get hundreds of questions every day. \"\n            \"Many of these questions have been asked before. We've compiled a list of the most \"\n            \"frequently asked questions along with their answers, which can be found on \"\n            f\"our [FAQ page]({url}).\"\n        )\n\n        await ctx.send(embed=embed)\n\n    @site_group.command(aliases=['r', 'rule'], name='rules')\n    @redirect_output(destination_channel=Channels.bot, bypass_roles=STAFF_ROLES)\n    async def site_rules(self, ctx: Context, *rules: int) -> None:\n        \"\"\"Provides a link to all rules or, if specified, displays specific rule(s).\"\"\"\n        rules_embed = Embed(title='Rules', color=Colour.blurple())\n        rules_embed.url = f\"{PAGES_URL}/rules\"\n\n        if not rules:\n            # Rules were not submitted. Return the default description.\n            rules_embed.description = (\n                \"The rules and guidelines that apply to this community can be found on\"\n                f\" our [rules page]({PAGES_URL}/rules). We expect\"\n                \" all members of the community to have read and understood these.\"\n            )\n\n            await ctx.send(embed=rules_embed)\n            return\n\n        full_rules = await self.bot.api_client.get('rules', params={'link_format': 'md'})\n        invalid_indices = tuple(\n            pick\n            for pick in rules\n            if pick < 0 or pick >= len(full_rules)\n        )\n\n        if invalid_indices:\n            indices = ', '.join(map(str, invalid_indices))\n            await ctx.send(f\":x: Invalid rule indices {indices}\")\n            return\n\n        final_rules = tuple(f\"**{pick}.** {full_rules[pick]}\" for pick in rules)\n\n        await LinePaginator.paginate(final_rules, ctx, rules_embed, max_lines=3)\n\n\ndef setup(bot: Bot) -> None:\n    \"\"\"Site cog load.\"\"\"\n    bot.add_cog(Site(bot))\n    log.info(\"Cog loaded: Site\")\n", "path": "bot/cogs/site.py"}, {"content": "import inspect\nimport logging\nfrom typing import Union\n\nfrom discord import Colour, Embed, Member, User\nfrom discord.ext.commands import Bot, Cog, Command, Context, clean_content, command, group\n\nfrom bot.cogs.watchchannels.watchchannel import proxy_user\nfrom bot.converters import TagNameConverter\nfrom bot.pagination import LinePaginator\n\nlog = logging.getLogger(__name__)\n\n\nclass Alias (Cog):\n    \"\"\"Aliases for commonly used commands.\"\"\"\n\n    def __init__(self, bot: Bot):\n        self.bot = bot\n\n    async def invoke(self, ctx: Context, cmd_name: str, *args, **kwargs) -> None:\n        \"\"\"Invokes a command with args and kwargs.\"\"\"\n        log.debug(f\"{cmd_name} was invoked through an alias\")\n        cmd = self.bot.get_command(cmd_name)\n        if not cmd:\n            return log.warning(f'Did not find command \"{cmd_name}\" to invoke.')\n        elif not await cmd.can_run(ctx):\n            return log.warning(\n                f'{str(ctx.author)} tried to run the command \"{cmd_name}\"'\n            )\n\n        await ctx.invoke(cmd, *args, **kwargs)\n\n    @command(name='aliases')\n    async def aliases_command(self, ctx: Context) -> None:\n        \"\"\"Show configured aliases on the bot.\"\"\"\n        embed = Embed(\n            title='Configured aliases',\n            colour=Colour.blue()\n        )\n        await LinePaginator.paginate(\n            (\n                f\"\u2022 `{ctx.prefix}{value.name}` \"\n                f\"=> `{ctx.prefix}{name[:-len('_alias')].replace('_', ' ')}`\"\n                for name, value in inspect.getmembers(self)\n                if isinstance(value, Command) and name.endswith('_alias')\n            ),\n            ctx, embed, empty=False, max_lines=20\n        )\n\n    @command(name=\"resources\", aliases=(\"resource\",), hidden=True)\n    async def site_resources_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>site resources.\"\"\"\n        await self.invoke(ctx, \"site resources\")\n\n    @command(name=\"watch\", hidden=True)\n    async def bigbrother_watch_alias(self, ctx: Context, user: Union[Member, User, proxy_user], *, reason: str) -> None:\n        \"\"\"Alias for invoking <prefix>bigbrother watch [user] [reason].\"\"\"\n        await self.invoke(ctx, \"bigbrother watch\", user, reason=reason)\n\n    @command(name=\"unwatch\", hidden=True)\n    async def bigbrother_unwatch_alias(self, ctx: Context, user: Union[User, proxy_user], *, reason: str) -> None:\n        \"\"\"Alias for invoking <prefix>bigbrother unwatch [user] [reason].\"\"\"\n        await self.invoke(ctx, \"bigbrother unwatch\", user, reason=reason)\n\n    @command(name=\"home\", hidden=True)\n    async def site_home_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>site home.\"\"\"\n        await self.invoke(ctx, \"site home\")\n\n    @command(name=\"faq\", hidden=True)\n    async def site_faq_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>site faq.\"\"\"\n        await self.invoke(ctx, \"site faq\")\n\n    @command(name=\"rules\", hidden=True)\n    async def site_rules_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>site rules.\"\"\"\n        await self.invoke(ctx, \"site rules\")\n\n    @command(name=\"reload\", hidden=True)\n    async def cogs_reload_alias(self, ctx: Context, *, cog_name: str) -> None:\n        \"\"\"Alias for invoking <prefix>cogs reload [cog_name].\"\"\"\n        await self.invoke(ctx, \"cogs reload\", cog_name)\n\n    @command(name=\"defon\", hidden=True)\n    async def defcon_enable_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>defcon enable.\"\"\"\n        await self.invoke(ctx, \"defcon enable\")\n\n    @command(name=\"defoff\", hidden=True)\n    async def defcon_disable_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>defcon disable.\"\"\"\n        await self.invoke(ctx, \"defcon disable\")\n\n    @command(name=\"exception\", hidden=True)\n    async def tags_get_traceback_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>tags get traceback.\"\"\"\n        await self.invoke(ctx, \"tags get\", tag_name=\"traceback\")\n\n    @group(name=\"get\",\n           aliases=(\"show\", \"g\"),\n           hidden=True,\n           invoke_without_command=True)\n    async def get_group_alias(self, ctx: Context) -> None:\n        \"\"\"Group for reverse aliases for commands like `tags get`, allowing for `get tags` or `get docs`.\"\"\"\n        pass\n\n    @get_group_alias.command(name=\"tags\", aliases=(\"tag\", \"t\"), hidden=True)\n    async def tags_get_alias(\n            self, ctx: Context, *, tag_name: TagNameConverter = None\n    ) -> None:\n        \"\"\"\n        Alias for invoking <prefix>tags get [tag_name].\n\n        tag_name: str - tag to be viewed.\n        \"\"\"\n        await self.invoke(ctx, \"tags get\", tag_name=tag_name)\n\n    @get_group_alias.command(name=\"docs\", aliases=(\"doc\", \"d\"), hidden=True)\n    async def docs_get_alias(\n            self, ctx: Context, symbol: clean_content = None\n    ) -> None:\n        \"\"\"Alias for invoking <prefix>docs get [symbol].\"\"\"\n        await self.invoke(ctx, \"docs get\", symbol)\n\n    @command(name=\"nominate\", hidden=True)\n    async def nomination_add_alias(self, ctx: Context, user: Union[Member, User, proxy_user], *, reason: str) -> None:\n        \"\"\"Alias for invoking <prefix>talentpool add [user] [reason].\"\"\"\n        await self.invoke(ctx, \"talentpool add\", user, reason=reason)\n\n    @command(name=\"unnominate\", hidden=True)\n    async def nomination_end_alias(self, ctx: Context, user: Union[User, proxy_user], *, reason: str) -> None:\n        \"\"\"Alias for invoking <prefix>nomination end [user] [reason].\"\"\"\n        await self.invoke(ctx, \"nomination end\", user, reason=reason)\n\n    @command(name=\"nominees\", hidden=True)\n    async def nominees_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>tp watched.\"\"\"\n        await self.invoke(ctx, \"talentpool watched\")\n\n\ndef setup(bot: Bot) -> None:\n    \"\"\"Alias cog load.\"\"\"\n    bot.add_cog(Alias(bot))\n    log.info(\"Cog loaded: Alias\")\n", "path": "bot/cogs/alias.py"}], "after_files": [{"content": "import logging\n\nfrom discord import Colour, Embed\nfrom discord.ext.commands import Bot, Cog, Context, group\n\nfrom bot.constants import Channels, STAFF_ROLES, URLs\nfrom bot.decorators import redirect_output\nfrom bot.pagination import LinePaginator\n\nlog = logging.getLogger(__name__)\n\nPAGES_URL = f\"{URLs.site_schema}{URLs.site}/pages\"\n\n\nclass Site(Cog):\n    \"\"\"Commands for linking to different parts of the site.\"\"\"\n\n    def __init__(self, bot: Bot):\n        self.bot = bot\n\n    @group(name=\"site\", aliases=(\"s\",), invoke_without_command=True)\n    async def site_group(self, ctx: Context) -> None:\n        \"\"\"Commands for getting info about our website.\"\"\"\n        await ctx.invoke(self.bot.get_command(\"help\"), \"site\")\n\n    @site_group.command(name=\"home\", aliases=(\"about\",))\n    async def site_main(self, ctx: Context) -> None:\n        \"\"\"Info about the website itself.\"\"\"\n        url = f\"{URLs.site_schema}{URLs.site}/\"\n\n        embed = Embed(title=\"Python Discord website\")\n        embed.set_footer(text=url)\n        embed.colour = Colour.blurple()\n        embed.description = (\n            f\"[Our official website]({url}) is an open-source community project \"\n            \"created with Python and Flask. It contains information about the server \"\n            \"itself, lets you sign up for upcoming events, has its own wiki, contains \"\n            \"a list of valuable learning resources, and much more.\"\n        )\n\n        await ctx.send(embed=embed)\n\n    @site_group.command(name=\"resources\")\n    async def site_resources(self, ctx: Context) -> None:\n        \"\"\"Info about the site's Resources page.\"\"\"\n        learning_url = f\"{PAGES_URL}/resources\"\n\n        embed = Embed(title=\"Resources\")\n        embed.set_footer(text=f\"{learning_url}\")\n        embed.colour = Colour.blurple()\n        embed.description = (\n            f\"The [Resources page]({learning_url}) on our website contains a \"\n            \"list of hand-selected learning resources that we regularly recommend \"\n            f\"to both beginners and experts.\"\n        )\n\n        await ctx.send(embed=embed)\n\n    @site_group.command(name=\"tools\")\n    async def site_tools(self, ctx: Context) -> None:\n        \"\"\"Info about the site's Tools page.\"\"\"\n        tools_url = f\"{PAGES_URL}/tools\"\n\n        embed = Embed(title=\"Tools\")\n        embed.set_footer(text=f\"{tools_url}\")\n        embed.colour = Colour.blurple()\n        embed.description = (\n            f\"The [Tools page]({tools_url}) on our website contains a \"\n            f\"couple of the most popular tools for programming in Python.\"\n        )\n\n        await ctx.send(embed=embed)\n\n    @site_group.command(name=\"help\")\n    async def site_help(self, ctx: Context) -> None:\n        \"\"\"Info about the site's Getting Help page.\"\"\"\n        url = f\"{PAGES_URL}/asking-good-questions\"\n\n        embed = Embed(title=\"Asking Good Questions\")\n        embed.set_footer(text=url)\n        embed.colour = Colour.blurple()\n        embed.description = (\n            \"Asking the right question about something that's new to you can sometimes be tricky. \"\n            f\"To help with this, we've created a [guide to asking good questions]({url}) on our website. \"\n            \"It contains everything you need to get the very best help from our community.\"\n        )\n\n        await ctx.send(embed=embed)\n\n    @site_group.command(name=\"faq\")\n    async def site_faq(self, ctx: Context) -> None:\n        \"\"\"Info about the site's FAQ page.\"\"\"\n        url = f\"{PAGES_URL}/frequently-asked-questions\"\n\n        embed = Embed(title=\"FAQ\")\n        embed.set_footer(text=url)\n        embed.colour = Colour.blurple()\n        embed.description = (\n            \"As the largest Python community on Discord, we get hundreds of questions every day. \"\n            \"Many of these questions have been asked before. We've compiled a list of the most \"\n            \"frequently asked questions along with their answers, which can be found on \"\n            f\"our [FAQ page]({url}).\"\n        )\n\n        await ctx.send(embed=embed)\n\n    @site_group.command(aliases=['r', 'rule'], name='rules')\n    @redirect_output(destination_channel=Channels.bot, bypass_roles=STAFF_ROLES)\n    async def site_rules(self, ctx: Context, *rules: int) -> None:\n        \"\"\"Provides a link to all rules or, if specified, displays specific rule(s).\"\"\"\n        rules_embed = Embed(title='Rules', color=Colour.blurple())\n        rules_embed.url = f\"{PAGES_URL}/rules\"\n\n        if not rules:\n            # Rules were not submitted. Return the default description.\n            rules_embed.description = (\n                \"The rules and guidelines that apply to this community can be found on\"\n                f\" our [rules page]({PAGES_URL}/rules). We expect\"\n                \" all members of the community to have read and understood these.\"\n            )\n\n            await ctx.send(embed=rules_embed)\n            return\n\n        full_rules = await self.bot.api_client.get('rules', params={'link_format': 'md'})\n        invalid_indices = tuple(\n            pick\n            for pick in rules\n            if pick < 0 or pick >= len(full_rules)\n        )\n\n        if invalid_indices:\n            indices = ', '.join(map(str, invalid_indices))\n            await ctx.send(f\":x: Invalid rule indices {indices}\")\n            return\n\n        final_rules = tuple(f\"**{pick}.** {full_rules[pick]}\" for pick in rules)\n\n        await LinePaginator.paginate(final_rules, ctx, rules_embed, max_lines=3)\n\n\ndef setup(bot: Bot) -> None:\n    \"\"\"Site cog load.\"\"\"\n    bot.add_cog(Site(bot))\n    log.info(\"Cog loaded: Site\")\n", "path": "bot/cogs/site.py"}, {"content": "import inspect\nimport logging\nfrom typing import Union\n\nfrom discord import Colour, Embed, Member, User\nfrom discord.ext.commands import Bot, Cog, Command, Context, clean_content, command, group\n\nfrom bot.cogs.watchchannels.watchchannel import proxy_user\nfrom bot.converters import TagNameConverter\nfrom bot.pagination import LinePaginator\n\nlog = logging.getLogger(__name__)\n\n\nclass Alias (Cog):\n    \"\"\"Aliases for commonly used commands.\"\"\"\n\n    def __init__(self, bot: Bot):\n        self.bot = bot\n\n    async def invoke(self, ctx: Context, cmd_name: str, *args, **kwargs) -> None:\n        \"\"\"Invokes a command with args and kwargs.\"\"\"\n        log.debug(f\"{cmd_name} was invoked through an alias\")\n        cmd = self.bot.get_command(cmd_name)\n        if not cmd:\n            return log.warning(f'Did not find command \"{cmd_name}\" to invoke.')\n        elif not await cmd.can_run(ctx):\n            return log.warning(\n                f'{str(ctx.author)} tried to run the command \"{cmd_name}\"'\n            )\n\n        await ctx.invoke(cmd, *args, **kwargs)\n\n    @command(name='aliases')\n    async def aliases_command(self, ctx: Context) -> None:\n        \"\"\"Show configured aliases on the bot.\"\"\"\n        embed = Embed(\n            title='Configured aliases',\n            colour=Colour.blue()\n        )\n        await LinePaginator.paginate(\n            (\n                f\"\u2022 `{ctx.prefix}{value.name}` \"\n                f\"=> `{ctx.prefix}{name[:-len('_alias')].replace('_', ' ')}`\"\n                for name, value in inspect.getmembers(self)\n                if isinstance(value, Command) and name.endswith('_alias')\n            ),\n            ctx, embed, empty=False, max_lines=20\n        )\n\n    @command(name=\"resources\", aliases=(\"resource\",), hidden=True)\n    async def site_resources_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>site resources.\"\"\"\n        await self.invoke(ctx, \"site resources\")\n\n    @command(name=\"tools\", hidden=True)\n    async def site_tools_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>site tools.\"\"\"\n        await self.invoke(ctx, \"site tools\")\n\n    @command(name=\"watch\", hidden=True)\n    async def bigbrother_watch_alias(self, ctx: Context, user: Union[Member, User, proxy_user], *, reason: str) -> None:\n        \"\"\"Alias for invoking <prefix>bigbrother watch [user] [reason].\"\"\"\n        await self.invoke(ctx, \"bigbrother watch\", user, reason=reason)\n\n    @command(name=\"unwatch\", hidden=True)\n    async def bigbrother_unwatch_alias(self, ctx: Context, user: Union[User, proxy_user], *, reason: str) -> None:\n        \"\"\"Alias for invoking <prefix>bigbrother unwatch [user] [reason].\"\"\"\n        await self.invoke(ctx, \"bigbrother unwatch\", user, reason=reason)\n\n    @command(name=\"home\", hidden=True)\n    async def site_home_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>site home.\"\"\"\n        await self.invoke(ctx, \"site home\")\n\n    @command(name=\"faq\", hidden=True)\n    async def site_faq_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>site faq.\"\"\"\n        await self.invoke(ctx, \"site faq\")\n\n    @command(name=\"rules\", hidden=True)\n    async def site_rules_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>site rules.\"\"\"\n        await self.invoke(ctx, \"site rules\")\n\n    @command(name=\"reload\", hidden=True)\n    async def cogs_reload_alias(self, ctx: Context, *, cog_name: str) -> None:\n        \"\"\"Alias for invoking <prefix>cogs reload [cog_name].\"\"\"\n        await self.invoke(ctx, \"cogs reload\", cog_name)\n\n    @command(name=\"defon\", hidden=True)\n    async def defcon_enable_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>defcon enable.\"\"\"\n        await self.invoke(ctx, \"defcon enable\")\n\n    @command(name=\"defoff\", hidden=True)\n    async def defcon_disable_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>defcon disable.\"\"\"\n        await self.invoke(ctx, \"defcon disable\")\n\n    @command(name=\"exception\", hidden=True)\n    async def tags_get_traceback_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>tags get traceback.\"\"\"\n        await self.invoke(ctx, \"tags get\", tag_name=\"traceback\")\n\n    @group(name=\"get\",\n           aliases=(\"show\", \"g\"),\n           hidden=True,\n           invoke_without_command=True)\n    async def get_group_alias(self, ctx: Context) -> None:\n        \"\"\"Group for reverse aliases for commands like `tags get`, allowing for `get tags` or `get docs`.\"\"\"\n        pass\n\n    @get_group_alias.command(name=\"tags\", aliases=(\"tag\", \"t\"), hidden=True)\n    async def tags_get_alias(\n            self, ctx: Context, *, tag_name: TagNameConverter = None\n    ) -> None:\n        \"\"\"\n        Alias for invoking <prefix>tags get [tag_name].\n\n        tag_name: str - tag to be viewed.\n        \"\"\"\n        await self.invoke(ctx, \"tags get\", tag_name=tag_name)\n\n    @get_group_alias.command(name=\"docs\", aliases=(\"doc\", \"d\"), hidden=True)\n    async def docs_get_alias(\n            self, ctx: Context, symbol: clean_content = None\n    ) -> None:\n        \"\"\"Alias for invoking <prefix>docs get [symbol].\"\"\"\n        await self.invoke(ctx, \"docs get\", symbol)\n\n    @command(name=\"nominate\", hidden=True)\n    async def nomination_add_alias(self, ctx: Context, user: Union[Member, User, proxy_user], *, reason: str) -> None:\n        \"\"\"Alias for invoking <prefix>talentpool add [user] [reason].\"\"\"\n        await self.invoke(ctx, \"talentpool add\", user, reason=reason)\n\n    @command(name=\"unnominate\", hidden=True)\n    async def nomination_end_alias(self, ctx: Context, user: Union[User, proxy_user], *, reason: str) -> None:\n        \"\"\"Alias for invoking <prefix>nomination end [user] [reason].\"\"\"\n        await self.invoke(ctx, \"nomination end\", user, reason=reason)\n\n    @command(name=\"nominees\", hidden=True)\n    async def nominees_alias(self, ctx: Context) -> None:\n        \"\"\"Alias for invoking <prefix>tp watched.\"\"\"\n        await self.invoke(ctx, \"talentpool watched\")\n\n\ndef setup(bot: Bot) -> None:\n    \"\"\"Alias cog load.\"\"\"\n    bot.add_cog(Alias(bot))\n    log.info(\"Cog loaded: Alias\")\n", "path": "bot/cogs/alias.py"}]}