From b5170b9c6557603c47c88333549bef988c093b07 Mon Sep 17 00:00:00 2001 From: SadlyNotSappho Date: Fri, 24 Feb 2023 12:51:24 -0800 Subject: [PATCH] set up "/roles new" --- .gitignore | 3 +- src/commands/eval.ts | 2 +- src/commands/help.ts | 21 ++++ src/commands/ping.ts | 4 +- src/commands/roles.ts | 23 +++-- src/commands/{ => testing}/test-slash.ts | 7 +- src/commands/{ => testing}/test.ts | 16 +++- src/listeners/ready.ts | 31 +----- src/listeners/rolesNew.ts | 117 +++++++++++++++++++++++ 9 files changed, 175 insertions(+), 49 deletions(-) create mode 100644 src/commands/help.ts rename src/commands/{ => testing}/test-slash.ts (83%) rename src/commands/{ => testing}/test.ts (64%) create mode 100644 src/listeners/rolesNew.ts diff --git a/.gitignore b/.gitignore index d4fae85..28443b2 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,5 @@ .env node_modules -dist \ No newline at end of file +dist +testing/* \ No newline at end of file diff --git a/src/commands/eval.ts b/src/commands/eval.ts index d1f2a07..98fec54 100644 --- a/src/commands/eval.ts +++ b/src/commands/eval.ts @@ -9,7 +9,7 @@ import type { Message } from 'discord.js'; }) export class UserCommand extends Command { public async messageRun(message: Message) { - let splitCode = message.content.split(' '); + const splitCode = message.content.split(' '); splitCode.shift(); const code = splitCode.join(' '); diff --git a/src/commands/help.ts b/src/commands/help.ts new file mode 100644 index 0000000..2251ccc --- /dev/null +++ b/src/commands/help.ts @@ -0,0 +1,21 @@ +import { ApplyOptions } from '@sapphire/decorators'; +import { Command } from '@sapphire/framework'; + +@ApplyOptions({ + description: 'A basic slash command' +}) +export class UserCommand extends Command { + public override registerApplicationCommands(registry: Command.Registry) { + registry.registerChatInputCommand( + (builder) => + builder // + .setName(this.name) + .setDescription(this.description), + { guildIds: ['1030563119132594187'] } + ); + } + + public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) { + return interaction.reply({ content: 'Hello world!' }); + } +} diff --git a/src/commands/ping.ts b/src/commands/ping.ts index 7ee405e..7082bfc 100644 --- a/src/commands/ping.ts +++ b/src/commands/ping.ts @@ -3,7 +3,7 @@ import { Command } from '@sapphire/framework'; @ApplyOptions({ name: 'ping', - description: 'A basic slash command' + description: 'Pong!' }) export class UserCommand extends Command { public override registerApplicationCommands(registry: Command.Registry) { @@ -21,6 +21,6 @@ export class UserCommand extends Command { } public override async chatInputRun(interaction: Command.ChatInputCommandInteraction) { - return interaction.reply({ content: 'Hello world!' }); + await interaction.reply({ content: 'omg it ping pong !!!' }); } } diff --git a/src/commands/roles.ts b/src/commands/roles.ts index 9ccb9c0..414652b 100644 --- a/src/commands/roles.ts +++ b/src/commands/roles.ts @@ -29,13 +29,15 @@ export class UserCommand extends Command { switch (subcommand) { case 'new': await this.new(interaction); break; case 'edit': await this.edit(interaction); break; + case 'show': await this.show(interaction); break; } } private async new(interaction: Command.ChatInputCommandInteraction) { const modal = new ModalBuilder() - .setCustomId('embedEditorModal') - .setTitle('Embed Editor'); + .setCustomId('newEmbedEditorModal') + .setTitle('Embed Editor') + const embedTitle = new TextInputBuilder() .setCustomId('embedTitle') .setLabel('Title') @@ -44,11 +46,17 @@ export class UserCommand extends Command { .setCustomId('embedDescription') .setLabel('Description') .setStyle(TextInputStyle.Paragraph) + const embedColor = new TextInputBuilder() + .setCustomId('embedColor') + .setLabel('Color') + .setPlaceholder('RGB color for the embed (e.g #FF0000)') + .setStyle(TextInputStyle.Short) - let firstRow = new ActionRowBuilder().addComponents(embedTitle); + let firstRow = new ActionRowBuilder().addComponents(embedTitle) let secondRow = new ActionRowBuilder().addComponents(embedDescription) + let thirdRow = new ActionRowBuilder().addComponents(embedColor) - modal.addComponents(firstRow, secondRow) + modal.addComponents(firstRow, secondRow, thirdRow) await interaction.showModal(modal) } @@ -56,7 +64,8 @@ export class UserCommand extends Command { private async edit(interaction: Command.ChatInputCommandInteraction) { await interaction.reply({content: 'edit', ephemeral: true}) } -} - -// new TextInputBuilder().setCustomId('embedName').setLabel("The embed's name").setRequired(false).setStyle(TextInputStyle.Short) \ No newline at end of file + private async show(interaction: Command.ChatInputCommandInteraction) { + await interaction.reply({content: 'show', ephemeral: true}) + } +} \ No newline at end of file diff --git a/src/commands/test-slash.ts b/src/commands/testing/test-slash.ts similarity index 83% rename from src/commands/test-slash.ts rename to src/commands/testing/test-slash.ts index f57bb2b..9384017 100644 --- a/src/commands/test-slash.ts +++ b/src/commands/testing/test-slash.ts @@ -1,10 +1,11 @@ import { ApplyOptions } from '@sapphire/decorators'; import { Command } from '@sapphire/framework'; import { ComponentType } from 'discord.js'; -import { RolesMessage } from '../lib/types'; +import { RolesMessage } from '../../lib/types'; @ApplyOptions({ - description: 'A basic slash command' + description: 'A basic slash command', + preconditions: ['OwnerOnly'] }) export class UserCommand extends Command { public override registerApplicationCommands(registry: Command.Registry) { @@ -36,6 +37,6 @@ export class UserCommand extends Command { ]}] }); - console.log(await RolesMessage.findAll()) + console.log(await (await RolesMessage.findAll()).map((m: RolesMessage) => m.dataValues)) } } diff --git a/src/commands/test.ts b/src/commands/testing/test.ts similarity index 64% rename from src/commands/test.ts rename to src/commands/testing/test.ts index b592887..d0889e6 100644 --- a/src/commands/test.ts +++ b/src/commands/testing/test.ts @@ -1,13 +1,15 @@ import { ApplyOptions } from '@sapphire/decorators'; import { Command } from '@sapphire/framework'; import type { Message } from 'discord.js'; -import { RolesMessage } from '../lib/types'; +import { RolesMessage } from '../../lib/types'; @ApplyOptions({ - description: 'A basic command' + description: 'A basic command', + preconditions: ['OwnerOnly'] }) export class UserCommand extends Command { public async messageRun(message: Message) { + message; // await message.guild?.commands.fetch() // console.log('message.guild.commands.cache, after fetching:', message.guild?.commands.cache) @@ -17,8 +19,12 @@ export class UserCommand extends Command { // await this.container.client.application?.commands.delete('1073818778254717019').then(console.log).catch(console.error) - console.log(await RolesMessage.findAll()) - await message.reply('yeah yeah fuck you djs'); - console.log(await RolesMessage.create({guildId: message.guild?.id, roles: ['1074464133371674624']})) + + const msgs = await RolesMessage.findAll(); + let stringArr = [] + for (const msg of msgs) { + stringArr.push(`${msg.dataValues.id} - [${msg.dataValues.roles.map((r: string) => `<@&${r}>`).join(',')}]`) + } + await message.reply(stringArr.join('\n')) } } diff --git a/src/listeners/ready.ts b/src/listeners/ready.ts index bd6a279..3a8bd9a 100644 --- a/src/listeners/ready.ts +++ b/src/listeners/ready.ts @@ -1,6 +1,6 @@ import { ApplyOptions } from '@sapphire/decorators'; import { Listener, Store } from '@sapphire/framework'; -import { blue, gray, green, magenta, magentaBright, white, yellow } from 'colorette'; +import { blue, gray, yellow } from 'colorette'; import { DataTypes } from 'sequelize'; import { RolesMessage } from '../lib/types'; @@ -11,34 +11,10 @@ export class UserEvent extends Listener { private readonly style = dev ? yellow : blue; public async run() { - this.printBanner(); this.printStoreDebugInformation(); - this.printMiscInformation(); await this.initDatabase(); } - private printBanner() { - const success = green('+'); - - const llc = dev ? magentaBright : white; - const blc = dev ? magenta : blue; - - const line01 = llc(''); - const line02 = llc(''); - const line03 = llc(''); - - // Offset Pad - const pad = ' '.repeat(7); - - console.log( - String.raw` -${line01} ${pad}${blc('1.0.0')} -${line02} ${pad}[${success}] Gateway -${line03}${dev ? ` ${pad}${blc('<')}${llc('/')}${blc('>')} ${llc('DEVELOPMENT MODE')}` : ''} - `.trim() - ); - } - private printStoreDebugInformation() { const { client, logger } = this.container; const stores = [...client.stores.values()]; @@ -52,10 +28,6 @@ ${line03}${dev ? ` ${pad}${blc('<')}${llc('/')}${blc('>')} ${llc('DEVELOPMENT MO return gray(`${last ? '└─' : '├─'} Loaded ${this.style(store.size.toString().padEnd(3, ' '))} ${store.name}.`); } - private printMiscInformation() { - console.log('Ready!'); - } - private async initDatabase() { RolesMessage.init({ id: { @@ -82,7 +54,6 @@ ${line03}${dev ? ` ${pad}${blc('<')}${llc('/')}${blc('>')} ${llc('DEVELOPMENT MO }, style: { type: DataTypes.STRING, - defaultValue: 'buttons' } }, { sequelize: this.container.db, diff --git a/src/listeners/rolesNew.ts b/src/listeners/rolesNew.ts new file mode 100644 index 0000000..8c23241 --- /dev/null +++ b/src/listeners/rolesNew.ts @@ -0,0 +1,117 @@ +import { ApplyOptions } from '@sapphire/decorators'; +import { Listener, ListenerOptions } from '@sapphire/framework'; +import { ButtonInteraction, ButtonStyle, ComponentType, Interaction, RoleSelectMenuInteraction } from 'discord.js'; +import { RolesMessage } from '../lib/types'; + +@ApplyOptions({ event: 'interactionCreate' }) +export class UserEvent extends Listener { + public async run(interaction: Interaction) { + if (!interaction.isModalSubmit()) return; + if (interaction.customId != 'newEmbedEditorModal') return; + + await interaction.reply({ content: 'modal recieved', ephemeral: true }); + let regex = /[0-9A-F]{6}/gi; + + let title = interaction.fields.fields.get('embedTitle')?.value; + let description = interaction.fields.fields.get('embedDescription')?.value; + let color: string = interaction.fields.fields.get('embedColor')?.value as string; + + let matches = color.match(regex); + if (matches == null) color = '0x36393E'; + else color = `0x${matches[0]}`; + + // await interaction.editReply({content: null, embeds: [{title, description, color: Number(color)}] }); + await interaction.editReply({ + content: + 'Would you like this message to assign its roles via **buttons** or a **drop-down menu**?\n*Due to technological limitations, you have 60 seconds to make a decision.*', + components: [ + { + type: ComponentType.ActionRow, + components: [ + { type: ComponentType.Button, label: 'Buttons', customId: 'selectButtons', style: ButtonStyle.Primary }, + { type: ComponentType.Button, label: 'Drop-down Menu', customId: 'selectDropdowns', style: ButtonStyle.Primary } + ] + } + ] + }); + + let button; + try { + button = await interaction.channel?.awaitMessageComponent({ + componentType: ComponentType.Button, + filter: async (i: ButtonInteraction) => { + return i.user.id == interaction.user.id; + }, + time: 60_000 + }); + } catch (err) { + await interaction.editReply({ + content: "You didn't make a decision in time. Here's the data you put into the modal, as an embed.", + embeds: [{ title, description, color: Number(color), fields: [{ name: 'Color', value: color }] }], + components: [] + }); + return null; + } + + if (!button) { + return; + } + + await button.deferUpdate(); + let type = button.customId; + + await interaction.editReply({ + content: `You've selected ${ + type == 'selectButtons' ? '**buttons**' : '**drop-down menus**' + } as the roles selection method for when the message is complete. Now, there's just one more step, and that's to pick the actual roles you'd like to give this message!\n*Note: Due to technological limitations, you have five minutes to select the roles you'd like.*`, + components: [ + { + type: ComponentType.ActionRow, + components: [ + { + type: ComponentType.RoleSelect, + customId: 'selectRolesForMessage', + maxValues: 25, + minValues: 1, + } + ] + } + ] + }); + + let roles; + try { + roles = await interaction.channel?.awaitMessageComponent({ + componentType: ComponentType.RoleSelect, + filter: async (i: RoleSelectMenuInteraction) => { + return i.user.id == interaction.user.id; + }, + time: 300_000 + }); + } catch (err) { + await interaction.editReply({ + content: "You didn't make a decision in time. Here's the data you put into the modal, as an embed.", + embeds: [{ title, description, color: Number(color), fields: [{ name: 'Color', value: color }] }], + components: [] + }); + return null; + } + + if (!roles) { + return; + } + + let data = await RolesMessage.create({ + guildId: interaction.guild?.id, + embedTitle: title, + embedDescription: description, + embedColor: color, + roles: roles.values, + style: type == 'selectButtons' ? 'buttons' : 'dropdown' + }) + + console.log(data) + + return; + } +}