diff --git a/.env.example b/.env.example index 24eb2b4..fc4d058 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ DISCORD_TOKEN=dein_bot_token_hier +MILESTONE_CHANNEL_ID=channel_id_hier # optional: Channel für Meilenstein-Nachrichten diff --git a/bot.py b/bot.py index dd97df8..1b94277 100644 --- a/bot.py +++ b/bot.py @@ -7,11 +7,24 @@ from dotenv import load_dotenv load_dotenv() TOKEN = os.getenv("DISCORD_TOKEN") +MILESTONE_CHANNEL_ID = int(os.getenv("MILESTONE_CHANNEL_ID", 0)) DATA_FILE = "data.json" # Datenformat: # { "guild_id": { "user_id": { "mic": , "deaf": } } } +MILESTONES = [10, 25, 50, 100, 250, 500, 1000] + +MILESTONE_MESSAGES = { + 10: ("🔇", "Erste Schritte in die Stille — **{name}** hat sich **10x** gemutet!"), + 25: ("😶", "**{name}** hält langsam die Klappe... **25 Mutes** erreicht!"), + 50: ("🤫", "**{name}** ist auf dem Weg zur Legende — **50 Mutes**!"), + 100: ("💯", "**{name}** hat die **100 Mutes** geknackt! Ein wahrer Schweiger."), + 250: ("🏅", "**{name}** erreicht **250 Mutes** — Professionelles Schweigen!"), + 500: ("🎖️", "**{name}** mit satten **500 Mutes**. Respekt."), + 1000: ("👑", "**{name}** ist der unbestrittene **MUTE-KÖNIG** mit **1000 Mutes**!"), +} + def load_data() -> dict: if os.path.exists(DATA_FILE): @@ -29,8 +42,8 @@ def get_user_entry(data: dict, guild_id: int, user_id: int) -> dict: return data.get(str(guild_id), {}).get(str(user_id), {"mic": 0, "deaf": 0}) -def increment(data: dict, guild_id: int, user_id: int, kind: str): - """kind: 'mic' oder 'deaf'""" +def increment(data: dict, guild_id: int, user_id: int, kind: str) -> int: + """Zählt hoch und gibt den neuen Gesamtwert (mic + deaf) zurück.""" gid = str(guild_id) uid = str(user_id) if gid not in data: @@ -38,6 +51,42 @@ def increment(data: dict, guild_id: int, user_id: int, kind: str): if uid not in data[gid]: data[gid][uid] = {"mic": 0, "deaf": 0} data[gid][uid][kind] += 1 + return data[gid][uid]["mic"] + data[gid][uid]["deaf"] + + +async def check_milestone(guild: discord.Guild, member: discord.Member, new_total: int): + """Prüft ob ein Meilenstein erreicht wurde und postet ggf. eine Nachricht.""" + if new_total not in MILESTONES: + return + + emoji, template = MILESTONE_MESSAGES[new_total] + message = template.format(name=member.display_name) + + # Ziel-Channel: konfigurierter Channel → System-Channel → erstes Text-Channel + channel = None + if MILESTONE_CHANNEL_ID: + channel = guild.get_channel(MILESTONE_CHANNEL_ID) + if channel is None: + channel = guild.system_channel + if channel is None: + channel = next( + (c for c in guild.text_channels if c.permissions_for(guild.me).send_messages), + None, + ) + + if channel is None: + print(f"[MILESTONE] Kein Channel gefunden für: {message}") + return + + embed = discord.Embed( + title=f"{emoji} Meilenstein erreicht!", + description=message, + color=discord.Color.gold(), + ) + embed.set_thumbnail(url=member.display_avatar.url) + embed.set_footer(text=f"Gesamt: {new_total} Mutes") + + await channel.send(embed=embed) intents = discord.Intents.default() @@ -83,22 +132,24 @@ async def on_voice_state_update( just_mic_muted = (not before.self_mute) and after.self_mute and (not after.self_deaf) if just_deafened: - increment(mute_data, guild.id, member.id, "deaf") + new_total = increment(mute_data, guild.id, member.id, "deaf") save_data(mute_data) entry = get_user_entry(mute_data, guild.id, member.id) print( f"[DEAF] {member.display_name} hat sich taubgestellt " f"(deaf={entry['deaf']}x, mic={entry['mic']}x) [{guild.name}]" ) + await check_milestone(guild, member, new_total) elif just_mic_muted: - increment(mute_data, guild.id, member.id, "mic") + new_total = increment(mute_data, guild.id, member.id, "mic") save_data(mute_data) entry = get_user_entry(mute_data, guild.id, member.id) print( f"[MIC] {member.display_name} hat nur sein Mikrofon gemutet " f"(mic={entry['mic']}x, deaf={entry['deaf']}x) [{guild.name}]" ) + await check_milestone(guild, member, new_total) @bot.tree.command(name="mutescore", description="Zeigt das Mute-Leaderboard des Servers.") @@ -114,11 +165,10 @@ async def mutescore(interaction: discord.Interaction, limit: int = 10): ) return - # Sortieren nach Gesamt-Mutes (mic + deaf) def total(entry): if isinstance(entry, dict): return entry.get("mic", 0) + entry.get("deaf", 0) - return entry # Fallback für altes Format + return entry sorted_entries = sorted(guild_data.items(), key=lambda x: total(x[1]), reverse=True) top = sorted_entries[:limit]