Repository: python-discord/bot

Issue:
Now that the !user command supports not-in-server members, we might want to add an is-bot field
Something like https://cdn.discordapp.com/emojis/230105988211015680.png?v=1, perhaps prepended to the username in the results? Or another line in the `Member Information` field: `This user is a Bot.`/ `This user is a Verified Bot.`.


Discussion:
I wonder if another field is a good idea, the embed is already quite long. I think adding the [bot] emoji at the end of the username to make it look like it does in a bot message would be the most intuitive

![image](https://user-images.githubusercontent.com/18114431/105017294-46fe0900-5a4c-11eb-8c5c-9b9f1e2ca3a2.png)
![image](https://user-images.githubusercontent.com/18114431/105017327-4feeda80-5a4c-11eb-92fe-8b64a2d98d56.png)

My idea was to add it as a badge, since verified bots will also have a badge provided by discord. 
What if it's not verified?
Another flag will be set, but it isn't a badge. I think we can just append a bot badge at the beginning of the badge list. 
Hmmm I sill think that just literally saying "bot" after the username is the clearest way to do it, assuming it's possible using an emoji
Can we even set custom emojis in embed titles? I'm not sure if that's even possible. 
> Can we even set custom emojis in embed titles? I'm not sure if that's even possible. 

We'd have to add it to the badges display below, which is probably fine because a bot shouldn't have any other badges (save for verified bot, perhaps).
it also looks like if you try to get the info of a verified bot, it will cause an error. This is because we don't have the `badge_verified_bot` emoji. Here's an image I pulled off discord for it.
![image](https://user-images.githubusercontent.com/9753350/106337243-992efd80-6288-11eb-9b5f-344e212a58bf.png)

575252669443211264 is a userID of a verified bot, which might be useful during testing :D


Resolving patch:
diff --git a/bot/constants.py b/bot/constants.py
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -175,13 +175,14 @@ def __getattr__(cls, name):
             if cls.subsection is not None:
                 return _CONFIG_YAML[cls.section][cls.subsection][name]
             return _CONFIG_YAML[cls.section][name]
-        except KeyError:
+        except KeyError as e:
             dotted_path = '.'.join(
                 (cls.section, cls.subsection, name)
                 if cls.subsection is not None else (cls.section, name)
             )
-            log.critical(f"Tried accessing configuration variable at `{dotted_path}`, but it could not be found.")
-            raise
+            # Only an INFO log since this can be caught through `hasattr` or `getattr`.
+            log.info(f"Tried accessing configuration variable at `{dotted_path}`, but it could not be found.")
+            raise AttributeError(repr(name)) from e
 
     def __getitem__(cls, name):
         return cls.__getattr__(name)
@@ -280,6 +281,8 @@ class Emojis(metaclass=YAMLGetter):
     badge_partner: str
     badge_staff: str
     badge_verified_bot_developer: str
+    verified_bot: str
+    bot: str
 
     defcon_shutdown: str  # noqa: E704
     defcon_unshutdown: str  # noqa: E704
diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py
--- a/bot/exts/info/information.py
+++ b/bot/exts/info/information.py
@@ -230,6 +230,11 @@ async def create_user_embed(self, ctx: Context, user: FetchedMember) -> Embed:
         if on_server and user.nick:
             name = f"{user.nick} ({name})"
 
+        if user.public_flags.verified_bot:
+            name += f" {constants.Emojis.verified_bot}"
+        elif user.bot:
+            name += f" {constants.Emojis.bot}"
+
         badges = []
 
         for badge, is_set in user.public_flags:


Test patch:
diff --git a/tests/bot/exts/info/test_information.py b/tests/bot/exts/info/test_information.py
--- a/tests/bot/exts/info/test_information.py
+++ b/tests/bot/exts/info/test_information.py
@@ -281,6 +281,7 @@ async def test_create_user_embed_uses_string_representation_of_user_in_title_if_
         """The embed should use the string representation of the user if they don't have a nick."""
         ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=1))
         user = helpers.MockMember()
+        user.public_flags = unittest.mock.MagicMock(verified_bot=False)
         user.nick = None
         user.__str__ = unittest.mock.Mock(return_value="Mr. Hemlock")
         user.colour = 0
@@ -297,6 +298,7 @@ async def test_create_user_embed_uses_nick_in_title_if_available(self):
         """The embed should use the nick if it's available."""
         ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=1))
         user = helpers.MockMember()
+        user.public_flags = unittest.mock.MagicMock(verified_bot=False)
         user.nick = "Cat lover"
         user.__str__ = unittest.mock.Mock(return_value="Mr. Hemlock")
         user.colour = 0