import discord from discord.ext import commands from discord import app_commands, ui import time import psutil import platform import GPUtil import distro # Import wmi for Windows motherboard info try: import wmi WMI_AVAILABLE = True except ImportError: WMI_AVAILABLE = False def create_progress_bar(value: float, total: float, length: int = 10) -> str: """Creates a text-based progress bar.""" if total == 0: percentage = 0 else: percentage = value / total filled_length = int(length * percentage) bar = '▓' * filled_length + '░' * (length - filled_length) return f"[{bar}] {percentage:.1%}" class SystemStatusView(ui.LayoutView): """ A view that displays system and bot statistics in a visually appealing way. It uses components v2 for a modern look. """ def __init__( self, bot_user: discord.User, guild_count: int, user_count: int, os_info: str, distro_info: str, hostname: str, uptime: str, motherboard_info: str, cpu_name: str, cpu_usage: float, ram_used: int, ram_total: int, gpu_info: str, requester: discord.User, ) -> None: super().__init__(timeout=None) # --- Store all data for the view --- self.bot_user = bot_user self.guild_count = guild_count self.user_count = user_count self.os_info = os_info self.distro_info = distro_info self.hostname = hostname self.uptime = uptime self.motherboard_info = motherboard_info self.cpu_name = cpu_name self.cpu_usage = cpu_usage self.ram_used = ram_used self.ram_total = ram_total self.gpu_info = gpu_info self.requester = requester # --- Build the UI --- self._build_ui() def _create_aligned_block(self, data: dict) -> str: """Creates a neatly aligned text block inside a markdown code block.""" max_key_len = max(len(k) for k in data.keys()) lines = [] for key, value in data.items(): lines.append(f"{key.ljust(max_key_len)} : {value}") return "```\n" + "\n".join(lines) + "\n```" def _build_ui(self): """Constructs the UI elements of the view.""" # Main container with Discord's "Blurple" color container = ui.Container(accent_colour=None) # --- Bot & System Info --- self._add_bot_system_info(container) # --- Hardware Info --- self._add_hardware_info(container) # --- Footer --- self._add_footer(container) self.add_item(container) def _add_bot_system_info(self, container: ui.Container): """Adds bot and system information fields.""" bot_data = { "Servers": self.guild_count, "Users": self.user_count } container.add_item(ui.TextDisplay("**🤖 Bot Info**" + self._create_aligned_block(bot_data))) system_data = { "OS": f"{self.os_info}{self.distro_info}", "Hostname": self.hostname, "Uptime": self.uptime } container.add_item(ui.TextDisplay("**🖥️ System Info**" + self._create_aligned_block(system_data))) def _add_hardware_info(self, container: ui.Container): """Adds hardware information with progress bars.""" container.add_item(ui.Separator(spacing=discord.SeparatorSpacing.small)) ram_usage_text = f"{self.ram_used // (1024**2):,}MB / {self.ram_total // (1024**2):,}MB" cpu_bar = create_progress_bar(self.cpu_usage, 100.0) ram_bar = create_progress_bar(self.ram_used, self.ram_total) hardware_data = { "CPU Usage": cpu_bar, "RAM Usage": f"{ram_bar}\n{''.ljust(len('RAM Usage'))} └ {ram_usage_text}", "Board": self.motherboard_info, "CPU": self.cpu_name, "GPU": self.gpu_info } container.add_item(ui.TextDisplay("**⚙️ Hardware Info**" + self._create_aligned_block(hardware_data))) def _add_footer(self, container: ui.Container): """Adds the footer with timestamp and requester info.""" container.add_item(ui.Separator(spacing=discord.SeparatorSpacing.small)) timestamp = discord.utils.format_dt(discord.utils.utcnow(), style="R") footer_text = f"Updated: {timestamp} | Requested by: {self.requester.display_name}" container.add_item(ui.TextDisplay(f"_{footer_text}_")) class SystemCheckCog(commands.Cog): def __init__(self, bot): self.bot = bot async def _build_system_check_view(self, context_or_interaction) -> SystemStatusView: """Gathers all system data and returns the constructed view.""" # Bot information guild_count = len(self.bot.guilds) # A more efficient way to get unique users, avoiding large member lists in memory user_ids = {member.id for guild in self.bot.guilds for member in guild.members if not member.bot} user_count = len(user_ids) # System information system = platform.system() os_info = f"{system} {platform.release()}" hostname = platform.node() distro_info_str = "" if system == "Linux": try: distro_name = distro.name(pretty=True) distro_info_str = f" ({distro_name})" except Exception: distro_info_str = "" # Fail silently elif system == "Windows": try: # Use a more reliable way to get Windows version win_ver = platform.win32_ver() os_info = f"Windows {win_ver[0]} {win_ver[2]}" except Exception: pass # Fail silently uptime_seconds = time.time() - psutil.boot_time() days, rem = divmod(uptime_seconds, 86400) hours, rem = divmod(rem, 3600) minutes, _ = divmod(rem, 60) uptime_str = f"{int(days)}d {int(hours)}h {int(minutes)}m" # Hardware information cpu_usage = psutil.cpu_percent(interval=0.1) try: cpu_name_base = "N/A" if system == "Linux": with open("/proc/cpuinfo") as f: for line in f: if line.startswith("model name"): cpu_name_base = line.split(":")[1].strip() break else: # Windows or fallback cpu_name_base = platform.processor() or "N/A" physical_cores = psutil.cpu_count(logical=False) total_threads = psutil.cpu_count(logical=True) cpu_name = f"{cpu_name_base} ({physical_cores}C/{total_threads}T)" except Exception: cpu_name = "N/A" motherboard_info = self._get_motherboard_info() memory = psutil.virtual_memory() # GPU Information try: gpus = GPUtil.getGPUs() if gpus: # Format multi-GPU info on new lines for readability gpu_info_lines = [f"{gpu.name} ({gpu.load*100:.1f}% Load)" for gpu in gpus] gpu_info = "\n".join(gpu_info_lines) else: gpu_info = "No dedicated GPU detected" except Exception: gpu_info = "N/A" # Determine user based on context type user = context_or_interaction.author if isinstance(context_or_interaction, commands.Context) else context_or_interaction.user return SystemStatusView( bot_user=self.bot.user, guild_count=guild_count, user_count=user_count, os_info=os_info, distro_info=distro_info_str, hostname=hostname, uptime=uptime_str, motherboard_info=motherboard_info, cpu_name=cpu_name, cpu_usage=cpu_usage, ram_used=memory.used, ram_total=memory.total, gpu_info=gpu_info, requester=user, ) def _get_motherboard_info(self) -> str: """Get motherboard information based on the operating system.""" system = platform.system() try: if system == "Windows" and WMI_AVAILABLE: w = wmi.WMI() board = w.Win32_BaseBoard()[0] return f"{board.Manufacturer} {board.Product}" elif system == "Linux": # Check for product_name first, then fallback to board_name try: with open("/sys/devices/virtual/dmi/id/product_name", "r") as f: return f.read().strip() except FileNotFoundError: with open("/sys/devices/virtual/dmi/id/board_name", "r") as f: return f.read().strip() return "N/A" except Exception: return "N/A" @commands.command(name="systemcheck", aliases=["status"]) async def system_check(self, ctx: commands.Context): """Check the bot and system status.""" view = await self._build_system_check_view(ctx) await ctx.reply(view=view, mention_author=False) @app_commands.command(name="systemcheck", description="Check the bot and system status") async def system_check_slash(self, interaction: discord.Interaction): """Slash command version of system check.""" await interaction.response.defer(thinking=True, ephemeral=False) view = await self._build_system_check_view(interaction) await interaction.followup.send(view=view) async def setup(bot): await bot.add_cog(SystemCheckCog(bot))