We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Remove periodic ping in #verification
This creates "accept bombs" that may trigger our anti-raid and burst spam filters, and is not really necessary anymore. We have more than enough people joining without having to periodically nag at them.

--- 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/verification.py`
Content:
```
1 import logging
2 from contextlib import suppress
3 from datetime import datetime
4 
5 from discord import Colour, Forbidden, Message, NotFound, Object
6 from discord.ext import tasks
7 from discord.ext.commands import Cog, Context, command
8 
9 from bot import constants
10 from bot.bot import Bot
11 from bot.cogs.moderation import ModLog
12 from bot.decorators import in_whitelist, without_role
13 from bot.utils.checks import InWhitelistCheckFailure, without_role_check
14 
15 log = logging.getLogger(__name__)
16 
17 WELCOME_MESSAGE = f"""
18 Hello! Welcome to the server, and thanks for verifying yourself!
19 
20 For your records, these are the documents you accepted:
21 
22 `1)` Our rules, here: <https://pythondiscord.com/pages/rules>
23 `2)` Our privacy policy, here: <https://pythondiscord.com/pages/privacy> - you can find information on how to have \
24 your information removed here as well.
25 
26 Feel free to review them at any point!
27 
28 Additionally, if you'd like to receive notifications for the announcements \
29 we post in <#{constants.Channels.announcements}>
30 from time to time, you can send `!subscribe` to <#{constants.Channels.bot_commands}> at any time \
31 to assign yourself the **Announcements** role. We'll mention this role every time we make an announcement.
32 
33 If you'd like to unsubscribe from the announcement notifications, simply send `!unsubscribe` to \
34 <#{constants.Channels.bot_commands}>.
35 """
36 
37 if constants.DEBUG_MODE:
38     PERIODIC_PING = "Periodic checkpoint message successfully sent."
39 else:
40     PERIODIC_PING = (
41         f"@everyone To verify that you have read our rules, please type `{constants.Bot.prefix}accept`."
42         " If you encounter any problems during the verification process, "
43         f"send a direct message to a staff member."
44     )
45 BOT_MESSAGE_DELETE_DELAY = 10
46 
47 
48 class Verification(Cog):
49     """User verification and role self-management."""
50 
51     def __init__(self, bot: Bot):
52         self.bot = bot
53         self.periodic_ping.start()
54 
55     @property
56     def mod_log(self) -> ModLog:
57         """Get currently loaded ModLog cog instance."""
58         return self.bot.get_cog("ModLog")
59 
60     @Cog.listener()
61     async def on_message(self, message: Message) -> None:
62         """Check new message event for messages to the checkpoint channel & process."""
63         if message.channel.id != constants.Channels.verification:
64             return  # Only listen for #checkpoint messages
65 
66         if message.author.bot:
67             # They're a bot, delete their message after the delay.
68             # But not the periodic ping; we like that one.
69             if message.content != PERIODIC_PING:
70                 await message.delete(delay=BOT_MESSAGE_DELETE_DELAY)
71             return
72 
73         # if a user mentions a role or guild member
74         # alert the mods in mod-alerts channel
75         if message.mentions or message.role_mentions:
76             log.debug(
77                 f"{message.author} mentioned one or more users "
78                 f"and/or roles in {message.channel.name}"
79             )
80 
81             embed_text = (
82                 f"{message.author.mention} sent a message in "
83                 f"{message.channel.mention} that contained user and/or role mentions."
84                 f"\n\n**Original message:**\n>>> {message.content}"
85             )
86 
87             # Send pretty mod log embed to mod-alerts
88             await self.mod_log.send_log_message(
89                 icon_url=constants.Icons.filtering,
90                 colour=Colour(constants.Colours.soft_red),
91                 title=f"User/Role mentioned in {message.channel.name}",
92                 text=embed_text,
93                 thumbnail=message.author.avatar_url_as(static_format="png"),
94                 channel_id=constants.Channels.mod_alerts,
95             )
96 
97         ctx: Context = await self.bot.get_context(message)
98         if ctx.command is not None and ctx.command.name == "accept":
99             return
100 
101         if any(r.id == constants.Roles.verified for r in ctx.author.roles):
102             log.info(
103                 f"{ctx.author} posted '{ctx.message.content}' "
104                 "in the verification channel, but is already verified."
105             )
106             return
107 
108         log.debug(
109             f"{ctx.author} posted '{ctx.message.content}' in the verification "
110             "channel. We are providing instructions how to verify."
111         )
112         await ctx.send(
113             f"{ctx.author.mention} Please type `!accept` to verify that you accept our rules, "
114             f"and gain access to the rest of the server.",
115             delete_after=20
116         )
117 
118         log.trace(f"Deleting the message posted by {ctx.author}")
119         with suppress(NotFound):
120             await ctx.message.delete()
121 
122     @command(name='accept', aliases=('verify', 'verified', 'accepted'), hidden=True)
123     @without_role(constants.Roles.verified)
124     @in_whitelist(channels=(constants.Channels.verification,))
125     async def accept_command(self, ctx: Context, *_) -> None:  # We don't actually care about the args
126         """Accept our rules and gain access to the rest of the server."""
127         log.debug(f"{ctx.author} called !accept. Assigning the 'Developer' role.")
128         await ctx.author.add_roles(Object(constants.Roles.verified), reason="Accepted the rules")
129         try:
130             await ctx.author.send(WELCOME_MESSAGE)
131         except Forbidden:
132             log.info(f"Sending welcome message failed for {ctx.author}.")
133         finally:
134             log.trace(f"Deleting accept message by {ctx.author}.")
135             with suppress(NotFound):
136                 self.mod_log.ignore(constants.Event.message_delete, ctx.message.id)
137                 await ctx.message.delete()
138 
139     @command(name='subscribe')
140     @in_whitelist(channels=(constants.Channels.bot_commands,))
141     async def subscribe_command(self, ctx: Context, *_) -> None:  # We don't actually care about the args
142         """Subscribe to announcement notifications by assigning yourself the role."""
143         has_role = False
144 
145         for role in ctx.author.roles:
146             if role.id == constants.Roles.announcements:
147                 has_role = True
148                 break
149 
150         if has_role:
151             await ctx.send(f"{ctx.author.mention} You're already subscribed!")
152             return
153 
154         log.debug(f"{ctx.author} called !subscribe. Assigning the 'Announcements' role.")
155         await ctx.author.add_roles(Object(constants.Roles.announcements), reason="Subscribed to announcements")
156 
157         log.trace(f"Deleting the message posted by {ctx.author}.")
158 
159         await ctx.send(
160             f"{ctx.author.mention} Subscribed to <#{constants.Channels.announcements}> notifications.",
161         )
162 
163     @command(name='unsubscribe')
164     @in_whitelist(channels=(constants.Channels.bot_commands,))
165     async def unsubscribe_command(self, ctx: Context, *_) -> None:  # We don't actually care about the args
166         """Unsubscribe from announcement notifications by removing the role from yourself."""
167         has_role = False
168 
169         for role in ctx.author.roles:
170             if role.id == constants.Roles.announcements:
171                 has_role = True
172                 break
173 
174         if not has_role:
175             await ctx.send(f"{ctx.author.mention} You're already unsubscribed!")
176             return
177 
178         log.debug(f"{ctx.author} called !unsubscribe. Removing the 'Announcements' role.")
179         await ctx.author.remove_roles(Object(constants.Roles.announcements), reason="Unsubscribed from announcements")
180 
181         log.trace(f"Deleting the message posted by {ctx.author}.")
182 
183         await ctx.send(
184             f"{ctx.author.mention} Unsubscribed from <#{constants.Channels.announcements}> notifications."
185         )
186 
187     # This cannot be static (must have a __func__ attribute).
188     async def cog_command_error(self, ctx: Context, error: Exception) -> None:
189         """Check for & ignore any InWhitelistCheckFailure."""
190         if isinstance(error, InWhitelistCheckFailure):
191             error.handled = True
192 
193     @staticmethod
194     def bot_check(ctx: Context) -> bool:
195         """Block any command within the verification channel that is not !accept."""
196         if ctx.channel.id == constants.Channels.verification and without_role_check(ctx, *constants.MODERATION_ROLES):
197             return ctx.command.name == "accept"
198         else:
199             return True
200 
201     @tasks.loop(hours=12)
202     async def periodic_ping(self) -> None:
203         """Every week, mention @everyone to remind them to verify."""
204         messages = self.bot.get_channel(constants.Channels.verification).history(limit=10)
205         need_to_post = True  # True if a new message needs to be sent.
206 
207         async for message in messages:
208             if message.author == self.bot.user and message.content == PERIODIC_PING:
209                 delta = datetime.utcnow() - message.created_at  # Time since last message.
210                 if delta.days >= 7:  # Message is older than a week.
211                     await message.delete()
212                 else:
213                     need_to_post = False
214 
215                 break
216 
217         if need_to_post:
218             await self.bot.get_channel(constants.Channels.verification).send(PERIODIC_PING)
219 
220     @periodic_ping.before_loop
221     async def before_ping(self) -> None:
222         """Only start the loop when the bot is ready."""
223         await self.bot.wait_until_guild_available()
224 
225     def cog_unload(self) -> None:
226         """Cancel the periodic ping task when the cog is unloaded."""
227         self.periodic_ping.cancel()
228 
229 
230 def setup(bot: Bot) -> None:
231     """Load the Verification cog."""
232     bot.add_cog(Verification(bot))
233
```
--- 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/verification.py b/bot/cogs/verification.py
--- a/bot/cogs/verification.py
+++ b/bot/cogs/verification.py
@@ -1,9 +1,7 @@
 import logging
 from contextlib import suppress
-from datetime import datetime
 
 from discord import Colour, Forbidden, Message, NotFound, Object
-from discord.ext import tasks
 from discord.ext.commands import Cog, Context, command
 
 from bot import constants
@@ -34,14 +32,6 @@
 <#{constants.Channels.bot_commands}>.
 """
 
-if constants.DEBUG_MODE:
-    PERIODIC_PING = "Periodic checkpoint message successfully sent."
-else:
-    PERIODIC_PING = (
-        f"@everyone To verify that you have read our rules, please type `{constants.Bot.prefix}accept`."
-        " If you encounter any problems during the verification process, "
-        f"send a direct message to a staff member."
-    )
 BOT_MESSAGE_DELETE_DELAY = 10
 
 
@@ -50,7 +40,6 @@
 
     def __init__(self, bot: Bot):
         self.bot = bot
-        self.periodic_ping.start()
 
     @property
     def mod_log(self) -> ModLog:
@@ -65,9 +54,7 @@
 
         if message.author.bot:
             # They're a bot, delete their message after the delay.
-            # But not the periodic ping; we like that one.
-            if message.content != PERIODIC_PING:
-                await message.delete(delay=BOT_MESSAGE_DELETE_DELAY)
+            await message.delete(delay=BOT_MESSAGE_DELETE_DELAY)
             return
 
         # if a user mentions a role or guild member
@@ -198,34 +185,6 @@
         else:
             return True
 
-    @tasks.loop(hours=12)
-    async def periodic_ping(self) -> None:
-        """Every week, mention @everyone to remind them to verify."""
-        messages = self.bot.get_channel(constants.Channels.verification).history(limit=10)
-        need_to_post = True  # True if a new message needs to be sent.
-
-        async for message in messages:
-            if message.author == self.bot.user and message.content == PERIODIC_PING:
-                delta = datetime.utcnow() - message.created_at  # Time since last message.
-                if delta.days >= 7:  # Message is older than a week.
-                    await message.delete()
-                else:
-                    need_to_post = False
-
-                break
-
-        if need_to_post:
-            await self.bot.get_channel(constants.Channels.verification).send(PERIODIC_PING)
-
-    @periodic_ping.before_loop
-    async def before_ping(self) -> None:
-        """Only start the loop when the bot is ready."""
-        await self.bot.wait_until_guild_available()
-
-    def cog_unload(self) -> None:
-        """Cancel the periodic ping task when the cog is unloaded."""
-        self.periodic_ping.cancel()
-
 
 def setup(bot: Bot) -> None:
     """Load the Verification cog."""

{"golden_diff": "diff --git a/bot/cogs/verification.py b/bot/cogs/verification.py\n--- a/bot/cogs/verification.py\n+++ b/bot/cogs/verification.py\n@@ -1,9 +1,7 @@\n import logging\n from contextlib import suppress\n-from datetime import datetime\n \n from discord import Colour, Forbidden, Message, NotFound, Object\n-from discord.ext import tasks\n from discord.ext.commands import Cog, Context, command\n \n from bot import constants\n@@ -34,14 +32,6 @@\n <#{constants.Channels.bot_commands}>.\n \"\"\"\n \n-if constants.DEBUG_MODE:\n-    PERIODIC_PING = \"Periodic checkpoint message successfully sent.\"\n-else:\n-    PERIODIC_PING = (\n-        f\"@everyone To verify that you have read our rules, please type `{constants.Bot.prefix}accept`.\"\n-        \" If you encounter any problems during the verification process, \"\n-        f\"send a direct message to a staff member.\"\n-    )\n BOT_MESSAGE_DELETE_DELAY = 10\n \n \n@@ -50,7 +40,6 @@\n \n     def __init__(self, bot: Bot):\n         self.bot = bot\n-        self.periodic_ping.start()\n \n     @property\n     def mod_log(self) -> ModLog:\n@@ -65,9 +54,7 @@\n \n         if message.author.bot:\n             # They're a bot, delete their message after the delay.\n-            # But not the periodic ping; we like that one.\n-            if message.content != PERIODIC_PING:\n-                await message.delete(delay=BOT_MESSAGE_DELETE_DELAY)\n+            await message.delete(delay=BOT_MESSAGE_DELETE_DELAY)\n             return\n \n         # if a user mentions a role or guild member\n@@ -198,34 +185,6 @@\n         else:\n             return True\n \n-    @tasks.loop(hours=12)\n-    async def periodic_ping(self) -> None:\n-        \"\"\"Every week, mention @everyone to remind them to verify.\"\"\"\n-        messages = self.bot.get_channel(constants.Channels.verification).history(limit=10)\n-        need_to_post = True  # True if a new message needs to be sent.\n-\n-        async for message in messages:\n-            if message.author == self.bot.user and message.content == PERIODIC_PING:\n-                delta = datetime.utcnow() - message.created_at  # Time since last message.\n-                if delta.days >= 7:  # Message is older than a week.\n-                    await message.delete()\n-                else:\n-                    need_to_post = False\n-\n-                break\n-\n-        if need_to_post:\n-            await self.bot.get_channel(constants.Channels.verification).send(PERIODIC_PING)\n-\n-    @periodic_ping.before_loop\n-    async def before_ping(self) -> None:\n-        \"\"\"Only start the loop when the bot is ready.\"\"\"\n-        await self.bot.wait_until_guild_available()\n-\n-    def cog_unload(self) -> None:\n-        \"\"\"Cancel the periodic ping task when the cog is unloaded.\"\"\"\n-        self.periodic_ping.cancel()\n-\n \n def setup(bot: Bot) -> None:\n     \"\"\"Load the Verification cog.\"\"\"\n", "issue": "Remove periodic ping in #verification\nThis creates \"accept bombs\" that may trigger our anti-raid and burst spam filters, and is not really necessary anymore. We have more than enough people joining without having to periodically nag at them.\n", "before_files": [{"content": "import logging\nfrom contextlib import suppress\nfrom datetime import datetime\n\nfrom discord import Colour, Forbidden, Message, NotFound, Object\nfrom discord.ext import tasks\nfrom discord.ext.commands import Cog, Context, command\n\nfrom bot import constants\nfrom bot.bot import Bot\nfrom bot.cogs.moderation import ModLog\nfrom bot.decorators import in_whitelist, without_role\nfrom bot.utils.checks import InWhitelistCheckFailure, without_role_check\n\nlog = logging.getLogger(__name__)\n\nWELCOME_MESSAGE = f\"\"\"\nHello! Welcome to the server, and thanks for verifying yourself!\n\nFor your records, these are the documents you accepted:\n\n`1)` Our rules, here: <https://pythondiscord.com/pages/rules>\n`2)` Our privacy policy, here: <https://pythondiscord.com/pages/privacy> - you can find information on how to have \\\nyour information removed here as well.\n\nFeel free to review them at any point!\n\nAdditionally, if you'd like to receive notifications for the announcements \\\nwe post in <#{constants.Channels.announcements}>\nfrom time to time, you can send `!subscribe` to <#{constants.Channels.bot_commands}> at any time \\\nto assign yourself the **Announcements** role. We'll mention this role every time we make an announcement.\n\nIf you'd like to unsubscribe from the announcement notifications, simply send `!unsubscribe` to \\\n<#{constants.Channels.bot_commands}>.\n\"\"\"\n\nif constants.DEBUG_MODE:\n    PERIODIC_PING = \"Periodic checkpoint message successfully sent.\"\nelse:\n    PERIODIC_PING = (\n        f\"@everyone To verify that you have read our rules, please type `{constants.Bot.prefix}accept`.\"\n        \" If you encounter any problems during the verification process, \"\n        f\"send a direct message to a staff member.\"\n    )\nBOT_MESSAGE_DELETE_DELAY = 10\n\n\nclass Verification(Cog):\n    \"\"\"User verification and role self-management.\"\"\"\n\n    def __init__(self, bot: Bot):\n        self.bot = bot\n        self.periodic_ping.start()\n\n    @property\n    def mod_log(self) -> ModLog:\n        \"\"\"Get currently loaded ModLog cog instance.\"\"\"\n        return self.bot.get_cog(\"ModLog\")\n\n    @Cog.listener()\n    async def on_message(self, message: Message) -> None:\n        \"\"\"Check new message event for messages to the checkpoint channel & process.\"\"\"\n        if message.channel.id != constants.Channels.verification:\n            return  # Only listen for #checkpoint messages\n\n        if message.author.bot:\n            # They're a bot, delete their message after the delay.\n            # But not the periodic ping; we like that one.\n            if message.content != PERIODIC_PING:\n                await message.delete(delay=BOT_MESSAGE_DELETE_DELAY)\n            return\n\n        # if a user mentions a role or guild member\n        # alert the mods in mod-alerts channel\n        if message.mentions or message.role_mentions:\n            log.debug(\n                f\"{message.author} mentioned one or more users \"\n                f\"and/or roles in {message.channel.name}\"\n            )\n\n            embed_text = (\n                f\"{message.author.mention} sent a message in \"\n                f\"{message.channel.mention} that contained user and/or role mentions.\"\n                f\"\\n\\n**Original message:**\\n>>> {message.content}\"\n            )\n\n            # Send pretty mod log embed to mod-alerts\n            await self.mod_log.send_log_message(\n                icon_url=constants.Icons.filtering,\n                colour=Colour(constants.Colours.soft_red),\n                title=f\"User/Role mentioned in {message.channel.name}\",\n                text=embed_text,\n                thumbnail=message.author.avatar_url_as(static_format=\"png\"),\n                channel_id=constants.Channels.mod_alerts,\n            )\n\n        ctx: Context = await self.bot.get_context(message)\n        if ctx.command is not None and ctx.command.name == \"accept\":\n            return\n\n        if any(r.id == constants.Roles.verified for r in ctx.author.roles):\n            log.info(\n                f\"{ctx.author} posted '{ctx.message.content}' \"\n                \"in the verification channel, but is already verified.\"\n            )\n            return\n\n        log.debug(\n            f\"{ctx.author} posted '{ctx.message.content}' in the verification \"\n            \"channel. We are providing instructions how to verify.\"\n        )\n        await ctx.send(\n            f\"{ctx.author.mention} Please type `!accept` to verify that you accept our rules, \"\n            f\"and gain access to the rest of the server.\",\n            delete_after=20\n        )\n\n        log.trace(f\"Deleting the message posted by {ctx.author}\")\n        with suppress(NotFound):\n            await ctx.message.delete()\n\n    @command(name='accept', aliases=('verify', 'verified', 'accepted'), hidden=True)\n    @without_role(constants.Roles.verified)\n    @in_whitelist(channels=(constants.Channels.verification,))\n    async def accept_command(self, ctx: Context, *_) -> None:  # We don't actually care about the args\n        \"\"\"Accept our rules and gain access to the rest of the server.\"\"\"\n        log.debug(f\"{ctx.author} called !accept. Assigning the 'Developer' role.\")\n        await ctx.author.add_roles(Object(constants.Roles.verified), reason=\"Accepted the rules\")\n        try:\n            await ctx.author.send(WELCOME_MESSAGE)\n        except Forbidden:\n            log.info(f\"Sending welcome message failed for {ctx.author}.\")\n        finally:\n            log.trace(f\"Deleting accept message by {ctx.author}.\")\n            with suppress(NotFound):\n                self.mod_log.ignore(constants.Event.message_delete, ctx.message.id)\n                await ctx.message.delete()\n\n    @command(name='subscribe')\n    @in_whitelist(channels=(constants.Channels.bot_commands,))\n    async def subscribe_command(self, ctx: Context, *_) -> None:  # We don't actually care about the args\n        \"\"\"Subscribe to announcement notifications by assigning yourself the role.\"\"\"\n        has_role = False\n\n        for role in ctx.author.roles:\n            if role.id == constants.Roles.announcements:\n                has_role = True\n                break\n\n        if has_role:\n            await ctx.send(f\"{ctx.author.mention} You're already subscribed!\")\n            return\n\n        log.debug(f\"{ctx.author} called !subscribe. Assigning the 'Announcements' role.\")\n        await ctx.author.add_roles(Object(constants.Roles.announcements), reason=\"Subscribed to announcements\")\n\n        log.trace(f\"Deleting the message posted by {ctx.author}.\")\n\n        await ctx.send(\n            f\"{ctx.author.mention} Subscribed to <#{constants.Channels.announcements}> notifications.\",\n        )\n\n    @command(name='unsubscribe')\n    @in_whitelist(channels=(constants.Channels.bot_commands,))\n    async def unsubscribe_command(self, ctx: Context, *_) -> None:  # We don't actually care about the args\n        \"\"\"Unsubscribe from announcement notifications by removing the role from yourself.\"\"\"\n        has_role = False\n\n        for role in ctx.author.roles:\n            if role.id == constants.Roles.announcements:\n                has_role = True\n                break\n\n        if not has_role:\n            await ctx.send(f\"{ctx.author.mention} You're already unsubscribed!\")\n            return\n\n        log.debug(f\"{ctx.author} called !unsubscribe. Removing the 'Announcements' role.\")\n        await ctx.author.remove_roles(Object(constants.Roles.announcements), reason=\"Unsubscribed from announcements\")\n\n        log.trace(f\"Deleting the message posted by {ctx.author}.\")\n\n        await ctx.send(\n            f\"{ctx.author.mention} Unsubscribed from <#{constants.Channels.announcements}> notifications.\"\n        )\n\n    # This cannot be static (must have a __func__ attribute).\n    async def cog_command_error(self, ctx: Context, error: Exception) -> None:\n        \"\"\"Check for & ignore any InWhitelistCheckFailure.\"\"\"\n        if isinstance(error, InWhitelistCheckFailure):\n            error.handled = True\n\n    @staticmethod\n    def bot_check(ctx: Context) -> bool:\n        \"\"\"Block any command within the verification channel that is not !accept.\"\"\"\n        if ctx.channel.id == constants.Channels.verification and without_role_check(ctx, *constants.MODERATION_ROLES):\n            return ctx.command.name == \"accept\"\n        else:\n            return True\n\n    @tasks.loop(hours=12)\n    async def periodic_ping(self) -> None:\n        \"\"\"Every week, mention @everyone to remind them to verify.\"\"\"\n        messages = self.bot.get_channel(constants.Channels.verification).history(limit=10)\n        need_to_post = True  # True if a new message needs to be sent.\n\n        async for message in messages:\n            if message.author == self.bot.user and message.content == PERIODIC_PING:\n                delta = datetime.utcnow() - message.created_at  # Time since last message.\n                if delta.days >= 7:  # Message is older than a week.\n                    await message.delete()\n                else:\n                    need_to_post = False\n\n                break\n\n        if need_to_post:\n            await self.bot.get_channel(constants.Channels.verification).send(PERIODIC_PING)\n\n    @periodic_ping.before_loop\n    async def before_ping(self) -> None:\n        \"\"\"Only start the loop when the bot is ready.\"\"\"\n        await self.bot.wait_until_guild_available()\n\n    def cog_unload(self) -> None:\n        \"\"\"Cancel the periodic ping task when the cog is unloaded.\"\"\"\n        self.periodic_ping.cancel()\n\n\ndef setup(bot: Bot) -> None:\n    \"\"\"Load the Verification cog.\"\"\"\n    bot.add_cog(Verification(bot))\n", "path": "bot/cogs/verification.py"}], "after_files": [{"content": "import logging\nfrom contextlib import suppress\n\nfrom discord import Colour, Forbidden, Message, NotFound, Object\nfrom discord.ext.commands import Cog, Context, command\n\nfrom bot import constants\nfrom bot.bot import Bot\nfrom bot.cogs.moderation import ModLog\nfrom bot.decorators import in_whitelist, without_role\nfrom bot.utils.checks import InWhitelistCheckFailure, without_role_check\n\nlog = logging.getLogger(__name__)\n\nWELCOME_MESSAGE = f\"\"\"\nHello! Welcome to the server, and thanks for verifying yourself!\n\nFor your records, these are the documents you accepted:\n\n`1)` Our rules, here: <https://pythondiscord.com/pages/rules>\n`2)` Our privacy policy, here: <https://pythondiscord.com/pages/privacy> - you can find information on how to have \\\nyour information removed here as well.\n\nFeel free to review them at any point!\n\nAdditionally, if you'd like to receive notifications for the announcements \\\nwe post in <#{constants.Channels.announcements}>\nfrom time to time, you can send `!subscribe` to <#{constants.Channels.bot_commands}> at any time \\\nto assign yourself the **Announcements** role. We'll mention this role every time we make an announcement.\n\nIf you'd like to unsubscribe from the announcement notifications, simply send `!unsubscribe` to \\\n<#{constants.Channels.bot_commands}>.\n\"\"\"\n\nBOT_MESSAGE_DELETE_DELAY = 10\n\n\nclass Verification(Cog):\n    \"\"\"User verification and role self-management.\"\"\"\n\n    def __init__(self, bot: Bot):\n        self.bot = bot\n\n    @property\n    def mod_log(self) -> ModLog:\n        \"\"\"Get currently loaded ModLog cog instance.\"\"\"\n        return self.bot.get_cog(\"ModLog\")\n\n    @Cog.listener()\n    async def on_message(self, message: Message) -> None:\n        \"\"\"Check new message event for messages to the checkpoint channel & process.\"\"\"\n        if message.channel.id != constants.Channels.verification:\n            return  # Only listen for #checkpoint messages\n\n        if message.author.bot:\n            # They're a bot, delete their message after the delay.\n            await message.delete(delay=BOT_MESSAGE_DELETE_DELAY)\n            return\n\n        # if a user mentions a role or guild member\n        # alert the mods in mod-alerts channel\n        if message.mentions or message.role_mentions:\n            log.debug(\n                f\"{message.author} mentioned one or more users \"\n                f\"and/or roles in {message.channel.name}\"\n            )\n\n            embed_text = (\n                f\"{message.author.mention} sent a message in \"\n                f\"{message.channel.mention} that contained user and/or role mentions.\"\n                f\"\\n\\n**Original message:**\\n>>> {message.content}\"\n            )\n\n            # Send pretty mod log embed to mod-alerts\n            await self.mod_log.send_log_message(\n                icon_url=constants.Icons.filtering,\n                colour=Colour(constants.Colours.soft_red),\n                title=f\"User/Role mentioned in {message.channel.name}\",\n                text=embed_text,\n                thumbnail=message.author.avatar_url_as(static_format=\"png\"),\n                channel_id=constants.Channels.mod_alerts,\n            )\n\n        ctx: Context = await self.bot.get_context(message)\n        if ctx.command is not None and ctx.command.name == \"accept\":\n            return\n\n        if any(r.id == constants.Roles.verified for r in ctx.author.roles):\n            log.info(\n                f\"{ctx.author} posted '{ctx.message.content}' \"\n                \"in the verification channel, but is already verified.\"\n            )\n            return\n\n        log.debug(\n            f\"{ctx.author} posted '{ctx.message.content}' in the verification \"\n            \"channel. We are providing instructions how to verify.\"\n        )\n        await ctx.send(\n            f\"{ctx.author.mention} Please type `!accept` to verify that you accept our rules, \"\n            f\"and gain access to the rest of the server.\",\n            delete_after=20\n        )\n\n        log.trace(f\"Deleting the message posted by {ctx.author}\")\n        with suppress(NotFound):\n            await ctx.message.delete()\n\n    @command(name='accept', aliases=('verify', 'verified', 'accepted'), hidden=True)\n    @without_role(constants.Roles.verified)\n    @in_whitelist(channels=(constants.Channels.verification,))\n    async def accept_command(self, ctx: Context, *_) -> None:  # We don't actually care about the args\n        \"\"\"Accept our rules and gain access to the rest of the server.\"\"\"\n        log.debug(f\"{ctx.author} called !accept. Assigning the 'Developer' role.\")\n        await ctx.author.add_roles(Object(constants.Roles.verified), reason=\"Accepted the rules\")\n        try:\n            await ctx.author.send(WELCOME_MESSAGE)\n        except Forbidden:\n            log.info(f\"Sending welcome message failed for {ctx.author}.\")\n        finally:\n            log.trace(f\"Deleting accept message by {ctx.author}.\")\n            with suppress(NotFound):\n                self.mod_log.ignore(constants.Event.message_delete, ctx.message.id)\n                await ctx.message.delete()\n\n    @command(name='subscribe')\n    @in_whitelist(channels=(constants.Channels.bot_commands,))\n    async def subscribe_command(self, ctx: Context, *_) -> None:  # We don't actually care about the args\n        \"\"\"Subscribe to announcement notifications by assigning yourself the role.\"\"\"\n        has_role = False\n\n        for role in ctx.author.roles:\n            if role.id == constants.Roles.announcements:\n                has_role = True\n                break\n\n        if has_role:\n            await ctx.send(f\"{ctx.author.mention} You're already subscribed!\")\n            return\n\n        log.debug(f\"{ctx.author} called !subscribe. Assigning the 'Announcements' role.\")\n        await ctx.author.add_roles(Object(constants.Roles.announcements), reason=\"Subscribed to announcements\")\n\n        log.trace(f\"Deleting the message posted by {ctx.author}.\")\n\n        await ctx.send(\n            f\"{ctx.author.mention} Subscribed to <#{constants.Channels.announcements}> notifications.\",\n        )\n\n    @command(name='unsubscribe')\n    @in_whitelist(channels=(constants.Channels.bot_commands,))\n    async def unsubscribe_command(self, ctx: Context, *_) -> None:  # We don't actually care about the args\n        \"\"\"Unsubscribe from announcement notifications by removing the role from yourself.\"\"\"\n        has_role = False\n\n        for role in ctx.author.roles:\n            if role.id == constants.Roles.announcements:\n                has_role = True\n                break\n\n        if not has_role:\n            await ctx.send(f\"{ctx.author.mention} You're already unsubscribed!\")\n            return\n\n        log.debug(f\"{ctx.author} called !unsubscribe. Removing the 'Announcements' role.\")\n        await ctx.author.remove_roles(Object(constants.Roles.announcements), reason=\"Unsubscribed from announcements\")\n\n        log.trace(f\"Deleting the message posted by {ctx.author}.\")\n\n        await ctx.send(\n            f\"{ctx.author.mention} Unsubscribed from <#{constants.Channels.announcements}> notifications.\"\n        )\n\n    # This cannot be static (must have a __func__ attribute).\n    async def cog_command_error(self, ctx: Context, error: Exception) -> None:\n        \"\"\"Check for & ignore any InWhitelistCheckFailure.\"\"\"\n        if isinstance(error, InWhitelistCheckFailure):\n            error.handled = True\n\n    @staticmethod\n    def bot_check(ctx: Context) -> bool:\n        \"\"\"Block any command within the verification channel that is not !accept.\"\"\"\n        if ctx.channel.id == constants.Channels.verification and without_role_check(ctx, *constants.MODERATION_ROLES):\n            return ctx.command.name == \"accept\"\n        else:\n            return True\n\n\ndef setup(bot: Bot) -> None:\n    \"\"\"Load the Verification cog.\"\"\"\n    bot.add_cog(Verification(bot))\n", "path": "bot/cogs/verification.py"}]}