Last active 1 month ago

nuno revised this gist 1 month ago. Go to revision

1 file changed, 64 insertions

post.ts(file created)

@@ -0,0 +1,64 @@
1 + import { ChatInputCommandInteraction, TextChannel, EmbedBuilder } from "discord.js";
2 + import { cfg } from "@systems/config";
3 + import { getCurrentWeek, getWeekKey, getBringer } from "@systems/wrank";
4 + import { getEmoji } from "@systems/emojis";
5 + import { replyAndDelete } from "@utils";
6 +
7 + export async function handleRankPost(interaction: ChatInputCommandInteraction): Promise<void> {
8 + const week = getCurrentWeek();
9 + const goal = cfg("wRankGoal");
10 + const weekKey = getWeekKey();
11 +
12 + const formatNation = (nation: "capella" | "procyon"): string => {
13 + const entries = [...week.entries[nation]].sort((a, b) => a.currentRank - b.currentRank);
14 + if (entries.length === 0) return "—";
15 +
16 + const bringer = getBringer(nation === "capella" ? "Capella" : "Procyon");
17 +
18 + return entries.map((e) => {
19 + const isDone = e.tgCount >= goal;
20 +
21 + // ── Rank indicator ───────────────────────────────────────────────────
22 + // Use wrank_1_gold emoji if rank 1 and done, wrank_N emoji if available,
23 + // otherwise bold number as fallback (no colors in Discord plain text)
24 + const rankKey = isDone ? `wrank_${e.currentRank}_gold` : `wrank_${e.currentRank}`;
25 + const rankEmoji = getEmoji(rankKey);
26 + const rankStr = rankEmoji ?? (isDone ? `**${e.currentRank}**` : `${e.currentRank}`);
27 +
28 +
29 + // ── Delta ────────────────────────────────────────────────────────────
30 + // Use wrank_up_N / wrank_down_N emoji if available, text arrow as fallback
31 + const delta = e.previousRank !== undefined ? e.currentRank - e.previousRank : 0;
32 + let deltaStr = "";
33 + if (delta < 0) {
34 + const abs = Math.abs(delta);
35 + deltaStr = " " + (getEmoji(`wrank_up_${abs}`) ?? `↑${abs}`);
36 + } else if (delta > 0) {
37 + deltaStr = " " + (getEmoji(`wrank_down_${delta}`) ?? `↓${delta}`);
38 + }
39 +
40 + console.log(`rankKey: ${rankKey} rankEmoji: ${rankEmoji} rankStr: ${rankStr} isDone: ${isDone} delta: ${delta}`);
41 +
42 + // ── Bringer label ────────────────────────────────────────────────────
43 + const bringerStr = bringer === e.userKey && isDone
44 + ? ` · ${nation === "capella" ? "Luminous Bringer" : "Storm Bringer"}`
45 + : "";
46 +
47 + return `${rankStr}${deltaStr} «${e.characterName}» — ${e.weeklyPoints} pts (${e.tgCount}/${goal}${bringerStr})`;
48 + }).join("\n");
49 + };
50 +
51 + const embed = new EmbedBuilder()
52 + .setTitle(`⚔️ W.Rank Leaderboard — ${weekKey}`)
53 + .setColor(0xe8a317)
54 + .addFields(
55 + { name: "🔵 Capella", value: formatNation("capella"), inline: true },
56 + { name: "🔴 Procyon", value: formatNation("procyon"), inline: true },
57 + )
58 + .setTimestamp();
59 +
60 + const channelId = cfg("resultsChannelId") || cfg("pollChannelId");
61 + const channel = await interaction.client.channels.fetch(channelId) as TextChannel;
62 + await channel.send({ embeds: [embed] });
63 + return void replyAndDelete(interaction, "✅ Leaderboard posted.");
64 + }
Newer Older