diff --git a/packages/plugin-modtools/src/commands/modmail/channel.ts b/packages/plugin-modtools/src/commands/modmail/channel.ts new file mode 100644 index 000000000..390dab291 --- /dev/null +++ b/packages/plugin-modtools/src/commands/modmail/channel.ts @@ -0,0 +1,37 @@ +import { ChannelType, CommandInteraction, PermissionFlagsBits } from "discord.js" +import { CommandConfig, CommandResult, Flashcore, client } from "robo.js" + +export const config: CommandConfig = { + defaultMemberPermissions: PermissionFlagsBits.ModerateMembers, + dmPermission: false, + description: `Set the forum channel in which modmail will send the mails.`, + options: [ + { + name: 'modmail', + description: 'id of the Forum channel for modmail', + type: 'string', + required: true + } + ] +} + + + +export default async (interaction: CommandInteraction): Promise => { + const option = interaction.options.get('modmail')?.value + + + if(option){ + const channel = await client.channels.fetch(option.toString()) + + if(channel && channel.type !== ChannelType.GuildForum){ + return {content: 'Please, input the id of a Forum channel.', ephemeral: true}; + } + + await Flashcore.set('modmail_forum', option.toString()); + + return {content: 'Modmail Forum has been correctly set !.', ephemeral: true} + } + + return {content: 'An error happened while executing the command, please try again or contact an Administrator.'} +} \ No newline at end of file diff --git a/packages/plugin-modtools/src/commands/modmail/customize-chatting-embed.ts b/packages/plugin-modtools/src/commands/modmail/customize-chatting-embed.ts new file mode 100644 index 000000000..a7a4e8359 --- /dev/null +++ b/packages/plugin-modtools/src/commands/modmail/customize-chatting-embed.ts @@ -0,0 +1,40 @@ +import { ActionRowBuilder, ChatInputCommandInteraction, ModalBuilder, TextInputBuilder, TextInputStyle } from "discord.js"; +import { CommandConfig, CommandResult } from "robo.js"; + +export const config: CommandConfig = { + description: "Customise the Title and Footer of mod DMs", + sage: { + defer: false + } +}; + +export default async (interaction: ChatInputCommandInteraction): Promise => { + if (interaction.guild === null) return; + + const modal = new ModalBuilder() + .setCustomId('modmail_modal_chatting') + + const one = new TextInputBuilder() + .setCustomId('title') + .setLabel("The Title") + .setMaxLength(100) + .setPlaceholder('Title of the embed that get sent') + .setRequired(true) + .setStyle(TextInputStyle.Short); + + const two = new TextInputBuilder() + .setCustomId('footer') + .setLabel("The Footer") + .setMaxLength(100) + .setPlaceholder('footer of embeds that get sent') + .setRequired(true) + .setStyle(TextInputStyle.Short); + + + const firstActionRow = new ActionRowBuilder().addComponents(one); + const secondActionRow = new ActionRowBuilder().addComponents(two); + + + modal.addComponents(firstActionRow, secondActionRow); + await interaction.showModal(modal); +} \ No newline at end of file diff --git a/packages/plugin-modtools/src/commands/modmail/customize-intro-embed.ts b/packages/plugin-modtools/src/commands/modmail/customize-intro-embed.ts new file mode 100644 index 000000000..2b1678fc4 --- /dev/null +++ b/packages/plugin-modtools/src/commands/modmail/customize-intro-embed.ts @@ -0,0 +1,51 @@ +import { ActionRowBuilder, ChatInputCommandInteraction, ModalBuilder, TextInputBuilder, TextInputStyle } from "discord.js"; +import { CommandConfig, CommandResult } from "robo.js"; + +export const config: CommandConfig = { + description: "Customise the Title and Footer of mod DMs", + sage: { + defer: false + } +}; + +export default async (interaction: ChatInputCommandInteraction): Promise => { + if (interaction.guild === null) return; + + const modal = new ModalBuilder() + .setCustomId('modmail_modal_intro') + .setTitle('Customise the title and footer'); + + const one = new TextInputBuilder() + .setCustomId('title') + .setLabel("The Title") + .setMaxLength(100) + .setPlaceholder('Title of the embed that get sent') + .setRequired(true) + .setStyle(TextInputStyle.Short); + + const two = new TextInputBuilder() + .setCustomId('description') + .setLabel("The description") + .setMaxLength(100) + .setPlaceholder('description of embeds that get sent') + .setRequired(true) + .setStyle(TextInputStyle.Short); + + const three = new TextInputBuilder() + .setCustomId('footer') + .setLabel("The Footer") + .setMaxLength(100) + .setPlaceholder('footer of embeds that get sent') + .setRequired(true) + .setStyle(TextInputStyle.Short); + + + const firstActionRow = new ActionRowBuilder().addComponents(one); + const secondActionRow = new ActionRowBuilder().addComponents(two); + const thirdActionRow = new ActionRowBuilder().addComponents(three); + + + + modal.addComponents(firstActionRow, secondActionRow, thirdActionRow); + await interaction.showModal(modal); +} \ No newline at end of file diff --git a/packages/plugin-modtools/src/events/interactionCreate/modal-modmail.ts b/packages/plugin-modtools/src/events/interactionCreate/modal-modmail.ts new file mode 100644 index 000000000..7c9a1f6c8 --- /dev/null +++ b/packages/plugin-modtools/src/events/interactionCreate/modal-modmail.ts @@ -0,0 +1,32 @@ +import { ModalSubmitInteraction, } from 'discord.js'; +import { Flashcore } from 'robo.js'; +import { ModalProperties } from '../../types'; + +export default async (interaction: ModalSubmitInteraction) => { + + if (!interaction.isModalSubmit()) return; + if (interaction.customId === 'modmail_modal_chatting') { + const title = interaction.fields.getTextInputValue('title'); + const footer = interaction.fields.getTextInputValue('footer'); + + await Flashcore.set('modmail_modal_custom_message', { + title, + footer, + }) + return await interaction.reply({content: 'Custom embed for the modmail message has been defined.', ephemeral: true}) + } + if (interaction.customId === 'modmail_modal_intro') { + const title = interaction.fields.getTextInputValue('title'); + const footer = interaction.fields.getTextInputValue('footer'); + const description = interaction.fields.getTextInputValue('description') + + await Flashcore.set('modmail_modal_custom_intro', { + title, + description, + footer, + }) + + return await interaction.reply({content: 'Custom embed for the intro modmail message has been defined.', ephemeral: true}) + } + +} \ No newline at end of file diff --git a/packages/plugin-modtools/src/events/messageCreate.ts b/packages/plugin-modtools/src/events/messageCreate.ts new file mode 100644 index 000000000..f1edb8741 --- /dev/null +++ b/packages/plugin-modtools/src/events/messageCreate.ts @@ -0,0 +1,114 @@ +import { Channel, ChannelType , EmbedBuilder, ForumChannel, Message, MessagePayload, ThreadChannel } from "discord.js"; +import { Flashcore, client, logger } from "robo.js"; +import { ModalProperties } from "../types"; + +export default async (message: Message) => { + if(message.channel.type === ChannelType.PublicThread || message.channel.type === ChannelType.PrivateThread){ + if(message.author.bot){ + return; + } + const threadUserData = await retrieveModmailDataFromFlashcore(message.channelId, "") + + if(threadUserData){ + const modalOptions = await Flashcore.get('modmail_modal_custom_message'); + + const embedded = new EmbedBuilder() + .setTitle(modalOptions?.title ? modalOptions.title : 'Moderation') + .setColor("Blue") + .setDescription(message.content.length > 0 ? message.content : ' ') + .setFooter({ +  text: modalOptions?.footer ? modalOptions?.footer : "The lovely moderation team ^.^" + }) + + + const user = await client.users.fetch(threadUserData.userId) + if(user){ + user.send({embeds: [embedded], files: [...message.attachments.map((attach) => attach.url)]}); + } + } + return; + } + if(message.channel.type === ChannelType.DM && !message.author.bot){ + const modmailChannel = await Flashcore.get('modmail_forum'); + + if(!modmailChannel) { + return message.reply({content: 'Please contact the adminstrators of the server to set a modmail channel using the /modmail channel command.', options: {ephemeral: true}}) + } + + const ForumMail = await client.channels.fetch(modmailChannel); + if(ForumMail && ForumMail.type === ChannelType.GuildForum){ + const hasAlreadyAThread = await createOrFetchThreadChannel(message, ForumMail); + + if(!hasAlreadyAThread){ + const modalOptions = await Flashcore.get('modmail_modal_custom_intro'); + + const embedded = new EmbedBuilder() + .setTitle(modalOptions?.title ? modalOptions?.title : 'Thread created') + .setColor("Blue") + .setDescription(modalOptions?.description ? modalOptions.description : 'Please state your issues.') + .setFooter({ +  text: modalOptions?.footer ? modalOptions?.footer : "The lovely moderation team ^.^" + }) + return message.reply({embeds: [embedded]}) + } else { + if(hasAlreadyAThread instanceof ThreadChannel){ + return hasAlreadyAThread.send({ + content: message.content.length > 0 ? message.content : ' ', + files: [...message.attachments.map((attach) => attach.url)] + }) + } + } + } + + } + +} + +const createOrFetchThreadChannel = async (message: Message, Forum: any): Promise => { + const user = await retrieveModmailDataFromFlashcore("", message.author.id) + + if(!user){ + const newThread = await Forum.threads.create({ + name: message.author.displayName, + message: {content: message.content} + }) + await saveModmailDataToFlashcore(newThread.id, message.author.id) + return false; + } else { + const threads = (await Forum.threads.fetch()).threads + const userThread = threads.find((thread: ThreadChannel) => thread.id === user.threadId) + return userThread; + } +} + + + +type ModMailUserData = { + threadId: string, + userId: string +} + +const retrieveModmailDataFromFlashcore = async (thread: string, userId: string) => { + const user = await Flashcore.get(thread ? thread : userId, { + namespace: 'modmail_thread' + }) + + return user; +} + + +const saveModmailDataToFlashcore = async (threadId: string, userId: string) => { + await Flashcore.set(threadId, { + threadId: threadId, + userId: userId + }, { + namespace: 'modmail_thread' + }) + await Flashcore.set(userId, { + threadId: threadId, + userId: userId + }, { + namespace: 'modmail_thread' + }) + +} \ No newline at end of file diff --git a/packages/plugin-modtools/src/types.ts b/packages/plugin-modtools/src/types.ts new file mode 100644 index 000000000..01d803fb0 --- /dev/null +++ b/packages/plugin-modtools/src/types.ts @@ -0,0 +1,5 @@ +export type ModalProperties = { + title: string, + description?: string, + footer: string +} \ No newline at end of file