aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar kwzrd <[email protected]>2020-08-04 22:12:12 +0200
committerGravatar kwzrd <[email protected]>2020-08-05 14:30:25 +0200
commit8f548f158e17481245809801b1285b17af279fb4 (patch)
tree6793e2bafdeb7e3c6c2eb0f1236c96e68e1e5d1a
parentVerification: ignore verification reminder message event (diff)
Verification: implement unverified role ping task
We're making good use of d.py's tasks framework. RedisCache is used to persist the reminder message ids, which can conveniently be converted into timestamps. It is therefore trivial to determine the time to sleep before the first ping. After that, the bot simply pings every n hours.
-rw-r--r--bot/cogs/verification.py52
1 files changed, 52 insertions, 0 deletions
diff --git a/bot/cogs/verification.py b/bot/cogs/verification.py
index ca7631db2..42088896d 100644
--- a/bot/cogs/verification.py
+++ b/bot/cogs/verification.py
@@ -7,6 +7,7 @@ from datetime import datetime, timedelta
import discord
from discord.ext import tasks
from discord.ext.commands import Cog, Context, command
+from discord.utils import snowflake_time
from bot import constants
from bot.bot import Bot
@@ -283,6 +284,57 @@ class Verification(Cog):
)
# endregion
+ # region: periodically ping @Unverified
+
+ @tasks.loop(hours=REMINDER_FREQUENCY)
+ async def ping_unverified(self) -> None:
+ """
+ Delete latest `REMINDER_MESSAGE` and send it again.
+
+ This utilizes RedisCache to persist the latest reminder message id.
+ """
+ await self.bot.wait_until_guild_available()
+ verification = self.bot.get_guild(constants.Guild.id).get_channel(constants.Channels.verification)
+
+ last_reminder: t.Optional[int] = await self.reminder_cache.get("last_reminder")
+
+ if last_reminder is not None:
+ log.trace(f"Found verification reminder message in cache, deleting: {last_reminder}")
+
+ with suppress(discord.HTTPException): # If something goes wrong, just ignore it
+ await self.bot.http.delete_message(verification.id, last_reminder)
+
+ log.trace("Sending verification reminder")
+ new_reminder = await verification.send(REMINDER_MESSAGE)
+
+ await self.reminder_cache.set("last_reminder", new_reminder.id)
+
+ @ping_unverified.before_loop
+ async def _before_first_ping(self) -> None:
+ """
+ Sleep until `REMINDER_MESSAGE` should be sent again.
+
+ If latest reminder is not cached, exit instantly. Otherwise, wait wait until the
+ configured `REMINDER_FREQUENCY` has passed.
+ """
+ last_reminder: t.Optional[int] = await self.reminder_cache.get("last_reminder")
+
+ if last_reminder is None:
+ log.trace("Latest verification reminder message not cached, task will not wait")
+ return
+
+ # Convert cached message id into a timestamp
+ time_since = datetime.utcnow() - snowflake_time(last_reminder)
+ log.trace(f"Time since latest verification reminder: {time_since}")
+
+ to_sleep = timedelta(hours=REMINDER_FREQUENCY) - time_since
+ log.trace(f"Time to sleep until next ping: {to_sleep}")
+
+ # Delta can be negative if `REMINDER_FREQUENCY` has already passed
+ secs = max(to_sleep.total_seconds(), 0)
+ await asyncio.sleep(secs)
+
+ # endregion
# region: listeners
@Cog.listener()