Repository: Cog-Creators/Red-DiscordBot

Issue:
Tempban failing to unban
# Command bugs

<!-- 
Did you find a bug with a command? Fill out the following:
-->

#### Command name

tempban

#### What cog is this command from?

mod

#### What were you expecting to happen?

after tempban ends user to be unbanned

#### What actually happened?

instead log is spammed with 

```
Jul 31 23:58:02 bb-8 redbot[26623]: [2019-07-31 23:58:02] [INFO] red.mod: Failed to unban member due to permissions
Jul 31 23:59:03 bb-8 redbot[26623]: [2019-07-31 23:59:03] [INFO] red.mod: Failed to unban member due to permissions
Aug 01 00:00:03 bb-8 redbot[26623]: [2019-08-01 00:00:03] [INFO] red.mod: Failed to unban member due to permissions
Aug 01 00:01:03 bb-8 redbot[26623]: [2019-08-01 00:01:03] [INFO] red.mod: Failed to unban member due to permissions
Aug 01 00:02:03 bb-8 redbot[26623]: [2019-08-01 00:02:03] [INFO] red.mod: Failed to unban member due to permissions
```
#### How can we reproduce this issue?

tempban someone and then wait for ban to be over and for the bot to attempt to unban



Discussion:
For information, I am also getting the same thing on an old version of Red (3.0.2).
```
[01/08/2019 00:22] INFO mod check_tempban_expirations 1504: Failed to unban member due to permissions
[01/08/2019 00:22] INFO mod check_tempban_expirations 1504: Failed to unban member due to permissions
```
Is the user actually banned? Can you still see them in the bans list for the server? And you're absolutely positive that the bot has unban permissions?

This message is literally only ever logged if `guild.unban()` raises a `discord.Forbidden` exception.

That means the bot is literally sending the ban request to Discord and it's responding with a 403.
I've tried unbanning by directly using `guild.unban()` on my own bot and the only time it ever responds with 403 is when the bot is missing the `BAN_MEMBERS` permission. If the user isn't banned, it responds with a 404 and would say as such in the logged message.
Hm yeah, sounds like since preda and I both run public red instances that both our bots lost the ban member perms in some server that we don't control. Which resulted in it spamming our logs with that 

Should probably be changed to skip even trying without ban perms and log the lack of perms (still needs to catch the forbidden due to 2FA related forbiddens) Upon a 2FA fail, skip the remaining unbans for that guild.
extra info should be in the log message as well (guild id at minimum, member id likely)

Resolving patch:
diff --git a/redbot/cogs/mod/kickban.py b/redbot/cogs/mod/kickban.py
--- a/redbot/cogs/mod/kickban.py
+++ b/redbot/cogs/mod/kickban.py
@@ -127,16 +127,20 @@ async def check_tempban_expirations(self):
                         unban_time = datetime.utcfromtimestamp(
                             await self.settings.member(member(uid, guild)).banned_until()
                         )
-                        now = datetime.utcnow()
-                        if now > unban_time:  # Time to unban the user
+                        if datetime.utcnow() > unban_time:  # Time to unban the user
                             user = await self.bot.fetch_user(uid)
                             queue_entry = (guild.id, user.id)
                             try:
                                 await guild.unban(user, reason=_("Tempban finished"))
                                 guild_tempbans.remove(uid)
-                            except discord.Forbidden:
-                                log.info("Failed to unban member due to permissions")
                             except discord.HTTPException as e:
+                                # 50013: Missing permissions error code or 403: Forbidden status
+                                if e.code == 50013 or e.status == 403:
+                                    log.info(
+                                        f"Failed to unban {user}({user.id}) user from "
+                                        f"{guild.name}({guild.id}) guild due to permissions"
+                                    )
+                                    break  # skip the rest of this guild
                                 log.info(f"Failed to unban member: error code: {e.code}")
             await asyncio.sleep(60)
 


Test patch: