mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
171 lines
5.5 KiB
Python
171 lines
5.5 KiB
Python
from __future__ import annotations
|
|
|
|
import getpass
|
|
import os
|
|
import platform
|
|
import sys
|
|
from typing import Optional
|
|
|
|
import discord
|
|
import pip
|
|
import psutil
|
|
|
|
from redbot import __version__
|
|
from redbot.core import data_manager
|
|
from redbot.core.bot import Red
|
|
from redbot.core.utils.chat_formatting import box
|
|
|
|
|
|
def noop_box(text: str, **kwargs) -> str:
|
|
return text
|
|
|
|
|
|
def _datasize(num: int):
|
|
for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]:
|
|
if abs(num) < 1024.0:
|
|
return "{0:.1f}{1}".format(num, unit)
|
|
num /= 1024.0
|
|
return "{0:.1f}{1}".format(num, "YB")
|
|
|
|
|
|
class DebugInfoSection:
|
|
def __init__(self, section_name: str, *section_parts: str) -> None:
|
|
self.section_name = section_name
|
|
self.section_parts = section_parts
|
|
|
|
def get_command_text(self) -> str:
|
|
parts = [box(f"## {self.section_name}:", lang="md")]
|
|
for part in self.section_parts:
|
|
parts.append(box(part))
|
|
return "".join(parts)
|
|
|
|
def get_cli_text(self) -> str:
|
|
parts = [f"\x1b[32m## {self.section_name}:\x1b[0m"]
|
|
for part in self.section_parts:
|
|
parts.append(part)
|
|
return "\n".join(parts)
|
|
|
|
|
|
class DebugInfo:
|
|
def __init__(self, bot: Optional[Red] = None) -> None:
|
|
self.bot = bot
|
|
|
|
async def get_text(self) -> str:
|
|
if self.bot is None:
|
|
return await self.get_cli_text()
|
|
else:
|
|
return await self.get_command_text()
|
|
|
|
async def get_cli_text(self) -> str:
|
|
parts = ["\x1b[31m# Debug Info for Red:\x1b[0m"]
|
|
for section in (
|
|
self._get_system_metadata_section(),
|
|
self._get_os_variables_section(),
|
|
await self._get_red_vars_section(),
|
|
):
|
|
parts.append("")
|
|
parts.append(section.get_cli_text())
|
|
|
|
return "\n".join(parts)
|
|
|
|
async def get_command_text(self) -> str:
|
|
parts = [box("# Debug Info for Red:", lang="md")]
|
|
for section in (
|
|
self._get_system_metadata_section(),
|
|
self._get_os_variables_section(),
|
|
await self._get_red_vars_section(),
|
|
):
|
|
parts.append("\n")
|
|
parts.append(section.get_command_text())
|
|
|
|
return "".join(parts)
|
|
|
|
def _get_system_metadata_section(self) -> DebugInfoSection:
|
|
memory_ram = psutil.virtual_memory()
|
|
ram_string = "{used}/{total} ({percent}%)".format(
|
|
used=_datasize(memory_ram.used),
|
|
total=_datasize(memory_ram.total),
|
|
percent=memory_ram.percent,
|
|
)
|
|
return DebugInfoSection(
|
|
"System Metadata",
|
|
f"CPU Cores: {psutil.cpu_count()} ({platform.machine()})\nRAM: {ram_string}",
|
|
)
|
|
|
|
def _get_os_variables_section(self) -> DebugInfoSection:
|
|
IS_WINDOWS = os.name == "nt"
|
|
IS_MAC = sys.platform == "darwin"
|
|
IS_LINUX = sys.platform == "linux"
|
|
|
|
python_version = ".".join(map(str, sys.version_info[:3]))
|
|
pyver = f"{python_version} ({platform.architecture()[0]})"
|
|
pipver = pip.__version__
|
|
redver = __version__
|
|
dpy_version = discord.__version__
|
|
if IS_WINDOWS:
|
|
os_info = platform.uname()
|
|
osver = f"{os_info.system} {os_info.release} (version {os_info.version})"
|
|
elif IS_MAC:
|
|
os_info = platform.mac_ver()
|
|
osver = f"Mac OSX {os_info[0]} {os_info[2]}"
|
|
elif IS_LINUX:
|
|
import distro
|
|
|
|
osver = f"{distro.name()} {distro.version()}".strip()
|
|
else:
|
|
osver = "Could not parse OS, report this on Github."
|
|
user_who_ran = getpass.getuser()
|
|
|
|
resp_os = f"OS version: {osver}\nUser: {user_who_ran}\n" # Ran where off to?!
|
|
resp_py_metadata = (
|
|
f"Python executable: {sys.executable}\n"
|
|
f"Python version: {pyver}\n"
|
|
f"Pip version: {pipver}\n"
|
|
)
|
|
resp_red_metadata = f"Red version: {redver}\nDiscord.py version: {dpy_version}"
|
|
return DebugInfoSection(
|
|
"OS variables",
|
|
resp_os,
|
|
resp_py_metadata,
|
|
resp_red_metadata,
|
|
)
|
|
|
|
async def _get_red_vars_section(self) -> DebugInfoSection:
|
|
if data_manager.instance_name is None:
|
|
return DebugInfoSection(
|
|
"Red variables",
|
|
f"Metadata file: {data_manager.config_file}",
|
|
)
|
|
|
|
parts = [f"Instance name: {data_manager.instance_name}"]
|
|
if self.bot is not None:
|
|
owners = []
|
|
for uid in self.bot.owner_ids:
|
|
try:
|
|
u = await self.bot.get_or_fetch_user(uid)
|
|
owners.append(f"{u.id} ({u})")
|
|
except discord.HTTPException:
|
|
owners.append(f"{uid} (Unresolvable)")
|
|
owners_string = ", ".join(owners) or "None"
|
|
parts.append(f"Owner(s): {', '.join(owners) or 'None'}")
|
|
|
|
if self.bot is not None:
|
|
disabled_intents = (
|
|
", ".join(
|
|
intent_name.replace("_", " ").title()
|
|
for intent_name, enabled in self.bot.intents
|
|
if not enabled
|
|
)
|
|
or "None"
|
|
)
|
|
parts.append(f"Disabled intents: {disabled_intents}")
|
|
|
|
parts.append(f"Storage type: {data_manager.storage_type()}")
|
|
parts.append(f"Data path: {data_manager.basic_config['DATA_PATH']}")
|
|
parts.append(f"Metadata file: {data_manager.config_file}")
|
|
|
|
return DebugInfoSection(
|
|
"Red variables",
|
|
"\n".join(parts),
|
|
)
|