Repository: python-discord/bot

Issue:
!ping command
## Abstract
For now, we don't have any way to know when the bot is laggy if it is the bot, the site or discord API that is laggy. This command can be used to report the latency of all of them. 

## Specification
When the command `!ping` is entered, the bot should respond with an embed containing the following information : 
* Bot latency : delta between the message `!ping` creation time and the moment the bot start processing the command. 
* Site latency : time taken by the bot to reach the site API. The implementation details needs to be determined : do we just run a ping to the site, or we use a special route?
* Discord latency : API latency [reported by discord](https://status.discordapp.com/)
In case the bot fail to gather any information, the command should gracefully fall back and display a red cross instead of the missing data, and still display the other data.



Discussion:
Forgot to mention @biskette's note : the embed should be named `Pong! `
I'm fine with everything here, but just one comment:

>  do we just run a ping to the site, or we use a special route?

I wonder, are the site and bot on hosted the same machine? In that case, I'd imagine there really wouldn't be any significant network latency between them.
The website and bot are on the same machine. It is probably still worthwhile to ping the website, as it does goes through CloudFlare. I'll be taking this issue if yall don't mind.

Resolving patch:
diff --git a/bot/exts/utils/ping.py b/bot/exts/utils/ping.py
new file mode 100644
--- /dev/null
+++ b/bot/exts/utils/ping.py
@@ -0,0 +1,59 @@
+import socket
+from datetime import datetime
+
+import aioping
+from discord import Embed
+from discord.ext import commands
+
+from bot.bot import Bot
+from bot.constants import Channels, Emojis, STAFF_ROLES, URLs
+from bot.decorators import in_whitelist
+
+DESCRIPTIONS = (
+    "Command processing time",
+    "Python Discord website latency",
+    "Discord API latency"
+)
+ROUND_LATENCY = 3
+
+
+class Latency(commands.Cog):
+    """Getting the latency between the bot and websites."""
+
+    def __init__(self, bot: Bot) -> None:
+        self.bot = bot
+
+    @commands.command()
+    @in_whitelist(channels=(Channels.bot_commands,), roles=STAFF_ROLES)
+    async def ping(self, ctx: commands.Context) -> None:
+        """
+        Gets different measures of latency within the bot.
+
+        Returns bot, Python Discord Site, Discord Protocol latency.
+        """
+        # datetime.datetime objects do not have the "milliseconds" attribute.
+        # It must be converted to seconds before converting to milliseconds.
+        bot_ping = (datetime.utcnow() - ctx.message.created_at).total_seconds() / 1000
+        bot_ping = f"{bot_ping:.{ROUND_LATENCY}f} ms"
+
+        try:
+            delay = await aioping.ping(URLs.site, family=socket.AddressFamily.AF_INET) * 1000
+            site_ping = f"{delay:.{ROUND_LATENCY}f} ms"
+
+        except TimeoutError:
+            site_ping = f"{Emojis.cross_mark} Connection timed out."
+
+        # Discord Protocol latency return value is in seconds, must be multiplied by 1000 to get milliseconds.
+        discord_ping = f"{self.bot.latency * 1000:.{ROUND_LATENCY}f} ms"
+
+        embed = Embed(title="Pong!")
+
+        for desc, latency in zip(DESCRIPTIONS, [bot_ping, site_ping, discord_ping]):
+            embed.add_field(name=desc, value=latency, inline=False)
+
+        await ctx.send(embed=embed)
+
+
+def setup(bot: Bot) -> None:
+    """Load the Latency cog."""
+    bot.add_cog(Latency(bot))


Test patch: