From 13b4d8cbde9796426af08a3a1bac496449b2c698 Mon Sep 17 00:00:00 2001 From: Zac <57011760+Zaczer@users.noreply.github.com> Date: Wed, 5 May 2021 17:09:58 +0100 Subject: [PATCH] Updated! Updated everything. The commands `kc!vote` and `kc!help` aren't functional right now though. --- Files/package.json | 17 +++- Files/src/commands/command-base.js | 40 +++++--- Files/src/commands/fun/clap.js | 16 ++++ Files/src/commands/fun/gif.js | 18 ++-- Files/src/commands/fun/owofy.js | 4 +- Files/src/commands/load-commands.js | 30 ++++++ Files/src/commands/misc/embed-sender.js | 8 +- Files/src/commands/misc/say.js | 6 +- Files/src/commands/misc/vote.js | 50 ++++++++++ Files/src/commands/moderation/ban.js | 17 ++++ Files/src/commands/moderation/clear.js | 8 +- .../src/commands/moderation/list-warnings.js | 6 +- Files/src/commands/moderation/rr-add.js | 75 +++++++++++++++ Files/src/commands/moderation/rr-edit.js | 93 +++++++++++++++++++ Files/src/commands/moderation/set-prefix.js | 2 +- .../src/commands/moderation/set-starboard.js | 47 ++++++++++ Files/src/commands/moderation/set-welcome.js | 47 ++++++++++ Files/src/commands/moderation/warn.js | 3 +- .../src/commands/user-commands/bannedwords.js | 25 +++++ Files/src/commands/user-commands/help.js | 57 +++++++++++- Files/src/commands/user-commands/ping.js | 22 +++++ Files/src/commands/user-commands/uptime.js | 3 +- Files/src/index.js | 68 +++++--------- Files/src/schemas/rr-message.js | 8 ++ Files/src/schemas/starboard-schema.js | 14 +++ Files/src/schemas/welcome-schema.js | 14 +++ Files/src/scripts/blocked_words.js | 17 +++- Files/src/scripts/canvas-welcome.js | 25 ++++- 28 files changed, 636 insertions(+), 104 deletions(-) create mode 100644 Files/src/commands/fun/clap.js create mode 100644 Files/src/commands/load-commands.js create mode 100644 Files/src/commands/misc/vote.js create mode 100644 Files/src/commands/moderation/ban.js create mode 100644 Files/src/commands/moderation/rr-add.js create mode 100644 Files/src/commands/moderation/rr-edit.js create mode 100644 Files/src/commands/moderation/set-starboard.js create mode 100644 Files/src/commands/moderation/set-welcome.js create mode 100644 Files/src/commands/user-commands/bannedwords.js create mode 100644 Files/src/commands/user-commands/ping.js create mode 100644 Files/src/schemas/rr-message.js create mode 100644 Files/src/schemas/starboard-schema.js create mode 100644 Files/src/schemas/welcome-schema.js diff --git a/Files/package.json b/Files/package.json index b03f149..ba38d8b 100644 --- a/Files/package.json +++ b/Files/package.json @@ -1,18 +1,27 @@ { "name": "kc-bot", - "version": "1.0.5", - "description": "kc-mod-bot - Zaczer", + "version": "1.0.6", + "description": "", "main": "index.js", "scripts": { "start": "node ./src/index.js", "dev": "nodemon ./src/index.js" }, "author": "Zaczer", - "license": "MIT", + "license": "ISC", "dependencies": { + "canvas": "^2.7.0", + "crypto": "^1.0.1", + "discord-reply": "^0.1.2", "discord.js": "^12.5.1", "dotenv": "^8.2.0", - "fs": "0.0.1-security", + "fs": "^0.0.1-security", + "http": "0.0.1-security", + "https": "^1.0.0", + "moment": "^2.29.1", + "mongo": "^0.1.0", + "mongoose": "^5.12.5", + "path": "^0.12.7", "unirest": "^0.6.0" }, "devDependencies": { diff --git a/Files/src/commands/command-base.js b/Files/src/commands/command-base.js index 13334c0..a218194 100644 --- a/Files/src/commands/command-base.js +++ b/Files/src/commands/command-base.js @@ -1,7 +1,14 @@ const mongo = require('../mongo') +const fs = require('fs') const commandPrefixSchema = require('../schemas/command-prefix-schema') const guildPrefixes = {} // { 'guildID' : 'prefix' } const { prefix: globalPrefix } = require('../config.json') +const { Client, Channel } = require ('discord.js') +const client = new Client(); +const Discord = require('discord.js') +const { version } = require ('../config.json') +const { embedIcon } = require ('../config.json') + //Ensures permissions listed in commands are valid. const validatePermissions = (permissions) => { const validatePermissions = [ @@ -66,28 +73,34 @@ module.exports = (client, commandOptions) => { - // Ensure permissions are in and array and valid. + //Ensure permissions are in and array and valid. if (permissions.length) { if (typeof permissions === 'string') { permissions = [permissions] } validatePermissions(permissions) } - // Listen for messages. + //Listen for messages. client.on('message', message => { const { member, content, guild } = message - const prefix = guildPrefixes[guild.id] || globalPrefix + + try { const prefix = guildPrefixes[guild.id] || globalPrefix} catch { return } for (const alias of commands) { - if (content.toLowerCase().startsWith(`${prefix}${alias.toLowerCase()}`)) { - // A command has been ran. + const command = `${prefix}${alias.toLowerCase()}` + + if ( + content.toLowerCase().startsWith(`${command} `) || + content.toLowerCase() === command + ) { + //A command has been ran - // Ensure user has required permissions. + //Ensure user has required permissions. for (const permission of permissions) { if (!member.hasPermission(permission)) { - message.reply(permissionError) + message.lineReplyNoMention(permissionError) .then(message => { - setTimeout(() => message.delete(), 10000) + setTimeout(() => message.delete(), 3000) }) return } @@ -98,9 +111,9 @@ module.exports = (client, commandOptions) => { role.name == requiredRole) if (!role || member.roles.cache.has(role.id)) { - member.reply(`You must have the "${requiredRole} role to use this command.`) + member.lineReplyNoMention(`You must have the "${requiredRole} role to use this command.`) .then(message => { - setTimeout(() => message.delete(), 10000) + setTimeout(() => message.delete(), 3000) }) return } @@ -113,14 +126,14 @@ module.exports = (client, commandOptions) => { if (arguments.length < minArgs || ( maxArgs !== null && arguments.length > maxArgs )) { - message.reply(`Incorret syntax! Use ${prefix}${alias} ${expectedArgs}.`) + message.lineReplyNoMention(`Incorret syntax! Use ${prefix}${alias} ${expectedArgs}.`) .then(message => { - setTimeout(() => message.delete(), 10000) + setTimeout(() => message.delete(), 3000) }) return } - //Handle custom command code. + //Handle custom command outputs. callback(message, arguments, arguments.join(' ')) @@ -130,6 +143,7 @@ module.exports = (client, commandOptions) => { }) } +//Load mongo and custom prefixes. module.exports.loadPrefixes = async (client) => { await mongo().then(async mongoose => { try { diff --git a/Files/src/commands/fun/clap.js b/Files/src/commands/fun/clap.js new file mode 100644 index 0000000..d111aa5 --- /dev/null +++ b/Files/src/commands/fun/clap.js @@ -0,0 +1,16 @@ + +const Discord = require('discord.js'); +const { Client, Channel } = require ('discord.js') +const client = new Client(); + +module.exports = { + commands:['clap', 'cheer'], + expectedArgs: '', + minArgs: 1, + callback: (message, arguments, text) => { + let sentence = arguments.join(' ๐Ÿ‘ '); + + message.lineReplyNoMention(sentence) + }, + permissions: 'SEND_MESSAGES' +} \ No newline at end of file diff --git a/Files/src/commands/fun/gif.js b/Files/src/commands/fun/gif.js index 6d41ad6..71a6a3f 100644 --- a/Files/src/commands/fun/gif.js +++ b/Files/src/commands/fun/gif.js @@ -1,4 +1,5 @@ -const TENORKEY = require("../../config.json") +const fs = require('fs') +const { TENORKEY } = require('../../config.json') const { Client, Channel } = require ('discord.js') const client = new Client() const fetch = require('node-fetch') @@ -6,17 +7,18 @@ const fetch = require('node-fetch') module.exports = { commands:['gif'], expectedArgs: '', - minArgs: 1, - maxArgs: 1, + minArgs: 0, callback: async (message, arguments, text) => { try { - let keywords = message.mentions.channels.first(); - let url = `https://api.tenor.com/v1/search?q=${keywords}&key=${process.env.TENORKEY}&contentfilter=high`; - let response = await fetch(url); + keywords = arguments.join(" ") + let tenorURL = `https://api.tenor.com/v1/search?q=${keywords}&key=${TENORKEY}&contentfilter=high`; + let response = await fetch(tenorURL); let json = await response.json(); - message.channel.send(json.results.url); + const index = Math.floor(Math.random() * json.results.length); + gif = json.results[index].url + message.lineReplyNoMention(gif); } catch (error) { - message.reply(`error!\n${error.message}`) + message.lineReplyNoMention(`Error!\n${error.message}`) .then(message => { setTimeout(() => message.delete(), 10000) }) diff --git a/Files/src/commands/fun/owofy.js b/Files/src/commands/fun/owofy.js index 5037f37..988d2ca 100644 --- a/Files/src/commands/fun/owofy.js +++ b/Files/src/commands/fun/owofy.js @@ -9,7 +9,7 @@ module.exports = { minArgs: 1, callback: (message, arguments, text) => { let sentence = arguments.join(' '); - if (!sentence) return message.reply('I can\'t owo-fy an empty message! uwu'); + if (!sentence) return message.lineReplyNoMention('I can\'t owo-fy an empty message! uwu'); let faces=["(ใƒป`ฯ‰ยดใƒป)",";;w;;","owo","UwU",">w<","^w^"]; @@ -22,7 +22,7 @@ module.exports = { newSentence = newSentence.replace(/ove/g, "uv"); newSentence = newSentence.replace(/\!+/g, " "+ faces[Math.floor(Math.random()*faces.length)]+ " "); // fuck you this is now finished - message.channel.send(newSentence); + message.lineReplyNoMention(newSentence); message.delete() }, permissions: 'SEND_MESSAGES' diff --git a/Files/src/commands/load-commands.js b/Files/src/commands/load-commands.js new file mode 100644 index 0000000..44f47cf --- /dev/null +++ b/Files/src/commands/load-commands.js @@ -0,0 +1,30 @@ +const path = require('path') +const fs = require('fs') + + +module.exports = (client) => { + const baseFile = 'command-base.js' + const commandBase = require(`../commands/${baseFile}`) + + const commands = [] + + const readCommands = (dir) => { + const files = fs.readdirSync(path.join(__dirname, dir)) + for (const file of files) { + const stat = fs.lstatSync(path.join(__dirname, dir, file)) + if (stat.isDirectory()) { + readCommands(path.join(dir, file)) + } else if (file !== baseFile && file !== 'load-commands.js') { + const option = require(path.join(__dirname, dir, file)) + commands.push(option) + if (client) { + commandBase(client, option) + } + } + } + } + + readCommands('.') + + return commands + } \ No newline at end of file diff --git a/Files/src/commands/misc/embed-sender.js b/Files/src/commands/misc/embed-sender.js index b5af35b..bd675d8 100644 --- a/Files/src/commands/misc/embed-sender.js +++ b/Files/src/commands/misc/embed-sender.js @@ -6,7 +6,7 @@ module.exports = { //Use targeted channel const targetChannel = message.mentions.channels.first(); if (!targetChannel) { - message.reply('please specifiy channel.') + message.lineReplyNoMention('Please specifiy channel.') .then(message => { setTimeout(() => message.delete(), 10000) }) @@ -26,15 +26,15 @@ module.exports = { embed: json }) - //Reply to confirm - message.reply('message sent!') + //lineReplyNoMention to confirm + message.lineReplyNoMention('Message sent!') .then(message => { setTimeout(() => message.delete(), 2000) }) message.delete() } catch (error) { - message.reply(`you used invalid JSON data!\n ${error.message}`) + message.lineReplyNoMention(`You used invalid JSON data!\n ${error.message}`) .then(message => { setTimeout(() => message.delete(), 10000) }) diff --git a/Files/src/commands/misc/say.js b/Files/src/commands/misc/say.js index a127ee8..bf9b929 100644 --- a/Files/src/commands/misc/say.js +++ b/Files/src/commands/misc/say.js @@ -6,7 +6,7 @@ module.exports = { //Use targeted channel const targetChannel = message.mentions.channels.first(); if (!targetChannel) { - message.reply('please specifiy channel.') + message.lineReplyNoMention('Please specifiy channel.') .then(message => { setTimeout(() => message.delete(), 10000) }) @@ -24,14 +24,14 @@ module.exports = { targetChannel.send(text) //Reply to confirm - message.reply('message sent!') + message.lineReplyNoMention('Message sent!') .then(message => { setTimeout(() => message.delete(), 2000) }) message.delete() } catch (error) { - message.reply(`error! ${error.message}`) + message.lineReplyNoMention(`Error! ${error.message}`) } }, permissions: 'MANAGE_GUILD' diff --git a/Files/src/commands/misc/vote.js b/Files/src/commands/misc/vote.js new file mode 100644 index 0000000..e345a21 --- /dev/null +++ b/Files/src/commands/misc/vote.js @@ -0,0 +1,50 @@ +const { Client, Channel } = require ('discord.js') +const client = new Client(); +const Discord = require('discord.js') +const { version } = require ('../../config.json') +const { embedIcon } = require ('../../config.json') + +module.exports = { + commands:['vote'], + description: 'Makes an anonymous vote.', + expectedArgs: '', + minArgs: 1, + callback: async (message, arguments, text) => { + const vote = arguments.join(" ") + var yesCounter = 0 + var noCounter = 0 + const embed = new Discord.MessageEmbed() + .setTitle(`__Anonymous Vote!__`) + .addField(`${vote}\n\n`, `<:upvote:707157967471902731> - ${yesCounter} votes.\n <:downvote:707158001496096808> - ${noCounter} votes.`) + .setColor('#a3ebfb') + .setFooter(`${version}`, embedIcon) + const sentEmbed = await message.channel.send(embed) + await sentEmbed.react('<:upvote:707157967471902731>') + await sentEmbed.react('<:downvote:707158001496096808>') + const filter = (reaction, user) => (['<:upvote:707157967471902731>', '<:downvote:707158001496096808>'].includes(reaction.emoji.name) && !user.bot) + const collector = sentEmbed.createReactionCollector(filter) + + downvotedEmbed = new Discord.MessageEmbed() + .setTitle(`__Anonymous Vote!__`) + .addField(`${vote}\n\n`, `<:upvote:707157967471902731> - ${yesCounter} votes.\n <:downvote:707158001496096808> - ${noCounter +1} votes.`) + .setColor('#a3ebfb') + .setFooter(`${version}`, embedIcon) + upvotedEmbed = new Discord.MessageEmbed() + .setTitle(`__Anonymous Vote!__`) + .addField(`${vote}\n\n`, `<:upvote:707157967471902731> - ${yesCounter +1} votes.\n <:downvote:707158001496096808> - ${noCounter} votes.`) + .setColor('#a3ebfb') + .setFooter(`${version}`, embedIcon) + + collector.on("collect", (reaction, user) => { + switch (reaction.emoji.name) { + case '<:upvote:707157967471902731>': + sentEmbed.edit(upvotedEmbed); + break; + case '<:downvote:707158001496096808>': + sentEmbed.edit(downvotedEmbed); + break; + } + }); + }, + permissions: 'MANAGE_GUILD' +} \ No newline at end of file diff --git a/Files/src/commands/moderation/ban.js b/Files/src/commands/moderation/ban.js new file mode 100644 index 0000000..e74d625 --- /dev/null +++ b/Files/src/commands/moderation/ban.js @@ -0,0 +1,17 @@ +const Discord = require('discord.js') + +module.exports = { + commands: ['ban'], + description: 'Bans a member.', + expectedArgs: ' ', + minArgs: 1, + permissions: 'BAN_MEMBERS', + callback: (message, arguments, text) => { + var memberToBan = message.guild.member(message.mentions.users.first()) + arguments.shift() + var banReason = arguments + memberToBan.ban({reason: `${banReason}`}) + message.lineReplyNoMention(`${memberToBan} has been banned for the reason: \`${banReason}\`.`) + } + +} \ No newline at end of file diff --git a/Files/src/commands/moderation/clear.js b/Files/src/commands/moderation/clear.js index 1f74079..fa9b2ce 100644 --- a/Files/src/commands/moderation/clear.js +++ b/Files/src/commands/moderation/clear.js @@ -10,18 +10,18 @@ module.exports = { const amount = arguments.join(" "); - if(!amount) return message.reply('please provide an amount of messages for me to delete!') + if(!amount) return message.lineReplyNoMention('Please provide an amount of messages for me to delete!') - if(amount > 100) return message.reply(`you cannot clear more than 100 messages at once.`) + if(amount > 1000) return message.lineReplyNoMention(`You cannot clear more than 100 messages at once.`) await message.channel.messages.fetch({limit: amount}).then(messages => { message.channel.bulkDelete(messages )}); - message.channel.send(`Deleted ${amount} messages!`) + message.lineReplyNoMention(`Deleted ${amount} messages!`) .then(message => { - setTimeout(() => message.delete(), 2000) + setTimeout(() => message.delete(), 5000) }) }, diff --git a/Files/src/commands/moderation/list-warnings.js b/Files/src/commands/moderation/list-warnings.js index 5677e9d..51711a1 100644 --- a/Files/src/commands/moderation/list-warnings.js +++ b/Files/src/commands/moderation/list-warnings.js @@ -9,7 +9,7 @@ module.exports = { callback: async (message, arguments, text) => { const target = message.mentions.users.first() if (!target) { - message.reply('Please specify a user to load the warnings for.') + message.lineReplyNoMention('Please specify a user to load the warnings for.') return } @@ -33,10 +33,10 @@ module.exports = { ).toLocaleDateString()} for "${reason}"\n\n` } } catch { - message.reply('no previous warnings found.') + message.lineReplyNoMention('No previous warnings found.') return } - message.reply(reply) + message.lineReplyNoMention(reply) } finally { mongoose.connection.close() } diff --git a/Files/src/commands/moderation/rr-add.js b/Files/src/commands/moderation/rr-add.js new file mode 100644 index 0000000..94f5b82 --- /dev/null +++ b/Files/src/commands/moderation/rr-add.js @@ -0,0 +1,75 @@ +const { MessageCollector } = require('discord.js'); +const MessageModel = require('../../schemas/rr-message'); + +let messageCollectorFilter = (newmessage, originalmessage) => newmessage.author.id === originalmessage.author.id; +module.exports = { + commands: ['rradd'], + expectedArgs: '', + minArgs: 1, + maxArgs: 3, + permissions: 'MANAGE_GUILD', + description: 'Adds role reactions to a message.', + callback: async(message, arguments, text) => { + if(arguments.length !== 1) { + console.log(err) + } + else { + try { + let fetchedMessage = await message.channel.messages.fetch(arguments); + if(fetchedMessage) { + await message.lineReplyNoMention("Please provide all of the emoji names with the role name, one by one, separated with a comma.\ne.g: snapchat, snapchat, where the emoji name comes first, role name comes second."); + let collector = new MessageCollector(message.channel, messageCollectorFilter.bind(null, message)); + let emojiRoleMappings = new Map(); + collector.on('collect', message => { + let { cache } = message.guild.emojis; + if(message.content.toLowerCase() === '?done') { + collector.stop('done command was issued.'); + return; + } + let [ emojiName, roleName ] = message.content.split(/,\s+/); + if(!emojiName && !roleName) return; + let emoji = cache.find(emoji => emoji.name.toLowerCase() === emojiName.toLowerCase()); + if(!emoji) { + message.lineReplyNoMention("Emoji does not exist. Try again.") + .then(message => message.delete({ timeout: 2000 })) + .catch(err => console.log(err)); + return; + } + let role = message.guild.roles.cache.find(role => role.name.toLowerCase() === roleName.toLowerCase()); + if(!role) { + message.lineReplyNoMention("Role does not exist. Try again.") + .then(message => message.delete({ timeout: 2000 })) + .catch(err => console.log(err)); + return; + } + fetchedMessage.react(emoji) + .then(emoji => console.log("Reacted.")) + .catch(err => console.log(err)); + emojiRoleMappings.set(emoji.id, role.id); + }); + collector.on('end', async (collected, reason) => { + let findmessageDocument = await MessageModel + .findOne({ messageId: fetchedMessage.id }) + .catch(err => console.log(err)); + if(findmessageDocument) { + console.log("The message exists.. Don't save..."); + message.lineReplyNoMention("A role reaction set up exists for this message already..."); + } + else { + let dbmessageModel = new MessageModel({ + messageId: fetchedMessage.id, + emojiRoleMappings: emojiRoleMappings + }); + dbmessageModel.save() + .then(m => console.log(m)) + .catch(err => console.log(err)); + } + }); + } + } + catch(err) { + console.log(err); + } + } + }, +} \ No newline at end of file diff --git a/Files/src/commands/moderation/rr-edit.js b/Files/src/commands/moderation/rr-edit.js new file mode 100644 index 0000000..e02906f --- /dev/null +++ b/Files/src/commands/moderation/rr-edit.js @@ -0,0 +1,93 @@ +const MessageModel = require('../../schemas/rr-message'); +const { MessageCollector } = require('discord.js'); + +module.exports = { + commands: ['rredit'], + expectedArgs: '', + minArgs: 1, + maxArgs: 1, + permissions: 'MANAGE_GUILD', + description: 'Edits role reaction configurations.', + callback: async(client, message, args) => { + if(args.split(" ").length !== 1) return; + // Check if the message exists. + const { channel, author } = message; + try { + let fetchedMessage = channel.messages.cache.get(args) || await channel.messages.fetch(args); + if(!fetchedMessage) + channel.send("Message not found."); + else { + // Check if the message exists in the DB. + let msgModel = await MessageModel.findOne({ messageId: args }); + if(msgModel) { + client.emit('msgDocFetched', msgModel); + // Prompt the user for configurations. + let filter = m => m.author.id === author.id && (m.content.toLowerCase() === 'add' || m.content.toLowerCase() === 'remove'); + let tempMsg = channel.send("Do you want to add or remove from the reaction configuration? Type 'add' or 'remove'."); + try { + let awaitMsgOps = { max: 1, time: 4000, errors: ['time'] }; + let choice = (await channel.awaitMessages(filter, awaitMsgOps)).first(); + if(choice.content === "add") { + let addMsgPrompt = await channel.send("Enter an emoji name followed by the corresponding role name, separated with a comma. e.g: some_emoji, some_role"); + let collectorResult = await handleCollector(fetchedMessage, author, channel, msgModel, args); + console.log(collectorResult); + } + else { + + } + } + catch(err) { + console.log(err); + } + } + else { + message.lineReplyNoMention("There is no configuration for that message. Please use ?addreactions on a message to set up Role Reactions on that message.") + } + } + } + catch(err) { + console.log(err); + } + }, + +} +function handleCollector(fetchedMessage, author, channel, msgModel, messageId) { + return new Promise((resolve, reject) => { + let collectorFilter = (m) => m.author.id === author.id; + let collector = new MessageCollector(channel, collectorFilter); + let emojiRoleMappings = new Map(Object.entries(msgModel.emojiRoleMappings)); + collector.on('collect', msg => { + if(msg.content.toLowerCase() === '?done') { + collector.stop(); + resolve(); + } + else { + let { cache } = msg.guild.emojis; + let [ emojiName, roleName ] = msg.content.split(/,\s+/); + if(!emojiName && !roleName) return; + let emoji = cache.find(emoji => emoji.name.toLowerCase() === emojiName.toLowerCase()); + if(!emoji) { + msg.channel.send("Emoji does not exist. Try again.") + .then(msg => msg.delete({ timeout: 2000 })) + .catch(err => console.log(err)); + return; + } + let role = msg.guild.roles.cache.find(role => role.name.toLowerCase() === roleName.toLowerCase()); + if(!role) { + msg.channel.send("Role does not exist. Try again.") + .then(msg => msg.delete({ timeout: 2000 })) + .catch(err => console.log(err)); + return; + } + fetchedMessage.react(emoji) + .then(emoji => console.log("Reacted!")) + .catch(err => console.log(err)); + emojiRoleMappings.set(emoji.id, role.id); + } + }); + collector.on('end', () => { + console.log("Done (rr)."); + resolve(emojiRoleMappings); + }); + }); +} \ No newline at end of file diff --git a/Files/src/commands/moderation/set-prefix.js b/Files/src/commands/moderation/set-prefix.js index 0280a3e..5db1509 100644 --- a/Files/src/commands/moderation/set-prefix.js +++ b/Files/src/commands/moderation/set-prefix.js @@ -23,7 +23,7 @@ module.exports = { upsert: true }) - message.reply(`the prefix for this bot is now \`${prefix}\``) + message.lineReplyNoMention(`The prefix for this bot is now \`${prefix}\`!`) } finally { mongoose.connection.close() } diff --git a/Files/src/commands/moderation/set-starboard.js b/Files/src/commands/moderation/set-starboard.js new file mode 100644 index 0000000..e9a80b3 --- /dev/null +++ b/Files/src/commands/moderation/set-starboard.js @@ -0,0 +1,47 @@ +const starboardSchema = require('../../schemas/starboard-schema') +const mongo = require('../../mongo') +const cache = new Map() + +const loadData = async () => { + const results = await starboardSchema.find() + + for (const result of results) { + cache.set(result._id, result.channelId) + } +} +loadData() + +module.exports = { + commands: ['setstarboard'], + permissionError: 'You need to have the MANAGE_GUILD permission to run this command.', + permissions: 'MANAGE_GUILD', + callback: async (message, arguments, text) => { + const { guild, channel } = message + await mongo().then(async mongoose => { + try { + await starboardSchema.findOneAndUpdate( + { + _id: guild.id, + }, + { + _id: guild.id, + channelId: channel.id, + }, + { + upsert: true, + } + ) + + cache.set(guild.id, channel.id) + + message.lineReplyNoMention('Starboard channel set!') + } finally { + mongoose.connection.close() + } + }) + } +} + +module.exports.getChannelId = (guildId) => { + return cache.get(guildId) +} diff --git a/Files/src/commands/moderation/set-welcome.js b/Files/src/commands/moderation/set-welcome.js new file mode 100644 index 0000000..0c43b8c --- /dev/null +++ b/Files/src/commands/moderation/set-welcome.js @@ -0,0 +1,47 @@ +const welcomeSchema = require('../../schemas/welcome-schema') +const mongo = require('../../mongo') +const cache = new Map() + +const loadData = async () => { + const results = await welcomeSchema.find() + + for (const result of results) { + cache.set(result._id, result.channelId) + } +} +loadData() + +module.exports = { + commands: ['setwelcome'], + permissionError: 'You need to have the MANAGE_GUILD permission to run this command.', + permissions: 'MANAGE_GUILD', + callback: async (message, arguments, text) => { + const { guild, channel } = message + await mongo().then(async mongoose => { + try { + await welcomeSchema.findOneAndUpdate( + { + _id: guild.id, + }, + { + _id: guild.id, + channelId: channel.id, + }, + { + upsert: true, + } + ) + + cache.set(guild.id, channel.id) + + message.lineReplyNoMention('Welcome channel set!') + } finally { + mongoose.connection.close() + } + }) + } +} + +module.exports.getChannelId = (guildId) => { + return cache.get(guildId) +} diff --git a/Files/src/commands/moderation/warn.js b/Files/src/commands/moderation/warn.js index 5c270ac..35e0ce9 100644 --- a/Files/src/commands/moderation/warn.js +++ b/Files/src/commands/moderation/warn.js @@ -9,7 +9,7 @@ module.exports = { callback: async (message, arguments) => { const target = message.mentions.users.first() if (!target) { - message.reply('please mention someone to warn!') + message.lineReplyNoMention('Please mention someone to warn!') .then(message => { setTimeout(() => message.delete(), 2000) }) @@ -48,6 +48,7 @@ module.exports = { ) } finally { mongoose.connection.close() + message.lineReplyNoMention('Target warned.') } }) }, diff --git a/Files/src/commands/user-commands/bannedwords.js b/Files/src/commands/user-commands/bannedwords.js new file mode 100644 index 0000000..8fa9e4b --- /dev/null +++ b/Files/src/commands/user-commands/bannedwords.js @@ -0,0 +1,25 @@ +const { Client, Channel } = require ('discord.js') +const client = new Client(); +const Discord = require('discord.js') +const { version } = require ('../../config.json') +const { embedIcon } = require ('../../config.json') +var { bannedWords } = require ('../../config.json') + + +module.exports = { + commands:['words', 'bannedwords'], + description: 'DMs a list of banned words.', + expectedArgs: '', + minArgs: 0, + maxArgs: 0, + callback: (message, arguments, text) => { + const embed = new Discord.MessageEmbed() + .setTitle(`__Banned Words__`) + .addField('The following words are banned:\n', `\`\`\`${bannedWords.join(", ")}\`\`\``) + .setColor('#a3ebfb') + .setFooter(`${version}`, embedIcon) + message.lineReplyNoMention("I've DMed you with a list of all the banned words!") + message.author.send(embed) + }, + permissions: 'SEND_MESSAGES' +} \ No newline at end of file diff --git a/Files/src/commands/user-commands/help.js b/Files/src/commands/user-commands/help.js index 9ad7cea..32ee1f1 100644 --- a/Files/src/commands/user-commands/help.js +++ b/Files/src/commands/user-commands/help.js @@ -1,8 +1,57 @@ +const loadCommands = require('../load-commands') +const { prefix } = require('../../config.json') +const { Client, Channel } = require ('discord.js') +const client = new Client(); +const Discord = require('discord.js') +const { version } = require ('../../config.json') +const { embedIcon } = require ('../../config.json') + module.exports = { - commands:['help'], + commands:['help', 'h', 'cmds', 'commands'], + description: 'Lists all commands!', minArgs: 0, maxArgs: 0, callback: (message, arguments, text) => { - message.reply('welcome to KC!\nI am your faithful moderation bot!') - }, -} + + const commands = loadCommands() + + for (const command of commands) { + // Check for permissions + let permissions = command.permission + + if (permissions) { + let hasPermission = true + if (typeof permissions === 'string') { + permissions = [permissions] + } + + for (const permission of permissions) { + if (!message.member.hasPermission(permission)) { + hasPermission = false + break + } + } + + if (!hasPermission) { + continue + } + } + + // Format the text + const mainCommand = + typeof command.commands === 'string' + ? command.commands + : command.commands[0] + const args = command.expectedArgs ? ` ${command.expectedArgs}` : '' + const { description } = command + + reply = new Discord.MessageEmbed() + .setTitle(`__All Commands:__`) + .addField(`**\`${mainCommand}${args}\`** = ${description}\n`) + .setColor('#a3ebfb') + .setFooter(`${version}`, embedIcon) + } + + message.lineReplyNoMention(reply) + }, + } diff --git a/Files/src/commands/user-commands/ping.js b/Files/src/commands/user-commands/ping.js new file mode 100644 index 0000000..59037fe --- /dev/null +++ b/Files/src/commands/user-commands/ping.js @@ -0,0 +1,22 @@ +const { Client, Channel } = require ('discord.js') +const client = new Client(); +const Discord = require('discord.js') +const { version } = require ('../../config.json') +const { embedIcon } = require ('../../config.json') + +module.exports = { + commands:['ping', 'test'], + description: 'Shows the delay of the bot.', + expectedArgs: '', + minArgs: 0, + maxArgs: 0, + callback: (message, arguments, text) => { + const embed = new Discord.MessageEmbed() + .setTitle(`__Pong! ๐Ÿ“__`) + .addField('Latency is:', `${Date.now() - message.createdTimestamp} ms!`) + .setColor('#a3ebfb') + .setFooter(`${version}`, embedIcon) + message.lineReplyNoMention(embed); + }, + permissions: 'SEND_MESSAGES' +} \ No newline at end of file diff --git a/Files/src/commands/user-commands/uptime.js b/Files/src/commands/user-commands/uptime.js index 45019a6..8d9815d 100644 --- a/Files/src/commands/user-commands/uptime.js +++ b/Files/src/commands/user-commands/uptime.js @@ -9,6 +9,7 @@ module.exports = { expectedArgs: '', minArgs: 0, maxArgs: 0, + description: 'Shows the uptime of the bot.', callback: (message, arguments, text) => { let days = Math.floor(message.client.uptime / 86400000); @@ -24,7 +25,7 @@ module.exports = { .addField("Seconds", `${seconds}`) .setColor('#a3ebfb') .setFooter(`${version}`, embedIcon) - message.channel.send(embed); + message.lineReplyNoMention(embed); }, permissions: 'SEND_MESSAGES' } \ No newline at end of file diff --git a/Files/src/index.js b/Files/src/index.js index e6382af..80ed69b 100644 --- a/Files/src/index.js +++ b/Files/src/index.js @@ -1,42 +1,35 @@ -require('dotenv').config(); +//Load token const { botToken } = require('./config.json') +//Load modules etc. const mongoose = require ('mongoose') const path = require('path') const fs = require('fs') -const welcome = require('./scripts/canvas-welcome') -const stats = require('./scripts/channel-stats') -const blocked_words = require('./scripts/blocked_words') +require('discord-reply') const { Client, Channel } = require ('discord.js') const Discord = require('discord.js') -const PREFIX = "kc!" const client = new Client(); -const unirest = require('unirest'); const mongo = require('./mongo.js') + +//Import scripts +const loadCommands = require('./commands/load-commands') +const starboard = require('./scripts/starboard') +const welcome = require('./scripts/canvas-welcome') +const stats = require('./scripts/channel-stats') +const status = require('./scripts/set-status') +const blocked_words = require('./scripts/blocked_words') + +//Load other stuff const commandBase = require('./commands/command-base') -client.login(`${botToken}`) mongoose.set('useFindAndModify', false); +//Login +client.login(`${botToken}`) + client.on('ready', async () => { - client.user.setActivity('Kingdoms Crusade', { type: 'WATCHING' }); console.log("Credit to Zaczer#0005") - const baseFile = 'command-base.js' - const commandBase = require(`./commands/${baseFile}`) - - const readCommands = dir => { - const files = fs.readdirSync(path.join(__dirname, dir)) - for (const file of files) { - const stat = fs.lstatSync(path.join(__dirname, dir, file)) - if (stat.isDirectory()) { - readCommands(path.join(dir, file)) - } else if (file !== baseFile) { - const option = require(path.join(__dirname, dir, file)) - commandBase(client, option) - } - } - } - + //Connect to mongo await mongo().then(mongoose => { try{ console.log('Connected to MongoDB!') @@ -45,29 +38,12 @@ client.on('ready', async () => { mongoose.connection.close() } }) - - readCommands('commands') + //Load scripts and commands + loadCommands(client) commandBase.loadPrefixes(client) blocked_words(client) welcome(client) + starboard(client) stats(client) -}); - - - - -client.on('message', async (message) => { - //Error Messages - const errorMessage = () => { - message.channel.send('Hmmm, something went wrong.'); - }; - - msg=message.content.toLowerCase(); - - //make shift error handling, send myself a message - const oatMeal = (message) => { - client.fetchUser('442243565494599701').then((user) => { - user.send(message); - }); - }; -}) + status(client) +}); \ No newline at end of file diff --git a/Files/src/schemas/rr-message.js b/Files/src/schemas/rr-message.js new file mode 100644 index 0000000..2077a1f --- /dev/null +++ b/Files/src/schemas/rr-message.js @@ -0,0 +1,8 @@ + +const mongoose = require('mongoose'); +const MessageSchema = new mongoose.Schema({ + messageId: { type: String, required: true }, + emojiRoleMappings: { type: mongoose.Schema.Types.Mixed } +}); + +const MessageModel = module.exports = mongoose.model('rr-message', MessageSchema); \ No newline at end of file diff --git a/Files/src/schemas/starboard-schema.js b/Files/src/schemas/starboard-schema.js new file mode 100644 index 0000000..e1adba5 --- /dev/null +++ b/Files/src/schemas/starboard-schema.js @@ -0,0 +1,14 @@ +const mongoose = require('mongoose') + +const reqString = { + type: String, + required: true, +} + +const starboardSchema = new mongoose.Schema({ + // Guild ID + _id: reqString, + channelId: reqString, +}) + +module.exports = mongoose.model('starboard', starboardSchema) \ No newline at end of file diff --git a/Files/src/schemas/welcome-schema.js b/Files/src/schemas/welcome-schema.js new file mode 100644 index 0000000..8255fb1 --- /dev/null +++ b/Files/src/schemas/welcome-schema.js @@ -0,0 +1,14 @@ +const mongoose = require('mongoose') + +const reqString = { + type: String, + required: true, +} + +const welcomeSchema = new mongoose.Schema({ + // Guild ID + _id: reqString, + channelId: reqString, +}) + +module.exports = mongoose.model('canvas-welcome', welcomeSchema) \ No newline at end of file diff --git a/Files/src/scripts/blocked_words.js b/Files/src/scripts/blocked_words.js index a23fcad..0e11b23 100644 --- a/Files/src/scripts/blocked_words.js +++ b/Files/src/scripts/blocked_words.js @@ -3,16 +3,23 @@ const Discord = require('discord.js') module.exports = client => { client.on('message', async(msg) => { - if(msg.author.bot) return; if(!msg.guild) return; var regex = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g; - var list = ['titties', 'nudes', 'WetAssPussy', 'hore', 'whore', 'masturbating', 'fag', 'noah morton', 'isaac wood', 'nigger', 'nigga', 'nibba', 'niga', 'n1gger', 'n1gga', 'cock', 'cum', 'vagina', 'hentai', 'penis', 'milf', 'porn', 'pornhub', 'pornhubpremium', 'dildo', 'rape', 'anal', 'clit', 'dick', 'pussy', 'orgy', 'gangbang', 'hcodes', 'fetish', 'pedo', 'pedophile', 'porno', 'pornos', 'pussys', 'pussies', 'pornography', 'pedophilia', 'pedophilliac', 'phonesex', 'dildos', 'fisting', 'doggystyle', 'doggiestyle', 'fingerfuck', 'blowjob', 'handjob', 'wanking', 'nazi', 'morton']; - if(!msg.member.hasPermission('MANAGE_MESSAGES')){ - if(list.some(w => ` ${msg.content.toLowerCase()} `.includes(` ${w} `))){ + var list = ["titties", "nudes", "dickhead", "cocaine", "pussy", "fucktard", "gaylord", "libtard", "cuck", "cucklord", "gaylors", "orgasm", "sex", "cum", "niggur", "nignog", "cumsickle", "retard", "threesome", "foursome", "cunt", "condom", "WetAssPussy", "negro", "negros", "hore", "whore", "masturbating", "fag", "nigger", "nigga", "nibba", "niga", "n1gger", "n1gga", "cock", "cum", "vagina", "hentai", "penis", "milf", "porn", "pornhub", "pornhubpremium", "dildo", "rape", "anal", "clit", "dick", "pussy", "orgy", "gangbang", "hcodes", "fetish", "pedo", "pedophile", "porno", "pornos", "pussys", "pussies", "pornography", "pedophilia", "pedophilliac", "phonesex", "dildos", "fisting", "doggystyle", "doggiestyle", "fingerfuck", "blowjob", "handjob", "wanking", "nazi"] + + if((msg.author.id == 800470294979543068) & (list.some(w => ` ${msg.content.toLowerCase()} `.includes(` ${w} `)))) { + const arguments = msg.content.split(/[ ]+/) + let name = arguments[0].replace(/,/g, "") + msg.channel.send(`${name}, please refrain from using banned/NSFW words.`) + msg.channel.send(`/warn ${name} using inappropriate language.`) + .then(message => { + setTimeout(() => message.delete(), 1000) + }) + } else if((list.some(w => ` ${msg.content.toLowerCase()} `.includes(` ${w} `)))){ msg.delete(); msg.reply('please refrain from using banned/NSFW words.') } - } + }) } diff --git a/Files/src/scripts/canvas-welcome.js b/Files/src/scripts/canvas-welcome.js index 3e902a7..c1899d1 100644 --- a/Files/src/scripts/canvas-welcome.js +++ b/Files/src/scripts/canvas-welcome.js @@ -3,15 +3,24 @@ const Canvas = require('canvas') const { MessageAttachment } = require('discord.js') const path = require('path') +const { getChannelId } = require('../commands/moderation/set-welcome') + module.exports = (client) => { client.on('guildMemberAdd', async (member) => { // Async function // Destructure the guild property from the member object const { guild } = member // Access the channel ID for this guild from the cache - const channelId = '743530164041809932' - // Access the actual channel and send the message + const channelId = getChannelId(guild.id) + if (!channelId) { + return + } + const channel = guild.channels.cache.get(channelId) + if (!channel) { + return + } + // Create a canvas and access the 2d context const canvas = Canvas.createCanvas(700, 250) const ctx = canvas.getContext('2d') @@ -44,8 +53,14 @@ module.exports = (client) => { ctx.fillText(text, x, 100 + pfp.height) // Attach the image to a message and send it const attachment = new MessageAttachment(canvas.toBuffer()) - const targetChannelID = '698580298182688809' //Rules - const targetChannelID2 = '805737859881369650' //Info - channel.send(`Welcome, <@${member.id}> to Kingdoms Crusade! Make sure you read ${member.guild.channels.cache.get(targetChannelID).toString()} and ${member.guild.channels.cache.get(targetChannelID2).toString()}!`, attachment) + + if (channelId === '743530164041809932') { + const targetChannelID = '698580298182688809' //Rules + const targetChannelID2 = '805737859881369650' //Info + channel.send(`Welcome, <@${member.id}> to Kingdoms Crusade! Make sure you read ${member.guild.channels.cache.get(targetChannelID).toString()} and ${member.guild.channels.cache.get(targetChannelID2).toString()}!`, attachment) + } else { + + channel.send(`Welcome, <@${member.id}>!`, attachment) + } }) } \ No newline at end of file