Skip to content

Commit

Permalink
Release v8.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
TFAGaming committed Oct 21, 2023
1 parent c1d0145 commit 0121da0
Show file tree
Hide file tree
Showing 14 changed files with 145 additions and 126 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
CLIENT_TOKEN = Your bot token
CLIENT_TOKEN="Your bot token"
WEBHOOK_URL="Your logging webhook URL"
1 change: 0 additions & 1 deletion JSON/bans.json

This file was deleted.

1 change: 0 additions & 1 deletion JSON/mails.json

This file was deleted.

55 changes: 14 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ If you find this project useful, please show your support by clicking the star (
- Simplifies the management of modmail.
- Robust error handling for a smooth experience.
- Transcript system.
- Webhook logging system.

<!--
# Preview
Expand All @@ -44,63 +45,35 @@ Closing a mail (by staff):<br>
<img src="https://media.discordapp.net/attachments/1111644651036876822/1121557698824130570/2023-06-22_22_49_26-TypeScript_Bot_-_Discord.png" alt="Closing Mail Preview">
-->

# Setup

## Requirements:

- [Node.js](https://nodejs.org/en/): version 16.9.0 or above.
- [discord.js](https://www.npmjs.com/package/discord.js): version 14.12.0 or above.
- [horizon-handler](https://www.npmjs.com/package/horizon-handler) (my package): version 1.1.0 or above.
- [@tfagaming/jsondb](https://www.npmjs.com/package/@tfagaming/jsondb) (my package): version 1.2.1 or above.
- [discord.js](https://www.npmjs.com/package/discord.js): version 14.13.0 or above.
- [horizon-handler](https://www.npmjs.com/package/horizon-handler) (my package): version 1.6.0 or above.
- [@tfadev/easy-sqlite](https://www.npmjs.com/package/@tfadev/easy-sqlite) (my package): version 1.0.1 or above.
- [colors](https://www.npmjs.com/package/ms): any version.

To set up the project, follow these steps:

1. Run `npm init -y` in your terminal to initialize a new project.
2. Install the required packages by running `npm i discord.js aqify.js tfa-jsonmap colors`.
3. Create a `config.js` file using the provided `example.config.js` as a template.
4. Fill in the empty values in the `config.js` file with the required information.

> **Warning**
> If you're using repl.it, use `process.env.CLIENT_TOKEN` as your bot token in `config.js`, and then create a new key in **Secrets** named **CLIENT_TOKEN** with the value of your bot token.
> ```ts
> client: {
> token: process.env.CLIENT_TOKEN,
> id: ...
> }, ...
> ```
5. Obtain your bot token from the [Discord Developer Portal](https://discord.com/developers) and add it to the `config.js` file.
6. Configure the necessary settings for your bot, such as the guild ID, category ID for modmail, staff roles, and whether to mention staff roles for new mail notifications.
7. Start the bot by running `node index.js`, `node .`, or `npm run start` in your terminal.
## Running on Replit:
## Setup the project:

To run the project on Replit, follow these additional steps:
1. Create an account on [replit.com](https://www.replit.com) (if you don't have one already).
2. Fork this project by clicking on the **Fork For: Replit** badge.
3. Click on **Import from GitHub** and wait for Replit to import the repository.
4. Configure the Run button to execute the appropriate command (`node index.js`, `node .`, or `npm run start`).
5. Fill in the required values in the `config.js` file.
6. Set up environment secret variables for your bot token by going to **Environment Secret Variables** and adding a key with the name `CLIENT_TOKEN` and the corresponding bot token as the value.
7. Click on the green **Run** button to start your bot.
## Running on Visual Studio Code:
To run the project on Visual Studio Code, follow these additional steps:
To run the project, follow these steps:

1. Download and unzip the source code.
2. Open Visual Studio Code and select the unzipped folder as your workspace.
3. Fill in the required values in the `config.js`
3. Use `npm init -y` and then `npm i`.
4. Fill in the empty values in the `config.js` file with the required information, you can use `.env` file for more security. Obtain your bot token from the [Discord Developer Portal](https://discord.com/developers).
5. Open the terminal in Visual Studio Code and run `node index.js`, `node .`, or `npm run start`.
6. Enjoy! =)

file. 4. Open the terminal in Visual Studio Code and run `node index.js`, `node .`, or `npm run start`. 5. Enjoy! =)
### Logging Discord webhook:
Create a new integration for a text channel (which is webhook, for sure), and copy it's URL and use it in `config.js` or `.env`. It's just a simple logging system, whichs logs the newly created mail and closed mails.

## Need Assistance?

If you encounter any issues or have questions about this project, please create an issue on this repository. I will respond to your inquiries as quickly as possible. Your feedback is valuable and helps improve the project.

## Contributors
Thank you to all the people who contributed to **DiscordJS-V14-ModMail-Bot**!

<img src="https://contrib.rocks/image?repo=TFAGaming/DiscordJS-V14-ModMail-Bot">

## License
Expand Down
Empty file added SQL/main.db
Empty file.
18 changes: 10 additions & 8 deletions commands/modmail.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { SlashCommandBuilder } = require("discord.js");
const { SlashCommandBuilder, PermissionFlagsBits } = require("discord.js");
const { commandshandler, db } = require("..");

module.exports = new commandshandler.command({
Expand Down Expand Up @@ -28,7 +28,8 @@ module.exports = new commandshandler.command({
.setDescription('The user to unban.')
.setRequired(true)
)
),
)
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
run: async (client, interaction) => {

const { options } = interaction;
Expand All @@ -38,9 +39,9 @@ module.exports = new commandshandler.command({
const user = options.getUser('user', true);
const reason = options.getString('reason') || 'No reason was provided';

const count = db.bans.count((v) => v.userId === user.id);
const count = await db.select('bans', { userId: user.id });

if (count > 0) {
if (count.length > 0) {
await interaction.reply({
content: 'That user is banned already.',
ephemeral: true
Expand All @@ -49,8 +50,9 @@ module.exports = new commandshandler.command({
return;
};

db.bans.create({
await db.insert('bans', {
userId: user.id,
guildId: interaction.guild.id,
reason: reason
});

Expand All @@ -65,9 +67,9 @@ module.exports = new commandshandler.command({
case 'unban': {
const user = options.getUser('user', true);

const count = db.bans.count((v) => v.userId === user.id);
const count = await db.select('bans', { userId: user.id });

if (count <= 0) {
if (count.length <= 0) {
await interaction.reply({
content: 'That user is not banned already.',
ephemeral: true
Expand All @@ -76,7 +78,7 @@ module.exports = new commandshandler.command({
return;
};

db.bans.findOneAndDelete((v) => v.userId === user.id);
await db.delete('bans', { userId: user.id });

await interaction.reply({
content: 'That user has been unbanned successfully.',
Expand Down
21 changes: 17 additions & 4 deletions events/buttons.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { EmbedBuilder, AttachmentBuilder } = require("discord.js");
const { eventshandler, db } = require("..");
const { eventshandler, db, webhookClient } = require("..");
const config = require("../config");
const { time } = require("../functions");

module.exports = new eventshandler.event({
event: 'interactionCreate',
Expand Down Expand Up @@ -34,15 +35,15 @@ module.exports = new eventshandler.event({

transcriptMessages.reverse();

// This will remove the first messages when the mail is created. Do not touch this to avoid errors.
// This will remove the first messages when the mail is created, do not touch this to avoid future errors.
transcriptMessages.shift();
transcriptMessages.shift();

const data = db.mails.findOne((v) => v.channelId === interaction.channelId);
const data = (await db.select('mails', { channelId: interaction.channelId }))[0];

await interaction.channel.delete();

const user = client.users.cache.get(data?.userId);
const user = client.users.cache.get(data?.authorId);

if (!user) return;

Expand All @@ -67,6 +68,18 @@ module.exports = new eventshandler.event({
}).catch(null);

break;

await webhookClient.send({
embeds: [
new EmbedBuilder()
.setTitle('Mail closed')
.setDescription(`<@${data?.authorId || '000000000000000000'}>'s mail has been closed by a staff.\n\n**Executed by**: ${interaction.user.displayName} (${interaction.user.toString()})\n**Date**: ${time(Date.now(), 'f')} (${time(Date.now(), 'R')})`)
.setFooter({ text: interaction.guild.name + '\'s logging system' })
.setColor('Red')
]
});

break;
};
};

Expand Down
2 changes: 1 addition & 1 deletion events/channelDelete.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = new eventshandler.event({

if (channel.type !== 0 && channel.parentId !== category.id) return;

db.mails.findOneAndDelete((v) => v.channelId === channel.id);
await db.delete('mails', { channelId: channel.id });

}
});
4 changes: 2 additions & 2 deletions events/interactionCreate.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const { eventshandler, collection } = require("..");
const { eventshandler, commandshandler } = require("..");

module.exports = new eventshandler.event({
event: 'interactionCreate',
run: async (client, interaction) => {

if (!interaction.isChatInputCommand()) return;

const command = collection.commands.get(interaction.commandName);
const command = commandshandler.collection.get(interaction.commandName);

if (!command || command.type !== 1) return;

Expand Down
70 changes: 42 additions & 28 deletions events/messageCreate.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const { EmbedBuilder, ButtonBuilder, ButtonStyle, ActionRowBuilder, roleMention } = require("discord.js");
const { eventshandler, db } = require("..");
const { eventshandler, db, webhookClient } = require("..");
const config = require("../config");
const { time, permissionsCalculator } = require("../functions");

Expand All @@ -19,8 +19,9 @@ module.exports = new eventshandler.event({
if (message.guild) {
if (message.channel.parentId !== category.id) return;

const data = db.mails.findOne((v) => v.channelId === message.channelId);
const user = client.users.cache.get(data?.userId);
const data = (await db.select('mails', { channelId: message.channelId }))[0];

const user = guild.members.cache.get(data?.authorId);

if (!user) {
await message.reply({
Expand All @@ -42,38 +43,39 @@ module.exports = new eventshandler.event({

if (message.attachments?.size) {
const imageAttachment = message.attachments.find(attachment => attachment.contentType.startsWith('image/'));

if (imageAttachment) {
embed.setImage(imageAttachment.proxyURL);
embed.setImage(imageAttachment.proxyURL);
} else {
message.attachments.forEach(attachment => {
user.send({ files: [attachment] });
});
}
}
message.attachments.forEach(attachment => {
user.send({ files: [attachment] });
});
};
};

await user.send({
embeds: [
embed
]
}).catch(async () => {
await message.reply({
content: 'The user has their DMs blocked.'
content: 'The user has their DMs closed, or they blocked me!'
});
});

await message.react('📨');
await message.react('📨').catch(null);
} else {
const bannedCheckr = db.bans.findOne((v) => v.userId === message.author.id);
const bannedCheckr = (await db.select('bans', { userId: message.author.id }))[0];

if (bannedCheckr) {
await message.reply({
content: 'You are currently banned for using the ModMail system. Reason: ' + bannedCheckr?.reason
content: 'You are currently banned for using the ModMail system.\n\n**Reason**: ' + bannedCheckr?.reason || 'No reason was provided.'
});

return;
};

const data = db.mails.findOne((v) => v.userId === message.author.id);
const data = (await db.select('mails', { authorId: message.author.id }))[0];

const channel = guild.channels.cache.find((channel) => channel.id === data?.channelId);

Expand Down Expand Up @@ -145,10 +147,10 @@ module.exports = new eventshandler.event({
permissionOverwrites: permissions
});

db.mails.create({
userId: message.author.id,
await db.insert('mails', {
authorId: message.author.id,
channelId: newchannel.id,
guildId: guild.id
guildId: guild.id,
});

await sent.edit({
Expand All @@ -158,7 +160,7 @@ module.exports = new eventshandler.event({
.setTitle(`${guild.name} - ModMail`)
.setDescription('Thank you for creating a new mail, a staff member should respond to your ticket any time soon!')
.setFooter({
text: TFA 7524, https://www.github.com/TFAGaming/DiscordJS-V14-ModMail-Bot'
text: T.F.A 7524, https://www.github.com/TFAGaming/DiscordJS-V14-ModMail-Bot'
})
.setColor('Blurple')
],
Expand Down Expand Up @@ -187,13 +189,13 @@ module.exports = new eventshandler.event({
if (message.attachments?.size) {
const imageAttachment = message.attachments.find(attachment => attachment.contentType.startsWith('image/'));
if (imageAttachment) {
embed.setImage(imageAttachment.proxyURL);
embed.setImage(imageAttachment.proxyURL);
} else {
message.attachments.forEach(attachment => {
newchannel.send({ files: [attachment] });
});
}
}
message.attachments.forEach(attachment => {
newchannel.send({ files: [attachment] });
});
};
};

await newchannel.send({
content: config.modmail.mentionStaffRolesOnNewMail ? config.modmail.staffRoles.map((v) => roleMention(v)).join(', ') : null,
Expand All @@ -210,6 +212,18 @@ module.exports = new eventshandler.event({
)
]
}).then(async (sent) => await sent.pin());

if (webhookClient === null) return;

await webhookClient.send({
embeds: [
new EmbedBuilder()
.setTitle('New mail created')
.setDescription(`<@${message.author.id || '000000000000000000'}>'s mail has been created.\n\n**Executed by**: ${message.author.displayName} (${message.author.toString()})\n**Date**: ${time(Date.now(), 'f')} (${time(Date.now(), 'R')})`)
.setFooter({ text: guild.name + '\'s logging system' })
.setColor('Green')
]
});

break;
};
Expand Down Expand Up @@ -267,11 +281,11 @@ module.exports = new eventshandler.event({
if (message.attachments?.size) {
const imageAttachment = message.attachments.find(attachment => attachment.contentType.startsWith('image/'));
if (imageAttachment) {
embed.setImage(imageAttachment.proxyURL);
embed.setImage(imageAttachment.proxyURL);
} else {
message.attachments.forEach(attachment => {
channel.send({ files: [attachment] });
});
message.attachments.forEach(attachment => {
channel.send({ files: [attachment] });
});
}
}

Expand Down
4 changes: 2 additions & 2 deletions events/ready.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ module.exports = new eventshandler.event({

console.log('Started checking the JSON files database...');

const mails = db.mails.findMany((v) => v.guildId === guild.id);
const mails = await db.select('mails', { guildId: guild.id });

let found = 0;

Expand All @@ -40,7 +40,7 @@ module.exports = new eventshandler.event({
if (!channel) {
found++;

db.mails.findOneAndDelete((v) => v.channelId === mail.channelId);
db.delete('mails', { channelId: mail.channelId });
};
};

Expand Down
Loading

0 comments on commit 0121da0

Please sign in to comment.