Repository: python-discord/bot

Issue:
Bot changing off-topic channel names more than once per daily cycle
The bot should change the channel names of the three off-topic channels only once after hitting UTC midnight. However, we've noticed that it may attempt to set new channel names far more often than that. The root of the cause is still unknown, but after looking at the recent audit log screenshotted by Scragly, I've come up with a conjecture to what's happening.

If you take a look at the logs below, then you'll notice that most of the channel name changes actually happen just before the whole hour (9:59 in Scragly's local time). My guess is that the sleep duration, which is set based on "the start of the current day" + "1 day time delta", is off by one second. The odd thing is that it's not obvious to me from the code why this happens.

However, if this is true, then it would explain the current behavior: The background task is triggered at 23:59:59 (UTC), it will cycle the channel names, and, **as we're still on the same day**, calculate a sleep second delta based on the previous midnight (which will be 0, since it's trying to find the seconds to 23:59:59, which it already is), so it will async.sleep for 0 seconds and run itself again.

The fact that it doesn't trigger more often is then caused because it needs to make API calls and has other `await` points in the execution. 

Since this behavior very much looks like what Discord would call "API Abuse", I think it's important to put in a bug fix as quickly as possible. Since the only thing I can think of is the off-by-one error described above, my proposal is aim for 1 minute past midnight, so we never run into "we're still on the same day" issues again:

```py
        today_at_midnight = datetime.utcnow().replace(microsecond=0, second=0, minute=0, hour=0)
        next_midnight = today_at_midnight + timedelta(days=1, minutes=1)
        seconds_to_sleep = (next_midnight - datetime.utcnow()).seconds
        await asyncio.sleep(seconds_to_sleep)
```

If that doesn't fix it, we need to investigate further, but I think this will work.

---

**Edit: some additional confirmation of the off-by-one-second error:**
```
Apr 15 08:08:35 pd.beardfist.com Bot: |       bot.cogs.off_topic_names |    DEBUG | update_names: seconds to sleep 24
```

I'd set the name change for `08:09:00`, but sleeping for 24 seconds at `08:08:35` will cause it to "wake up" at `08:08:59`.

---

![Audit Log Screenshot showing channel name changes](https://cdn.discordapp.com/attachments/365960823622991872/567137248630407194/unknown.png)






Discussion:

Resolving patch:
diff --git a/bot/cogs/off_topic_names.py b/bot/cogs/off_topic_names.py
--- a/bot/cogs/off_topic_names.py
+++ b/bot/cogs/off_topic_names.py
@@ -48,9 +48,11 @@ async def update_names(bot: Bot, headers: dict):
     """
 
     while True:
+        # Since we truncate the compute timedelta to seconds, we add one second to ensure
+        # we go past midnight in the `seconds_to_sleep` set below.
         today_at_midnight = datetime.utcnow().replace(microsecond=0, second=0, minute=0, hour=0)
         next_midnight = today_at_midnight + timedelta(days=1)
-        seconds_to_sleep = (next_midnight - datetime.utcnow()).seconds
+        seconds_to_sleep = (next_midnight - datetime.utcnow()).seconds + 1
         await asyncio.sleep(seconds_to_sleep)
 
         response = await bot.http_session.get(


Test patch: