From e24523d1b3e202075ba685dc90b219a7d5835d32 Mon Sep 17 00:00:00 2001 From: Leander Furumo Date: Sun, 1 Nov 2026 19:32:53 +0100 Subject: [PATCH] simplify member status counting in /botinfo and /guild info Count statuses with a Counter over discord.Status instead of one set or counter per status, and share the emoji formatting between both commands. Co-Authored-By: Claude Opus 5.5 --- src/cogs/botinfo.py | 37 +++++++-------------------------- src/cogs/info.py | 25 +++++----------------- src/cogs/utils/discord_utils.py | 21 +++++++++++++++++++ 3 files changed, 34 insertions(+), 49 deletions(-) diff --git a/src/cogs/botinfo.py b/src/cogs/botinfo.py index 8589db4..f20443f 100644 --- a/src/cogs/botinfo.py +++ b/src/cogs/botinfo.py @@ -1,4 +1,5 @@ import platform +from collections import Counter from os import getpid from os.path import exists from time import time @@ -8,6 +9,7 @@ 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 @@ -54,30 +56,10 @@ class BotInfo(commands.Cog): memory_usage = round(process.memory_info().rss / 1000000, 1) # Member stats - # - # This is a pretty stupid way of doing things but it's the best I can come up with. - # Using curly brackets for both dicts and sets is retarded becuase - # I have to do this shit in order to create a fucking empty set. - # - # Apparently you can't access user presences, only member presences - # Because of that I have to use sets instead of ints in order to not count duplicate users. - # Fucking hell discord... - total_members = set([]) - online_members = set([]) - idle_members = set([]) - dnd_members = set([]) - offline_members = set([]) - for guild in self.bot.guilds: - for member in guild.members: - total_members.add(member.id) - if str(member.status) == "online": - online_members.add(member.id) - elif str(member.status) == "idle": - idle_members.add(member.id) - elif str(member.status) == "dnd": - dnd_members.add(member.id) - elif str(member.status) == "offline": - offline_members.add(member.id) + # 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"]) @@ -99,11 +81,8 @@ class BotInfo(commands.Cog): 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(total_members)})", - value=f'{self.bot.emoji["online"]}{len(online_members)}\n' - + f'{self.bot.emoji["idle"]}{len(idle_members)}\n' - + f'{self.bot.emoji["dnd"]}{len(dnd_members)}\n' - + f'{self.bot.emoji["offline"]}{len(offline_members)}', + name=f"Brukere ({len(statuses)})", + value=discord_utils.format_status_counts(status_counts, self.bot.emoji, "\n"), ) embed.add_field( name="Lenker", diff --git a/src/cogs/info.py b/src/cogs/info.py index 8a8def0..71dc8e3 100644 --- a/src/cogs/info.py +++ b/src/cogs/info.py @@ -1,3 +1,5 @@ +from collections import Counter + import discord from discord import app_commands from discord.ext import commands @@ -107,22 +109,8 @@ class Info(commands.Cog): # Member count and status counts total_members = interaction.guild.member_count - bot_members = 0 - online_members = 0 - idle_members = 0 - dnd_members = 0 - offline_members = 0 - for member in interaction.guild.members: - if member.bot: - bot_members += 1 - if str(member.status) == "online": - online_members += 1 - elif str(member.status) == "idle": - idle_members += 1 - elif str(member.status) == "dnd": - dnd_members += 1 - elif str(member.status) == "offline": - offline_members += 1 + bot_members = sum(member.bot for member in interaction.guild.members) + status_counts = Counter(member.status for member in interaction.guild.members) # Roles roles = self.construct_role_string(interaction.guild.roles) @@ -223,10 +211,7 @@ class Info(commands.Cog): name=f"Medlemmer ({total_members})", value=f"👤 Mennesker: **{int(total_members) - int(bot_members)}**\n" + f"🤖 Båtter: **{bot_members}**\n" - + f'{self.bot.emoji["online"]}{online_members} ' - + f'{self.bot.emoji["idle"]}{idle_members} ' - + f'{self.bot.emoji["dnd"]}{dnd_members} ' - + f'{self.bot.emoji["offline"]}{offline_members}', + + discord_utils.format_status_counts(status_counts, self.bot.emoji, " "), ) embed.add_field(name=f"Roller ({len(interaction.guild.roles) - 1})", value=roles, inline=False) if interaction.guild.premium_tier != 0: diff --git a/src/cogs/utils/discord_utils.py b/src/cogs/utils/discord_utils.py index 1eb660f..7226013 100644 --- a/src/cogs/utils/discord_utils.py +++ b/src/cogs/utils/discord_utils.py @@ -1,3 +1,4 @@ +from collections import Counter from dataclasses import dataclass from dataclasses import field from datetime import datetime @@ -12,6 +13,26 @@ from discord.ext import tasks from cogs.utils import embed_templates from cogs.utils import misc_utils +SHOWN_STATUSES = (discord.Status.online, discord.Status.idle, discord.Status.dnd, discord.Status.offline) + + +def format_status_counts(status_counts: Counter[discord.Status], emoji: dict[str, str], separator: str) -> str: + """ + Format how many members have each status, as status emojis followed by the counts + + Parameters + ---------- + status_counts (Counter[discord.Status]): How many members have each status + emoji (dict[str, str]): The bot's emojis, which have an entry for every status + separator (str): What to put between the statuses + + Returns + ---------- + (str): The formatted status counts + """ + + return separator.join(f"{emoji[status.value]}{status_counts[status]}" for status in SHOWN_STATUSES) + async def send_as_txt_file(interaction: discord.Interaction, content: str, filename: str): """