Naposledy aktivní 1 month ago

nuno revidoval tento gist 1 month ago. Přejít na revizi

1 file changed, 226 insertions

tgAdmin.ts(vytvořil soubor)

@@ -0,0 +1,226 @@
1 + import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
2 + import {
3 + handleAdminUserMap,
4 + handleAdminPollFixVoter,
5 + handleAdminPollShowEntry,
6 + } from "@subcommands/admin/userMap";
7 +
8 + import { UpdatesCommands } from "@subcommands/admin/updates";
9 + import { ScoreInjectCommands } from "@subcommands/admin/score-inject";
10 + import { ResultCommands } from "@subcommands/admin/result-post";
11 + import { TestAlignCommands } from "@subcommands/admin/test-align";
12 + import { ResetWeekCommands } from "../subcommands/admin/reset-week";
13 + import { AnnouncementCommands } from "../subcommands/admin/announcement";
14 +
15 + export function buildTgAdminCommand(): SlashCommandBuilder {
16 + const cmd = new SlashCommandBuilder()
17 + .setName("tg-admin")
18 + .setDescription("Administrative commands for TG bot management");
19 +
20 + // ── user group ────────────────────────────────────────────────────────────────
21 + cmd.addSubcommandGroup((g) => g
22 + .setName("user")
23 + .setDescription("Manage player registrations")
24 + .addSubcommand((s) => s
25 + .setName("map")
26 + .setDescription("Register a Discord user to a userKey")
27 + .addUserOption((o) => o
28 + .setName("user")
29 + .setDescription("Discord user to map")
30 + .setRequired(true)
31 + )
32 + .addStringOption((o) => o
33 + .setName("userkey")
34 + .setDescription("The userKey to map this player to (must exist in characters.json)")
35 + .setRequired(true)
36 + .setAutocomplete(true)
37 + )
38 + )
39 + .addSubcommand((s) => s
40 + .setName("unmap")
41 + .setDescription("Remove a player's registration")
42 + .addUserOption((o) => o
43 + .setName("user")
44 + .setDescription("Discord user to unmap")
45 + .setRequired(true)
46 + )
47 + )
48 + .addSubcommand((s) => s
49 + .setName("list")
50 + .setDescription("List all registered player mappings")
51 + )
52 + );
53 +
54 + // ── poll group ─────────────────────────────────────────────────────────────────
55 + cmd.addSubcommandGroup((g) => g
56 + .setName("poll")
57 + .setDescription("Manage active poll entries")
58 + .addSubcommand((s) => s
59 + .setName("fix-voter")
60 + .setDescription("Re-resolve a voter's character in the active poll")
61 + .addUserOption((o) => o
62 + .setName("user")
63 + .setDescription("Discord user whose entry needs fixing")
64 + .setRequired(true)
65 + )
66 + )
67 + .addSubcommand((s) => s
68 + .setName("show-entry")
69 + .setDescription("Show raw poll entry for a user")
70 + .addUserOption((o) => o
71 + .setName("user")
72 + .setDescription("Discord user to inspect")
73 + .setRequired(true)
74 + )
75 + )
76 + );
77 +
78 + cmd.addSubcommandGroup((g) => g
79 + .setName("updates")
80 + .setDescription("Manage update posts")
81 + .addSubcommand((s) => s
82 + .setName("post")
83 + .setDescription("Post or edit an update embed")
84 + .addStringOption((o) => o
85 + .setName("version")
86 + .setDescription("Version to post (defaults to latest)")
87 + .setRequired(false)
88 + .setAutocomplete(true)
89 + )
90 + )
91 + .addSubcommand((s) => s
92 + .setName("preview")
93 + .setDescription("Preview an update embed (ephemeral)")
94 + .addStringOption((o) => o
95 + .setName("version")
96 + .setDescription("Version to preview (defaults to latest)")
97 + .setRequired(false)
98 + .setAutocomplete(true)
99 + )
100 + )
101 + .addSubcommand((s) => s
102 + .setName("list")
103 + .setDescription("List all versions and their post status")
104 + )
105 + )
106 +
107 + // ── result group ─────────────────────────────────────────────────────────────────
108 +
109 + cmd.addSubcommandGroup((g) => g
110 + .setName("result")
111 + .setDescription("Manage TG results")
112 + .addSubcommand((s) => s
113 + .setName("post")
114 + .setDescription("Post or edit a TG result")
115 + .addStringOption((o) => o.setName("history_key").setDescription("TG to post").setRequired(true).setAutocomplete(true))
116 + )
117 + )
118 +
119 + // ── leaderboard group ─────────────────────────────────────────────────────────────────
120 +
121 + cmd.addSubcommandGroup((g) => g
122 + .setName("leaderboard")
123 + .setDescription("Manage leaderboard")
124 + .addSubcommand((s) => s
125 + .setName("post")
126 + .setDescription("Post or edit the leaderboard")
127 + .addStringOption((o) => o.setName("week_key").setDescription("Week e.g. 2026-W24 (defaults current)").setAutocomplete(true))
128 + )
129 + .addSubcommand((s) => s
130 + .setName("post-highlights")
131 + .setDescription("Post or edit the leaderboard highlights")
132 + .addStringOption((o) => o.setName("week_key").setDescription("Week e.g. 2026-W24 (defaults current)").setAutocomplete(true))
133 + )
134 + )
135 +
136 + cmd.addSubcommand((s) => s
137 + .setName("score-inject")
138 + .setDescription("Inject a score for any player (officer only)")
139 + .addStringOption((o) => o.setName("char_name").setDescription("Character").setRequired(true).setAutocomplete(true))
140 + .addIntegerOption((o) => o.setName("pts").setDescription("Points").setRequired(true))
141 + .addIntegerOption((o) => o.setName("slot").setDescription("TG slot hour").setRequired(true))
142 + .addStringOption((o) => o.setName("date").setDescription("Date YYYY-MM-DD (defaults today)"))
143 + .addIntegerOption((o) => o.setName("k").setDescription("Kills"))
144 + .addIntegerOption((o) => o.setName("d").setDescription("Deaths"))
145 + .addIntegerOption((o) => o.setName("atk").setDescription("ATK damage"))
146 + .addIntegerOption((o) => o.setName("def").setDescription("DEF damage taken"))
147 + .addIntegerOption((o) => o.setName("heal").setDescription("Healing done"))
148 + .addStringOption((o) => o
149 + .setName("played_by")
150 + .setDescription("Userkey of who actually played (if different from character owner)")
151 + )
152 + )
153 +
154 + cmd.addSubcommand((s) => s
155 + .setName("test-align")
156 + .setDescription("[TEMP] Test embed text alignment calibration")
157 + .addStringOption((o) => o.setName("name_a").setDescription("First name").setRequired(true))
158 + .addStringOption((o) => o.setName("name_b").setDescription("Second name").setRequired(true))
159 + .addIntegerOption((o) => o.setName("fillers").setDescription("Filler count to add to name_a").setRequired(true))
160 + .addStringOption((o) => o
161 + .setName("filler_type")
162 + .setDescription("Which invisible character to use")
163 + .addChoices(
164 + { name: "Hangul Filler", value: "hangul" },
165 + { name: "Thin Space", value: "thin" },
166 + { name: "Hair Space", value: "hair" },
167 + )
168 + )
169 + )
170 +
171 + cmd.addSubcommandGroup((g) => g
172 + .setName("announcement")
173 + .setDescription("Manage announcements")
174 + .addSubcommand((s) => s
175 + .setName("post")
176 + .setDescription("Post an announcement")
177 + .addStringOption((o) => o.setName("id").setDescription("Announcement ID").setRequired(true).setAutocomplete(true))
178 + .addBooleanOption((o) => o.setName("force").setDescription("Repost even if already posted"))
179 + )
180 + .addSubcommand((s) => s
181 + .setName("preview")
182 + .setDescription("Preview an announcement")
183 + .addStringOption((o) => o.setName("id").setDescription("Announcement ID").setRequired(true).setAutocomplete(true))
184 + )
185 + .addSubcommand((s) => s
186 + .setName("list")
187 + .setDescription("List all announcements")
188 + )
189 + )
190 +
191 + return cmd;
192 + }
193 +
194 + export async function handleTgAdminCommand(interaction: ChatInputCommandInteraction): Promise<void> {
195 + const group = interaction.options.getSubcommandGroup(false);
196 + const sub = interaction.options.getSubcommand();
197 +
198 + if (group === "user") {
199 + if (sub === "map" || sub === "unmap" || sub === "list") {
200 + return handleAdminUserMap(interaction);
201 + }
202 + }
203 +
204 + if (group === "poll") {
205 + if (sub === "fix-voter") return handleAdminPollFixVoter(interaction);
206 + if (sub === "show-entry") return handleAdminPollShowEntry(interaction);
207 + }
208 +
209 + if (group === "updates") {
210 + if (sub === "post") return UpdatesCommands.post(interaction);
211 + if (sub === "preview") return UpdatesCommands.preview(interaction);
212 + if (sub === "list") return UpdatesCommands.list(interaction);
213 + }
214 +
215 + if (group === null && sub === "score-inject") return ScoreInjectCommands.inject(interaction);
216 + if (group === "result" && sub === "post") return ResultCommands.post(interaction);
217 + if (group === "leaderboard" && sub === "post") return ResultCommands.leaderboardPost(interaction);
218 + if (group === "leaderboard" && sub === "post-highlights") return ResultCommands.leaderboardHighlights(interaction);
219 +
220 + if (group === "announcement" && sub === "post") return AnnouncementCommands.post(interaction);
221 + if (group === "announcement" && sub === "preview") return AnnouncementCommands.preview(interaction);
222 + if (group === "announcement" && sub === "list") return AnnouncementCommands.list(interaction);
223 +
224 + if (group === null && sub === "test-align") return TestAlignCommands.handle(interaction);
225 + if (group === null && sub === "reset-week") return ResetWeekCommands.handle(interaction);
226 + }
Novější Starší