From 8bcdddccae184ae2ed82c284337dea395b591ee2 Mon Sep 17 00:00:00 2001 From: Ryan Cao <70191398+ryanccn@users.noreply.github.com> Date: Fri, 16 Sep 2022 22:48:07 +0800 Subject: [PATCH] feat: add role menu --- src/_reupload.ts | 5 ++ src/commands/rolemenu.ts | 22 +++++++ src/index.ts | 130 +++++++++++++++++++++++++++++++-------- 3 files changed, 131 insertions(+), 26 deletions(-) create mode 100644 src/commands/rolemenu.ts diff --git a/src/_reupload.ts b/src/_reupload.ts index c7b5ed6..682bd16 100644 --- a/src/_reupload.ts +++ b/src/_reupload.ts @@ -51,6 +51,11 @@ export const reuploadCommands = async () => { ) .setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers) .setDMPermission(false), + new SlashCommandBuilder() + .setName('rolemenu') + .setDescription('Make a role menu') + .setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers) + .setDMPermission(false), new SlashCommandBuilder().setName('joke').setDescription("it's a joke"), ].map((command) => command.toJSON()); diff --git a/src/commands/rolemenu.ts b/src/commands/rolemenu.ts new file mode 100644 index 0000000..09f4b52 --- /dev/null +++ b/src/commands/rolemenu.ts @@ -0,0 +1,22 @@ +import { + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + CacheType, + ChatInputCommandInteraction, +} from 'discord.js'; + +export const roleMenuCommand = async ( + i: ChatInputCommandInteraction +) => { + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setCustomId('showRoleMenu') + .setLabel('Show role menu') + .setStyle(ButtonStyle.Primary) + ); + + await i.channel?.send({ content: '**Role menu**', components: [row] }); + + await i.reply({ content: 'Done!', ephemeral: true }); +}; diff --git a/src/index.ts b/src/index.ts index bfe78a6..049dc5f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,9 @@ import { Partials, OAuth2Scopes, InteractionType, + SelectMenuBuilder, + ActionRowBuilder, + GuildMemberRoleManager, } from 'discord.js'; import { reuploadCommands } from './_reupload'; @@ -20,6 +23,7 @@ import { jokeCommand } from './commands/joke'; import random from 'just-random'; import { green, bold, yellow } from 'kleur/colors'; import 'dotenv/config'; +import { roleMenuCommand } from './commands/rolemenu'; const client = new Client({ intents: [ @@ -35,6 +39,14 @@ const client = new Client({ partials: [Partials.Channel], }); +const allowedRoles = [ + 'Alert', + 'Events', + 'Progress', + 'Lenny is very special and thinks the UK needs a role', + 'Roly Poly Cult', +]; + client.once('ready', async () => { console.log(green('Discord bot ready!')); @@ -91,35 +103,101 @@ client.once('ready', async () => { }); client.on('interactionCreate', async (interaction) => { - if (!interaction.isChatInputCommand()) return; + if (interaction.isChatInputCommand()) { + const { commandName } = interaction; - const { commandName } = interaction; + if (commandName === 'ping') { + await interaction.reply({ + content: `Pong! \`${client.ws.ping}ms\``, + ephemeral: true, + }); + } else if (commandName === 'members') { + await membersCommand(interaction); + } else if (commandName === 'stars') { + await starsCommand(interaction); + } else if (commandName === 'modrinth') { + await modrinthCommand(interaction); + } else if (commandName === 'rolypoly') { + await interaction.reply( + 'https://media.discordapp.net/attachments/985048903126769764/985051373886382100/rollin-time.gif?width=324&height=216' + ); + } else if (commandName === 'say') { + if (!interaction.channel) return; - if (commandName === 'ping') { - await interaction.reply({ - content: `Pong! \`${client.ws.ping}ms\``, - ephemeral: true, - }); - } else if (commandName === 'members') { - await membersCommand(interaction); - } else if (commandName === 'stars') { - await starsCommand(interaction); - } else if (commandName === 'modrinth') { - await modrinthCommand(interaction); - } else if (commandName === 'rolypoly') { - await interaction.reply( - 'https://media.discordapp.net/attachments/985048903126769764/985051373886382100/rollin-time.gif?width=324&height=216' - ); - } else if (commandName === 'say') { - if (!interaction.channel) return; + await interaction.deferReply({ ephemeral: true }); + await interaction.channel.send(interaction.options.getString('content')!); + await interaction.editReply('I said what you said!'); + } else if (commandName === 'tag') { + await tagsCommand(interaction); + } else if (commandName === 'joke') { + await jokeCommand(interaction); + } else if (commandName === 'rolemenu') { + await roleMenuCommand(interaction); + } + } else if (interaction.isButton()) { + if (interaction.customId === 'showRoleMenu') { + if (!interaction.guild || !interaction.member) return; - await interaction.deferReply({ ephemeral: true }); - await interaction.channel.send(interaction.options.getString('content')!); - await interaction.editReply('I said what you said!'); - } else if (commandName === 'tag') { - await tagsCommand(interaction); - } else if (commandName === 'joke') { - await jokeCommand(interaction); + const roles = await interaction.guild.roles + .fetch() + .then((a) => a.filter((b) => allowedRoles.includes(b.name))); + + const row = new ActionRowBuilder().addComponents( + new SelectMenuBuilder() + .setCustomId('roleMenuSelect') + .setPlaceholder('Nothing selected') + .addOptions( + roles.map((role) => ({ + label: role.name, + value: role.id, + default: ( + interaction.member!.roles as GuildMemberRoleManager + ).cache.has(role.id), + })) + ) + .setMaxValues(roles.toJSON().length) + .setMinValues(0) + ); + + await interaction.reply({ + content: 'Select your roles here.', + components: [row], + ephemeral: true, + }); + } + } else if (interaction.isSelectMenu()) { + if (interaction.customId === 'roleMenuSelect') { + if (!interaction.guild || !interaction.member) return; + + await interaction.deferReply({ ephemeral: true }); + + const selectedRoles = interaction.values; + + const roleManager = interaction.member.roles as GuildMemberRoleManager; + + for (const role of allowedRoles) { + const roleID = interaction.guild.roles.cache + .find((a) => a.name === role) + ?.id.toString(); + + if (!roleID) continue; + + if (roleManager.cache.has(roleID) && !selectedRoles.includes(roleID)) { + await roleManager.remove(roleID); + } + if (!roleManager.cache.has(roleID) && selectedRoles.includes(roleID)) { + await roleManager.add(roleID); + } + } + + await interaction.editReply({ + content: 'Roles updated.', + }); + + setTimeout(() => { + interaction.deleteReply(); + }, 3000); + } } });