Repository: Cog-Creators/Red-DiscordBot

Issue:
[Core] Bug in blacklist add
# Command bugs

<!-- 
Did you find a bug with a command? Fill out the following:
-->

#### Command name

<!-- Replace this line with the name of the command --> ``[p]blacklist add``

#### What cog is this command from?

<!-- Replace this line with the name of the cog -->
Core I think.
#### What were you expecting to happen?

<!-- Replace this line with a description of what you were expecting to happen --> the command to work

#### What actually happened?

<!-- Replace this line with a description of what actually happened. Include any error messages -->
It didn't work.

This was brought up by another member in the support discord.(GraveyardEnthusiast#7958) After a bot restart the command worked again. However, this error makes no sense to me. https://pastebin.com/fbgYHHdu

In the code, a dict is accessed with the key "gid" if gid=None. Isn't this guaranteed to cause a KeyError? Maybe i'm overlooking something but this doesn't really make sense to me.
#### How can we reproduce this issue?

<!-- Replace with numbered steps to reproduce the issue --> I don't know.

#### Discord conversation:
Start: https://discordapp.com/channels/133049272517001216/387398816317440000/686123128656625711
End: https://discordapp.com/channels/133049272517001216/387398816317440000/686143352571297808



Discussion:

Resolving patch:
diff --git a/redbot/core/settings_caches.py b/redbot/core/settings_caches.py
--- a/redbot/core/settings_caches.py
+++ b/redbot/core/settings_caches.py
@@ -130,7 +130,7 @@ async def get_whitelist(self, guild: Optional[discord.Guild] = None) -> List[int
             ret = self._cached_whitelist[gid].copy()
         else:
             if gid is not None:
-                ret = await self._config.guild_from_id(gid).whitelsit()
+                ret = await self._config.guild_from_id(gid).whitelist()
                 if not ret:
                     ret = []
             else:
@@ -143,26 +143,31 @@ async def get_whitelist(self, guild: Optional[discord.Guild] = None) -> List[int
     async def add_to_whitelist(self, guild: Optional[discord.Guild], role_or_user: List[int]):
         gid: Optional[int] = guild.id if guild else None
         role_or_user = role_or_user or []
-        if not isinstance(role_or_user, list) and not all(
-            isinstance(r_or_u, str) for r_or_u in role_or_user
+        if not isinstance(role_or_user, list) or not all(
+            isinstance(r_or_u, int) for r_or_u in role_or_user
         ):
             raise TypeError("Whitelisted objects must be a list of ints")
+
         if gid is None:
+            if gid not in self._cached_whitelist:
+                self._cached_whitelist[gid] = await self._config.whitelist()
             for obj_id in role_or_user:
-                if obj_id not in self._cached_whitelist:
+                if obj_id not in self._cached_whitelist[gid]:
                     self._cached_whitelist[gid].append(obj_id)
                     async with self._config.whitelist() as curr_list:
                         curr_list.append(obj_id)
         else:
+            if gid not in self._cached_whitelist:
+                self._cached_whitelist[gid] = await self._config.guild_from_id(gid).whitelist()
             for obj_id in role_or_user:
-                if obj_id not in self._cached_whitelist:
+                if obj_id not in self._cached_whitelist[gid]:
                     self._cached_whitelist[gid].append(obj_id)
                     async with self._config.guild_from_id(gid).whitelist() as curr_list:
                         curr_list.append(obj_id)
 
     async def clear_whitelist(self, guild: Optional[discord.Guild] = None):
         gid: Optional[int] = guild.id if guild else None
-        self._cached_whitelist[gid]
+        self._cached_whitelist[gid] = []
         if gid is None:
             await self._config.whitelist.clear()
         else:
@@ -171,19 +176,24 @@ async def clear_whitelist(self, guild: Optional[discord.Guild] = None):
     async def remove_from_whitelist(self, guild: Optional[discord.Guild], role_or_user: List[int]):
         gid: Optional[int] = guild.id if guild else None
         role_or_user = role_or_user or []
-        if not isinstance(role_or_user, list) and not all(
-            isinstance(r_or_u, str) for r_or_u in role_or_user
+        if not isinstance(role_or_user, list) or not all(
+            isinstance(r_or_u, int) for r_or_u in role_or_user
         ):
             raise TypeError("Whitelisted objects must be a list of ints")
+
         if gid is None:
+            if gid not in self._cached_whitelist:
+                self._cached_whitelist[gid] = await self._config.whitelist()
             for obj_id in role_or_user:
-                if obj_id in self._cached_whitelist:
+                if obj_id in self._cached_whitelist[gid]:
                     self._cached_whitelist[gid].remove(obj_id)
                     async with self._config.whitelist() as curr_list:
                         curr_list.remove(obj_id)
         else:
+            if gid not in self._cached_whitelist:
+                self._cached_whitelist[gid] = await self._config.guild_from_id(gid).whitelist()
             for obj_id in role_or_user:
-                if obj_id not in self._cached_whitelist:
+                if obj_id in self._cached_whitelist[gid]:
                     self._cached_whitelist[gid].remove(obj_id)
                     async with self._config.guild_from_id(gid).whitelist() as curr_list:
                         curr_list.remove(obj_id)
@@ -197,7 +207,7 @@ async def get_blacklist(self, guild: Optional[discord.Guild] = None) -> List[int
             ret = self._cached_blacklist[gid].copy()
         else:
             if gid is not None:
-                ret = await self._config.guild_from_id(gid).whitelsit()
+                ret = await self._config.guild_from_id(gid).blacklist()
                 if not ret:
                     ret = []
             else:
@@ -210,26 +220,30 @@ async def get_blacklist(self, guild: Optional[discord.Guild] = None) -> List[int
     async def add_to_blacklist(self, guild: Optional[discord.Guild], role_or_user: List[int]):
         gid: Optional[int] = guild.id if guild else None
         role_or_user = role_or_user or []
-        if not isinstance(role_or_user, list) and not all(
-            isinstance(r_or_u, str) for r_or_u in role_or_user
+        if not isinstance(role_or_user, list) or not all(
+            isinstance(r_or_u, int) for r_or_u in role_or_user
         ):
             raise TypeError("Blacklisted objects must be a list of ints")
         if gid is None:
+            if gid not in self._cached_blacklist:
+                self._cached_blacklist[gid] = await self._config.blacklist()
             for obj_id in role_or_user:
-                if obj_id not in self._cached_blacklist:
+                if obj_id not in self._cached_blacklist[gid]:
                     self._cached_blacklist[gid].append(obj_id)
                     async with self._config.blacklist() as curr_list:
                         curr_list.append(obj_id)
         else:
+            if gid not in self._cached_blacklist:
+                self._cached_blacklist[gid] = self._config.guild_from_id(gid).blacklist()
             for obj_id in role_or_user:
-                if obj_id not in self._cached_blacklist:
+                if obj_id not in self._cached_blacklist[gid]:
                     self._cached_blacklist[gid].append(obj_id)
                     async with self._config.guild_from_id(gid).blacklist() as curr_list:
                         curr_list.append(obj_id)
 
     async def clear_blacklist(self, guild: Optional[discord.Guild] = None):
         gid: Optional[int] = guild.id if guild else None
-        self._cached_whitelist[gid]
+        self._cached_blacklist[gid] = []
         if gid is None:
             await self._config.blacklist.clear()
         else:
@@ -238,19 +252,23 @@ async def clear_blacklist(self, guild: Optional[discord.Guild] = None):
     async def remove_from_blacklist(self, guild: Optional[discord.Guild], role_or_user: List[int]):
         gid: Optional[int] = guild.id if guild else None
         role_or_user = role_or_user or []
-        if not isinstance(role_or_user, list) and not all(
-            isinstance(r_or_u, str) for r_or_u in role_or_user
+        if not isinstance(role_or_user, list) or not all(
+            isinstance(r_or_u, int) for r_or_u in role_or_user
         ):
             raise TypeError("Blacklisted objects must be a list of ints")
         if gid is None:
+            if gid not in self._cached_blacklist:
+                self._cached_blacklist[gid] = await self._config.blacklist()
             for obj_id in role_or_user:
-                if obj_id in self._cached_blacklist:
+                if obj_id in self._cached_blacklist[gid]:
                     self._cached_blacklist[gid].remove(obj_id)
                     async with self._config.blacklist() as curr_list:
                         curr_list.remove(obj_id)
         else:
+            if gid not in self._cached_blacklist:
+                self._cached_blacklist[gid] = self._config.guild_from_id(gid).blacklist()
             for obj_id in role_or_user:
-                if obj_id not in self._cached_blacklist:
+                if obj_id in self._cached_blacklist[gid]:
                     self._cached_blacklist[gid].remove(obj_id)
                     async with self._config.guild_from_id(gid).blacklist() as curr_list:
                         curr_list.remove(obj_id)


Test patch: