inject.ts
· 3.2 KiB · TypeScript
Surowy
import { ChatInputCommandInteraction, TextChannel } from "discord.js";
import { cfg } from "../../systems/config";
import { polls, updatePollMessage } from "../../systems/poll";
import { getActiveCharacter } from "../../systems/characters";
import { resolveNation } from "../../systems/nations";
import { nowFormatted, resolveMessage } from "../../systems/messages";
import { replyAndDelete } from "../../utils";
import { VoteEntry } from "../../types";
export async function handleInject(interaction: ChatInputCommandInteraction): Promise<void> {
const usermapKey = interaction.options.getString("name", true);
const voteType = interaction.options.getString("vote_type", true) as "yes" | "no";
console.log("[inject] called");
const slot = [...polls.keys()][0];
console.log("[inject] slot:", slot);
if (slot === undefined) return void replyAndDelete(interaction, "❌ No active poll found.");
const state = polls.get(slot)!;
if (state.locked || state.confirmed !== null) {
return void replyAndDelete(interaction, "❌ Poll is locked or confirmed.");
}
const char = getActiveCharacter(usermapKey);
console.log(`[DEBUG inject] usermapKey=${usermapKey} char=${JSON.stringify(char)}`);
if (!char) return void replyAndDelete(interaction, `❌ No active character found for **${usermapKey}**.`);
// Use a synthetic userId based on usermapKey to avoid collisions
const syntheticId = `injected:${usermapKey}`;
const now = nowFormatted();
const publicMsg = resolveMessage("public", voteType, 1, usermapKey, null, null);
const entry: VoteEntry = {
usermapKey,
displayName: char.name,
characterName: char.name,
characterClass: char.class,
characterLevel: char.level,
characterNation: char.nation,
votedAt: now,
publicMessage: publicMsg ?? undefined,
};
if (voteType === "yes") {
state.no.delete(syntheticId);
state.yes.set(syntheticId, entry);
} else {
state.yes.delete(syntheticId);
state.no.set(syntheticId, entry);
}
const channel = await interaction.client.channels.fetch(cfg("pollChannelId")) as TextChannel;
await updatePollMessage(channel, slot);
return void replyAndDelete(interaction, `✅ Injected **${usermapKey}** as **${voteType}**.`);
}
export async function handleRemoveVote(interaction: ChatInputCommandInteraction): Promise<void> {
const usermapKey = interaction.options.getString("name", true);
const slot = [...polls.keys()][0];
if (slot === undefined) return void replyAndDelete(interaction, "❌ No active poll found.");
const state = polls.get(slot)!;
const syntheticId = `injected:${usermapKey}`;
// Also try removing real votes by scanning for usermapKey
let removed = false;
for (const [id, entry] of [...state.yes.entries(), ...state.no.entries()]) {
if (entry.usermapKey === usermapKey || id === syntheticId) {
state.yes.delete(id);
state.no.delete(id);
removed = true;
}
}
if (!removed) return void replyAndDelete(interaction, `❌ No vote found for **${usermapKey}**.`);
const channel = await interaction.client.channels.fetch(cfg("pollChannelId")) as TextChannel;
await updatePollMessage(channel, slot);
return void replyAndDelete(interaction, `✅ Vote removed for **${usermapKey}**.`);
}
| 1 | import { ChatInputCommandInteraction, TextChannel } from "discord.js"; |
| 2 | import { cfg } from "../../systems/config"; |
| 3 | import { polls, updatePollMessage } from "../../systems/poll"; |
| 4 | import { getActiveCharacter } from "../../systems/characters"; |
| 5 | import { resolveNation } from "../../systems/nations"; |
| 6 | import { nowFormatted, resolveMessage } from "../../systems/messages"; |
| 7 | import { replyAndDelete } from "../../utils"; |
| 8 | import { VoteEntry } from "../../types"; |
| 9 | |
| 10 | export async function handleInject(interaction: ChatInputCommandInteraction): Promise<void> { |
| 11 | const usermapKey = interaction.options.getString("name", true); |
| 12 | const voteType = interaction.options.getString("vote_type", true) as "yes" | "no"; |
| 13 | |
| 14 | console.log("[inject] called"); |
| 15 | const slot = [...polls.keys()][0]; |
| 16 | console.log("[inject] slot:", slot); |
| 17 | if (slot === undefined) return void replyAndDelete(interaction, "❌ No active poll found."); |
| 18 | |
| 19 | const state = polls.get(slot)!; |
| 20 | if (state.locked || state.confirmed !== null) { |
| 21 | return void replyAndDelete(interaction, "❌ Poll is locked or confirmed."); |
| 22 | } |
| 23 | |
| 24 | const char = getActiveCharacter(usermapKey); |
| 25 | console.log(`[DEBUG inject] usermapKey=${usermapKey} char=${JSON.stringify(char)}`); |
| 26 | if (!char) return void replyAndDelete(interaction, `❌ No active character found for **${usermapKey}**.`); |
| 27 | |
| 28 | // Use a synthetic userId based on usermapKey to avoid collisions |
| 29 | const syntheticId = `injected:${usermapKey}`; |
| 30 | const now = nowFormatted(); |
| 31 | |
| 32 | const publicMsg = resolveMessage("public", voteType, 1, usermapKey, null, null); |
| 33 | |
| 34 | const entry: VoteEntry = { |
| 35 | usermapKey, |
| 36 | displayName: char.name, |
| 37 | characterName: char.name, |
| 38 | characterClass: char.class, |
| 39 | characterLevel: char.level, |
| 40 | characterNation: char.nation, |
| 41 | votedAt: now, |
| 42 | publicMessage: publicMsg ?? undefined, |
| 43 | }; |
| 44 | |
| 45 | if (voteType === "yes") { |
| 46 | state.no.delete(syntheticId); |
| 47 | state.yes.set(syntheticId, entry); |
| 48 | } else { |
| 49 | state.yes.delete(syntheticId); |
| 50 | state.no.set(syntheticId, entry); |
| 51 | } |
| 52 | |
| 53 | const channel = await interaction.client.channels.fetch(cfg("pollChannelId")) as TextChannel; |
| 54 | await updatePollMessage(channel, slot); |
| 55 | return void replyAndDelete(interaction, `✅ Injected **${usermapKey}** as **${voteType}**.`); |
| 56 | } |
| 57 | |
| 58 | export async function handleRemoveVote(interaction: ChatInputCommandInteraction): Promise<void> { |
| 59 | const usermapKey = interaction.options.getString("name", true); |
| 60 | |
| 61 | const slot = [...polls.keys()][0]; |
| 62 | if (slot === undefined) return void replyAndDelete(interaction, "❌ No active poll found."); |
| 63 | |
| 64 | const state = polls.get(slot)!; |
| 65 | const syntheticId = `injected:${usermapKey}`; |
| 66 | |
| 67 | // Also try removing real votes by scanning for usermapKey |
| 68 | let removed = false; |
| 69 | for (const [id, entry] of [...state.yes.entries(), ...state.no.entries()]) { |
| 70 | if (entry.usermapKey === usermapKey || id === syntheticId) { |
| 71 | state.yes.delete(id); |
| 72 | state.no.delete(id); |
| 73 | removed = true; |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | if (!removed) return void replyAndDelete(interaction, `❌ No vote found for **${usermapKey}**.`); |
| 78 | |
| 79 | const channel = await interaction.client.channels.fetch(cfg("pollChannelId")) as TextChannel; |
| 80 | await updatePollMessage(channel, slot); |
| 81 | return void replyAndDelete(interaction, `✅ Vote removed for **${usermapKey}**.`); |
| 82 | } |