A portion of my soul.

This commit is contained in:
Kwafuri
2024-02-03 21:32:04 +00:00
parent 6d47fb7bab
commit dca679131a
15 changed files with 362 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
node_modules
.env
package-lock.json
+1
View File
@@ -1,2 +1,3 @@
# discordjs-verification-bot
Nothing to read here, every
+27
View File
@@ -0,0 +1,27 @@
module.exports = {
"prefix": "!?",
"guilds": {
"1033940528317866105": { //guild id
"channelId": "1033941062101766245", //channel id where the command is allowed
'roleToAdd': '1033996796109795408', //verified role id
'firstRole': '1203243427081355264', //unverified role id
},
"1203447255491809351": {
"channelId": "1203448057723748382",
'roleToAdd': '1203448287894704178',
'firstRole': '1203448332144611328',
}
},
'captchaCount': '7',
'captchaTimeout': '120000', //in milliseconds (seconds multiplied by 1000)
'messages': {
//literally messages lmao
'toVerify': 'Please verify that you are not a robot.',
'success': 'You have been verified successfully.',
'fail': 'You have failed the captcha verification. Please try again.',
'wrongChannel': 'You can\'t use this command here.',
'alreadyVerified': 'You are already verified.',
'tookTooLong': 'You took too long to respond. Please try again.',
'unableToDM': 'I was unable to send you a DM. Please make sure "Allow Direct Message" for this guild is enabled.'
}
}
+9
View File
@@ -0,0 +1,9 @@
const { EmbedBuilder, AttachmentBuilder } = require('discord.js');
const client = require('..');
const cfg = require('../config/config.js');
client.on('guildMemberAdd', async member => {
//get guild id
const guildId = member.guild.id;
await member.roles.add(cfg.guilds[guildId].firstRole);
});
+22
View File
@@ -0,0 +1,22 @@
const { EmbedBuilder, Collection, PermissionsBitField, ChannelType } = require('discord.js');
const client = require('..');
const config = require('../config/config.js');
client.on('interactionCreate', async interaction => {
const slashCommand = client.slashCommands.get(interaction.commandName);
if (interaction.type === 4) {
if (slashCommand.autocomplete) {
const choices = [];
await slashCommand.autocomplete(interaction, choices);
}
}
if (!interaction.type === 2) return;
if (interaction.channel.type === ChannelType.DM) {
return interaction.reply({ content: "This weren't supposed to be used here...", ephemeral: true });
}
if (!slashCommand) return client.slashCommands.delete(interaction.commandName);
await slashCommand.run(client, interaction);
});
+15
View File
@@ -0,0 +1,15 @@
const { EmbedBuilder, Collection, PermissionsBitField, ChannelType } = require('discord.js');
const client = require('..');
const config = require('../config/config.js');
client.on('messageCreate', async message => {
if (message.author.bot) return;
if (message.channel.type === ChannelType.DM) return;
if (!message.content.startsWith(config.prefix)) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/);
const cmd = args.shift().toLowerCase();
if (cmd.length === 0) return;
const commands = client.commands.get(cmd);
commands.run(client, message, args);
})
+7
View File
@@ -0,0 +1,7 @@
const { ActivityType } = require('discord.js');
const client = require('..');
const chalk = require('chalk');
client.on('ready', () => {
console.log(chalk.green(`Logged in as ${client.user.tag}!`));
});
+16
View File
@@ -0,0 +1,16 @@
const fs = require('fs');
const chalk = require('chalk');
var AsciiTable = require('ascii-table');
var table = new AsciiTable();
table.setHeading('Buttons', 'Status').setBorder('|', '-', '+', '+');
module.exports.name = 'buttons';
module.exports = (client) => {
fs.readdirSync('./buttons/').filter((file) => file.endsWith('.js')).forEach((file) => {
const button = require(`../buttons/${file}`);
client.buttons.set(button.id, button);
table.addRow(button.id, chalk.green('Loaded'));
});
console.log(chalk.magenta(table.toString()));
};
+23
View File
@@ -0,0 +1,23 @@
const chalk = require('chalk');
const fs = require('fs');
const AsciiTable = require('ascii-table');
const table = new AsciiTable();
table.setHeading('Commands', 'Status').setBorder('|', '-', '+', '+');
module.exports.name = 'commands';
module.exports = (client) => {
fs.readdirSync('./commands/').forEach((dir) => {
const files = fs.readdirSync(`./commands/${dir}`).filter((file) => file.endsWith('.js'));
if (files.length <= 0) return;
files.forEach((file) => {
let command = require(`../commands/${dir}/${file}`);
if (command) {
client.commands.set(command.name, command);
table.addRow(command.name, chalk.green('Loaded'));
} else {
table.addRow(file, chalk.red('Failed'));
}
});
});
console.log(chalk.magenta(table.toString()));
}
+15
View File
@@ -0,0 +1,15 @@
const fs = require('fs');
const chalk = require('chalk');
var AsciiTable = require('ascii-table');
var table = new AsciiTable();
table.setHeading('Events', 'Status').setBorder('|', '-', '+', '+');
module.exports.name = 'events';
module.exports = (client) => {
fs.readdirSync('./events/').filter((file) => file.endsWith('.js')).forEach((file) => {
require(`../events/${file}`);
table.addRow(file.split('.js')[0], chalk.green('Loaded'));
});
console.log(chalk.magenta(table.toString()));
};
+15
View File
@@ -0,0 +1,15 @@
const fs = require('fs');
const chalk = require('chalk');
var AsciiTable = require('ascii-table');
var table = new AsciiTable();
table.setHeading('Handlers', 'Status').setBorder('|', '-', '+', '+');
module.exports.name = 'handlers';
module.exports = (client) => {
fs.readdirSync('./handlers/').filter((file) => file.endsWith('.js')).forEach((file) => {
if (file === 'handlers.js') return;
require(`./${file}`)(client);
table.addRow(file.split('.js')[0], chalk.green('Loaded'));
});
console.log(chalk.magenta(table.toString()));
};
+51
View File
@@ -0,0 +1,51 @@
const fs = require('fs');
const chalk = require('chalk');
const { PermissionsBitField } = require('discord.js');
const { Routes } = require('discord-api-types/v9');
const { REST } = require('@discordjs/rest');
const AsciiTable = require('ascii-table');
const table = new AsciiTable().setHeading('Slash Commands', 'Status').setBorder('|', '-', '+', '+');
const token = process.env.TOKEN;
const clientId = process.env.CLIENTID;
const rest = new REST({ version: '9' }).setToken(token);
module.exports.name = 'slashCommands';
module.exports = async (client) => {
const slashCommands = [];
fs.readdirSync('./slashCommands/').forEach(async dir => {
const files = fs.readdirSync(`./slashCommands/${dir}`).filter(file => file.endsWith('.js'));
for (const file of files) {
const slashCommand = require(`../slashCommands/${dir}/${file}`);
slashCommands.push({
name: slashCommand.name,
description: slashCommand.description,
type: slashCommand.type
});
if (slashCommand.name) {
client.slashCommands.set(slashCommand.name, slashCommand);
table.addRow(file.split('.js')[0], chalk.green('Loaded'));
} else {
table.addRow(file.split('.js')[0], chalk.red('Failed'));
}
}
});
console.log(chalk.blue(table.toString()));
(async () => {
try {
await rest.put(
Routes.applicationCommands(clientId),
{ body: slashCommands },
);
console.log(chalk.cyan('Successfully registered application commands.'));
} catch (error) {
console.error(chalk.red('Error while registering application commands:'), error);
}
})();
};
+28
View File
@@ -0,0 +1,28 @@
const { Client, Collection, Permissions, GatewayIntentBits, Partials } = require('discord.js');
require('dotenv').config();
const client = new Client({
allowedMentions: { parse: ['users', 'roles'], repliedUser: true },
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.MessageContent,
],
partials: [
Partials.Channel,
Partials.Message,
Partials.User,
]
});
module.exports = client;
client.commands = new Collection();
client.slashCommands = new Collection();
client.buttons = new Collection();
require('./handlers/handlers.js')(client);
client.login(process.env.TOKEN);
+24
View File
@@ -0,0 +1,24 @@
{
"name": "discordjs-verification-bot",
"version": "0.0.0-no-version",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node main.js"
},
"repository": {
"type": "git",
"url": "https://git.ssh.surf/Nahokey/discordjs-verification-bot/"
},
"author": "Nahokey",
"license": "ISC",
"dependencies": {
"ascii-table": "^0.0.9",
"canvas": "^2.11.2",
"chalk": "^2.4.1",
"discord.js": "^14.14.1",
"dotenv": "^16.4.1",
"fs": "^0.0.1-security"
}
}
+106
View File
@@ -0,0 +1,106 @@
const { EmbedBuilder, ApplicationCommandType, Collection, AttachmentBuilder } = require('discord.js');
const { createCanvas, loadImage } = require('canvas');
const cfg = require('../../config/config.js');
const captchaUser = new Collection();
module.exports = {
name: 'verify',
description: 'To verify yourself.',
type: ApplicationCommandType.ChatInput,
run: async (client, interaction) => {
const guildId = interaction.guild.id;
//functions here
async function generateCaptcha(count) {
var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
var captcha = '';
for (var i = 0; i < count; i++) {
captcha += chars.charAt(Math.floor(Math.random() * chars.length));
}
return captcha;
}
async function createCaptcha(captcha) {
const canvas = createCanvas(200, 75);
const ctx = canvas.getContext('2d');
ctx.font = '30px Arial';
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.fillStyle = 'white';
ctx.fillText(captcha, 100, 37.5);
const buffer = canvas.toBuffer('image/png');
return buffer;
}
//check if user is in the correct channel
if (interaction.channel.id !== cfg.guilds[guildId].channelId) {
return interaction.reply({ content: cfg.messages.wrongChannel, ephemeral: true })
}
//check if user has the roleToRemove
if (interaction.member.roles.cache.has(cfg.guilds[guildId].roleToAdd)) {
return interaction.reply({ content: cfg.messages.alreadyVerified, ephemeral: true })
}
const captcha = await generateCaptcha(cfg.captchaCount);
const buff = await createCaptcha(captcha);
const attachment = new AttachmentBuilder(buff, { name: 'captcha.png' });
const embed = new EmbedBuilder()
.setTitle("Captcha Verification")
.setDescription(`Please type the captcha below. You have ${cfg.captchaTimeout / 1000} seconds to respond.`)
.setColor('Green')
.setImage('attachment://captcha.png')
.setTimestamp();
await interaction.user.send({
embeds: [embed], files: [attachment]
}).then(async (msg) => {
await interaction.reply({
content: cfg.messages.toVerify,
ephemeral: true
})
const filter = m => m.author.id === interaction.user.id;
const collector = msg.channel.createMessageCollector({
filter,
time: cfg.captchaTimeout
});
collector.on('collect', async (m) => {
if (m.content === captcha) {
await interaction.member.roles.add(cfg.guilds[guildId].roleToAdd);
await interaction.member.roles.remove(cfg.guilds[guildId].firstRole);
await interaction.user.send(cfg.messages.success);
collector.stop();
} else {
await interaction.user.send(cfg.messages.fail);
collector.stop();
}
});
collector.on('end', async (collected, reason) => {
if (reason === 'time') {
await interaction.user.send(cfg.messages.tookTooLong);
}
});
})
.catch(async (err) => {
await interaction.reply({
content: cfg.messages.unableToDM,
ephemeral: true
});
});
}
}
/*
Note from Naoki:
This looks simple enough but damn.
Canvas is driving me nuts due to how hard to work with it.
Had to StackOverFlow-ed it to get it to work.
I'm not sure if this is the best way to do it but it works.
Big shoutout to StackOverFlow and the people I got the code from.
*/