Files
mustafa/src/cogs/botinfo.py
T

207 lines
7.6 KiB
Python

import platform
from collections import Counter
from os import getpid
from os.path import exists
from time import time
import discord
from discord import app_commands
from discord.ext import commands
from psutil import Process
from cogs.utils import discord_utils
from cogs.utils import embed_templates
from cogs.utils import misc_utils
# Shown as the dev when neither a dev is set in the config nor the application belongs to a team
FALLBACK_DEV_ID = 170506717140877312
class BotInfo(commands.Cog):
"""View information about the bot"""
def __init__(self, bot: commands.Bot):
"""
Parameters
----------
bot (commands.Bot): The bot instance
"""
self.bot = bot
@app_commands.checks.bot_has_permissions(embed_links=True, external_emojis=True)
@app_commands.checks.cooldown(1, 2)
@app_commands.command(name="botinfo", description="Se informasjon om botten")
async def botinfo(self, interaction: discord.Interaction):
"""
View information about the bot
Parameters
----------
interaction (discord.Interaction): The slash command interaction
"""
# Dev user info
team = None
if dev_id := self.bot.user_ids.get("dev"):
dev = await self.bot.fetch_user(dev_id)
else:
app_info = self.bot.application or await self.bot.application_info()
team = app_info.team
if not team:
dev = self.bot.get_user(FALLBACK_DEV_ID) or await self.bot.fetch_user(FALLBACK_DEV_ID)
# Memory usage
process = Process(getpid())
memory_usage = round(process.memory_info().rss / 1000000, 1)
# Member stats
# Presences are only available on members, and a user in several servers shows up once per server,
# so key by id to count every user once
statuses = {member.id: member.status for member in self.bot.get_all_members()}
status_counts = Counter(statuses.values())
# Build embed
embed = discord.Embed(color=interaction.client.user.color, url=self.bot.misc["website"])
if team:
embed.set_author(name=team.name, icon_url=team.icon)
else:
embed.set_author(name=dev.name, icon_url=dev.display_avatar)
embed.set_thumbnail(url=self.bot.user.display_avatar)
embed.add_field(name="Dev", value=team.name if team else f"{dev.mention}\n{dev.display_name}")
embed.add_field(name="Oppetid", value=self.get_uptime())
embed.add_field(name="Ping", value=f"Websocket ping: {self.get_ping()} ms")
embed.add_field(name="Servere", value=len(self.bot.guilds))
embed.add_field(name="Discord.py", value=discord.__version__)
embed.add_field(name="Python", value=platform.python_version())
embed.add_field(name="Ressursbruk", value=f"RAM: {memory_usage} MB")
embed.add_field(name="Kernel", value=f"{platform.system()} {platform.release()}")
if exists("/.dockerenv"):
embed.add_field(name="Docker", value="✅")
if version := self.bot.version:
embed.add_field(name="Versjon", value=f"`{version.branch}`\n{self.commit_link(version)}")
embed.add_field(
name=f"Brukere ({len(statuses)})",
value=discord_utils.format_status_counts(status_counts, self.bot.emoji, "\n"),
)
embed.add_field(
name="Lenker",
value=f'[Nettside]({self.bot.misc["website"]}) | ' + f'[Kildekode]({self.bot.misc["source_code"]})',
)
await interaction.response.send_message(embed=embed)
@app_commands.checks.bot_has_permissions(embed_links=True)
@app_commands.checks.cooldown(1, 2)
@app_commands.command(name="oppetid", description="Se hvor lenge botten har kjørt")
async def uptime(self, interaction: discord.Interaction):
"""
View the bot's uptime
Parameters
----------
interaction (discord.Interaction): The slash command interaction
"""
embed = discord.Embed(color=interaction.client.user.color)
embed.add_field(name="🔌 Oppetid", value=self.get_uptime())
await interaction.response.send_message(embed=embed)
@app_commands.checks.bot_has_permissions(embed_links=True)
@app_commands.checks.cooldown(1, 2)
@app_commands.command(name="ping", description="Se botten sin nåværende ping")
async def ping(self, interaction: discord.Interaction):
"""
View the bot's ping
Parameters
----------
interaction (discord.Interaction): The slash command interaction
"""
embed = discord.Embed(color=interaction.client.user.color)
embed.add_field(name="📶 Ping", value=f"* **Websocket ping:** {self.get_ping()} ms\n* **I hodet:** ∞")
await interaction.response.send_message(embed=embed, content=None)
@app_commands.checks.bot_has_permissions(embed_links=True)
@app_commands.checks.cooldown(1, 2)
@app_commands.command(name="versjon", description="Se hvilken branch og commit botten kjører")
async def version(self, interaction: discord.Interaction):
"""
View the branch and commit the bot is running
Parameters
----------
interaction (discord.Interaction): The slash command interaction
"""
if not (version := self.bot.version):
embed = embed_templates.error_warning("Fant ikke versjonen. Botten kjører kanskje ikke fra et git-repo")
return await interaction.response.send_message(embed=embed)
embed = discord.Embed(color=interaction.client.user.color, title="Versjon")
embed.add_field(name="Branch", value=f"`{version.branch}`")
embed.add_field(name="Commit", value=self.commit_link(version))
embed.add_field(name="Dato", value=discord.utils.format_dt(version.committed, style="f"))
embed.add_field(name="Melding", value=discord.utils.escape_markdown(version.subject), inline=False)
if version.dirty:
embed.set_footer(text="Kjører med endringer som ikke er committet")
await interaction.response.send_message(embed=embed)
def commit_link(self, version: misc_utils.GitVersion) -> str:
"""
Format the commit as a link to it in the source code repository
Parameters
----------
version (misc_utils.GitVersion): The version the bot runs
Returns
----------
(str): The short commit hash, linked if the source code url is configured
"""
short = f"`{version.commit[:7]}`"
if source_code := self.bot.misc.get("source_code"):
return f"[{short}]({source_code}/commit/{version.commit})"
return short
def get_ping(self) -> int:
"""
Get the bot's ping in milliseconds
Returns
----------
(int): The bot's ping in milliseconds
"""
return int(self.bot.latency * 1000)
def get_uptime(self) -> str:
"""
Returns the current uptime of the bot in string format
Returns
----------
(str): The bot's uptime in human readable format
"""
now = time()
diff = int(now - self.bot.uptime)
days, remainder = divmod(diff, 24 * 60 * 60)
hours, remainder = divmod(remainder, 60 * 60)
minutes, seconds = divmod(remainder, 60)
return f"{days}d, {hours}t, {minutes}m, {seconds}s"
async def setup(bot: commands.Bot):
"""
Add the cog to the bot on extension load
Parameters
----------
bot (commands.Bot): The bot instance
"""
await bot.add_cog(BotInfo(bot))