get.ts
· 2.7 KiB · TypeScript
Raw
import { ChatInputCommandInteraction } from "discord.js";
import { cfg } from "../../systems/config";
import { resolveUser, hasOfficerRole } from "../../systems/users";
import { normalizeSlot, detectSlot } from "../../systems/scores";
import { loadResult, todayString } from "../../systems/history";
import { getEmoji } from "../../systems/emojis";
import { replyAndDelete } from "../../utils";
export async function handleScoreGet(interaction: ChatInputCommandInteraction): Promise<void> {
const member = await interaction.guild!.members.fetch(interaction.user.id);
const isOfficer = hasOfficerRole(member, cfg("officerRoles"));
const nameArg = interaction.options.getString("name");
const slotArg = interaction.options.getString("slot");
if (nameArg && !isOfficer) {
return void replyAndDelete(interaction, "❌ Only officers can view other players' scores.", true);
}
let userKey: string | null;
if (nameArg) {
userKey = nameArg;
} else {
const user = await resolveUser(member);
userKey = user.userKey;
}
if (!userKey) return void replyAndDelete(interaction, "❌ You are not registered in the system.", true);
let slot: number | null = null;
if (slotArg) {
slot = normalizeSlot(slotArg);
if (slot === null) return void replyAndDelete(interaction, `❌ Could not parse slot "${slotArg}".`, true);
} else {
slot = detectSlot() ?? cfg("slots").find((s) => s.active)?.tgHour ?? 20;
}
const result = loadResult(todayString(), slot);
if (!result) return void replyAndDelete(interaction, `❌ No result found for **${slot}:00** TG today.`, true);
// Find score — check both direct ownership and borrowed (playedBy)
const score = result.scores.find(
(s) => s.userKey === userKey || (s as any).playedBy === userKey
);
if (!score) return void replyAndDelete(interaction, `❌ No score submitted for **${userKey}** in the **${slot}:00** TG.`, true);
const scoreEmoji = getEmoji("score") || "📊";
const kdEmoji = getEmoji("kd") || "⚔️";
const playedBy = (score as any).playedBy && (score as any).playedBy !== score.userKey
? `\n*(played by ${(score as any).playedBy})*`
: "";
const lines = [
`**${score.characterName}** (${score.class} · ${score.nation})${playedBy}`,
`${scoreEmoji} **${score.pts}** pts`,
score.atk !== undefined ? `ATK: ${score.atk}` : null,
score.def !== undefined ? `DEF: ${score.def}` : null,
score.heal !== undefined ? `HEAL: ${score.heal}` : null,
`*Submitted at ${new Date(score.submittedAt).toLocaleTimeString("en-GB", { timeZone: process.env.TZ ?? "Etc/GMT-2" })}*`,
].filter(Boolean).join("\n");
return void replyAndDelete(interaction, lines, true);
}
| 1 | import { ChatInputCommandInteraction } from "discord.js"; |
| 2 | import { cfg } from "../../systems/config"; |
| 3 | import { resolveUser, hasOfficerRole } from "../../systems/users"; |
| 4 | import { normalizeSlot, detectSlot } from "../../systems/scores"; |
| 5 | import { loadResult, todayString } from "../../systems/history"; |
| 6 | import { getEmoji } from "../../systems/emojis"; |
| 7 | import { replyAndDelete } from "../../utils"; |
| 8 | |
| 9 | export async function handleScoreGet(interaction: ChatInputCommandInteraction): Promise<void> { |
| 10 | const member = await interaction.guild!.members.fetch(interaction.user.id); |
| 11 | const isOfficer = hasOfficerRole(member, cfg("officerRoles")); |
| 12 | const nameArg = interaction.options.getString("name"); |
| 13 | const slotArg = interaction.options.getString("slot"); |
| 14 | |
| 15 | if (nameArg && !isOfficer) { |
| 16 | return void replyAndDelete(interaction, "❌ Only officers can view other players' scores.", true); |
| 17 | } |
| 18 | |
| 19 | let userKey: string | null; |
| 20 | if (nameArg) { |
| 21 | userKey = nameArg; |
| 22 | } else { |
| 23 | const user = await resolveUser(member); |
| 24 | userKey = user.userKey; |
| 25 | } |
| 26 | |
| 27 | if (!userKey) return void replyAndDelete(interaction, "❌ You are not registered in the system.", true); |
| 28 | |
| 29 | let slot: number | null = null; |
| 30 | if (slotArg) { |
| 31 | slot = normalizeSlot(slotArg); |
| 32 | if (slot === null) return void replyAndDelete(interaction, `❌ Could not parse slot "${slotArg}".`, true); |
| 33 | } else { |
| 34 | slot = detectSlot() ?? cfg("slots").find((s) => s.active)?.tgHour ?? 20; |
| 35 | } |
| 36 | |
| 37 | const result = loadResult(todayString(), slot); |
| 38 | if (!result) return void replyAndDelete(interaction, `❌ No result found for **${slot}:00** TG today.`, true); |
| 39 | |
| 40 | // Find score — check both direct ownership and borrowed (playedBy) |
| 41 | const score = result.scores.find( |
| 42 | (s) => s.userKey === userKey || (s as any).playedBy === userKey |
| 43 | ); |
| 44 | |
| 45 | if (!score) return void replyAndDelete(interaction, `❌ No score submitted for **${userKey}** in the **${slot}:00** TG.`, true); |
| 46 | |
| 47 | const scoreEmoji = getEmoji("score") || "📊"; |
| 48 | const kdEmoji = getEmoji("kd") || "⚔️"; |
| 49 | const playedBy = (score as any).playedBy && (score as any).playedBy !== score.userKey |
| 50 | ? `\n*(played by ${(score as any).playedBy})*` |
| 51 | : ""; |
| 52 | |
| 53 | const lines = [ |
| 54 | `**${score.characterName}** (${score.class} · ${score.nation})${playedBy}`, |
| 55 | `${scoreEmoji} **${score.pts}** pts`, |
| 56 | score.atk !== undefined ? `ATK: ${score.atk}` : null, |
| 57 | score.def !== undefined ? `DEF: ${score.def}` : null, |
| 58 | score.heal !== undefined ? `HEAL: ${score.heal}` : null, |
| 59 | `*Submitted at ${new Date(score.submittedAt).toLocaleTimeString("en-GB", { timeZone: process.env.TZ ?? "Etc/GMT-2" })}*`, |
| 60 | ].filter(Boolean).join("\n"); |
| 61 | |
| 62 | return void replyAndDelete(interaction, lines, true); |
| 63 | } |