import { ChatInputCommandInteraction, TextChannel } from "discord.js"; import { cfg } from "../../systems/config"; import { polls, updatePollMessage } from "../../systems/poll"; import { getEffectiveCharacter } from "../../systems/borrow"; import { nowFormatted, resolveMessage } from "../../systems/messages"; import { replyAndDelete } from "../../utils"; import { VoteEntry } from "../../types"; export async function handleInject(interaction: ChatInputCommandInteraction): Promise { const userKey = 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, borrowedFrom } = getEffectiveCharacter(userKey); console.log(`[DEBUG inject] userKey=${userKey} char=${JSON.stringify(char)} borrowedFrom=${JSON.stringify(borrowedFrom)}`); if (!char) return void replyAndDelete(interaction, `❌ No active character found for **${userKey}**.`); // Use a synthetic userId based on userKey to avoid collisions const syntheticId = `injected:${userKey}`; const now = nowFormatted(); const publicMsg = resolveMessage("public", voteType, 1, userKey, null, null); const entry: VoteEntry = { userKey, displayName: char.name, characterName: char.name, characterClass: char.class, characterLevel: char.level, characterNation: char.nation, borrowedFrom: borrowedFrom ?? undefined, 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 **${userKey}** as **${voteType}**.`); } export async function handleRemoveVote(interaction: ChatInputCommandInteraction): Promise { const userKey = 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:${userKey}`; // Also try removing real votes by scanning for userKey let removed = false; for (const [id, entry] of [...state.yes.entries(), ...state.no.entries()]) { if (entry.userKey === userKey || id === syntheticId) { state.yes.delete(id); state.no.delete(id); removed = true; } } if (!removed) return void replyAndDelete(interaction, `❌ No vote found for **${userKey}**.`); const channel = await interaction.client.channels.fetch(cfg("pollChannelId")) as TextChannel; await updatePollMessage(channel, slot); return void replyAndDelete(interaction, `✅ Vote removed for **${userKey}**.`); }