We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
PEP Command Fails on Empty Metadata
Currently, the PEP command assumes that if a metadata field is present in the PEP's summary table that the value is populated:

https://github.com/python-discord/bot/blob/74d990540a1072c1782fa7593d7d1abe3c165f49/bot/cogs/utils.py#L64-L72

However, this is not always the case, e.g. [PEP 249](https://www.python.org/dev/peps/pep-0249/):

![image](https://user-images.githubusercontent.com/5323929/72211253-23e26600-3496-11ea-847b-29300866532b.png)

Because of this, the embed field's `value` can be provided an empty string, causing an exception to be raised:

```
HTTPException: 400 BAD REQUEST (error code: 50035): Invalid Form Body
In embed.fields.1.value: This field is required
```

To fix this, there should be a catch for empty values to prevent a field being added if there's no value to populate.

--- 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/utils.py`
Content:
```
1 import logging
2 import re
3 import unicodedata
4 from asyncio import TimeoutError, sleep
5 from email.parser import HeaderParser
6 from io import StringIO
7 from typing import Tuple
8 
9 from dateutil import relativedelta
10 from discord import Colour, Embed, Message, Role
11 from discord.ext.commands import Cog, Context, command
12 
13 from bot.bot import Bot
14 from bot.constants import Channels, MODERATION_ROLES, Mention, STAFF_ROLES
15 from bot.decorators import in_channel, with_role
16 from bot.utils.time import humanize_delta
17 
18 log = logging.getLogger(__name__)
19 
20 
21 class Utils(Cog):
22     """A selection of utilities which don't have a clear category."""
23 
24     def __init__(self, bot: Bot):
25         self.bot = bot
26 
27         self.base_pep_url = "http://www.python.org/dev/peps/pep-"
28         self.base_github_pep_url = "https://raw.githubusercontent.com/python/peps/master/pep-"
29 
30     @command(name='pep', aliases=('get_pep', 'p'))
31     async def pep_command(self, ctx: Context, pep_number: str) -> None:
32         """Fetches information about a PEP and sends it to the channel."""
33         if pep_number.isdigit():
34             pep_number = int(pep_number)
35         else:
36             await ctx.invoke(self.bot.get_command("help"), "pep")
37             return
38 
39         possible_extensions = ['.txt', '.rst']
40         found_pep = False
41         for extension in possible_extensions:
42             # Attempt to fetch the PEP
43             pep_url = f"{self.base_github_pep_url}{pep_number:04}{extension}"
44             log.trace(f"Requesting PEP {pep_number} with {pep_url}")
45             response = await self.bot.http_session.get(pep_url)
46 
47             if response.status == 200:
48                 log.trace("PEP found")
49                 found_pep = True
50 
51                 pep_content = await response.text()
52 
53                 # Taken from https://github.com/python/peps/blob/master/pep0/pep.py#L179
54                 pep_header = HeaderParser().parse(StringIO(pep_content))
55 
56                 # Assemble the embed
57                 pep_embed = Embed(
58                     title=f"**PEP {pep_number} - {pep_header['Title']}**",
59                     description=f"[Link]({self.base_pep_url}{pep_number:04})",
60                 )
61 
62                 pep_embed.set_thumbnail(url="https://www.python.org/static/opengraph-icon-200x200.png")
63 
64                 # Add the interesting information
65                 if "Status" in pep_header:
66                     pep_embed.add_field(name="Status", value=pep_header["Status"])
67                 if "Python-Version" in pep_header:
68                     pep_embed.add_field(name="Python-Version", value=pep_header["Python-Version"])
69                 if "Created" in pep_header:
70                     pep_embed.add_field(name="Created", value=pep_header["Created"])
71                 if "Type" in pep_header:
72                     pep_embed.add_field(name="Type", value=pep_header["Type"])
73 
74             elif response.status != 404:
75                 # any response except 200 and 404 is expected
76                 found_pep = True  # actually not, but it's easier to display this way
77                 log.trace(f"The user requested PEP {pep_number}, but the response had an unexpected status code: "
78                           f"{response.status}.\n{response.text}")
79 
80                 error_message = "Unexpected HTTP error during PEP search. Please let us know."
81                 pep_embed = Embed(title="Unexpected error", description=error_message)
82                 pep_embed.colour = Colour.red()
83                 break
84 
85         if not found_pep:
86             log.trace("PEP was not found")
87             not_found = f"PEP {pep_number} does not exist."
88             pep_embed = Embed(title="PEP not found", description=not_found)
89             pep_embed.colour = Colour.red()
90 
91         await ctx.message.channel.send(embed=pep_embed)
92 
93     @command()
94     @in_channel(Channels.bot, bypass_roles=STAFF_ROLES)
95     async def charinfo(self, ctx: Context, *, characters: str) -> None:
96         """Shows you information on up to 25 unicode characters."""
97         match = re.match(r"<(a?):(\w+):(\d+)>", characters)
98         if match:
99             embed = Embed(
100                 title="Non-Character Detected",
101                 description=(
102                     "Only unicode characters can be processed, but a custom Discord emoji "
103                     "was found. Please remove it and try again."
104                 )
105             )
106             embed.colour = Colour.red()
107             await ctx.send(embed=embed)
108             return
109 
110         if len(characters) > 25:
111             embed = Embed(title=f"Too many characters ({len(characters)}/25)")
112             embed.colour = Colour.red()
113             await ctx.send(embed=embed)
114             return
115 
116         def get_info(char: str) -> Tuple[str, str]:
117             digit = f"{ord(char):x}"
118             if len(digit) <= 4:
119                 u_code = f"\\u{digit:>04}"
120             else:
121                 u_code = f"\\U{digit:>08}"
122             url = f"https://www.compart.com/en/unicode/U+{digit:>04}"
123             name = f"[{unicodedata.name(char, '')}]({url})"
124             info = f"`{u_code.ljust(10)}`: {name} - {char}"
125             return info, u_code
126 
127         charlist, rawlist = zip(*(get_info(c) for c in characters))
128 
129         embed = Embed(description="\n".join(charlist))
130         embed.set_author(name="Character Info")
131 
132         if len(characters) > 1:
133             embed.add_field(name='Raw', value=f"`{''.join(rawlist)}`", inline=False)
134 
135         await ctx.send(embed=embed)
136 
137     @command()
138     @with_role(*MODERATION_ROLES)
139     async def mention(self, ctx: Context, *, role: Role) -> None:
140         """Set a role to be mentionable for a limited time."""
141         if role.mentionable:
142             await ctx.send(f"{role} is already mentionable!")
143             return
144 
145         await role.edit(reason=f"Role unlocked by {ctx.author}", mentionable=True)
146 
147         human_time = humanize_delta(relativedelta.relativedelta(seconds=Mention.message_timeout))
148         await ctx.send(
149             f"{role} has been made mentionable. I will reset it in {human_time}, or when someone mentions this role."
150         )
151 
152         def check(m: Message) -> bool:
153             """Checks that the message contains the role mention."""
154             return role in m.role_mentions
155 
156         try:
157             msg = await self.bot.wait_for("message", check=check, timeout=Mention.message_timeout)
158         except TimeoutError:
159             await role.edit(mentionable=False, reason="Automatic role lock - timeout.")
160             await ctx.send(f"{ctx.author.mention}, you took too long. I have reset {role} to be unmentionable.")
161             return
162 
163         if any(r.id in MODERATION_ROLES for r in msg.author.roles):
164             await sleep(Mention.reset_delay)
165             await role.edit(mentionable=False, reason=f"Automatic role lock by {msg.author}")
166             await ctx.send(
167                 f"{ctx.author.mention}, I have reset {role} to be unmentionable as "
168                 f"{msg.author if msg.author != ctx.author else 'you'} sent a message mentioning it."
169             )
170             return
171 
172         await role.edit(mentionable=False, reason=f"Automatic role lock - unauthorised use by {msg.author}")
173         await ctx.send(
174             f"{ctx.author.mention}, I have reset {role} to be unmentionable "
175             f"as I detected unauthorised use by {msg.author} (ID: {msg.author.id})."
176         )
177 
178 
179 def setup(bot: Bot) -> None:
180     """Load the Utils cog."""
181     bot.add_cog(Utils(bot))
182
```
--- 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/utils.py b/bot/cogs/utils.py
--- a/bot/cogs/utils.py
+++ b/bot/cogs/utils.py
@@ -62,14 +62,12 @@
                 pep_embed.set_thumbnail(url="https://www.python.org/static/opengraph-icon-200x200.png")
 
                 # Add the interesting information
-                if "Status" in pep_header:
-                    pep_embed.add_field(name="Status", value=pep_header["Status"])
-                if "Python-Version" in pep_header:
-                    pep_embed.add_field(name="Python-Version", value=pep_header["Python-Version"])
-                if "Created" in pep_header:
-                    pep_embed.add_field(name="Created", value=pep_header["Created"])
-                if "Type" in pep_header:
-                    pep_embed.add_field(name="Type", value=pep_header["Type"])
+                fields_to_check = ("Status", "Python-Version", "Created", "Type")
+                for field in fields_to_check:
+                    # Check for a PEP metadata field that is present but has an empty value
+                    # embed field values can't contain an empty string
+                    if pep_header.get(field, ""):
+                        pep_embed.add_field(name=field, value=pep_header[field])
 
             elif response.status != 404:
                 # any response except 200 and 404 is expected

{"golden_diff": "diff --git a/bot/cogs/utils.py b/bot/cogs/utils.py\n--- a/bot/cogs/utils.py\n+++ b/bot/cogs/utils.py\n@@ -62,14 +62,12 @@\n                 pep_embed.set_thumbnail(url=\"https://www.python.org/static/opengraph-icon-200x200.png\")\n \n                 # Add the interesting information\n-                if \"Status\" in pep_header:\n-                    pep_embed.add_field(name=\"Status\", value=pep_header[\"Status\"])\n-                if \"Python-Version\" in pep_header:\n-                    pep_embed.add_field(name=\"Python-Version\", value=pep_header[\"Python-Version\"])\n-                if \"Created\" in pep_header:\n-                    pep_embed.add_field(name=\"Created\", value=pep_header[\"Created\"])\n-                if \"Type\" in pep_header:\n-                    pep_embed.add_field(name=\"Type\", value=pep_header[\"Type\"])\n+                fields_to_check = (\"Status\", \"Python-Version\", \"Created\", \"Type\")\n+                for field in fields_to_check:\n+                    # Check for a PEP metadata field that is present but has an empty value\n+                    # embed field values can't contain an empty string\n+                    if pep_header.get(field, \"\"):\n+                        pep_embed.add_field(name=field, value=pep_header[field])\n \n             elif response.status != 404:\n                 # any response except 200 and 404 is expected\n", "issue": "PEP Command Fails on Empty Metadata\nCurrently, the PEP command assumes that if a metadata field is present in the PEP's summary table that the value is populated:\r\n\r\nhttps://github.com/python-discord/bot/blob/74d990540a1072c1782fa7593d7d1abe3c165f49/bot/cogs/utils.py#L64-L72\r\n\r\nHowever, this is not always the case, e.g. [PEP 249](https://www.python.org/dev/peps/pep-0249/):\r\n\r\n![image](https://user-images.githubusercontent.com/5323929/72211253-23e26600-3496-11ea-847b-29300866532b.png)\r\n\r\nBecause of this, the embed field's `value` can be provided an empty string, causing an exception to be raised:\r\n\r\n```\r\nHTTPException: 400 BAD REQUEST (error code: 50035): Invalid Form Body\r\nIn embed.fields.1.value: This field is required\r\n```\r\n\r\nTo fix this, there should be a catch for empty values to prevent a field being added if there's no value to populate.\n", "before_files": [{"content": "import logging\nimport re\nimport unicodedata\nfrom asyncio import TimeoutError, sleep\nfrom email.parser import HeaderParser\nfrom io import StringIO\nfrom typing import Tuple\n\nfrom dateutil import relativedelta\nfrom discord import Colour, Embed, Message, Role\nfrom discord.ext.commands import Cog, Context, command\n\nfrom bot.bot import Bot\nfrom bot.constants import Channels, MODERATION_ROLES, Mention, STAFF_ROLES\nfrom bot.decorators import in_channel, with_role\nfrom bot.utils.time import humanize_delta\n\nlog = logging.getLogger(__name__)\n\n\nclass Utils(Cog):\n    \"\"\"A selection of utilities which don't have a clear category.\"\"\"\n\n    def __init__(self, bot: Bot):\n        self.bot = bot\n\n        self.base_pep_url = \"http://www.python.org/dev/peps/pep-\"\n        self.base_github_pep_url = \"https://raw.githubusercontent.com/python/peps/master/pep-\"\n\n    @command(name='pep', aliases=('get_pep', 'p'))\n    async def pep_command(self, ctx: Context, pep_number: str) -> None:\n        \"\"\"Fetches information about a PEP and sends it to the channel.\"\"\"\n        if pep_number.isdigit():\n            pep_number = int(pep_number)\n        else:\n            await ctx.invoke(self.bot.get_command(\"help\"), \"pep\")\n            return\n\n        possible_extensions = ['.txt', '.rst']\n        found_pep = False\n        for extension in possible_extensions:\n            # Attempt to fetch the PEP\n            pep_url = f\"{self.base_github_pep_url}{pep_number:04}{extension}\"\n            log.trace(f\"Requesting PEP {pep_number} with {pep_url}\")\n            response = await self.bot.http_session.get(pep_url)\n\n            if response.status == 200:\n                log.trace(\"PEP found\")\n                found_pep = True\n\n                pep_content = await response.text()\n\n                # Taken from https://github.com/python/peps/blob/master/pep0/pep.py#L179\n                pep_header = HeaderParser().parse(StringIO(pep_content))\n\n                # Assemble the embed\n                pep_embed = Embed(\n                    title=f\"**PEP {pep_number} - {pep_header['Title']}**\",\n                    description=f\"[Link]({self.base_pep_url}{pep_number:04})\",\n                )\n\n                pep_embed.set_thumbnail(url=\"https://www.python.org/static/opengraph-icon-200x200.png\")\n\n                # Add the interesting information\n                if \"Status\" in pep_header:\n                    pep_embed.add_field(name=\"Status\", value=pep_header[\"Status\"])\n                if \"Python-Version\" in pep_header:\n                    pep_embed.add_field(name=\"Python-Version\", value=pep_header[\"Python-Version\"])\n                if \"Created\" in pep_header:\n                    pep_embed.add_field(name=\"Created\", value=pep_header[\"Created\"])\n                if \"Type\" in pep_header:\n                    pep_embed.add_field(name=\"Type\", value=pep_header[\"Type\"])\n\n            elif response.status != 404:\n                # any response except 200 and 404 is expected\n                found_pep = True  # actually not, but it's easier to display this way\n                log.trace(f\"The user requested PEP {pep_number}, but the response had an unexpected status code: \"\n                          f\"{response.status}.\\n{response.text}\")\n\n                error_message = \"Unexpected HTTP error during PEP search. Please let us know.\"\n                pep_embed = Embed(title=\"Unexpected error\", description=error_message)\n                pep_embed.colour = Colour.red()\n                break\n\n        if not found_pep:\n            log.trace(\"PEP was not found\")\n            not_found = f\"PEP {pep_number} does not exist.\"\n            pep_embed = Embed(title=\"PEP not found\", description=not_found)\n            pep_embed.colour = Colour.red()\n\n        await ctx.message.channel.send(embed=pep_embed)\n\n    @command()\n    @in_channel(Channels.bot, bypass_roles=STAFF_ROLES)\n    async def charinfo(self, ctx: Context, *, characters: str) -> None:\n        \"\"\"Shows you information on up to 25 unicode characters.\"\"\"\n        match = re.match(r\"<(a?):(\\w+):(\\d+)>\", characters)\n        if match:\n            embed = Embed(\n                title=\"Non-Character Detected\",\n                description=(\n                    \"Only unicode characters can be processed, but a custom Discord emoji \"\n                    \"was found. Please remove it and try again.\"\n                )\n            )\n            embed.colour = Colour.red()\n            await ctx.send(embed=embed)\n            return\n\n        if len(characters) > 25:\n            embed = Embed(title=f\"Too many characters ({len(characters)}/25)\")\n            embed.colour = Colour.red()\n            await ctx.send(embed=embed)\n            return\n\n        def get_info(char: str) -> Tuple[str, str]:\n            digit = f\"{ord(char):x}\"\n            if len(digit) <= 4:\n                u_code = f\"\\\\u{digit:>04}\"\n            else:\n                u_code = f\"\\\\U{digit:>08}\"\n            url = f\"https://www.compart.com/en/unicode/U+{digit:>04}\"\n            name = f\"[{unicodedata.name(char, '')}]({url})\"\n            info = f\"`{u_code.ljust(10)}`: {name} - {char}\"\n            return info, u_code\n\n        charlist, rawlist = zip(*(get_info(c) for c in characters))\n\n        embed = Embed(description=\"\\n\".join(charlist))\n        embed.set_author(name=\"Character Info\")\n\n        if len(characters) > 1:\n            embed.add_field(name='Raw', value=f\"`{''.join(rawlist)}`\", inline=False)\n\n        await ctx.send(embed=embed)\n\n    @command()\n    @with_role(*MODERATION_ROLES)\n    async def mention(self, ctx: Context, *, role: Role) -> None:\n        \"\"\"Set a role to be mentionable for a limited time.\"\"\"\n        if role.mentionable:\n            await ctx.send(f\"{role} is already mentionable!\")\n            return\n\n        await role.edit(reason=f\"Role unlocked by {ctx.author}\", mentionable=True)\n\n        human_time = humanize_delta(relativedelta.relativedelta(seconds=Mention.message_timeout))\n        await ctx.send(\n            f\"{role} has been made mentionable. I will reset it in {human_time}, or when someone mentions this role.\"\n        )\n\n        def check(m: Message) -> bool:\n            \"\"\"Checks that the message contains the role mention.\"\"\"\n            return role in m.role_mentions\n\n        try:\n            msg = await self.bot.wait_for(\"message\", check=check, timeout=Mention.message_timeout)\n        except TimeoutError:\n            await role.edit(mentionable=False, reason=\"Automatic role lock - timeout.\")\n            await ctx.send(f\"{ctx.author.mention}, you took too long. I have reset {role} to be unmentionable.\")\n            return\n\n        if any(r.id in MODERATION_ROLES for r in msg.author.roles):\n            await sleep(Mention.reset_delay)\n            await role.edit(mentionable=False, reason=f\"Automatic role lock by {msg.author}\")\n            await ctx.send(\n                f\"{ctx.author.mention}, I have reset {role} to be unmentionable as \"\n                f\"{msg.author if msg.author != ctx.author else 'you'} sent a message mentioning it.\"\n            )\n            return\n\n        await role.edit(mentionable=False, reason=f\"Automatic role lock - unauthorised use by {msg.author}\")\n        await ctx.send(\n            f\"{ctx.author.mention}, I have reset {role} to be unmentionable \"\n            f\"as I detected unauthorised use by {msg.author} (ID: {msg.author.id}).\"\n        )\n\n\ndef setup(bot: Bot) -> None:\n    \"\"\"Load the Utils cog.\"\"\"\n    bot.add_cog(Utils(bot))\n", "path": "bot/cogs/utils.py"}], "after_files": [{"content": "import logging\nimport re\nimport unicodedata\nfrom asyncio import TimeoutError, sleep\nfrom email.parser import HeaderParser\nfrom io import StringIO\nfrom typing import Tuple\n\nfrom dateutil import relativedelta\nfrom discord import Colour, Embed, Message, Role\nfrom discord.ext.commands import Cog, Context, command\n\nfrom bot.bot import Bot\nfrom bot.constants import Channels, MODERATION_ROLES, Mention, STAFF_ROLES\nfrom bot.decorators import in_channel, with_role\nfrom bot.utils.time import humanize_delta\n\nlog = logging.getLogger(__name__)\n\n\nclass Utils(Cog):\n    \"\"\"A selection of utilities which don't have a clear category.\"\"\"\n\n    def __init__(self, bot: Bot):\n        self.bot = bot\n\n        self.base_pep_url = \"http://www.python.org/dev/peps/pep-\"\n        self.base_github_pep_url = \"https://raw.githubusercontent.com/python/peps/master/pep-\"\n\n    @command(name='pep', aliases=('get_pep', 'p'))\n    async def pep_command(self, ctx: Context, pep_number: str) -> None:\n        \"\"\"Fetches information about a PEP and sends it to the channel.\"\"\"\n        if pep_number.isdigit():\n            pep_number = int(pep_number)\n        else:\n            await ctx.invoke(self.bot.get_command(\"help\"), \"pep\")\n            return\n\n        possible_extensions = ['.txt', '.rst']\n        found_pep = False\n        for extension in possible_extensions:\n            # Attempt to fetch the PEP\n            pep_url = f\"{self.base_github_pep_url}{pep_number:04}{extension}\"\n            log.trace(f\"Requesting PEP {pep_number} with {pep_url}\")\n            response = await self.bot.http_session.get(pep_url)\n\n            if response.status == 200:\n                log.trace(\"PEP found\")\n                found_pep = True\n\n                pep_content = await response.text()\n\n                # Taken from https://github.com/python/peps/blob/master/pep0/pep.py#L179\n                pep_header = HeaderParser().parse(StringIO(pep_content))\n\n                # Assemble the embed\n                pep_embed = Embed(\n                    title=f\"**PEP {pep_number} - {pep_header['Title']}**\",\n                    description=f\"[Link]({self.base_pep_url}{pep_number:04})\",\n                )\n\n                pep_embed.set_thumbnail(url=\"https://www.python.org/static/opengraph-icon-200x200.png\")\n\n                # Add the interesting information\n                fields_to_check = (\"Status\", \"Python-Version\", \"Created\", \"Type\")\n                for field in fields_to_check:\n                    # Check for a PEP metadata field that is present but has an empty value\n                    # embed field values can't contain an empty string\n                    if pep_header.get(field, \"\"):\n                        pep_embed.add_field(name=field, value=pep_header[field])\n\n            elif response.status != 404:\n                # any response except 200 and 404 is expected\n                found_pep = True  # actually not, but it's easier to display this way\n                log.trace(f\"The user requested PEP {pep_number}, but the response had an unexpected status code: \"\n                          f\"{response.status}.\\n{response.text}\")\n\n                error_message = \"Unexpected HTTP error during PEP search. Please let us know.\"\n                pep_embed = Embed(title=\"Unexpected error\", description=error_message)\n                pep_embed.colour = Colour.red()\n                break\n\n        if not found_pep:\n            log.trace(\"PEP was not found\")\n            not_found = f\"PEP {pep_number} does not exist.\"\n            pep_embed = Embed(title=\"PEP not found\", description=not_found)\n            pep_embed.colour = Colour.red()\n\n        await ctx.message.channel.send(embed=pep_embed)\n\n    @command()\n    @in_channel(Channels.bot, bypass_roles=STAFF_ROLES)\n    async def charinfo(self, ctx: Context, *, characters: str) -> None:\n        \"\"\"Shows you information on up to 25 unicode characters.\"\"\"\n        match = re.match(r\"<(a?):(\\w+):(\\d+)>\", characters)\n        if match:\n            embed = Embed(\n                title=\"Non-Character Detected\",\n                description=(\n                    \"Only unicode characters can be processed, but a custom Discord emoji \"\n                    \"was found. Please remove it and try again.\"\n                )\n            )\n            embed.colour = Colour.red()\n            await ctx.send(embed=embed)\n            return\n\n        if len(characters) > 25:\n            embed = Embed(title=f\"Too many characters ({len(characters)}/25)\")\n            embed.colour = Colour.red()\n            await ctx.send(embed=embed)\n            return\n\n        def get_info(char: str) -> Tuple[str, str]:\n            digit = f\"{ord(char):x}\"\n            if len(digit) <= 4:\n                u_code = f\"\\\\u{digit:>04}\"\n            else:\n                u_code = f\"\\\\U{digit:>08}\"\n            url = f\"https://www.compart.com/en/unicode/U+{digit:>04}\"\n            name = f\"[{unicodedata.name(char, '')}]({url})\"\n            info = f\"`{u_code.ljust(10)}`: {name} - {char}\"\n            return info, u_code\n\n        charlist, rawlist = zip(*(get_info(c) for c in characters))\n\n        embed = Embed(description=\"\\n\".join(charlist))\n        embed.set_author(name=\"Character Info\")\n\n        if len(characters) > 1:\n            embed.add_field(name='Raw', value=f\"`{''.join(rawlist)}`\", inline=False)\n\n        await ctx.send(embed=embed)\n\n    @command()\n    @with_role(*MODERATION_ROLES)\n    async def mention(self, ctx: Context, *, role: Role) -> None:\n        \"\"\"Set a role to be mentionable for a limited time.\"\"\"\n        if role.mentionable:\n            await ctx.send(f\"{role} is already mentionable!\")\n            return\n\n        await role.edit(reason=f\"Role unlocked by {ctx.author}\", mentionable=True)\n\n        human_time = humanize_delta(relativedelta.relativedelta(seconds=Mention.message_timeout))\n        await ctx.send(\n            f\"{role} has been made mentionable. I will reset it in {human_time}, or when someone mentions this role.\"\n        )\n\n        def check(m: Message) -> bool:\n            \"\"\"Checks that the message contains the role mention.\"\"\"\n            return role in m.role_mentions\n\n        try:\n            msg = await self.bot.wait_for(\"message\", check=check, timeout=Mention.message_timeout)\n        except TimeoutError:\n            await role.edit(mentionable=False, reason=\"Automatic role lock - timeout.\")\n            await ctx.send(f\"{ctx.author.mention}, you took too long. I have reset {role} to be unmentionable.\")\n            return\n\n        if any(r.id in MODERATION_ROLES for r in msg.author.roles):\n            await sleep(Mention.reset_delay)\n            await role.edit(mentionable=False, reason=f\"Automatic role lock by {msg.author}\")\n            await ctx.send(\n                f\"{ctx.author.mention}, I have reset {role} to be unmentionable as \"\n                f\"{msg.author if msg.author != ctx.author else 'you'} sent a message mentioning it.\"\n            )\n            return\n\n        await role.edit(mentionable=False, reason=f\"Automatic role lock - unauthorised use by {msg.author}\")\n        await ctx.send(\n            f\"{ctx.author.mention}, I have reset {role} to be unmentionable \"\n            f\"as I detected unauthorised use by {msg.author} (ID: {msg.author.id}).\"\n        )\n\n\ndef setup(bot: Bot) -> None:\n    \"\"\"Load the Utils cog.\"\"\"\n    bot.add_cog(Utils(bot))\n", "path": "bot/cogs/utils.py"}]}