import { MessageActionRow, MessageButton, MessageComponent, MessageMenu, MessageMenuOption } from "discord-buttons"; import { Message } from "discord.js"; import { TextChannel } from "discord.js"; import * as Opt from "../types/Opt"; import InteractionRoles from "./data"; //initialize discord const Discord = require('discord.js'), client = new Discord.Client({ ws: { intents: Discord.Intents.ALL } }), disbut = require('discord-buttons'); disbut(client); //configure discord-buttons with client //on read client.on('ready', () => console.log('ready')); /** * send message containing menu * @param c text channel to send message * @param menuOpts menu data object */ function sendMenu(c: TextChannel, menuOpts: Opt.Menu) { let select = new MessageMenu() .setID(menuOpts.id) .setPlaceholder(menuOpts.palceholder) .setMaxValues(menuOpts.max === 'all' ? menuOpts.options.length : menuOpts.max) .setMinValues(0); for (let i = 0; i < menuOpts.options.length; i++) { let opts: Opt.MenuOptions = menuOpts.options[i]; let option = new MessageMenuOption() .setLabel(opts.label) .setValue(opts.val); if (opts.emoji && opts.emoji.length) option.setEmoji(opts.emoji); if (opts.desc && opts.desc.length) option.setDescription(opts.desc); if (opts.default) option.setDefault(); select.addOption(option); } c.send(menuOpts.message, select); } /** * send message containing row * @param c text channel to send message * @param rowOpts row data object */ function sendRow(c: TextChannel, rowOpts: Opt.Row) { let row = new MessageActionRow(); for (let i = 0; i < rowOpts.buttons.length; i++) { let opts: Opt.RowButton = rowOpts.buttons[i]; let option = new MessageButton() .setStyle(opts.style) .setLabel(opts.label) .setID(opts.id); row.addComponent(option); } c.send(rowOpts.message, row); } //uncomment if you want to create a message, will change to slash command client.on('message', (m: Message) => { if (m.author.id === '167336999844315137' && m.content === '.') { for (let i = 0; i < InteractionRoles.length; i++) { switch (InteractionRoles[i].type) { case 'menu': sendMenu(m.channel as TextChannel, InteractionRoles[i] as Opt.Menu); break; case 'row': sendRow(m.channel as TextChannel, InteractionRoles[i] as Opt.Row); break; } } } }); //on menu click client.on('clickMenu', (menu: MessageComponent) => { menu.reply.think(true).then(async () => { //list of menus from data with matching id let menus = InteractionRoles.filter(opt => opt.type === 'menu' && opt.id === menu.id); if (menus.length) { //use first menu with matching id let m = menus[0] as Opt.Menu, vals = menu.values || []; //list of changes let changed: { add: string[], rem: string[] } = { add: [], rem: [] }; //loop through all the options in the menu for (let i = 0; i < m.options.length; i++) { let opt = m.options[i], {roleid} = opt; //if there's no role id, then nothing can be done if (roleid) { //get corresponding role let role = await menu.guild.roles.fetch(roleid); //if enabled if (vals && vals.includes(opt.val)) { //if clicker (member) doesn't have the role if (!menu.clicker.member.roles.cache.some(r => r.id === role.id)) { //give role await menu.clicker.member.roles.add(role); changed.add.push(role.name); } //else if clicker (member) does have the role } else if (menu.clicker.member.roles.cache.some(r => r.id === role.id)) { //remove role await menu.clicker.member.roles.remove(role); changed.rem.push(role.name); } } } //convert changes to a message let message = []; if (changed.add.length) message.push(`Added \`${changed.add.join(', ')}\``); if (changed.rem.length) message.push(`Removed \`${changed.rem.join(', ')}\``); menu.reply.edit(message.length ? message.join('\n') : 'No Changes'); } else menu.reply.edit('Error: Unknown menu'); }); }); client.on('clickButton', (button: MessageComponent) => { button.reply.think(true).then(async () => { //list of button rows from data let rows = InteractionRoles.filter(opt => opt.type === 'row'); //loop through each the buttons rows for (let i = 0; i < rows.length; i++) { let row = rows[i] as Opt.Row; //filter to just buttons with matching id let matchingButtons = row.buttons.filter(opt => opt.id === button.id); if (matchingButtons.length) { //get corresponding role let role = await button.guild.roles.fetch(matchingButtons[0].roleid); //if clicker (member) does have the role if (button.clicker.member.roles.cache.some(r => r.id === role.id)) { //remove role await button.clicker.member.roles.remove(role.id); button.reply.edit(`Removed \`${role.name}\``); } else { //add role await button.clicker.member.roles.add(role.id); button.reply.edit(`Added \`${role.name}\``); } break; } } }); }); //login with token client.login(require('fs').readFileSync('../token').toString());