Füge Unterstützung für Meilensteine hinzu: Implementiere Meilenstein-Überprüfung und -Benachrichtigung

This commit is contained in:
2026-02-20 15:36:24 +01:00
parent a6d5651842
commit e459f0a035
2 changed files with 57 additions and 6 deletions

View File

@@ -1 +1,2 @@
DISCORD_TOKEN=dein_bot_token_hier DISCORD_TOKEN=dein_bot_token_hier
MILESTONE_CHANNEL_ID=channel_id_hier # optional: Channel für Meilenstein-Nachrichten

62
bot.py
View File

@@ -7,11 +7,24 @@ from dotenv import load_dotenv
load_dotenv() load_dotenv()
TOKEN = os.getenv("DISCORD_TOKEN") TOKEN = os.getenv("DISCORD_TOKEN")
MILESTONE_CHANNEL_ID = int(os.getenv("MILESTONE_CHANNEL_ID", 0))
DATA_FILE = "data.json" DATA_FILE = "data.json"
# Datenformat: # Datenformat:
# { "guild_id": { "user_id": { "mic": <int>, "deaf": <int> } } } # { "guild_id": { "user_id": { "mic": <int>, "deaf": <int> } } }
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: def load_data() -> dict:
if os.path.exists(DATA_FILE): 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}) 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): def increment(data: dict, guild_id: int, user_id: int, kind: str) -> int:
"""kind: 'mic' oder 'deaf'""" """Zählt hoch und gibt den neuen Gesamtwert (mic + deaf) zurück."""
gid = str(guild_id) gid = str(guild_id)
uid = str(user_id) uid = str(user_id)
if gid not in data: 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]: if uid not in data[gid]:
data[gid][uid] = {"mic": 0, "deaf": 0} data[gid][uid] = {"mic": 0, "deaf": 0}
data[gid][uid][kind] += 1 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() 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) just_mic_muted = (not before.self_mute) and after.self_mute and (not after.self_deaf)
if just_deafened: 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) save_data(mute_data)
entry = get_user_entry(mute_data, guild.id, member.id) entry = get_user_entry(mute_data, guild.id, member.id)
print( print(
f"[DEAF] {member.display_name} hat sich taubgestellt " f"[DEAF] {member.display_name} hat sich taubgestellt "
f"(deaf={entry['deaf']}x, mic={entry['mic']}x) [{guild.name}]" f"(deaf={entry['deaf']}x, mic={entry['mic']}x) [{guild.name}]"
) )
await check_milestone(guild, member, new_total)
elif just_mic_muted: 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) save_data(mute_data)
entry = get_user_entry(mute_data, guild.id, member.id) entry = get_user_entry(mute_data, guild.id, member.id)
print( print(
f"[MIC] {member.display_name} hat nur sein Mikrofon gemutet " f"[MIC] {member.display_name} hat nur sein Mikrofon gemutet "
f"(mic={entry['mic']}x, deaf={entry['deaf']}x) [{guild.name}]" 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.") @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 return
# Sortieren nach Gesamt-Mutes (mic + deaf)
def total(entry): def total(entry):
if isinstance(entry, dict): if isinstance(entry, dict):
return entry.get("mic", 0) + entry.get("deaf", 0) 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) sorted_entries = sorted(guild_data.items(), key=lambda x: total(x[1]), reverse=True)
top = sorted_entries[:limit] top = sorted_entries[:limit]