Files
discordbot/cogs/sysinfo.py
T
esefandClaude Opus 5 93e22a8364 statchannel: ignore steam's bogus zero player counts
Steam's GetNumberOfCurrentPlayers occasionally answers 200 with
player_count: 0 for a valid appid. Both Strinova stat channels were
renamed to "0" on the same 09:48 tick on 2026-10-20 (the only zero in
~300 renames over 3 days), and the name sat wrong until the next
10-minute tick.

Skip the rename on a non-positive count so the channel keeps its last
good value, and log it so the next one is visible. !strinova had the
same bug and would reply "0 players online right now".

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-20 13:12:57 +03:00

128 lines
4.7 KiB
Python

import asyncio
import logging
import re
from discord.ext import commands
import psutil
import aiohttp
log = logging.getLogger(__name__)
class SysInfo(commands.Cog):
def __init__(self, bot):
self.bot = bot
@staticmethod
def _strip_ansi(text: str) -> str:
return re.sub(r'\x1b\[[0-9;]*[a-zA-Z]|\[[0-9]+[A-Z]', '', text)
@staticmethod
async def _run_command(*args: str, timeout: float = 8) -> str:
"""Run a shell command asynchronously, return stdout or '' on failure."""
try:
proc = await asyncio.create_subprocess_exec(
*args,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.DEVNULL,
)
stdout, _ = await asyncio.wait_for(proc.communicate(), timeout=timeout)
return stdout.decode().strip()
except Exception:
log.debug("Command failed: %s", args, exc_info=True)
return ""
# ── commands ────────────────────────────────────────────────────────
@commands.command()
async def sysinfo(self, ctx):
"""List available sysinfo commands."""
cmds = [f'!{cmd.name}' for cmd in self.get_commands()]
await ctx.reply('\n'.join(cmds))
@commands.command(name="fetch")
async def fetch_cmd(self, ctx):
"""Show system info via fastfetch."""
out = await self._run_command("fastfetch", "--pipe", "--logo", "none")
if not out:
return await ctx.reply("fastfetch not available")
clean = self._strip_ansi(out)
await ctx.reply(f'```\n{clean}\n```')
@commands.command()
async def uptime(self, ctx):
out = await self._run_command("uptime", "-p")
await ctx.reply(f'⏱️ {out}' if out else "uptime not available")
@commands.command()
async def temps(self, ctx):
out = await self._run_command("sensors")
await ctx.reply(f'```\n{out}\n```' if out else "sensors not available")
@commands.command()
async def gpu(self, ctx):
out = await self._run_command("envycontrol", "--query")
await ctx.reply(f'I am on {out} mode esef!' if out else "envycontrol not available")
@commands.command()
async def top(self, ctx):
out = await self._run_command("ps", "aux", "--sort=-%cpu")
if not out:
return await ctx.reply("ps not available")
lines = out.splitlines()
top5 = '\n'.join(lines[:6])
await ctx.reply(f'```\n{top5}\n```')
@commands.command()
async def mem(self, ctx):
mem = psutil.virtual_memory()
await ctx.reply(f'💾 Memory Usage: {mem.percent}% ({mem.used // (1024**2)}MB / {mem.total // (1024**2)}MB)')
@commands.command()
async def cpu(self, ctx):
cpu_percent = psutil.cpu_percent(interval=1)
await ctx.reply(f'⚡ CPU Usage: {cpu_percent}%')
@commands.command()
async def load(self, ctx):
load1, load5, load15 = psutil.getloadavg()
await ctx.reply(f'📊 Load Average: {load1:.2f}, {load5:.2f}, {load15:.2f}')
@commands.command()
async def net(self, ctx):
net = psutil.net_io_counters()
await ctx.reply(f'📡 Network I/O: {net.bytes_sent} sent, {net.bytes_recv} received')
@commands.command()
async def battery(self, ctx):
battery = psutil.sensors_battery()
if battery:
await ctx.reply(f'Battery: {battery.percent}% {"Charging" if battery.power_plugged else "Not Charging"}')
@commands.command()
async def processes(self, ctx):
processes = psutil.pids()
await ctx.reply(f'Processes: {len(processes)} running processes')
@commands.command()
async def stats(self, ctx):
cpu = psutil.cpu_percent(interval=1)
ram = psutil.virtual_memory().percent
disk = psutil.disk_usage('/').percent
reply = f'CPU: {cpu}% | RAM: {ram}% | Disk: {disk}%'
await ctx.reply(reply)
@commands.command()
async def strinova(self, ctx):
async with aiohttp.ClientSession() as session:
async with session.get('https://api.steampowered.com/ISteamUserStats/GetNumberOfCurrentPlayers/v1/?appid=1282270') as r:
data = await r.json()
count = data['response']['player_count']
if not isinstance(count, int) or count <= 0:
await ctx.reply('🎮 Strinova — Steam is not returning a player count right now, try again in a bit')
return
await ctx.reply(f'🎮 Strinova — {count:,} players online right now')
async def setup(bot):
await bot.add_cog(SysInfo(bot))