import { ChatInputCommandInteraction, ButtonInteraction, ButtonBuilder, ButtonStyle, ActionRowBuilder, EmbedBuilder, } from "discord.js"; import { cfg } from "@systems/config"; import { hasOfficerRole } from "@systems/users"; import { getRegisteredUsers, setImpersonation, clearImpersonation, getImpersonation } from "@systems/impersonate"; import { replyAndDelete } from "@utils"; const PAGE_SIZE = 5; // users per page (1 button each + nav row) function buildImpersonateEmbed(users: { userKey: string; aliases: string[] }[], page: number, currentImpersonation: string | null): EmbedBuilder { const start = page * PAGE_SIZE; const pageUsers = users.slice(start, start + PAGE_SIZE); const lines = pageUsers.map((u, i) => { const display = u.aliases[0] ?? u.userKey; const current = u.userKey === currentImpersonation ? " ← *active*" : ""; return `${start + i + 1}. **${display}** (${u.userKey})${current}`; }); return new EmbedBuilder() .setTitle("🎭 Impersonate User") .setDescription( (currentImpersonation ? `Currently impersonating: **${currentImpersonation}**\n\n` : "Not impersonating anyone.\n\n") + lines.join("\n") ) .setColor(0x5865f2) .setFooter({ text: `Page ${page + 1} of ${Math.ceil(users.length / PAGE_SIZE)}` }); } function buildImpersonateButtons( users: { userKey: string; aliases: string[] }[], page: number, realDiscordId: string ): ActionRowBuilder[] { const start = page * PAGE_SIZE; const pageUsers = users.slice(start, start + PAGE_SIZE); const hasNext = users.length > (page + 1) * PAGE_SIZE; const hasPrev = page > 0; const rows: ActionRowBuilder[] = []; // One button per user on this page const userButtons = pageUsers.map((u) => new ButtonBuilder() .setCustomId(`impersonate_set:${u.userKey}:${page}`) .setLabel(`${u.aliases[0] ?? u.userKey}`) .setStyle(ButtonStyle.Primary) ); if (userButtons.length > 0) { rows.push(new ActionRowBuilder().addComponents(...userButtons)); } // Nav + release row const navBtns: ButtonBuilder[] = []; if (hasPrev) navBtns.push(new ButtonBuilder().setCustomId(`impersonate_page:${page - 1}`).setLabel("← Prev").setStyle(ButtonStyle.Secondary)); if (hasNext) navBtns.push(new ButtonBuilder().setCustomId(`impersonate_page:${page + 1}`).setLabel("Next →").setStyle(ButtonStyle.Secondary)); navBtns.push(new ButtonBuilder().setCustomId(`impersonate_release:${page}`).setLabel("🚫 Release").setStyle(ButtonStyle.Danger)); rows.push(new ActionRowBuilder().addComponents(...navBtns)); return rows; } // Slash command handler export async function handleImpersonate(interaction: ChatInputCommandInteraction): Promise { const member = await interaction.guild!.members.fetch(interaction.user.id); if (!hasOfficerRole(member, cfg("officerRoles"))) { return void replyAndDelete(interaction, "❌ You don't have permission to use this command."); } const users = getRegisteredUsers(); if (users.length === 0) return void replyAndDelete(interaction, "❌ No registered users found in usermap.json."); const current = getImpersonation(interaction.user.id); const embed = buildImpersonateEmbed(users, 0, current); const buttons = buildImpersonateButtons(users, 0, interaction.user.id); await interaction.reply({ embeds: [embed], components: buttons, ephemeral: true }); } // Button handler export async function handleImpersonateButton(interaction: ButtonInteraction): Promise { const { customId } = interaction; const realId = interaction.user.id; if (customId.startsWith("impersonate_set:")) { const parts = customId.split(":"); const userKey = parts[1]; const page = parseInt(parts[2] ?? "0"); setImpersonation(realId, userKey); const users = getRegisteredUsers(); const embed = buildImpersonateEmbed(users, page, userKey); const buttons = buildImpersonateButtons(users, page, realId); await interaction.update({ embeds: [embed], components: buttons }); return; } if (customId.startsWith("impersonate_page:")) { const page = parseInt(customId.split(":")[1]); const current = getImpersonation(realId); const users = getRegisteredUsers(); const embed = buildImpersonateEmbed(users, page, current); const buttons = buildImpersonateButtons(users, page, realId); await interaction.update({ embeds: [embed], components: buttons }); return; } if (customId.startsWith("impersonate_release")) { clearImpersonation(realId); const users = getRegisteredUsers(); const embed = buildImpersonateEmbed(users, 0, null); const buttons = buildImpersonateButtons(users, 0, realId); await interaction.update({ embeds: [embed], components: buttons }); return; } }