From 8d35faa04a500c07ba33530b63fc33d1eaeab4be Mon Sep 17 00:00:00 2001 From: Raghav Viswakumar Date: Sun, 18 Feb 2024 16:05:52 +0000 Subject: [PATCH 1/3] Updated roleAssignment.js - Removed roleAssignment.js and vibotChannels.js from ESLint + roleAssignment.js now has a slash command variant + roleAssignment.js now restarts bot listeners + roleAssignment.js had code structure modernised + botSetup.js now references roleAssignment.js --- .eslintignore | 2 - botSetup.js | 4 +- commands/roleAssignment.js | 280 +++++++++++++++++++------------------ commands/vibotChannels.js | 246 -------------------------------- 4 files changed, 145 insertions(+), 387 deletions(-) delete mode 100644 commands/vibotChannels.js diff --git a/.eslintignore b/.eslintignore index eeb3faa1..664e17c3 100644 --- a/.eslintignore +++ b/.eslintignore @@ -45,7 +45,6 @@ commands/reload.js commands/removeAlt.js commands/removePending.js commands/request.js -commands/roleAssignment.js commands/russianRoulette.js commands/script.js commands/setStatus.js @@ -66,7 +65,6 @@ commands/updateIP.js commands/verification.js commands/vetBan.js commands/vetVerification.js -commands/vibotChannels.js commands/warnRemove.js commands/warns.js jobs/runner.js diff --git a/botSetup.js b/botSetup.js index 0a522708..da0007d2 100644 --- a/botSetup.js +++ b/botSetup.js @@ -13,7 +13,7 @@ const ErrorLogger = require('./lib/logError'); // Commands const emoji = require('./commands/emoji.js'); const afkCheck = require('./commands/afkCheck.js'); -const vibotChannels = require('./commands/vibotChannels'); +const roleAssignment = require('./commands/roleAssignment.js'); const vetVerification = require('./commands/vetVerification'); const verification = require('./commands/verification'); // Specific Jobs @@ -128,8 +128,8 @@ async function setup(bot) { // initialize components (eg. modmail, verification) iterServers(bot, (bot, g) => { const db = dbSetup.getDB(g.id); - vibotChannels.update(g, bot, db).catch(er => { }); afkCheck.loadBotAfkChecks(g, bot, db); + if (bot.settings[g.id].backend.roleassignment) roleAssignment.updateRoleAssignmentListeners(g, bot).catch(er => { ErrorLogger.log(er, bot, g); }); if (bot.settings[g.id].backend.verification) verification.init(g, bot, db).catch(er => { ErrorLogger.log(er, bot, g); }); if (bot.settings[g.id].backend.vetverification) vetVerification.init(g, bot, db).catch(er => { ErrorLogger.log(er, bot, g); }); }); diff --git a/commands/roleAssignment.js b/commands/roleAssignment.js index 407008ca..1991297d 100644 --- a/commands/roleAssignment.js +++ b/commands/roleAssignment.js @@ -1,148 +1,154 @@ -const ErrorLogger = require('../lib/logError') const Discord = require('discord.js'); - -//add this to settings eventually:registered: -const reacts = require('../data/roleAssignment.json') - -module.exports = { - addInteractionButtons, - name: 'roleassignment', - args: 'send/init', - role: 'moderator', - async execute(message, args, bot, db) { - let settings = bot.settings[message.guild.id] - if (!settings || !settings.backend.roleassignment) return message.channel.send('roleassignment has been turned off in this server'); - - let guildReacts = reacts[message.guild.id] - if (!guildReacts) return message.channel.send('Reactions not setup for this guild') - - //make embed - let embed = getEmbed(guildReacts) - - //get channel - let channel = message.guild.channels.cache.get(settings.channels.roleassignment) - if (!channel) return message.channel.send('Could not find channel: ' + settings.channels.roleassignment) - - //get arg - if (args.length == 0) return message.channel.send('Inavlid arguements: ``;roleassignment ``') - switch (args[0].toLowerCase()) { - case 'send': - - let message = await channel.send({ embeds: [embed] }) - - setTimeout(async () => { - await addInteractionButtons(message, bot) - }, 1000); - - break; +const reacts = require('../data/roleAssignment.json'); +const SlashArgType = require('discord-api-types/v10').ApplicationCommandOptionType; +const { slashArg, slashChoices, slashCommandJSON } = require('../utils.js'); + +async function interactionHandler(interaction, botSettings, guildReacts) { + const embed = new Discord.EmbedBuilder() + .setColor(Discord.Colors.Green) + .setFooter({ text: interaction.guild.name, iconURL: interaction.guild.iconURL() }) + .setTimestamp(); + + switch (interaction.customId) { + case 'giveAllRoles': { + const guildReactsToAdd = guildReacts.filter(reaction => !interaction.member.roles.cache.has(botSettings.roles[reaction.role])); + const rolesToAdd = guildReactsToAdd.map(reaction => interaction.guild.roles.cache.get(botSettings.roles[reaction.role])); + await interaction.member.roles.add(rolesToAdd); + if (rolesToAdd.length == 0) embed.setDescription('You already **have** all the roles to receive pings'); + else embed.setDescription(`You now **have** the roles to receive pings for the following dungeons:\n${rolesToAdd.map((role, i) => `- ${guildReactsToAdd[i].emoji} ${guildReactsToAdd[i].name}: ${role}`).join('\n')} `); + await interaction.reply({ embeds: [embed], ephemeral: true }); + break; } - } -} - -async function addInteractionButtons(message, bot) { - if (!bot.settings[message.guild.id].backend.roleassignment) return; - let guildReacts = reacts[message.guild.id] - if (!guildReacts) return - - const giveAllRolesButton = new Discord.ButtonBuilder() - .setCustomId('giveAllRoles') - .setLabel('✅ Give All') - .setStyle(3); - const takeAllRolesButton = new Discord.ButtonBuilder() - .setCustomId('takeAllRoles') - .setLabel('❌ Take All') - .setStyle(4); - - let buttons = []; - buttons.push(giveAllRolesButton) - const actionRows = new Array; - for (let i in guildReacts) { - reaction = guildReacts[i] - const buttonToAdd = new Discord.ButtonBuilder() - .setCustomId(reaction.emojiId) - .setEmoji(reaction.emojiId) - .setStyle(Discord.ButtonStyle.Secondary); - buttons.push(buttonToAdd); - if (buttons.length >= 5) { - actionRows.push(new Discord.ActionRowBuilder().addComponents(buttons)); - buttons = []; - } - } - if (buttons.length == 5) { - actionRows.push(new Discord.ActionRowBuilder().addComponents(buttons)); - actionRows.push(new Discord.ActionRowBuilder().addComponents(takeAllRolesButton)); - } else { - buttons.push(takeAllRolesButton) - actionRows.push(new Discord.ActionRowBuilder().addComponents(buttons)); - } - - message = await message.edit({ components: actionRows }) - roleAssignmentInteractionCollector = new Discord.InteractionCollector(bot, { message: message, interactionType: Discord.InteractionType.MessageComponent, componentType: Discord.ComponentType.Button }) - roleAssignmentInteractionCollector.on('collect', (interaction) => interactionHandler(interaction, bot)) -} - -async function interactionHandler(interaction, bot) { - if (!bot.settings[interaction.guild.id].backend.roleassignment) return; - if (!interaction.isButton()) return; - - failedEmbed = new Discord.EmbedBuilder() - .setColor('#FF0000') - .setDescription(`Something went wrong, please try again or contact any Head Raid Leader+ to fix this`) - .setFooter({ text: `${interaction.customId}` }) - - settings = bot.settings[interaction.guild.id] - let guildReacts = reacts[interaction.guild.id] - if (!guildReacts) return await interaction.reply({ embeds: [failedEmbed], ephemeral: true }) - - if (interaction.customId === "giveAllRoles") { - for (let i in guildReacts) { - reaction = guildReacts[i] - role = interaction.guild.roles.cache.get(settings.roles[reaction.role]) - if (!interaction.member.roles.cache.has(role.id)) { - // The user does not have the reactable role, and therefor we will add it - interaction.member.roles.add(role) - } + case 'takeAllRoles': { + const guildReactsToRemove = guildReacts.filter(reaction => interaction.member.roles.cache.has(botSettings.roles[reaction.role])); + const rolesToRemove = guildReactsToRemove.map(reaction => interaction.guild.roles.cache.get(botSettings.roles[reaction.role])); + await interaction.member.roles.remove(rolesToRemove); + if (rolesToRemove.length == 0) embed.setDescription('You already **no longer** have any of the roles to receive pings'); + else embed.setDescription(`You now **no longer have** the roles to receive pings for the following dungeons:\n${rolesToRemove.map((role, i) => `- ${guildReactsToRemove[i].emoji} ${guildReactsToRemove[i].name}: ${role}`).join('\n')} `); + await interaction.reply({ embeds: [embed], ephemeral: true }); + break; } - await interaction.reply({ content: `You now have ${guildReacts.map(role => interaction.guild.roles.cache.get(settings.roles[role.role])).join(', ')}\nand will recieve pings for ${guildReacts.map(name => name.name).join(', ')}`, ephemeral: true }) - } - else if (interaction.customId === "takeAllRoles") { - for (let i in guildReacts) { - reaction = guildReacts[i] - role = interaction.guild.roles.cache.get(settings.roles[reaction.role]) + default: { + const guildReact = guildReacts.find(reaction => reaction.emojiId === interaction.customId); + const role = interaction.guild.roles.cache.get(botSettings.roles[guildReact.role]); if (interaction.member.roles.cache.has(role.id)) { - // The user has the reactable role, and therefor we will remove it - interaction.member.roles.remove(role) + await interaction.member.roles.remove(role); + embed.setDescription(`You now **no longer have** the role to receive pings for ${guildReact.emoji} ${guildReact.name}: ${role}`); + } else { + await interaction.member.roles.add(role); + embed.setDescription(`You now **have** the role to receive pings for ${guildReact.emoji} ${guildReact.name}: ${role}`); } + await interaction.reply({ embeds: [embed], ephemeral: true }); } - await interaction.reply({ content: `You no longer have ${guildReacts.map(role => interaction.guild.roles.cache.get(settings.roles[role.role])).join(', ')}\nand will not recieve pings for ${guildReacts.map(name => name.name).join(', ')}`, ephemeral: true }) } - else { - for (let i in guildReacts) { - reaction = guildReacts[i] - if (interaction.customId === reaction.emojiId) { - role = interaction.guild.roles.cache.get(settings.roles[reaction.role]) +} - if (interaction.member.roles.cache.has(role.id)) { - // The user has the reactable role, and therefor we will remove it - interaction.member.roles.remove(role) - await interaction.reply({ content: `You no longer have ${role} and will no longer recieve pings for ${reaction.name}`, ephemeral: true }) - } else { - // The user does not have the reactable role, and therefor we will add it - interaction.member.roles.add(role) - await interaction.reply({ content: `You now have ${role} and will recieve pings for ${reaction.name}`, ephemeral: true }) - } +module.exports = { + name: 'roleassignment', + description: 'Creates or updates role assignment', + requiredArgs: 1, + args: [ + slashArg(SlashArgType.String, 'type', { + description: 'Type of role assignment function to use', + choices: slashChoices(['Send', 'Update']) + }) + ], + role: 'moderator', + getSlashCommandData(guild) { return slashCommandJSON(this, guild); }, + /** + * @param {Discord.Message} message + * @param {string[]} args + * @param {Discord.Client} bot + */ + async execute(message, args, bot) { await this.processRoleAssignment(message, bot); }, + /** + * @param {Discord.CommandInteraction} interaction + * @param {Discord.Client} bot + */ + async slashCommandExecute(interaction, bot) { await this.processRoleAssignment(interaction, bot); }, + /** + * @param {Discord.Message | Discord.CommandInteraction} interaction + * @param {Discord.Client} bot + */ + async processRoleAssignment(interaction, bot) { + const botSettings = bot.settings[interaction.guild.id]; + if (!botSettings || !botSettings.backend.roleassignment) return interaction.reply(`Role Assignment not setup for guild ${interaction.guild.name}`); + const guildReacts = reacts[interaction.guild.id]; + if (!guildReacts) return interaction.reply(`Reactions not setup for guild ${interaction.guild.name}`); + const channel = interaction.guild.channels.cache.get(botSettings.channels.roleassignment); + if (!channel) return interaction.reply(`Role Assignment channel not setup for guild ${interaction.guild.name}`); + const type = interaction.options.getString('type'); + switch (type.toLowerCase()) { + case 'send': { + const embed = new Discord.EmbedBuilder() + .setTitle('Assign Roles') + .setColor(Discord.Colors.Blue) + .setDescription('Press the buttons with one of the following emojis to get pinged for specific runs\nCan be disabled by pressing the same button after recieving your role') + .setFooter({ text: interaction.guild.name, iconURL: interaction.guild.iconURL() }) + .setTimestamp(); + guildReacts.map(reaction => embed.addFields([{ name: reaction.name, value: reaction.emoji, inline: true }])); + const message = await channel.send({ embeds: [embed], components: this.addInteractionComponents(guildReacts) }); + const roleAssignmentInteractionCollector = new Discord.InteractionCollector(bot, { message, interactionType: Discord.InteractionType.MessageComponent, componentType: Discord.ComponentType.Button }); + roleAssignmentInteractionCollector.on('collect', (interaction) => interactionHandler(interaction, botSettings, guildReacts)); + interaction.reply(`Role Assignment message has been successfully sent ${message.url}`); + break; + } + case 'update': { + await this.updateRoleAssignmentListeners(interaction.guild, bot); + interaction.reply(`Role Assignment message has been successfully updated ${channel.url}`); + break; + } + default: { + return interaction.reply('Invalid type of role assignment function, please try again.'); } } + }, + /** + * @param {Discord.Guild} guild + * @param {Discord.Client} bot + */ + async updateRoleAssignmentListeners(guild, bot) { + const botSettings = bot.settings[guild.id]; + if (!botSettings) return; // If roleassignment is not setup for the guild it will not continue + const guildReacts = reacts[guild.id]; + if (!guildReacts) return; // If there are no reacts for the guild it will not continue + const roleAssignmentChannel = guild.channels.cache.get(botSettings.channels.roleassignment); + if (!roleAssignmentChannel) return; // If there is no roleassignment channel it will not continue + + const roleAssignmentChannelMessages = await roleAssignmentChannel.messages.fetch(); // This fetches all the messages in the roleassignment channel + roleAssignmentChannelMessages.map(async message => { // This will loop through the roleassignment channel messages + if (message.author.id !== bot.user.id) return; // If the roleassignment message author is not the same id as ViBot it will not continue with this message + if (message.embeds.length == 0) return; // If the message has no embeds it will not continue + if (message.components == 0) return; // If the message has no components it will not continue + // Anything below this code inside this function is for roleassignment messages, and we need to reset them + await message.edit({ components: this.addInteractionComponents(guildReacts) }); // This will add a roleassignment button listeners to the message + const roleAssignmentInteractionCollector = new Discord.InteractionCollector(bot, { message, interactionType: Discord.InteractionType.MessageComponent, componentType: Discord.ComponentType.Button }); + roleAssignmentInteractionCollector.on('collect', (interaction) => interactionHandler(interaction, botSettings, guildReacts)); + }); + }, + addInteractionComponents(guildReacts) { + const components = []; + + components.push(new Discord.ButtonBuilder() + .setCustomId('giveAllRoles') + .setLabel('✅ Give All') + .setStyle(Discord.ButtonStyle.Success)); + + guildReacts.map(reaction => + components.push(new Discord.ButtonBuilder() + .setCustomId(reaction.emojiId) + .setEmoji(reaction.emojiId) + .setStyle(Discord.ButtonStyle.Secondary)) + ); + + components.push(new Discord.ButtonBuilder() + .setCustomId('takeAllRoles') + .setLabel('❌ Take All') + .setStyle(Discord.ButtonStyle.Danger)); + return components.reduce((rows, btn, idx) => { + if (idx % 5 == 0) rows.push(new Discord.ActionRowBuilder()); + rows[rows.length - 1].addComponents(btn); + return rows; + }, []); } -} - -function getEmbed(guildReacts) { - let embed = new Discord.EmbedBuilder() - .setTitle('Assign Roles') - .setColor('#6fa8dc') - .setDescription('Press the buttons with one of the following emojis to get pinged for specific runs\nCan be disabled by pressing the same button after recieving your role') - for (let i of guildReacts) { - embed.addFields([{name: i.name, value: i.emoji, inline: true}]) - } - return embed -} \ No newline at end of file +}; diff --git a/commands/vibotChannels.js b/commands/vibotChannels.js deleted file mode 100644 index 33f2058c..00000000 --- a/commands/vibotChannels.js +++ /dev/null @@ -1,246 +0,0 @@ -const Discord = require('discord.js') -const fs = require('fs') -const botSettings = require('../settings.json') -const ErrorLogger = require('../lib/logError') -const vibotChannel = require('./vibotChannels.js') -const modmail = require('../lib/modmail.js') -const roleassignment = require('./roleAssignment.js') -var watchedMessages = [] -var watchedButtons = {}; //the keys for this are the id of a VC -//{VC_ID: {hndlr: ACTIVATE_CHANNEL_MESSAGE_HANDLER, -// confirm_hndlrs: EPHMRL_CONFIRMATION_MESSAGE_HANDLERS} -//} -let afkCheckModule; //if a channel is closed while the afk check is active -//we need to abort the run -//since afkCheck.js requires this module already we have -//afkCheck.js register itself here the first time someone -//uses the afk command - -module.exports = { - name: 'vibotchannels', - description: 'update', - role: 'developer', - async execute(message, args, bot, db) { - if (args[0].toLowerCase() == 'update') this.update(message.guild, bot, db) - }, - async update(guild, bot, db) { - let settings = bot.settings[guild.id] - await updateRoleAssignmentListeners(guild.channels.cache.get(settings.channels.roleassignment), settings, bot, db) - async function updateRoleAssignmentListeners(roleassignmentChannel, settings, bot, db) { - if (!settings.backend.roleassignment) return; - if (!roleassignmentChannel) { return } // If there is no roleassignment channel it will not continue - let roleassignmentChannelMessages = await roleassignmentChannel.messages.fetch() // This fetches all the messages in the roleassignment channel - roleassignmentChannelMessages.each(async message => { // This will loop through the roleassignment channel messages - if (message.author.id !== bot.user.id) return; // If the roleassignment message author is not the same id as ViBot it will not continue with this message - if (message.embeds.length == 0) return; // If the message has no embeds it will not continue - let embed = new Discord.EmbedBuilder() // This creates a empty embed, able to be edited later - embed.data = message.embeds[0].data // This will change the empty embed to have the message embed data - - /* We have a message -> check if it has no components - **EXPLANATION** roleassignment message is supposed to have components - */ - if (message.components == 0) { return } - // Anything below this code inside this function is for roleassignment messages, and we need to reset them - roleassignment.addInteractionButtons(message, bot) // This will add a roleassignment button listeners to the message - }) - } - for (let i in bot.afkChecks) { - if (!guild.channels.cache.get(i)) delete bot.afkChecks[i]; - if (watchedButtons[i] && bot.afkChecks[i].RSAMessagePacket) { - let rsa_m = await getAFKChannelMessage(bot, guild, i); - if (rsa_m) module.exports.addReconnectButton(bot, rsa_m, i); - } - } - // fs.writeFile('./data/afkChecks.json', JSON.stringify(bot.afkChecks, null, 4), err => { - // if (err) ErrorLogger.log(err, bot, guild) - // }) - }, - async watchMessage(message, bot, settings) { - let m = message - let embed = new Discord.EmbedBuilder() - embed.data = m.embeds[0].data - if (watchedMessages.includes(embed.data.footer)) return - watchedMessages.push(embed.data.footer) - let channel = message.guild.channels.cache.get(embed.data.footer.text) - if (!channel) return m.delete() - let channelName = channel.name - let reactionCollector = new Discord.ReactionCollector(m, { filter: xFilter }) - reactionCollector.on('collect', async (r, u) => { - reactionCollector.stop() - if (!m.mentions.members.first()) return remove() - if (u.id == m.mentions.members.first().id) remove() - else { - await m.reactions.removeAll() - await m.react('✅') - await m.react('❌') - embed.data.footer.text = `Opened By ${m.guild.members.cache.get(u.id).nickname || u.tag} • ${embed.data.footer.text}`; - message = m = await m.edit({ embeds: m.embeds }) - embed.data = message.embeds[0].data - let confirmReactionCollector = new Discord.ReactionCollector(m, { filter: (r, uu) => (r.emoji.name === '✅' || r.emoji.name === '❌') && u.id == uu.id }) - - confirmReactionCollector.on('collect', async (r, u) => { - if (r.emoji.name == '❌') { - await m.reactions.removeAll() - confirmReactionCollector.stop() - await m.react('❌') - m.embeds[0].footer.text = embed.data.footer.text.split(' ').pop() - message = m = await m.edit({ embeds: m.embeds }) - embed.data = message.embeds[0].data - await this.update(m.guild, bot) - } else remove() - }) - } - async function remove() { - for (let i in bot.afkChecks) { - const id = embed.data.footer.text.split(' ').pop() - if (i == id) { - let key = await message.guild.members.cache.get(bot.afkChecks[i].key) - if (key) { - let keyRole = await message.guild.roles.cache.get(settings.roles.tempkey) - await key.roles.remove(keyRole.id).catch(r => ErrorLogger.log(r, bot, message.guild)) - } - delete bot.afkChecks[i]; - fs.writeFile('./data/afkChecks.json', JSON.stringify(bot.afkChecks, null, 4), err => { - if (err) ErrorLogger.log(err, bot, message.guild) - }) - } - } - message.guild.channels.cache.get(settings.channels.history).send({ - embeds: [ - new Discord.EmbedBuilder() - .setDescription(`${channelName} deleted by <@!${u.id}>`) - ] - }) - if (!channel) return - await channel.delete().catch(er => { }) - await m.delete() - } - }) - }, - - async addModmailUnlockButton(message, settings, bot, db) { - if (message.components[0].components[0]?.customId != 'modmailUnlock') { - let components = new Discord.ActionRowBuilder() - .addComponents(new Discord.ButtonBuilder() - .setLabel('🔓 Unlock') - .setStyle(3) - .setCustomId('modmailUnlock')) - message = await message.edit({ components: [components] }) - } - }, - - async addCloseChannelButtons(bot, m, rsaMessage) { - let ar = new Discord.ActionRowBuilder() - .addComponents(new Discord.ButtonBuilder() - .setLabel('Delete Channel') - .setStyle(4) - .setCustomId('delete')) - m = await m.edit({ components: [ar] }); - let hndlr = m.createMessageComponentCollector({ componentType: Discord.ComponentType.Button }); - hndlr.on('collect', async (interaction) => closeChannelButtonsHandler(interaction, bot, rsaMessage)); - let button_manager = { hndlr: hndlr, confirm_hndlrs: [], RSAMessage: undefined, reconnect_hndlr: undefined }; - watchedButtons[m.embeds[0].footer.text] = button_manager; - }, - async registerAFKCheck(afkCheckMod) { - afkCheckModule = afkCheckMod; - }, - - async deleteChannel(bot, vc_channel_id, run_title, who_closed, guild, active_channel_msg, ephemeral_response_interaction, rsaMessage) { - watchedButtons[vc_channel_id].hndlr.stop(); - for (let i of watchedButtons[vc_channel_id].confirm_hndlrs) { - i.stop(); - } - if (watchedButtons[vc_channel_id].reconnect_hndlr) { - watchedButtons[vc_channel_id].reconnect_hndlr.stop() - } - if (watchedButtons[vc_channel_id].RSAMessage) { - watchedButtons[vc_channel_id].RSAMessage.edit({ components: [] }); - - } - await active_channel_msg.delete().then().catch(console.error); - if (ephemeral_response_interaction) { - await ephemeral_response_interaction.update({ content: `${run_title} has been deleted. Have a nice day!`, components: [] }); - } - if (rsaMessage) { rsaMessage.edit({ content: '', components: [] }) } - if (afkCheckModule) { - let active_run = await afkCheckModule.returnRunByID(vc_channel_id); - if (active_run) { - await active_run.abortAfk(who_closed); - } - } - delete (bot.afkChecks[vc_channel_id]); - fs.writeFile('./data/afkChecks.json', JSON.stringify(bot.afkChecks, null, 4), err => { - if (err) ErrorLogger.log(err, bot, message.guild) - }); - let channel = guild.channels.cache.get(vc_channel_id); - if (!channel) return - await channel.delete().catch(er => { }) - if (bot.settings[guild.id].channels.history) { - guild.channels.cache.get(bot.settings[guild.id].channels.history).send({ - embeds: [ - new Discord.EmbedBuilder() - .setDescription(`${channel.name} deleted by ${who_closed}`) - ] - }); - } - delete (watchedButtons[vc_channel_id]); - } -} - -async function getAFKChannelMessage(bot, guild, vc_channel_id) { - rsaMessageId = bot.afkChecks[vc_channel_id].RSAMessagePacket.messageId; - rsaChannelId = bot.afkChecks[vc_channel_id].RSAMessagePacket.channelId; - c = guild.channels.cache.get(rsaChannelId); - if (!c) return undefined; - return await c.messages.fetch(rsaMessageId); -} - -async function closeChannelButtonsHandler(interaction, bot, rsaMessage) { - if (!interaction.isButton()) return; - if (interaction.customId === 'delete') { - let confirm_buttons = new Discord.ActionRowBuilder().addComponents([ - new Discord.ButtonBuilder() - .setLabel('Delete Channel') - .setStyle(4) - .setCustomId('delete_confirmed'), - new Discord.ButtonBuilder() - .setLabel('Cancel') - .setStyle(2) - .setCustomId('delete_cancel') - ]) - if (bot.afkChecks[interaction.message.embeds[0].footer.text] && - bot.afkChecks[interaction.message.embeds[0].footer.text].runType && - bot.afkChecks[interaction.message.embeds[0].footer.text].runType.raidLeader === interaction.member.id) { - interaction.deferUpdate(); - module.exports.deleteChannel(bot, interaction.message.embeds[0].footer.text, interaction.message.embeds[0].title, interaction.member, interaction.guild, interaction.message, rsaMessage); - } else { - await interaction.reply({ - content: `Are you sure you want to delete <#${interaction.message.embeds[0].footer.text}>? Only do this if the run is over.`, - components: [confirm_buttons], - ephemeral: true - }); - let confirm_m = await interaction.fetchReply(); - let confirm_hndlr = confirm_m.createMessageComponentCollector({ componentType: Discord.ComponentType.Button, time: 30000 }); - confirm_hndlr.on('collect', async (new_interaction) => watchConfirmButtonsHandler(new_interaction, interaction, bot, confirm_hndlr, rsaMessage)) - watchedButtons[interaction.message.embeds[0].footer.text].confirm_hndlrs.push(confirm_hndlr); - } - } -} - -async function watchConfirmButtonsHandler(interaction, prev_interaction, bot, this_hndlr, rsaMessage) { - if (!interaction.isButton()) return; - if (interaction.customId === 'delete_confirmed') { - module.exports.deleteChannel(bot, prev_interaction.message.embeds[0].footer.text, prev_interaction.message.embeds[0].title, interaction.member, interaction.guild, prev_interaction.message, interaction, rsaMessage); - } else if (interaction.customId === 'delete_cancel') { - await interaction.update({ content: `ඞ`, components: [] }); - for (let i = 0; i < watchedButtons[prev_interaction.message.embeds[0].footer.text].confirm_hndlrs.length; i++) { - if (watchedButtons[prev_interaction.message.embeds[0].footer.text].confirm_hndlrs[i] === this_hndlr) { - this_hndlr.stop(); - watchedButtons[prev_interaction.message.embeds[0].footer.text].confirm_hndlrs.splice(i, 1); - return; - } - } - } -} - -const xFilter = (r, u) => r.emoji.name === '❌' && !u.bot From 562728a28bea1edec169d44ef2823ee6ec0da80d Mon Sep 17 00:00:00 2001 From: Raghav Viswakumar Date: Sun, 18 Feb 2024 16:47:02 +0000 Subject: [PATCH 2/3] Updated roleAssignment.js + roleAssignment.js, roleAssignment.json now references bot.storedEmojis --- commands/roleAssignment.js | 71 ++++++++--------- data/roleAssignment.json | 159 +++++++++++++------------------------ 2 files changed, 88 insertions(+), 142 deletions(-) diff --git a/commands/roleAssignment.js b/commands/roleAssignment.js index 1991297d..58880601 100644 --- a/commands/roleAssignment.js +++ b/commands/roleAssignment.js @@ -3,7 +3,31 @@ const reacts = require('../data/roleAssignment.json'); const SlashArgType = require('discord-api-types/v10').ApplicationCommandOptionType; const { slashArg, slashChoices, slashCommandJSON } = require('../utils.js'); -async function interactionHandler(interaction, botSettings, guildReacts) { +function addInteractionComponents(bot, guildReacts) { + const components = []; + components.push(new Discord.ButtonBuilder() + .setCustomId('giveAllRoles') + .setLabel('✅ Give All') + .setStyle(Discord.ButtonStyle.Success)); + guildReacts.map(reaction => + components.push(new Discord.ButtonBuilder() + .setCustomId(reaction.emote) + .setEmoji(bot.storedEmojis[reaction.emote].id) + .setStyle(Discord.ButtonStyle.Secondary)) + ); + components.push(new Discord.ButtonBuilder() + .setCustomId('takeAllRoles') + .setLabel('❌ Take All') + .setStyle(Discord.ButtonStyle.Danger)); + return components.reduce((rows, btn, idx) => { + if (idx % 5 == 0) rows.push(new Discord.ActionRowBuilder()); + rows[rows.length - 1].addComponents(btn); + return rows; + }, []); +} + +async function interactionHandler(interaction, bot, guildReacts) { + const botSettings = bot.settings[interaction.guild.id]; const embed = new Discord.EmbedBuilder() .setColor(Discord.Colors.Green) .setFooter({ text: interaction.guild.name, iconURL: interaction.guild.iconURL() }) @@ -15,7 +39,7 @@ async function interactionHandler(interaction, botSettings, guildReacts) { const rolesToAdd = guildReactsToAdd.map(reaction => interaction.guild.roles.cache.get(botSettings.roles[reaction.role])); await interaction.member.roles.add(rolesToAdd); if (rolesToAdd.length == 0) embed.setDescription('You already **have** all the roles to receive pings'); - else embed.setDescription(`You now **have** the roles to receive pings for the following dungeons:\n${rolesToAdd.map((role, i) => `- ${guildReactsToAdd[i].emoji} ${guildReactsToAdd[i].name}: ${role}`).join('\n')} `); + else embed.setDescription(`You now **have** the roles to receive pings for the following dungeons:\n${rolesToAdd.map((role, i) => `- ${bot.storedEmojis[guildReactsToAdd[i].emote].text} ${guildReactsToAdd[i].name}: ${role}`).join('\n')} `); await interaction.reply({ embeds: [embed], ephemeral: true }); break; } @@ -24,19 +48,19 @@ async function interactionHandler(interaction, botSettings, guildReacts) { const rolesToRemove = guildReactsToRemove.map(reaction => interaction.guild.roles.cache.get(botSettings.roles[reaction.role])); await interaction.member.roles.remove(rolesToRemove); if (rolesToRemove.length == 0) embed.setDescription('You already **no longer** have any of the roles to receive pings'); - else embed.setDescription(`You now **no longer have** the roles to receive pings for the following dungeons:\n${rolesToRemove.map((role, i) => `- ${guildReactsToRemove[i].emoji} ${guildReactsToRemove[i].name}: ${role}`).join('\n')} `); + else embed.setDescription(`You now **no longer have** the roles to receive pings for the following dungeons:\n${rolesToRemove.map((role, i) => `- ${bot.storedEmojis[guildReactsToRemove[i].emote].text} ${guildReactsToRemove[i].name}: ${role}`).join('\n')} `); await interaction.reply({ embeds: [embed], ephemeral: true }); break; } default: { - const guildReact = guildReacts.find(reaction => reaction.emojiId === interaction.customId); + const guildReact = guildReacts.find(reaction => reaction.emote === interaction.customId); const role = interaction.guild.roles.cache.get(botSettings.roles[guildReact.role]); if (interaction.member.roles.cache.has(role.id)) { await interaction.member.roles.remove(role); - embed.setDescription(`You now **no longer have** the role to receive pings for ${guildReact.emoji} ${guildReact.name}: ${role}`); + embed.setDescription(`You now **no longer have** the role to receive pings for ${bot.storedEmojis[guildReact.emote].text} ${guildReact.name}: ${role}`); } else { await interaction.member.roles.add(role); - embed.setDescription(`You now **have** the role to receive pings for ${guildReact.emoji} ${guildReact.name}: ${role}`); + embed.setDescription(`You now **have** the role to receive pings for ${bot.storedEmojis[guildReact.emote].text} ${guildReact.name}: ${role}`); } await interaction.reply({ embeds: [embed], ephemeral: true }); } @@ -86,10 +110,10 @@ module.exports = { .setDescription('Press the buttons with one of the following emojis to get pinged for specific runs\nCan be disabled by pressing the same button after recieving your role') .setFooter({ text: interaction.guild.name, iconURL: interaction.guild.iconURL() }) .setTimestamp(); - guildReacts.map(reaction => embed.addFields([{ name: reaction.name, value: reaction.emoji, inline: true }])); - const message = await channel.send({ embeds: [embed], components: this.addInteractionComponents(guildReacts) }); + guildReacts.map(reaction => embed.addFields([{ name: reaction.name, value: bot.storedEmojis[reaction.emote].text, inline: true }])); + const message = await channel.send({ embeds: [embed], components: addInteractionComponents(bot, guildReacts) }); const roleAssignmentInteractionCollector = new Discord.InteractionCollector(bot, { message, interactionType: Discord.InteractionType.MessageComponent, componentType: Discord.ComponentType.Button }); - roleAssignmentInteractionCollector.on('collect', (interaction) => interactionHandler(interaction, botSettings, guildReacts)); + roleAssignmentInteractionCollector.on('collect', (interaction) => interactionHandler(interaction, bot, guildReacts)); interaction.reply(`Role Assignment message has been successfully sent ${message.url}`); break; } @@ -121,34 +145,9 @@ module.exports = { if (message.embeds.length == 0) return; // If the message has no embeds it will not continue if (message.components == 0) return; // If the message has no components it will not continue // Anything below this code inside this function is for roleassignment messages, and we need to reset them - await message.edit({ components: this.addInteractionComponents(guildReacts) }); // This will add a roleassignment button listeners to the message + await message.edit({ components: addInteractionComponents(bot, guildReacts) }); // This will add a roleassignment button listeners to the message const roleAssignmentInteractionCollector = new Discord.InteractionCollector(bot, { message, interactionType: Discord.InteractionType.MessageComponent, componentType: Discord.ComponentType.Button }); - roleAssignmentInteractionCollector.on('collect', (interaction) => interactionHandler(interaction, botSettings, guildReacts)); + roleAssignmentInteractionCollector.on('collect', (interaction) => interactionHandler(interaction, bot, guildReacts)); }); - }, - addInteractionComponents(guildReacts) { - const components = []; - - components.push(new Discord.ButtonBuilder() - .setCustomId('giveAllRoles') - .setLabel('✅ Give All') - .setStyle(Discord.ButtonStyle.Success)); - - guildReacts.map(reaction => - components.push(new Discord.ButtonBuilder() - .setCustomId(reaction.emojiId) - .setEmoji(reaction.emojiId) - .setStyle(Discord.ButtonStyle.Secondary)) - ); - - components.push(new Discord.ButtonBuilder() - .setCustomId('takeAllRoles') - .setLabel('❌ Take All') - .setStyle(Discord.ButtonStyle.Danger)); - return components.reduce((rows, btn, idx) => { - if (idx % 5 == 0) rows.push(new Discord.ActionRowBuilder()); - rows[rows.length - 1].addComponents(btn); - return rows; - }, []); } }; diff --git a/data/roleAssignment.json b/data/roleAssignment.json index 5ed968a2..3d9a5580 100644 --- a/data/roleAssignment.json +++ b/data/roleAssignment.json @@ -3,328 +3,275 @@ { "role": "cultping", "name": "Cults", - "emojiId": "701491230332157972", - "emoji": "<:malus:701491230332157972>" + "emote": "cultist" }, { "role": "fameReact", "name": "Fame Runs", - "emojiId": "1024104144845406248", - "emoji": "<:fame:1024104144845406248>" + "emote": "fame" }, { "role": "voidping", "name": "Voids", - "emojiId": "701491230210523247", - "emoji": "<:void:701491230210523247>" + "emote": "void" }, { "role": "fskipReact", "name": "Full-Skip Voids", - "emojiId": "701491230391140453", - "emoji": "<:SkipBoi:701491230391140453>" + "emote": "fullskip" }, { "role": "shattsReact", "name": "Shatters", - "emojiId": "1008068892071055512", - "emoji": "<:forgottenking:1008068892071055512>" + "emote": "forgottenking" }, { "role": "accursedReact", "name": "Accursed", - "emojiId": "1142347997670289471", - "emoji": "<:accursedKing:1142347997670289471>" + "emote": "accursedKing" }, { "role": "nestReact", "name": "Nests", - "emojiId": "723001215407095899", - "emoji": "<:nest:723001215407095899>" + "emote": "nest" }, { "role": "advancedNestPing", "name": "Advanced Nests", - "emojiId": "1135560355750359050", - "emoji": "<:advancedNestPortal:1135560355750359050>" + "emote": "advancedNestPortal" }, { "role": "steamworksping", "name": "Steamworks", - "emojiId": "1050156386547413012", - "emoji": "" + "emote": "steamworksPortal" }, { "role": "advancedSteamworksPing", "name": "Advanced Steamworks", - "emojiId": "1129901525674758274", - "emoji": "<:advancedSteamworks:1129901525674758274>" + "emote": "advancedSteamworks" }, { "role": "fungalReact", "name": "Fungals", - "emojiId": "723001215696240660", - "emoji": "<:fungal:723001215696240660>" + "emote": "fungal" }, { "role": "moonlightping", "name": "Moonlight", - "emojiId": "1090163554872737866", - "emoji": "<:mv:1090163554872737866>" + "emote": "mv" }, { "role": "eventBoiPing", "name": "Miscellaneous Dungeons", - "emojiId": "723001215184535553", - "emoji": "<:pcave:723001215184535553>" + "emote": "pcave" }, { "role": "o3Ping", "name": "Oryx Sanctuary", - "emojiId": "831047591096745984", - "emoji": "<:oryxThree:831047591096745984>" + "emote": "oryxThree" } ], "708026927721480254": [ { "role": "o3Ping", "name": "Oryx 3", - "emojiId": "831047591096745984", - "emoji": "<:oryxThree:831047591096745984>" + "emote": "oryxThree" }, { "role": "rcPing", "name": "Realm Clearing", - "emojiId": "1156373714976378971", - "emoji": "<:realmClearing:1156373714976378971>" + "emote": "realmClearing" }, { "role": "cultping", "name": "Cults", - "emojiId": "701491230332157972", - "emoji": "<:malus:701491230332157972>" + "emote": "cultist" }, { "role": "voidping", "name": "Voids", - "emojiId": "701491230210523247", - "emoji": "<:void:701491230210523247>" + "emote": "void" }, { "role": "shattsReact", "name": "Shatters", - "emojiId": "1008068892071055512", - "emoji": "<:forgottenking:1008068892071055512>" + "emote": "forgottenking" }, { "role": "nestReact", "name": "Nests", - "emojiId": "723001215407095899", - "emoji": "<:nest:723001215407095899>" + "emote": "nest" }, { "role": "advancedNestPing", "name": "Advanced Nests", - "emojiId": "1135560355750359050", - "emoji": "<:advancedNestPortal:1135560355750359050>" + "emote": "advancedNestPortal" }, { "role": "steamworksping", "name": "Steamworks", - "emojiId": "1050156386547413012", - "emoji": "" + "emote": "steamworksPortal" }, { "role": "advancedSteamworksPing", "name": "Advanced Steamworks", - "emojiId": "1129901525674758274", - "emoji": "<:advancedSteamworks:1129901525674758274>" + "emote": "advancedSteamworks" }, { "role": "fungalReact", "name": "Fungals", - "emojiId": "723001215696240660", - "emoji": "<:fungal:723001215696240660>" + "emote": "fungal" }, { "role": "moonlightping", "name": "Moonlight", - "emojiId": "1090163554872737866", - "emoji": "<:mv:1090163554872737866>" + "emote": "mv" }, { "role": "eventBoiPing", "name": "Miscellaneous Dungeons", - "emojiId": "723001215184535553", - "emoji": "<:pcave:723001215184535553>" + "emote": "pcave" } ], "451171819672698920": [ { "role": "eventraider", "name": "All Events", - "emojiId": "723009084814524449", - "emoji": "<:oryx:723009084814524449>" + "emote": "oryx" } ], "934611202787643412": [ { "role": "o3Ping", "name": "Oryx 3", - "emojiId": "831047591096745984", - "emoji": "<:oryxThree:831047591096745984>" + "emote": "oryxThree" }, { "role": "rcPing", "name": "Realm Clearing", - "emojiId": "1156373714976378971", - "emoji": "<:realmClearing:1156373714976378971>" + "emote": "realmClearing" }, { "role": "cultping", "name": "Cults", - "emojiId": "701491230332157972", - "emoji": "<:malus:701491230332157972>" + "emote": "cultist" }, { "role": "voidping", "name": "Voids", - "emojiId": "701491230210523247", - "emoji": "<:void:701491230210523247>" + "emote": "void" }, { "role": "shattsReact", "name": "Shatters", - "emojiId": "1008068892071055512", - "emoji": "<:forgottenking:1008068892071055512>" + "emote": "forgottenking" }, { "role": "nestReact", "name": "Nests", - "emojiId": "723001215407095899", - "emoji": "<:nest:723001215407095899>" + "emote": "nest" }, { "role": "advancedNestPing", "name": "Advanced Nests", - "emojiId": "1135560355750359050", - "emoji": "<:advancedNestPortal:1135560355750359050>" + "emote": "advancedNestPortal" }, { "role": "steamworksping", "name": "Steamworks", - "emojiId": "1050156386547413012", - "emoji": "" + "emote": "steamworksPortal" }, { "role": "advancedSteamworksPing", "name": "Advanced Steamworks", - "emojiId": "1129901525674758274", - "emoji": "<:advancedSteamworks:1129901525674758274>" + "emote": "advancedSteamworks" }, { "role": "fungalReact", "name": "Fungals", - "emojiId": "723001215696240660", - "emoji": "<:fungal:723001215696240660>" + "emote": "fungal" }, { "role": "moonlightping", "name": "Moonlight", - "emojiId": "1090163554872737866", - "emoji": "<:mv:1090163554872737866>" + "emote": "mv" }, { "role": "eventBoiPing", "name": "Miscellaneous Dungeons", - "emojiId": "723001215184535553", - "emoji": "<:pcave:723001215184535553>" + "emote": "pcave" } ], "701483950559985705": [ { "role": "cultping", "name": "Cults", - "emojiId": "701491230332157972", - "emoji": "<:malus:701491230332157972>" + "emote": "cultist" }, { "role": "fameReact", "name": "Fame Runs", - "emojiId": "1024104144845406248", - "emoji": "<:fame:1024104144845406248>" + "emote": "fame" }, { "role": "voidping", "name": "Voids", - "emojiId": "701491230210523247", - "emoji": "<:void:701491230210523247>" + "emote": "void" }, { "role": "fskipReact", "name": "Full-Skip Voids", - "emojiId": "701491230391140453", - "emoji": "<:SkipBoi:701491230391140453>" + "emote": "fullskip" }, { "role": "shattsReact", "name": "Shatters", - "emojiId": "1008068892071055512", - "emoji": "<:forgottenking:1008068892071055512>" + "emote": "forgottenking" }, { "role": "accursedReact", "name": "Accursed", - "emojiId": "1142347997670289471", - "emoji": "<:accursedKing:1142347997670289471>" + "emote": "accursedKing" }, { "role": "nestReact", "name": "Nests", - "emojiId": "723001215407095899", - "emoji": "<:nest:723001215407095899>" + "emote": "nest" }, { "role": "advancedNestPing", "name": "Advanced Nests", - "emojiId": "1135560355750359050", - "emoji": "<:advancedNestPortal:1135560355750359050>" + "emote": "advancedNestPortal" }, { "role": "steamworksping", "name": "Steamworks", - "emojiId": "1050156386547413012", - "emoji": "" + "emote": "steamworksPortal" }, { "role": "advancedSteamworksPing", "name": "Advanced Steamworks", - "emojiId": "1129901525674758274", - "emoji": "<:advancedSteamworks:1129901525674758274>" + "emote": "advancedSteamworks" }, { "role": "fungalReact", "name": "Fungals", - "emojiId": "723001215696240660", - "emoji": "<:fungal:723001215696240660>" + "emote": "fungal" }, { "role": "moonlightping", "name": "Moonlight", - "emojiId": "1090163554872737866", - "emoji": "<:mv:1090163554872737866>" + "emote": "mv" }, { "role": "eventBoiPing", "name": "Miscellaneous Dungeons", - "emojiId": "723001215184535553", - "emoji": "<:pcave:723001215184535553>" + "emote": "pcave" }, { "role": "o3Ping", "name": "Oryx Sanctuary", - "emojiId": "831047591096745984", - "emoji": "<:oryxThree:831047591096745984>" + "emote": "oryxThree" } ] } \ No newline at end of file From 54c0f964d73d2b191fdfa19167f354b331eb52d8 Mon Sep 17 00:00:00 2001 From: Raghav Viswakumar Date: Wed, 21 Feb 2024 23:33:24 +0000 Subject: [PATCH 3/3] Added Redis Reaction Rows - botSetup.js no longer references roleassignment.js + redis.js now works with component rows + pop.js uses component rows with redis.js + roleassignment uses redis.js with interactions --- botSetup.js | 2 - commands/pop.js | 2 +- commands/roleAssignment.js | 95 +++++++++++++++++++------------------- redis.js | 2 +- 4 files changed, 50 insertions(+), 51 deletions(-) diff --git a/botSetup.js b/botSetup.js index da0007d2..904565c1 100644 --- a/botSetup.js +++ b/botSetup.js @@ -13,7 +13,6 @@ const ErrorLogger = require('./lib/logError'); // Commands const emoji = require('./commands/emoji.js'); const afkCheck = require('./commands/afkCheck.js'); -const roleAssignment = require('./commands/roleAssignment.js'); const vetVerification = require('./commands/vetVerification'); const verification = require('./commands/verification'); // Specific Jobs @@ -129,7 +128,6 @@ async function setup(bot) { iterServers(bot, (bot, g) => { const db = dbSetup.getDB(g.id); afkCheck.loadBotAfkChecks(g, bot, db); - if (bot.settings[g.id].backend.roleassignment) roleAssignment.updateRoleAssignmentListeners(g, bot).catch(er => { ErrorLogger.log(er, bot, g); }); if (bot.settings[g.id].backend.verification) verification.init(g, bot, db).catch(er => { ErrorLogger.log(er, bot, g); }); if (bot.settings[g.id].backend.vetverification) vetVerification.init(g, bot, db).catch(er => { ErrorLogger.log(er, bot, g); }); }); diff --git a/commands/pop.js b/commands/pop.js index c37907da..341d7b82 100644 --- a/commands/pop.js +++ b/commands/pop.js @@ -78,7 +78,7 @@ module.exports = { ); const reply = await message.reply({ embeds: [confirmEmbed], components: [buttons], ephemeral: true }); - createReactionRow(reply, module.exports.name, 'handleButtons', buttons, message.author, { memberId: member.id, keyInfo, count }); + createReactionRow(reply, module.exports.name, 'handleButtons', [buttons], message.author, { memberId: member.id, keyInfo, count }); }, async handleButtons(bot, confirmMessage, db, choice, state) { const member = confirmMessage.interaction.guild.members.cache.get(state.memberId); diff --git a/commands/roleAssignment.js b/commands/roleAssignment.js index 58880601..fab59e39 100644 --- a/commands/roleAssignment.js +++ b/commands/roleAssignment.js @@ -2,6 +2,7 @@ const Discord = require('discord.js'); const reacts = require('../data/roleAssignment.json'); const SlashArgType = require('discord-api-types/v10').ApplicationCommandOptionType; const { slashArg, slashChoices, slashCommandJSON } = require('../utils.js'); +const { createReactionRow } = require('../redis.js'); function addInteractionComponents(bot, guildReacts) { const components = []; @@ -26,47 +27,6 @@ function addInteractionComponents(bot, guildReacts) { }, []); } -async function interactionHandler(interaction, bot, guildReacts) { - const botSettings = bot.settings[interaction.guild.id]; - const embed = new Discord.EmbedBuilder() - .setColor(Discord.Colors.Green) - .setFooter({ text: interaction.guild.name, iconURL: interaction.guild.iconURL() }) - .setTimestamp(); - - switch (interaction.customId) { - case 'giveAllRoles': { - const guildReactsToAdd = guildReacts.filter(reaction => !interaction.member.roles.cache.has(botSettings.roles[reaction.role])); - const rolesToAdd = guildReactsToAdd.map(reaction => interaction.guild.roles.cache.get(botSettings.roles[reaction.role])); - await interaction.member.roles.add(rolesToAdd); - if (rolesToAdd.length == 0) embed.setDescription('You already **have** all the roles to receive pings'); - else embed.setDescription(`You now **have** the roles to receive pings for the following dungeons:\n${rolesToAdd.map((role, i) => `- ${bot.storedEmojis[guildReactsToAdd[i].emote].text} ${guildReactsToAdd[i].name}: ${role}`).join('\n')} `); - await interaction.reply({ embeds: [embed], ephemeral: true }); - break; - } - case 'takeAllRoles': { - const guildReactsToRemove = guildReacts.filter(reaction => interaction.member.roles.cache.has(botSettings.roles[reaction.role])); - const rolesToRemove = guildReactsToRemove.map(reaction => interaction.guild.roles.cache.get(botSettings.roles[reaction.role])); - await interaction.member.roles.remove(rolesToRemove); - if (rolesToRemove.length == 0) embed.setDescription('You already **no longer** have any of the roles to receive pings'); - else embed.setDescription(`You now **no longer have** the roles to receive pings for the following dungeons:\n${rolesToRemove.map((role, i) => `- ${bot.storedEmojis[guildReactsToRemove[i].emote].text} ${guildReactsToRemove[i].name}: ${role}`).join('\n')} `); - await interaction.reply({ embeds: [embed], ephemeral: true }); - break; - } - default: { - const guildReact = guildReacts.find(reaction => reaction.emote === interaction.customId); - const role = interaction.guild.roles.cache.get(botSettings.roles[guildReact.role]); - if (interaction.member.roles.cache.has(role.id)) { - await interaction.member.roles.remove(role); - embed.setDescription(`You now **no longer have** the role to receive pings for ${bot.storedEmojis[guildReact.emote].text} ${guildReact.name}: ${role}`); - } else { - await interaction.member.roles.add(role); - embed.setDescription(`You now **have** the role to receive pings for ${bot.storedEmojis[guildReact.emote].text} ${guildReact.name}: ${role}`); - } - await interaction.reply({ embeds: [embed], ephemeral: true }); - } - } -} - module.exports = { name: 'roleassignment', description: 'Creates or updates role assignment', @@ -112,8 +72,7 @@ module.exports = { .setTimestamp(); guildReacts.map(reaction => embed.addFields([{ name: reaction.name, value: bot.storedEmojis[reaction.emote].text, inline: true }])); const message = await channel.send({ embeds: [embed], components: addInteractionComponents(bot, guildReacts) }); - const roleAssignmentInteractionCollector = new Discord.InteractionCollector(bot, { message, interactionType: Discord.InteractionType.MessageComponent, componentType: Discord.ComponentType.Button }); - roleAssignmentInteractionCollector.on('collect', (interaction) => interactionHandler(interaction, bot, guildReacts)); + createReactionRow(message, module.exports.name, 'interactionHandler', addInteractionComponents(bot, guildReacts), null, guildReacts); interaction.reply(`Role Assignment message has been successfully sent ${message.url}`); break; } @@ -140,14 +99,56 @@ module.exports = { if (!roleAssignmentChannel) return; // If there is no roleassignment channel it will not continue const roleAssignmentChannelMessages = await roleAssignmentChannel.messages.fetch(); // This fetches all the messages in the roleassignment channel - roleAssignmentChannelMessages.map(async message => { // This will loop through the roleassignment channel messages + Promise.all(roleAssignmentChannelMessages.map(async message => { // This will loop through the roleassignment channel messages if (message.author.id !== bot.user.id) return; // If the roleassignment message author is not the same id as ViBot it will not continue with this message if (message.embeds.length == 0) return; // If the message has no embeds it will not continue if (message.components == 0) return; // If the message has no components it will not continue // Anything below this code inside this function is for roleassignment messages, and we need to reset them await message.edit({ components: addInteractionComponents(bot, guildReacts) }); // This will add a roleassignment button listeners to the message - const roleAssignmentInteractionCollector = new Discord.InteractionCollector(bot, { message, interactionType: Discord.InteractionType.MessageComponent, componentType: Discord.ComponentType.Button }); - roleAssignmentInteractionCollector.on('collect', (interaction) => interactionHandler(interaction, bot, guildReacts)); - }); + createReactionRow(message, module.exports.name, 'interactionHandler', addInteractionComponents(bot, guildReacts), null, guildReacts); + })); + }, + async interactionHandler(bot, message, db, choice, guildReacts) { + const interaction = message.interaction; // eslint-disable-line prefer-destructuring + const guild = interaction.guild; // eslint-disable-line prefer-destructuring + const member = interaction.member; // eslint-disable-line prefer-destructuring + const botSettings = bot.settings[interaction.guild.id]; + const embed = new Discord.EmbedBuilder() + .setColor(Discord.Colors.Green) + .setFooter({ text: guild.name, iconURL: guild.iconURL() }) + .setTimestamp(); + + switch (choice) { + case 'giveAllRoles': { + const guildReactsToAdd = guildReacts.filter(reaction => !member.roles.cache.has(botSettings.roles[reaction.role])); + const rolesToAdd = guildReactsToAdd.map(reaction => guild.roles.cache.get(botSettings.roles[reaction.role])); + await member.roles.add(rolesToAdd); + if (rolesToAdd.length == 0) embed.setDescription('You already **have** all the roles to receive pings'); + else embed.setDescription(`You now **have** the roles to receive pings for the following dungeons:\n${rolesToAdd.map((role, i) => `- ${bot.storedEmojis[guildReactsToAdd[i].emote].text} ${guildReactsToAdd[i].name}: ${role}`).join('\n')} `); + await interaction.reply({ embeds: [embed], ephemeral: true }); + break; + } + case 'takeAllRoles': { + const guildReactsToRemove = guildReacts.filter(reaction => member.roles.cache.has(botSettings.roles[reaction.role])); + const rolesToRemove = guildReactsToRemove.map(reaction => guild.roles.cache.get(botSettings.roles[reaction.role])); + await member.roles.remove(rolesToRemove); + if (rolesToRemove.length == 0) embed.setDescription('You already **no longer** have any of the roles to receive pings'); + else embed.setDescription(`You now **no longer have** the roles to receive pings for the following dungeons:\n${rolesToRemove.map((role, i) => `- ${bot.storedEmojis[guildReactsToRemove[i].emote].text} ${guildReactsToRemove[i].name}: ${role}`).join('\n')} `); + await interaction.reply({ embeds: [embed], ephemeral: true }); + break; + } + default: { + const guildReact = guildReacts.find(reaction => reaction.emote === choice); + const role = guild.roles.cache.get(botSettings.roles[guildReact.role]); + if (member.roles.cache.has(role.id)) { + await member.roles.remove(role); + embed.setDescription(`You now **no longer have** the role to receive pings for ${bot.storedEmojis[guildReact.emote].text} ${guildReact.name}: ${role}`); + } else { + await member.roles.add(role); + embed.setDescription(`You now **have** the role to receive pings for ${bot.storedEmojis[guildReact.emote].text} ${guildReact.name}: ${role}`); + } + await interaction.reply({ embeds: [embed], ephemeral: true }); + } + } } }; diff --git a/redis.js b/redis.js index 0b98c9d3..b0f1665a 100644 --- a/redis.js +++ b/redis.js @@ -33,7 +33,7 @@ module.exports = { }, async createReactionRow(message, commandName, callback, buttons, allowedUser, state) { // eslint-disable-next-line camelcase - let opts = { valid_ids: JSON.stringify(buttons.components.map((c) => c.data.custom_id)), command: commandName, callback, state: JSON.stringify(state) }; + let opts = { valid_ids: JSON.stringify(buttons.map(({ components }) => components.map(c => c.data.custom_id)).flat()), command: commandName, callback, state: JSON.stringify(state) }; if (message instanceof Discord.InteractionResponse) opts = { token: message.interaction.token, whid: message.interaction.webhook.id, ...opts }; if (allowedUser) opts.allowedUser = allowedUser.id; const key = 'messagebuttons:' + (await message.fetch()).id;