import { GuildMember, Message, MessageActionRow, MessageSelectMenu } from "discord.js"; import { defineCommand, type ICommandInteraction } from "../../lib/util/valeriyya.types"; import { ValeriyyaEmbed } from "../../lib/util/valeriyya.embed"; export default defineCommand({ data: { name: "settings", description: "Changes the settings in this guild." }, execute: async (int: ICommandInteraction) => { await int.deferReply({ ephemeral: true }); const member = int.member; const db = await int.client.db(int.guild!); if (!(member instanceof GuildMember)) return; if (!member.permissions.has("MANAGE_GUILD", true)) return { embeds: [ new ValeriyyaEmbed(undefined, "error") .setAuthor(`${int.user.tag} (${int.user.id})`, int.user.displayAvatarURL({ dynamic: true })) .setDescription("You are missing the `MANAGE_GUILD` permission") ] } let row = new MessageActionRow() let settingsMenu = new MessageSelectMenu() .setCustomId("settings") .setPlaceholder("Select what setting to change.") .addOptions( { value: "staff", description: "Choose a staff role.", label: "staff" }, { value: "mute", description: "Choose a mute role.", label: "mute" }, { value: "welcome", description: "Choose a welcome channel.", label: "welcome" }, { value: "logs", description: "Choose a logs channel.", label: "logs" } ) row.setComponents(settingsMenu) let channels = Array.from(int.guild!.channels.cache.filter(c => { if (member.permissions.has("ADMINISTRATOR")) return c.type === "GUILD_TEXT"; return c.type === "GUILD_TEXT" && c.permissionsFor(member, true).has("VIEW_CHANNEL"); }).values()); let start = 0; let end = 25; const channelMenus: MessageActionRow[] = []; while (end <= channels.length) { const menu = new MessageActionRow().setComponents(new MessageSelectMenu() .setCustomId(`settings.channels[${end}]`) .addOptions(channels.slice(start, end).map(c => { return { value: `channel.log.${c.id}`, label: c.name } }))) end += channels.length - end; start += 25; channelMenus.push(menu) } let rolesMenu1 = new MessageSelectMenu() .setCustomId("settings.roles.staff") .setPlaceholder("Provide a role that will be used as a staff role.") int.guild!.roles.cache.filter(r => r.id !== r.guild.id).each(r => { // TODO Divide Roles in more menus rolesMenu1.addOptions( { value: r.id, description: `Select a role to set it as a staff role.`, label: r.name } ) }) let rolesMenu2 = new MessageSelectMenu() .setCustomId("settings.roles.mute") .setPlaceholder("Provide a role that will be used as a mute role.") int.guild!.roles.cache.filter(r => r.id !== r.guild.id).each(r => { // TODO Divide Roles in more menus rolesMenu2.addOptions( { value: r.id, description: `Select a role to set it as a mute role.`, label: r.name } ) }) const settings_menu = await int.followUp({ content: `Select what role/channel to change.`, components: [row], fetchReply: true }); let menu; try { const type_collector = await (settings_menu as Message).awaitMessageComponent({ time: 30000, componentType: "SELECT_MENU" }); if (type_collector.values[0] === "welcome") { menu = await type_collector.update({ content: `Select a ${type_collector.values[0]} channel`, components: channelMenus, fetchReply: true }) } else if (type_collector.values[0] === "logs") { menu = await type_collector.update({ content: `Select a ${type_collector.values[0]} channel`, components: channelMenus, fetchReply: true }) } if (type_collector.values[0] === "staff") { menu = await type_collector.update({ content: `Select a ${type_collector.values[0]} role.`, components: [row.setComponents(rolesMenu1)], fetchReply: true }) } else if (type_collector.values[0] === "mute") { menu = await type_collector.update({ content: `Select a ${type_collector.values[0]} role.`, components: [row.setComponents(rolesMenu2)], fetchReply: true }) } } catch (e: any) { int.client.logger.error`The type collector has failed ${e.message}` int.editReply({ content: `Selection has been canceled. ${e.stack}`, components: [] }) } try { const collector = await (menu as Message).awaitMessageComponent({ time: 30000, componentType: "SELECT_MENU" }) if (collector.values[0].startsWith(`role.staff`)) { const id = collector.values[0].slice(`role.staff.`.length); db.roles.staff = id; db.save(); collector.update({ content: `The staff role has been updated to ${int.guild!.roles.resolve(id)}`, components: [] }) } else if (collector.values[0].startsWith(`channel.log`)) { const id = collector.values[0].slice(`channel.log.`.length); db.channels.logs = id; db.save(); collector.update({ content: `The logs channel has been updated to ${int.guild!.channels.resolve(id)}`, components: [] }) } else if (collector.values[0].startsWith(`role.mute`)) { const id = collector.values[0].slice(`role.mute.`.length); db.roles.mute = id; db.save(); collector.update({ content: `The mute role has been updated to ${int.guild!.roles.resolve(id)}`, components: [] }) } else if (collector.values[0].startsWith(`channel.welcome`)) { const id = collector.values[0].slice(`channel.welcome.`.length); db.channels.welcome = id; db.save(); collector.update({ content: `The welcome channel has been updated to ${int.guild!.channels.resolve(id)}`, components: [] }) } } catch (e: any) { int.client.logger.error`The role | channel collector has failed ${e.message}` int.editReply({ content: `Selection has been canceled. ${e.stack}`, components: [] }) } return; } })