import { type ButtonInteraction, type ChatInputCommandInteraction, type Client, type GuildMember, SlashCommandBuilder, } from "discord.js"; import config from "@/config"; import { isApiErrorV2, roblox } from "@/roblox/client"; import { constructBansContainer, constructBansSummaryContainer, constructUserContainer, } from "@/roblox/profile"; import type { RobloxUserId } from "@/roblox/types"; import { hasManagerPermissions } from "@/utils/discord/permissions"; const commandData = new SlashCommandBuilder() .setName("ban-history") .setDescription( `Get a user's ban history in the selected ${config.terminology}`, ) // .addSubcommand((subcommand) => // subcommand // .setName("discord") // .setDescription("Use Bloxlink to get Roblox info from a Discord user") // .addUserOption((option) => // option // .setName("user") // .setDescription("The Discord user to look up") // .setRequired(true), // ) // .addStringOption((option) => // option // .setName(config.terminology) // .setDescription(`The ${config.terminology} to filter by (optional)`) // .addChoices( // ...Object.values(config.projects).map((project) => ({ // name: project.displayName, // value: project.name, // })), // ) // .setRequired(true), // ), // ) .addSubcommand((subcommand) => subcommand .setName("roblox") .setDescription("Get Roblox info from a user ID or username") .addStringOption((option) => option .setName("input") .setDescription( "The Roblox username to lookup - prefix with id: for IDs", ) .setRequired(true), ) .addStringOption((option) => option .setName(config.terminology) .setDescription(`The ${config.terminology} to filter by (optional)`) .addChoices( ...Object.entries(config.projects).map(([projectKey, project]) => ({ name: project.displayName, value: projectKey, })), ) .setRequired(true), ), ); async function execute( _client: Client, interaction: ChatInputCommandInteraction, ) { const subcommand = interaction.options.getSubcommand(); const projectKey = interaction.options.getString( config.terminology, true, ) as keyof typeof config.projects; const project = config.projects[projectKey]; const universeId = project.universe; const isModerator = await hasManagerPermissions( interaction.member as GuildMember, ); await interaction.deferReply(); try { let id: RobloxUserId; if (subcommand === "discord") { const target = interaction.options.getUser("user", true); const [linkedRes, linkedErr] = await roblox.getLinkedAccount(target.id); if (linkedErr) { const message = linkedErr.error; if (message === "User not found") { await interaction.editReply( "No linked Roblox account found for that user.", ); return; } await interaction.editReply( `There was an error fetching the linked account: ${linkedErr.error}`, ); return; } id = linkedRes.robloxID; } else { const input = interaction.options.getString("input", true); const isId = input.startsWith("id:"); if (isId) { id = input.slice(3); if (!id) { await interaction.editReply("Invalid ID provided."); return; } } else { const [usersRes] = await roblox.getUsersByUsernames([input]); if (!usersRes || !usersRes.data || usersRes.data.length === 0) { await interaction.editReply("User not found"); return; } id = usersRes.data[0].id; } } await interaction.editReply(`Fetching user with ID ${id}...`); const [user, userErr] = await roblox.getUser(id); if (userErr) { if (isApiErrorV2(userErr)) { await interaction.editReply( `There was an error fetching the user: ${userErr.message}`, ); } else { await interaction.editReply("There was an error fetching the user."); } return; } await interaction.editReply( `Found user with username ${user.name}, fetching thumbnail...`, ); const [thumbnailRes] = await roblox.getThumbnail(id, { shape: "SQUARE" }); const thumbnailUri = thumbnailRes ? thumbnailRes.response?.imageUri : null; const randomMessages = [ "grok is this true", "<:swagong:1176858666452922469>", "awawawawawawawawawawwaawawawwa", "<:wawa:1158423817698430977>", "<:max:1476776753845370991>", "<:snickerdoodle:1477173429575749716>", ]; const message = randomMessages[Math.floor(Math.random() * randomMessages.length)]; await interaction.editReply(message); const { mainContainer } = await constructUserContainer(user, { thumbnailUri, }); const [bansRes] = await roblox.getUserRestrictionLogs(universeId, id); const bans = bansRes ?? null; const { container: bansContainer } = await constructBansContainer(bans, { showPrivate: isModerator, }); await interaction.editReply(user.id); await interaction.followUp({ flags: ["IsComponentsV2"], components: [mainContainer, bansContainer], }); } catch (err) { console.error(err); await interaction.editReply( "An unexpected error occurred while fetching the user.", ); } } async function buttonExecute(_client: Client, interaction: ButtonInteraction) { const [, action, userId] = interaction.customId.split(":"); const isModerator = await hasManagerPermissions( interaction.member as GuildMember, ); const { container } = await constructBansSummaryContainer(userId, { showPrivate: isModerator, }); await interaction.reply({ components: [container], flags: ["IsComponentsV2"], }); } export default { data: commandData, buttonExecute, execute, };