Files
2026-07-12 01:13:09 +02:00

249 lines
7.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const {
SlashCommandBuilder,
EmbedBuilder,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
MessageFlags
} = require('discord.js');
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('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) {
switch (interaction.options._subcommand) {
case 'show':
ezdShow(interaction)
break;
case 'leaderboard':
ezdLeaderboard(interaction)
break;
default:
break;
}
}
};
// helper: shift YYYY-MM-DD safely
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()]
});
});
}