diff --git a/commands/slash/applications/ezd.js b/commands/slash/applications/ezd.js index fa61dd9..eeabbe9 100644 --- a/commands/slash/applications/ezd.js +++ b/commands/slash/applications/ezd.js @@ -9,95 +9,36 @@ const { const { mClient } = require('../../..'); require('dotenv').config() +const db = mClient.db(process.env.M_DB); // adjust if needed +const coll = db.collection('items_daily_numbers'); + module.exports = { data: new SlashCommandBuilder() .setName('ezd') - .setDescription('Zeigt die täglichen Erster/Zweiter/Dritter Ergebnisse'), - + .setDescription('Ersti Zweiti Dritti') + .addSubcommand(s => + s + .setName('show') + .setDescription('Zeigt die täglichen Erster/Zweiter/Dritter Ergebnisse') + ) + .addSubcommand(s => + s + .setName('leaderboard') + .setDescription('Zeigt die Rangliste der EZDler') + ) + , async execute(interaction, client) { - const db = mClient.db(process.env.M_DB); // adjust if needed - const coll = db.collection('items_daily_numbers'); + switch (interaction.options._subcommand) { + case 'show': + ezdShow(interaction) + break; + case 'leaderboard': + ezdLeaderboard(interaction) + break; - const today = new Date().toLocaleDateString("en-CA", { - timeZone: "Europe/Berlin" - }); - - let currentDate = today; - - const sessionId = `${interaction.user.id}-${Date.now()}`; - - const buildEmbed = (doc, date) => { - const p = doc?.positions || {}; - - const line = (emoji, label, key) => { - const v = p[key]; - return `${emoji} **${label}:** ${v ? `<@${v.userId}>` : "—"}`; - }; - - const germanDate = new Date(`${date}T00:00:00`).toLocaleDateString("de-DE", { - timeZone: "Europe/Berlin", - day: "2-digit", - month: "2-digit", - year: "numeric" - }); - - return new EmbedBuilder() - .setTitle(`📊 EZD Übersicht – ${germanDate}`) - .setColor(0x2b2d31) - .setDescription([ - line("🥇", "Ersti", "Ersti"), - line("🥈", "Zweiti", "Zweiti"), - line("🥉", "Dritti", "Dritti") - ].join("\n")); - }; - - const buildButtons = (date) => { - return new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setCustomId(`ezd_prev`) - .setLabel("⬅️") - .setStyle(ButtonStyle.Secondary), - new ButtonBuilder() - .setCustomId(`ezd_next`) - .setLabel("➡️") - .setStyle(ButtonStyle.Secondary) - ); - }; - - const doc = await coll.findOne({ date: currentDate }); - - const msg = await interaction.reply({ - embeds: [buildEmbed(doc, currentDate)], - components: [buildButtons(currentDate)] - }); - - const collector = msg.createMessageComponentCollector({ - time: 1000 * 60 * 10 // 10 minutes - }); - - collector.on("collect", async (btn) => { - if (btn.user.id !== interaction.user.id) { - return btn.reply({ - content: "❌ Diese Buttons gehören nicht dir.", - flags: MessageFlags.Ephemeral - }); - } - - if (btn.customId === `ezd_prev`) { - currentDate = shiftDate(currentDate, -1); - } - - if (btn.customId === `ezd_next`) { - currentDate = shiftDate(currentDate, 1); - } - - const newDoc = await coll.findOne({ date: currentDate }); - - await btn.update({ - embeds: [buildEmbed(newDoc, currentDate)], - components: [buildButtons(currentDate)] - }); - }); + default: + break; + } } }; @@ -106,4 +47,203 @@ function shiftDate(dateStr, offset) { const d = new Date(dateStr); d.setDate(d.getDate() + offset); return d.toISOString().slice(0, 10); +} + +async function ezdShow(interaction) { + const today = new Date().toLocaleDateString("en-CA", { + timeZone: "Europe/Berlin" + }); + + let currentDate = today; + + const sessionId = `${interaction.user.id}-${Date.now()}`; + + const buildEmbed = (doc, date) => { + const p = doc?.positions || {}; + + const line = (emoji, label, key) => { + const v = p[key]; + return `${emoji} **${label}:** ${v ? `<@${v.userId}>` : "—"}`; + }; + + const germanDate = new Date(`${date}T00:00:00`).toLocaleDateString("de-DE", { + timeZone: "Europe/Berlin", + day: "2-digit", + month: "2-digit", + year: "numeric" + }); + + return new EmbedBuilder() + .setTitle(`📊 EZD Übersicht – ${germanDate}`) + .setColor(0x2b2d31) + .setDescription([ + line("🥇", "Ersti", "Ersti"), + line("🥈", "Zweiti", "Zweiti"), + line("🥉", "Dritti", "Dritti") + ].join("\n")); + }; + + const buildButtons = (date) => { + return new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setCustomId(`ezd_prev`) + .setLabel("⬅️") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId(`ezd_next`) + .setLabel("➡️") + .setStyle(ButtonStyle.Secondary) + ); + }; + + const doc = await coll.findOne({ date: currentDate }); + + const msg = await interaction.reply({ + embeds: [buildEmbed(doc, currentDate)], + components: [buildButtons(currentDate)] + }); + + const collector = msg.createMessageComponentCollector({ + time: 1000 * 60 * 10 // 10 minutes + }); + + collector.on("collect", async (btn) => { + if (btn.user.id !== interaction.user.id) { + return btn.reply({ + content: "❌ Diese Buttons gehören nicht dir.", + flags: MessageFlags.Ephemeral + }); + } + + if (btn.customId === `ezd_prev`) { + currentDate = shiftDate(currentDate, -1); + } + + if (btn.customId === `ezd_next`) { + currentDate = shiftDate(currentDate, 1); + } + + const newDoc = await coll.findOne({ date: currentDate }); + + await btn.update({ + embeds: [buildEmbed(newDoc, currentDate)], + components: [buildButtons(currentDate)] + }); + }); +} + +async function ezdLeaderboard(interaction) { + const docs = await coll.find({}).toArray(); + + const leaderboard = new Map(); + + const add = (entry, place) => { + if (!entry?.userId) return; + + if (!leaderboard.has(entry.userId)) { + leaderboard.set(entry.userId, { + userId: entry.userId, + points: 0, + Ersti: 0, + Zweiti: 0, + Dritti: 0 + }); + } + + const user = leaderboard.get(entry.userId); + + user[place]++; + + if (place === "Ersti") user.points += 3; + if (place === "Zweiti") user.points += 2; + if (place === "Dritti") user.points += 1; + }; + + for (const doc of docs) { + const p = doc.positions || {}; + + add(p.Ersti, "Ersti"); + add(p.Zweiti, "Zweiti"); + add(p.Dritti, "Dritti"); + } + + const users = [...leaderboard.values()].sort((a, b) => { + if (b.points !== a.points) return b.points - a.points; + if (b.Ersti !== a.Ersti) return b.Ersti - a.Ersti; + if (b.Zweiti !== a.Zweiti) return b.Zweiti - a.Zweiti; + return b.Dritti - a.Dritti; + }); + + const PAGE_SIZE = 5; + const pageCount = Math.max(1, Math.ceil(users.length / PAGE_SIZE)); + let page = 0; + + const buildEmbed = () => { + const slice = users.slice( + page * PAGE_SIZE, + page * PAGE_SIZE + PAGE_SIZE + ); + + const description = slice.length + ? slice.map((u, i) => { + const rank = page * PAGE_SIZE + i + 1; + + return `**#${rank}** <@${u.userId}> — **${u.points}** +🥇 ${u.Ersti} · 🥈 ${u.Zweiti} · 🥉 ${u.Dritti}`; + }).join("\n\n") + : "—"; + + return new EmbedBuilder() + .setTitle("🏆 EZD Rangliste") + .setColor(0x2b2d31) + .setDescription(description); + }; + + const buildButtons = () => + new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setCustomId("ezd_lb_prev") + .setLabel("⬅️") + .setStyle(ButtonStyle.Secondary), + + new ButtonBuilder() + .setCustomId("ezd_lb_page") + .setLabel(`${page + 1}/${pageCount}`) + .setStyle(ButtonStyle.Primary) + .setDisabled(true), + + new ButtonBuilder() + .setCustomId("ezd_lb_next") + .setLabel("➡️") + .setStyle(ButtonStyle.Secondary) + ); + + const msg = await interaction.reply({ + embeds: [buildEmbed()], + components: [buildButtons()] + }); + + const collector = msg.createMessageComponentCollector({ + time: 1000 * 60 * 10 + }); + + collector.on("collect", async btn => { + if (btn.user.id !== interaction.user.id) { + return btn.reply({ + content: "❌ Diese Buttons gehören nicht dir.", + flags: MessageFlags.Ephemeral + }); + } + + if (btn.customId === "ezd_lb_prev") + page = (page - 1 + pageCount) % pageCount; + + if (btn.customId === "ezd_lb_next") + page = (page + 1) % pageCount; + + await btn.update({ + embeds: [buildEmbed()], + components: [buildButtons()] + }); + }); } \ No newline at end of file diff --git a/events/MessageCreate.js b/events/MessageCreate.js index d46f328..fdf8c6a 100644 --- a/events/MessageCreate.js +++ b/events/MessageCreate.js @@ -19,7 +19,7 @@ module.exports = { }; const found = Object.entries(numbered).find(([stem]) => - new RegExp(`\\b${stem}\\w*\\b`, "i").test(message.content) + new RegExp(`\\b\\w*${stem}\\w*\\b`, "i").test(message.content) )?.[1]; if (!found) return;