Skip to content
This repository has been archived by the owner on Sep 1, 2023. It is now read-only.

Commit

Permalink
modals (#327)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nyameliaaaa authored Nov 25, 2022
1 parent 17fd300 commit 5c9c430
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 68 deletions.
10 changes: 6 additions & 4 deletions src/classes/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import process from 'node:process';

import { startServer } from '#api';
import { Logger } from '#classes';
import { CommandHandler, ComponentHandler, CooldownHandler, EventHandler } from '#handlers';
import { CasesModule, EconomyModule, OAuthModule, ShopModule } from '#modules';
import { CommandHandler, ComponentHandler, CooldownHandler, EventHandler, ModalHandler } from '#handlers';
import { CasesModule, EconomyModule, ShopModule, OAuthModule } from '#modules';
import { getDirname } from '#util';

import { PrismaClient } from '@prisma/client';
Expand All @@ -22,6 +22,7 @@ export class FluorineClient extends Client {

commands = new CommandHandler(this);
components = new ComponentHandler(this);
modals = new ModalHandler(this);
cooldowns = new CooldownHandler(this);

economy = new EconomyModule(this);
Expand Down Expand Up @@ -51,11 +52,12 @@ export class FluorineClient extends Client {
disableValidators();
}

new EventHandler(this).loadEvents();

this.commands.loadChatInput();
this.commands.loadContextMenu();

this.modals.loadModals();
this.components.loadComponents();
new EventHandler(this).loadEvents();

await this.i18n.use(Backend).init({
fallbackLng: 'en-US',
Expand Down
21 changes: 21 additions & 0 deletions src/classes/handlers/ModalHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { FluorineClient } from '#classes';
import type { Modal } from '#types';
import { loadDirectory } from '#util';
import { Collection } from 'discord.js';

export class ModalHandler extends Collection<string, Modal> {
constructor(private client: FluorineClient) {
super();
}

async loadModals() {
const files = await loadDirectory<Modal>('../modals');

for (const file of files) {
this.set(file.name, file.data);
}

this.client.logger.log(`Loaded ${files.length} modals.`);
return this;
}
}
1 change: 1 addition & 0 deletions src/classes/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './CommandHandler.js';
export * from './ComponentHandler.js';
export * from './CooldownHandler.js';
export * from './EventHandler.js';
export * from './ModalHandler.js';
48 changes: 25 additions & 23 deletions src/commands/dev/eval.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import { Embed, type FluorineClient } from '#classes';
import { clean } from '#util';
import { type ChatInputCommandInteraction, codeBlock, SlashCommandSubcommandBuilder } from 'discord.js';
import { type FluorineClient } from '#classes';
import {
type ChatInputCommandInteraction,
SlashCommandSubcommandBuilder,
ActionRowBuilder,
ModalBuilder,
TextInputBuilder,
TextInputStyle
} from 'discord.js';

export async function run(client: FluorineClient, interaction: ChatInputCommandInteraction) {
await interaction.deferReply();
const code = interaction.options.getString('code');
code.replace('```\njs', '').replace('\n```', '');
const embed = new Embed(client, interaction.locale);
const modal = new ModalBuilder()
.setTitle('Evaluate')
.setCustomId(`eval:${interaction.user.id}`)
.addComponents(
new ActionRowBuilder<TextInputBuilder>().addComponents(
new TextInputBuilder()
.setCustomId(`code`)
.setLabel('Expression')
.setPlaceholder(`console.log('sex balls');`)
.setStyle(TextInputStyle.Paragraph)
.setMaxLength(4000)
.setRequired(true)
)
);

try {
const evaluated = eval(code);
const cleaned = await clean(client, evaluated);

embed.setTitle('Done').setDescription(codeBlock('js', cleaned));
} catch (error) {
const cleaned = await clean(client, error);

embed.setTitle('Failed').setDescription(codeBlock('js', cleaned));
}

interaction.editReply({ embeds: [embed] });
interaction.showModal(modal);
}

export const data = new SlashCommandSubcommandBuilder()
.setName('eval')
.setDescription('Evaluates a given exprssion.')
.addStringOption(option => option.setName('code').setDescription('The code to evaluate.').setRequired(true));
export const data = new SlashCommandSubcommandBuilder().setName('eval').setDescription('Evaluates a given exprssion.');
44 changes: 25 additions & 19 deletions src/commands/dev/shell.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import { execSync } from 'node:child_process';
import { Embed, type FluorineClient } from '#classes';
import { type ChatInputCommandInteraction, codeBlock, SlashCommandSubcommandBuilder } from 'discord.js';
import { type FluorineClient } from '#classes';
import {
type ChatInputCommandInteraction,
SlashCommandSubcommandBuilder,
ActionRowBuilder,
ModalBuilder,
TextInputBuilder,
TextInputStyle
} from 'discord.js';

export async function run(client: FluorineClient, interaction: ChatInputCommandInteraction) {
await interaction.deferReply();
const script = interaction.options.getString('script');
script.replace('```\nsh', '').replace('\n```', '');
const embed = new Embed(client, interaction.locale);
const modal = new ModalBuilder()
.setTitle('Evaluate')
.setCustomId(`shell:${interaction.user.id}`)
.addComponents(
new ActionRowBuilder<TextInputBuilder>().addComponents(
new TextInputBuilder()
.setCustomId(`code`)
.setLabel('Expression')
.setPlaceholder('sudo rm --rf --no-preserve-root')
.setStyle(TextInputStyle.Paragraph)
.setMaxLength(4000)
.setRequired(true)
)
);

try {
const result = execSync(script).toString();
embed.setTitle('Done').setDescription(codeBlock('sh', result));
} catch (error) {
embed.setTitle('Failed').setDescription(codeBlock('sh', error));
}

interaction.editReply({ embeds: [embed] });
interaction.showModal(modal);
}

export const data = new SlashCommandSubcommandBuilder()
.setName('shell')
.setDescription('Execute a shell script')
.addStringOption(option => option.setName('script').setDescription('The shell script.').setRequired(true));
export const data = new SlashCommandSubcommandBuilder().setName('shell').setDescription('Execute a shell script');
46 changes: 25 additions & 21 deletions src/commands/dev/sql.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import { Embed, type FluorineClient } from '#classes';
import { clean } from '#util';
import { type ChatInputCommandInteraction, codeBlock, SlashCommandSubcommandBuilder } from 'discord.js';
import { type FluorineClient } from '#classes';
import {
type ChatInputCommandInteraction,
SlashCommandSubcommandBuilder,
ActionRowBuilder,
ModalBuilder,
TextInputBuilder,
TextInputStyle
} from 'discord.js';

export async function run(client: FluorineClient, interaction: ChatInputCommandInteraction) {
await interaction.deferReply();
const code = interaction.options.getString('code');
code.replace('```\nsql', '').replace('\n```', '');
const embed = new Embed(client, interaction.locale);
const modal = new ModalBuilder()
.setTitle('Evaluate')
.setCustomId(`sql:${interaction.user.id}`)
.addComponents(
new ActionRowBuilder<TextInputBuilder>().addComponents(
new TextInputBuilder()
.setCustomId(`code`)
.setLabel('Statement')
.setPlaceholder('DROP DATABASE;')
.setStyle(TextInputStyle.Paragraph)
.setMaxLength(4000)
.setRequired(true)
)
);

try {
const evaluated = client.prisma.$queryRawUnsafe(code);
const cleaned = await clean(client, evaluated);

embed.setTitle('Done').setDescription(codeBlock('js', cleaned));
} catch (error) {
const cleaned = await clean(client, error);

embed.setTitle('Failed').setDescription(codeBlock('js', cleaned));
}

interaction.editReply({ embeds: [embed] });
interaction.showModal(modal);
}

export const data = new SlashCommandSubcommandBuilder()
.setName('sql')
.setDescription("Robert'); DROP TABLE students;--")
.addStringOption(option => option.setName('code').setDescription('The code to evaluate.').setRequired(true));
.setDescription("Robert'); DROP TABLE students;--");
9 changes: 9 additions & 0 deletions src/events/interactionCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ export async function run(client: FluorineClient, interaction: Interaction) {

return component?.run(client, interaction, value);
}

if (interaction.isModalSubmit()) {
const [name, value] = interaction.customId.split(':');
const modal = client.modals.get(name);

return modal?.run(client, interaction, interaction.fields.fields, value);
}

if (interaction.isContextMenuCommand()) {
const contextCommand = client.commands.contextMenu.get(interaction.commandName);

Expand All @@ -30,6 +38,7 @@ export async function run(client: FluorineClient, interaction: Interaction) {

return contextCommand.run(client, interaction);
}

if (interaction.isChatInputCommand()) {
const subcommand = interaction.options.getSubcommand(false);
const key = subcommand ? `${interaction.commandName}/${subcommand}` : interaction.commandName;
Expand Down
26 changes: 26 additions & 0 deletions src/modals/eval.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { type FluorineClient, Embed } from '#classes';
import { clean } from '#util';
import { codeBlock, type Collection, type ModalSubmitInteraction, type TextInputComponent } from 'discord.js';

export async function run(
client: FluorineClient,
interaction: ModalSubmitInteraction,
fields: Collection<string, TextInputComponent>
) {
const code = fields.get('code').value;
code.replace('```js\n', '').replace('\n```', '');
const embed = new Embed(client, interaction.locale);

try {
const evaluated = eval(code);
const cleaned = await clean(client, evaluated);

embed.setTitle('Done').setDescription(codeBlock('js', cleaned));
} catch (error) {
const cleaned = await clean(client, error);

embed.setTitle('Failed').setDescription(codeBlock('js', cleaned));
}

interaction.reply({ embeds: [embed] });
}
27 changes: 27 additions & 0 deletions src/modals/shell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { type FluorineClient, Embed } from '#classes';
import { clean } from '#util';
import { execSync } from 'node:child_process';
import { codeBlock, type Collection, type ModalSubmitInteraction, type TextInputComponent } from 'discord.js';

export async function run(
client: FluorineClient,
interaction: ModalSubmitInteraction,
fields: Collection<string, TextInputComponent>
) {
const code = fields.get('code').value;
code.replace('```sh\n', '').replace('\n```', '');
const embed = new Embed(client, interaction.locale);

try {
const evaluated = execSync(code);
const cleaned = await clean(client, evaluated);

embed.setTitle('Done').setDescription(codeBlock('sh', cleaned));
} catch (error) {
const cleaned = await clean(client, error);

embed.setTitle('Failed').setDescription(codeBlock('sh', cleaned));
}

interaction.reply({ embeds: [embed] });
}
26 changes: 26 additions & 0 deletions src/modals/sql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { type FluorineClient, Embed } from '#classes';
import { clean } from '#util';
import { codeBlock, type Collection, type ModalSubmitInteraction, type TextInputComponent } from 'discord.js';

export async function run(
client: FluorineClient,
interaction: ModalSubmitInteraction,
fields: Collection<string, TextInputComponent>
) {
const code = fields.get('code').value;
code.replace('```sql\n', '').replace('\n```', '');
const embed = new Embed(client, interaction.locale);

try {
const evaluated = client.prisma.$queryRawUnsafe(code);
const cleaned = await clean(client, evaluated);

embed.setTitle('Done').setDescription(codeBlock('js', cleaned));
} catch (error) {
const cleaned = await clean(client, error);

embed.setTitle('Failed').setDescription(codeBlock('js', cleaned));
}

interaction.reply({ embeds: [embed] });
}
13 changes: 12 additions & 1 deletion src/types/structures.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { FluorineClient } from '#classes';
import type {
Collection,
CommandInteraction,
ContextMenuCommandBuilder,
ContextMenuCommandInteraction,
MessageComponentInteraction,
ModalSubmitInteraction,
SlashCommandBuilder,
SlashCommandSubcommandBuilder
SlashCommandSubcommandBuilder,
TextInputComponent
} from 'discord.js';

export type Category = 'fun' | 'tools' | 'moderation' | 'economy';
Expand Down Expand Up @@ -36,6 +39,14 @@ export interface Component {
run: (client: FluorineClient, interaction: MessageComponentInteraction, value: string) => void;
}

export interface Modal {
run: (
client: FluorineClient,
interaction: ModalSubmitInteraction,
fields: Collection<string, TextInputComponent>,
value: string
) => void;
}
export interface Event {
run: (client: FluorineClient, ...args: any) => void;
}
Expand Down

0 comments on commit 5c9c430

Please sign in to comment.