Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions packages/plugin-modtools/src/commands/modmail/channel.ts
Original file line number Diff line number Diff line change
@@ -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<CommandResult> => {
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<string>('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.'}
}
Original file line number Diff line number Diff line change
@@ -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<CommandResult> => {
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<TextInputBuilder>().addComponents(one);
const secondActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(two);


modal.addComponents(firstActionRow, secondActionRow);
await interaction.showModal(modal);
}
Original file line number Diff line number Diff line change
@@ -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<CommandResult> => {
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<TextInputBuilder>().addComponents(one);
const secondActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(two);
const thirdActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(three);



modal.addComponents(firstActionRow, secondActionRow, thirdActionRow);
await interaction.showModal(modal);
}
Original file line number Diff line number Diff line change
@@ -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<ModalProperties>('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<ModalProperties>('modmail_modal_custom_intro', {
title,
description,
footer,
})

return await interaction.reply({content: 'Custom embed for the intro modmail message has been defined.', ephemeral: true})
}

}
114 changes: 114 additions & 0 deletions packages/plugin-modtools/src/events/messageCreate.ts
Original file line number Diff line number Diff line change
@@ -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<ModalProperties>('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<string>('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<ModalProperties>('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<ThreadChannel | boolean> => {
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<ModMailUserData>(thread ? thread : userId, {
namespace: 'modmail_thread'
})

return user;
}


const saveModmailDataToFlashcore = async (threadId: string, userId: string) => {
await Flashcore.set<ModMailUserData>(threadId, {
threadId: threadId,
userId: userId
}, {
namespace: 'modmail_thread'
})
await Flashcore.set<ModMailUserData>(userId, {
threadId: threadId,
userId: userId
}, {
namespace: 'modmail_thread'
})

}
5 changes: 5 additions & 0 deletions packages/plugin-modtools/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type ModalProperties = {
title: string,
description?: string,
footer: string
}