From de88eaaf71701b8d8a75450af8d9941edc9a0af9 Mon Sep 17 00:00:00 2001 From: AkimotoRyou <39645219+AkimotoRyou@users.noreply.github.com> Date: Fri, 24 Apr 2020 12:29:04 +0700 Subject: [PATCH] Restructuring bot --- commands/aclose.js | 67 ++ commands/areply.js | 70 ++ commands/bind.js | 50 + commands/block.js | 53 + commands/blockinfo.js | 53 + commands/blocklist.js | 53 + commands/close.js | 67 ++ commands/commands.js | 107 ++ commands/configinfo.js | 50 + commands/configuration.js | 51 + commands/guilds.js | 52 + commands/help.js | 46 + commands/helpchs.js | 20 + commands/helpcht.js | 20 + commands/helpde.js | 20 + commands/helpes.js | 20 + commands/helpfr.js | 20 + commands/helpkr.js | 20 + commands/helppt.js | 20 + commands/helpru.js | 20 + commands/helptr.js | 20 + commands/leave.js | 38 + commands/new.js | 44 + commands/ping.js | 30 + commands/reload.js | 43 + commands/reply.js | 70 ++ commands/reset.js | 67 ++ commands/restart.js | 59 + commands/set.js | 50 + commands/threadinfo.js | 55 + commands/unblock.js | 53 + config.json | 6 +- functions/aclose.js | 73 ++ functions/areply.js | 85 ++ functions/bind.js | 43 + functions/block.js | 33 + functions/blockinfo.js | 30 + functions/blocklist.js | 41 + functions/close.js | 73 ++ functions/configInfo.js | 96 ++ functions/configSync.js | 38 + functions/configuration.js | 48 + functions/getEmbed.js | 12 + functions/isBlocked.js | 13 + functions/isMember.js | 15 + functions/newThread.js | 106 ++ functions/reply.js | 85 ++ functions/reset.js | 27 + functions/roleCheck.js | 12 + functions/set.js | 119 ++ functions/threadInfo.js | 52 + functions/unblock.js | 24 + functions/userReply.js | 64 ++ index.js | 2145 ++++++------------------------------ 54 files changed, 2826 insertions(+), 1822 deletions(-) create mode 100644 commands/aclose.js create mode 100644 commands/areply.js create mode 100644 commands/bind.js create mode 100644 commands/block.js create mode 100644 commands/blockinfo.js create mode 100644 commands/blocklist.js create mode 100644 commands/close.js create mode 100644 commands/commands.js create mode 100644 commands/configinfo.js create mode 100644 commands/configuration.js create mode 100644 commands/guilds.js create mode 100644 commands/help.js create mode 100644 commands/helpchs.js create mode 100644 commands/helpcht.js create mode 100644 commands/helpde.js create mode 100644 commands/helpes.js create mode 100644 commands/helpfr.js create mode 100644 commands/helpkr.js create mode 100644 commands/helppt.js create mode 100644 commands/helpru.js create mode 100644 commands/helptr.js create mode 100644 commands/leave.js create mode 100644 commands/new.js create mode 100644 commands/ping.js create mode 100644 commands/reload.js create mode 100644 commands/reply.js create mode 100644 commands/reset.js create mode 100644 commands/restart.js create mode 100644 commands/set.js create mode 100644 commands/threadinfo.js create mode 100644 commands/unblock.js create mode 100644 functions/aclose.js create mode 100644 functions/areply.js create mode 100644 functions/bind.js create mode 100644 functions/block.js create mode 100644 functions/blockinfo.js create mode 100644 functions/blocklist.js create mode 100644 functions/close.js create mode 100644 functions/configInfo.js create mode 100644 functions/configSync.js create mode 100644 functions/configuration.js create mode 100644 functions/getEmbed.js create mode 100644 functions/isBlocked.js create mode 100644 functions/isMember.js create mode 100644 functions/newThread.js create mode 100644 functions/reply.js create mode 100644 functions/reset.js create mode 100644 functions/roleCheck.js create mode 100644 functions/set.js create mode 100644 functions/threadInfo.js create mode 100644 functions/unblock.js create mode 100644 functions/userReply.js diff --git a/commands/aclose.js b/commands/aclose.js new file mode 100644 index 0000000..4dc9ae3 --- /dev/null +++ b/commands/aclose.js @@ -0,0 +1,67 @@ +module.exports = { + name: 'aclose', + aliases: false, + level: 'Moderator', + guildOnly: true, + args: true, + usage: '[reason]-[note]', + description: 'Anonymously close a user thread.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const aclose = param.aclose; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noChannelEmbed = getEmbed.execute(param, config.error_color, "Configuration Needed", "\`categoryID\` and/or \`logChannelID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` and/or \`modRoleID\` value is empty."); + const notChannelEmbed = getEmbed.execute(param, config.error_color, "Invalid Channel", `This isn\'t thread channel.`); + + //Yes i know it's nasty to look at that many nested if else but it's needed @,@ + if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + return message.channel.send(noServerEmbed); + } else { + if(message.guild.id == config.threadServerID){ + //inside thread server + if (config.adminRoleID == "empty" || config.modRoleID == "empty"){ + //adminRoleID or modRoleID empty + return message.channel.send(noAdminEmbed); + } else if(config.categoryID == "empty" || config.logChannelID == "empty"){ + //categoryID or logChannelID empty + return message.channel.send(noChannelEmbed); + } else { + //adminRoleID, modRoleID, categoryID and logChannelID not empty + if (message.channel.parentID != config.categoryID || message.channel.id == config.logChannelID || message.channel.id == config.botChannelID) { + //the channel isn't under modmail category or it's a log channel or it's bot channel -_- + return message.channel.send(notChannelEmbed); + } else { + //the channel is under modmail category, it's not a log channel, and it's not bot channel + if(message.author.id == config.botOwnerID){ + return aclose.execute(param, message, args); + } else if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return aclose.execute(param, message, args); + } else if (await param.roleCheck.execute(message, config.modRoleID)){ + //user has moderator role + return aclose.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + + } + } + + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/areply.js b/commands/areply.js new file mode 100644 index 0000000..cadb143 --- /dev/null +++ b/commands/areply.js @@ -0,0 +1,70 @@ +module.exports = { + name: 'areply', + aliases: false, + level: 'Moderator', + guildOnly: true, + args: false,//in case only attachment no message + usage: '[reply message]', + description: 'Anonymously reply to a user thread.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const areply = param.areply; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noChannelEmbed = getEmbed.execute(param, config.error_color, "Configuration Needed", "\`categoryID\` and/or \`logChannelID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` and/or \`modRoleID\` value is empty."); + const notChannelEmbed = getEmbed.execute(param, config.error_color, "Invalid Channel", `This isn\'t thread channel.`); + const noArgsEmbed = param.getEmbed.execute(param, config.warning_color, "Missing Arguments", `You didn\'t provide any arguments nor attachments.`); + + //Yes i know it's nasty to look at that many nested if else but it's needed @,@ + if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + return message.channel.send(noServerEmbed); + } else { + if(message.guild.id == config.threadServerID){ + //inside thread server + if (config.adminRoleID == "empty" || config.modRoleID == "empty"){ + //adminRoleID or modRoleID empty + return message.channel.send(noAdminEmbed); + } else if(config.categoryID == "empty" || config.logChannelID == "empty"){ + //categoryID or logChannelID empty + return message.channel.send(noChannelEmbed); + } else { + //adminRoleID, modRoleID, categoryID and logChannelID not empty + if (message.channel.parentID != config.categoryID || message.channel.id == config.logChannelID || message.channel.id == config.botChannelID) { + //the channel isn't under modmail category or it's a log channel or it's bot channel -_- + return message.channel.send(notChannelEmbed); + } else { + //the channel is under modmail category, it's not a log channel, and it's not bot channel + if(!args.length && message.attachments.size == 0){ + return message.channel.send(noArgsEmbed); + } else if(message.author.id == config.botOwnerID){ + return areply.execute(param, message, args); + } else if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return areply.execute(param, message, args); + } else if (await param.roleCheck.execute(message, config.modRoleID)){ + //user has moderator role + return areply.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + + } + } + + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/bind.js b/commands/bind.js new file mode 100644 index 0000000..b230556 --- /dev/null +++ b/commands/bind.js @@ -0,0 +1,50 @@ +module.exports = { + name: 'bind', + aliases: false, + level: 'Admin', + guildOnly: true, + args: true, + usage: '<userID> <channelID>', + description: 'Bind user thread to a channel.', + note: 'Only use under these circumtances : \n> There is an open thread from other bot.\n> The channel was accidentally deleted.\n> Category channel was accidentally deleted and changed.', + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const bind = param.bind; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` value is empty."); + + if (message.author.id === config.botOwnerID) { + //bot owner + return bind.execute(param, message, args); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return bind.execute(param, message, args); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return bind.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/block.js b/commands/block.js new file mode 100644 index 0000000..6d8e659 --- /dev/null +++ b/commands/block.js @@ -0,0 +1,53 @@ +module.exports = { + name: 'block', + aliases: false, + level: 'Moderator', + guildOnly: true, + args: true, + usage: '<userID> [reason]', + description: 'Block a user from creating new thread and replying to a thread.', + note: 'User presence isn\'t checked to enable blocking users that are outside the server.', + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const block = param.block; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` and/or \`modRoleID\` value is empty."); + + if (message.author.id === config.botOwnerID) { + //bot owner + return block.execute(param, message, args); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return block.execute(param, message, args); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty" || config.modRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return block.execute(param, message, args); + } else if (await param.roleCheck.execute(message, config.modRoleID)){ + //user has moderator role + return block.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/blockinfo.js b/commands/blockinfo.js new file mode 100644 index 0000000..1b54e1b --- /dev/null +++ b/commands/blockinfo.js @@ -0,0 +1,53 @@ +module.exports = { + name: 'blockinfo', + aliases: false, + level: 'Moderator', + guildOnly: true, + args: true, + usage: '<userID>', + description: 'Information about a user\'s block.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const blockinfo = param.blockinfo; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` and/or \`modRoleID\` value is empty."); + + if (message.author.id === config.botOwnerID) { + //bot owner + return blockinfo.execute(param, message, args); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return blockinfo.execute(param, message, args); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty" || config.modRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return blockinfo.execute(param, message, args); + } else if (await param.roleCheck.execute(message, config.modRoleID)){ + //user has moderator role + return blockinfo.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/blocklist.js b/commands/blocklist.js new file mode 100644 index 0000000..84c0595 --- /dev/null +++ b/commands/blocklist.js @@ -0,0 +1,53 @@ +module.exports = { + name: 'blocklist', + aliases: false, + level: 'Moderator', + guildOnly: true, + args: false, + usage: '[page number]', + description: 'List of blocked users.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const blocklist = param.blocklist; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` and/or \`modRoleID\` value is empty."); + + if (message.author.id === config.botOwnerID) { + //bot owner + return blocklist.execute(param, message, args); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return blocklist.execute(param, message, args); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty" || config.modRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return blocklist.execute(param, message, args); + } else if (await param.roleCheck.execute(message, config.modRoleID)){ + //user has moderator role + return blocklist.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/close.js b/commands/close.js new file mode 100644 index 0000000..31e8966 --- /dev/null +++ b/commands/close.js @@ -0,0 +1,67 @@ +module.exports = { + name: 'close', + aliases: false, + level: 'Moderator', + guildOnly: true, + args: true, + usage: '[reason]-[note]', + description: 'Close a user thread.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const close = param.close; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noChannelEmbed = getEmbed.execute(param, config.error_color, "Configuration Needed", "\`categoryID\` and/or \`logChannelID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` and/or \`modRoleID\` value is empty."); + const notChannelEmbed = getEmbed.execute(param, config.error_color, "Invalid Channel", `This isn\'t thread channel.`); + + //Yes i know it's nasty to look at that many nested if else but it's needed @,@ + if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + return message.channel.send(noServerEmbed); + } else { + if(message.guild.id == config.threadServerID){ + //inside thread server + if (config.adminRoleID == "empty" || config.modRoleID == "empty"){ + //adminRoleID or modRoleID empty + return message.channel.send(noAdminEmbed); + } else if(config.categoryID == "empty" || config.logChannelID == "empty"){ + //categoryID or logChannelID empty + return message.channel.send(noChannelEmbed); + } else { + //adminRoleID, modRoleID, categoryID and logChannelID not empty + if (message.channel.parentID != config.categoryID || message.channel.id == config.logChannelID || message.channel.id == config.botChannelID) { + //the channel isn't under modmail category or it's a log channel or it's bot channel -_- + return message.channel.send(notChannelEmbed); + } else { + //the channel is under modmail category, it's not a log channel, and it's not bot channel + if(message.author.id == config.botOwnerID){ + return close.execute(param, message, args); + } else if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return close.execute(param, message, args); + } else if (await param.roleCheck.execute(message, config.modRoleID)){ + //user has moderator role + return close.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + + } + } + + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/commands.js b/commands/commands.js new file mode 100644 index 0000000..ef61443 --- /dev/null +++ b/commands/commands.js @@ -0,0 +1,107 @@ +module.exports = { + name: 'commands', + aliases: ['cmd'], + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: 'List of all available commands according to your permission level.', + note: false, + async execute(param, message, args){ + const Discord = param.Discord; + const client = param.client; + const config = param.config; + const getEmbed = param.getEmbed; + const commands = param.client.commands; + + //collections + const ownerCollection = commands.filter(command => command.level === 'Owner'); + const ownerLevel = ownerCollection.map(command => `**${command.name}** : ${command.description}`).join('\n'); + const adminCollection = commands.filter(command => command.level === 'Admin'); + const adminLevel = adminCollection.map(command => `**${command.name}** : ${command.description}`).join('\n'); + const moderatorCollection = commands.filter(command => command.level === 'Moderator'); + const moderatorLevel = moderatorCollection.map(command => `**${command.name}** : ${command.description}`).join('\n'); + const userCollection = commands.filter(command => command.level === 'User'); + const userLevel = userCollection.map(command => `**${command.name}** : ${command.description}`).join('\n'); + + //embeds + const ownerEmbed = new Discord.RichEmbed() + .setColor(config.info_color) + .setTitle("Commands") + .setDescription(`Use \`${config.prefix}help [command name]\` to get information for each command.`) + .addField("~ Owner Level ~", ownerLevel || "empty") + .addField("~ Admin Level ~", adminLevel || "empty") + .addField("~ Moderator Level ~", moderatorLevel || "empty") + .addField("~ User level ~", userLevel || "empty") + .setThumbnail(client.user.avatarURL) + .setFooter(client.user.tag, client.user.avatarURL) + .setTimestamp(); + const adminEmbed = new Discord.RichEmbed() + .setColor(config.info_color) + .setTitle("Command List") + .setDescription(`Use \`${config.prefix}help [command name]\` to get information for each command.`) + .addField("~ Admin Level ~", adminLevel || "empty") + .addField("~ Moderator Level ~", moderatorLevel || "empty") + .addField("~ User level ~", userLevel || "empty") + .setThumbnail(client.user.avatarURL) + .setFooter(client.user.tag, client.user.avatarURL) + .setTimestamp(); + const moderatorEmbed = new Discord.RichEmbed() + .setColor(config.info_color) + .setTitle("Command List") + .setDescription(`Use \`${config.prefix}help [command name]\` to get information for each command.`) + .addField("~ Moderator Level ~", moderatorLevel || "empty") + .addField("~ User level ~", userLevel || "empty") + .setThumbnail(client.user.avatarURL) + .setFooter(client.user.tag, client.user.avatarURL) + .setTimestamp(); + const userEmbed = new Discord.RichEmbed() + .setColor(config.info_color) + .setTitle("Command List") + .setDescription(`Use \`${config.prefix}help [command name]\` to get information for each command.`) + .addField("~ User level ~", userLevel || "empty") + .setThumbnail(client.user.avatarURL) + .setFooter(client.user.tag, client.user.avatarURL) + .setTimestamp(); + + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` and/or \`modRoleID\` value is empty."); + + if (message.author.id === config.botOwnerID) { + //bot owner + return message.channel.send(ownerEmbed); + } else if(message.guild == null) { + //Direct Message not bot owner + return message.channel.send(userEmbed); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return message.channel.send(adminEmbed) + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty" || config.modRoleID == "empty"){ + //adminRoleID or modRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return message.channel.send(adminEmbed); + } else if (await param.roleCheck.execute(message, config.modRoleID)){ + //user has moderator role + return message.channel.send(moderatorEmbed); + } else { + //user didn't have ADMINISTRATOR permission, admin role, nor moderator role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(userEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(userEmbed); + } + }; + } +}; diff --git a/commands/configinfo.js b/commands/configinfo.js new file mode 100644 index 0000000..c8f233a --- /dev/null +++ b/commands/configinfo.js @@ -0,0 +1,50 @@ +module.exports = { + name: 'configinfo', + aliases: false, + level: 'Admin', + guildOnly: true, + args: true, + usage: '[config name]', + description: 'Show a configuration information.', + note: 'Config name case is sensitive (upper case and lower case are different).', + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const configInfo = param.configInfo; + + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` value is empty."); + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + + if (message.author.id === config.botOwnerID) { + //bot owner + return await configInfo.execute(param, message, args); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return await configInfo.execute(param, message, args); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return await configInfo.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/configuration.js b/commands/configuration.js new file mode 100644 index 0000000..2bb9033 --- /dev/null +++ b/commands/configuration.js @@ -0,0 +1,51 @@ +module.exports = { + name: 'configuration', + aliases: ['config', 'settings'], + level: 'Admin', + guildOnly: true, + args: false, + usage: false, + description: 'Bot configuration.', + note: 'If [mainServerID] and/or [threadServerID] config isn\'t empty, only administrator in that server can use this command.', + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const configuration = param.configuration; + + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` value is empty."); + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const configEmbed = await configuration.execute(param); + + if (message.author.id === config.botOwnerID) { + //bot owner + return message.channel.send(configEmbed); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return message.channel.send(configEmbed); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return message.channel.send(configEmbed); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/guilds.js b/commands/guilds.js new file mode 100644 index 0000000..d12640c --- /dev/null +++ b/commands/guilds.js @@ -0,0 +1,52 @@ +module.exports = { + name: 'guilds', + aliases: ['servers', 'serverlist'], + level: 'Admin', + guildOnly: true, + args: false, + usage: false, + description: 'List of guilds (servers) that have this bot.', + note: 'If [mainServerID] and/or [threadServerID] config isn\'t empty, only administrator in that server can use this command.', + async execute(param, message, args){ + const client = param.client; + const config = param.config; + const getEmbed = param.getEmbed; + + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\`` value is empty."); + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const guildList = client.guilds.map(guild => `[**${guild.name}**] (\`${guild.id}\`)`).join("\n") || "This bot hasn't joined any guild yet."; + const listEmbed = getEmbed.execute(param, config.info_color, "Guilds", guildList); + + if (message.author.id === config.botOwnerID) { + //bot owner + return message.channel.send(listEmbed); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return message.channel.send(listEmbed); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return message.channel.send(listEmbed); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/help.js b/commands/help.js new file mode 100644 index 0000000..4962bc9 --- /dev/null +++ b/commands/help.js @@ -0,0 +1,46 @@ +module.exports = { + name: 'help', + aliases: false, + level: 'User', + guildOnly: false, + args: false, + usage: '[command name]', + description: 'Short instruction on how to create a new thread or info on a specific command.', + note: 'Command name case is insensitive (upper case and lower case are same).', + async execute(param, message, args){ + const data = []; + const commands = param.client.commands; + const config = param.config; + const prefix = config.prefix; + const getEmbed = param.getEmbed; + + const helpEmbed = getEmbed.execute(param, config.info_color, "Instruction", `In Direct Message, use \`${prefix}new Your thread title here\` to create a new thread (**Thread Created!** will be displayed). You don't need to use any command after your thread created. Describe your issue afterward.`); + const notCmdEmbed = getEmbed.execute(param, config.warning_color, "Not a Command", `That\'s not a valid command name or alias.\nUse \`${prefix}commands\` to show available commands.`); + + if(!args.length){ + return message.channel.send(helpEmbed); + } + + const name = args[0].toLowerCase(); + const command = commands.get(name) || commands.find(cmd => cmd.aliases && cmd.aliases.includes(name)); + + if(!command){ + return message.channel.send(notCmdEmbed); + } + + data.push(`**Name** : ${command.name}`); + if (command.aliases) data.push(`**Aliases** : ${command.aliases.join(', ')}`); + if (command.level) data.push(`**Required Level** : ${command.level}`); + if(command.guildOnly){ + data.push(`**Direct Message** : false`); + } else { + data.push(`**Direct Message** : true`); + } + if (command.usage) data.push(`**Usage** : \`${prefix}${command.name} ${command.usage}\``); + if (command.description) data.push(`**Description** : ${command.description}`); + if (command.note) data.push(`**Note** : \`${command.note}\``); + + const dataEmbed = getEmbed.execute(param, config.info_color, "Command Info", data.join('\n')); + return message.channel.send(dataEmbed); + } +}; diff --git a/commands/helpchs.js b/commands/helpchs.js new file mode 100644 index 0000000..adec3bc --- /dev/null +++ b/commands/helpchs.js @@ -0,0 +1,20 @@ +module.exports = { + name: 'helpchs', + aliases: ['助攻'], + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: '显示如何使用操作这个系统的说明.', + note: false, + async execute(param, message, args){ + const config = param.config; + const prefix = config.prefix; + const getEmbed = param.getEmbed; + + const helpEmbed = getEmbed.execute(param, config.info_color, "指令", `在“直接消息”中,使用\`${config.prefix}new 您的线程标题在这里\`创建一个新线程(显示“**Thread Created!**”)。创建线程后,无需使用任何命令。然后描述你的问题。`); + + return message.channel.send(helpEmbed); + + } +}; diff --git a/commands/helpcht.js b/commands/helpcht.js new file mode 100644 index 0000000..b7e9de4 --- /dev/null +++ b/commands/helpcht.js @@ -0,0 +1,20 @@ +module.exports = { + name: 'helpcht', + aliases: ['助攻'], + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: '顯示如何使用操作這個系統的說明.', + note: false, + async execute(param, message, args){ + const config = param.config; + const prefix = config.prefix; + const getEmbed = param.getEmbed; + + const helpEmbed = getEmbed.execute(param, config.info_color, "指令", `在“直接消息”中,使用\`${config.prefix}new 您的線程標題在這裡\`創建一個新線程(顯示“**Thread Created!**”)。創建線程後,無需使用任何命令。然後描述你的問題。`); + + return message.channel.send(helpEmbed); + + } +}; diff --git a/commands/helpde.js b/commands/helpde.js new file mode 100644 index 0000000..9c19dd4 --- /dev/null +++ b/commands/helpde.js @@ -0,0 +1,20 @@ +module.exports = { + name: 'helpde', + aliases: ['hilfe'], + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: 'Anleitung zur Verwendung des Bots anzeigen.', + note: false, + async execute(param, message, args){ + const config = param.config; + const prefix = config.prefix; + const getEmbed = param.getEmbed; + + const helpEmbed = getEmbed.execute(param, config.info_color, "Anweisung", `In Direktnachrichten, Verwenden Sie \`${config.prefix}new Dein Threadtitel hier\`, um einen neuen Thread zu erstellen (es wird **Thread Created!** Angezeigt). Sie müssen nach dem Erstellen Ihres Threads keinen Befehl mehr verwenden. Beschreiben Sie anschließend Ihr Problem.`); + + return message.channel.send(helpEmbed); + + } +}; diff --git a/commands/helpes.js b/commands/helpes.js new file mode 100644 index 0000000..1d1f158 --- /dev/null +++ b/commands/helpes.js @@ -0,0 +1,20 @@ +module.exports = { + name: 'helpes', + aliases: ['ayuda'], + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: 'Mostrar instrucciones sobre cómo usar el bot.', + note: false, + async execute(param, message, args){ + const config = param.config; + const prefix = config.prefix; + const getEmbed = param.getEmbed; + + const helpEmbed = getEmbed.execute(param, config.info_color, "Instrucción", `En un mensaje privado, utilice \`${config.prefix}new el tema de su problema\` para crear un nuevo ticket (se muestra **Thread Created!**). No necesita usar ningún comando después de la creación del ticket. Luego describe su problema.`); + + return message.channel.send(helpEmbed); + + } +}; diff --git a/commands/helpfr.js b/commands/helpfr.js new file mode 100644 index 0000000..c13dbc6 --- /dev/null +++ b/commands/helpfr.js @@ -0,0 +1,20 @@ +module.exports = { + name: 'helpfr', + aliases: ['aide'], + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: 'Afficher les instructions sur l\'utilisation du bot.', + note: false, + async execute(param, message, args){ + const config = param.config; + const prefix = config.prefix; + const getEmbed = param.getEmbed; + + const helpEmbed = getEmbed.execute(param, config.info_color, "Instruction", `En message privé, utilisez \`${config.prefix}new le sujet de votre problème\` pour créer un nouveau ticket (**Thread Created!** s'affiche). Vous n'avez pas besoin d'utiliser de commande après la création du ticket. Décrivez ensuite votre problème.`); + + return message.channel.send(helpEmbed); + + } +}; diff --git a/commands/helpkr.js b/commands/helpkr.js new file mode 100644 index 0000000..4da61ea --- /dev/null +++ b/commands/helpkr.js @@ -0,0 +1,20 @@ +module.exports = { + name: 'helpkr', + aliases: ['도움'], + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: '봇 사용 방법에 대한 지시 사항 표시.', + note: false, + async execute(param, message, args){ + const config = param.config; + const prefix = config.prefix; + const getEmbed = param.getEmbed; + + const helpEmbed = getEmbed.execute(param, config.info_color, "훈령", `직접 메시지에서\`${config.prefix}new 스레드 제목은 여기\`를 사용하여 새 스레드를 만듭니다 (**Thread Created!**가 표시됨). 스레드가 작성된 후 명령을 사용할 필요가 없습니다. 그런 다음 문제를 설명하십시오.`); + + return message.channel.send(helpEmbed); + + } +}; diff --git a/commands/helppt.js b/commands/helppt.js new file mode 100644 index 0000000..8e4e979 --- /dev/null +++ b/commands/helppt.js @@ -0,0 +1,20 @@ +module.exports = { + name: 'helppt', + aliases: ['ajuda'], + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: 'Mostrar instruções sobre como usar o bot.', + note: false, + async execute(param, message, args){ + const config = param.config; + const prefix = config.prefix; + const getEmbed = param.getEmbed; + + const helpEmbed = getEmbed.execute(param, config.info_color, "Instrução", `Na mensagem direta, usar \`${config.prefix}new Título do assunto\` para criar um novo tópico (**Thread Created!** é exibido). Não precisa de usar nenhum comando depois de criar o seu tópico. Em seguida, descreva o seu problema.`); + + return message.channel.send(helpEmbed); + + } +}; diff --git a/commands/helpru.js b/commands/helpru.js new file mode 100644 index 0000000..af42863 --- /dev/null +++ b/commands/helpru.js @@ -0,0 +1,20 @@ +module.exports = { + name: 'helpru', + aliases: ['помощь'], + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: 'Показать инструкцию о том, как использовать бот.', + note: false, + async execute(param, message, args){ + const config = param.config; + const prefix = config.prefix; + const getEmbed = param.getEmbed; + + const helpEmbed = getEmbed.execute(param, config.info_color, "инструкция", `В прямом сообщении используйте \`${config.prefix}new Ваше название темы здесь\`, чтобы создать новую тему (**Thread Created!** Отображается). Вам не нужно использовать какую-либо команду после создания вашего потока. Тогда опишите свою проблему.`); + + return message.channel.send(helpEmbed); + + } +}; diff --git a/commands/helptr.js b/commands/helptr.js new file mode 100644 index 0000000..6435489 --- /dev/null +++ b/commands/helptr.js @@ -0,0 +1,20 @@ +module.exports = { + name: 'helptr', + aliases: ['yardım'], + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: 'Bot kullanımı hakkında talimat göster.', + note: false, + async execute(param, message, args){ + const config = param.config; + const prefix = config.prefix; + const getEmbed = param.getEmbed; + + const helpEmbed = getEmbed.execute(param, config.info_color, "Talimat", `Doğrudan Mesaj'da, yeni bir bilet oluşturmak için \`${config.prefix}new konuyu buraya yazın\` yazın ve gönderin (**Thread Created!** görüntülenir). Konuyu oluşturduktan sonra herhangi bir komut kullanmanıza gerek yoktur. Daha sonra sorununuzu açıklayın.`); + + return message.channel.send(helpEmbed); + + } +}; diff --git a/commands/leave.js b/commands/leave.js new file mode 100644 index 0000000..0a7b3ec --- /dev/null +++ b/commands/leave.js @@ -0,0 +1,38 @@ +module.exports = { + name: 'leave', + aliases: false, + level: 'Owner', + guildOnly: false, + args: true, + usage: '<guildID>', + description: 'Leave a guild (server).', + note: false, + async execute(param, message, args){ + const client = param.client; + const config = param.config; + const getEmbed = param.getEmbed; + + const serverID = args.shift(); + const getServer = client.guilds.get(serverID); + + const notFoundEmbed = getEmbed.execute(param, config.error_color, "Not Found", `Can\'t find guild with ID (\`${serverID}\`) in my collection.`); + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + + if (message.author.id === config.botOwnerID) { + //bot owner + if(getServer){ + const successEmbed = getEmbed.execute(param, config.info_color, "Leaving", `Leaving [**${getServer.name}**] (\`${getServer.id}\`) guild.`); + console.log(`Leaving [${getServer.name}] guild.`); + return getServer.leave().then(message.channel.send(successEmbed)); + } else { + message.channel.send(notFoundEmbed); + } + } else { + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + }; + } +}; diff --git a/commands/new.js b/commands/new.js new file mode 100644 index 0000000..f5812bd --- /dev/null +++ b/commands/new.js @@ -0,0 +1,44 @@ +module.exports = { + name: 'new', + aliases: ['neu', 'yeni', '새로운', 'novo', 'nouveau', 'новый', '新', 'nuevo'], + level: 'User', + guildOnly: false, + args: true, + usage: '[thread title]', + description: 'Create new thread.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const newThread = param.newThread; + + const mainServerID = config.mainServerID; + const threadServerID = config.threadServerID; + const botChannelID = config.botChannelID; + const categoryID = config.categoryID; + const logChannelID = config.logChannelID; + + const noServerEmbed = getEmbed.execute(param, config.error_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noChannelEmbed = getEmbed.execute(param, config.error_color, "Configuration Needed", "\`categoryID\` and/or \`logChannelID\` value is empty."); + const notDMEmbed = getEmbed.execute(param, config.error_color, "Command Unavailable", "This command can only be used in Direct Message.") + + if (message.guild != null && (message.guild.id == mainServerID || message.guild.id == threadServerID)) { + if(botChannelID != "empty" && message.channel.id == botChannelID){ + return; + } else { + return message.channel.send(notDMEmbed); + } + } else if(message.guild != null){ + return message.channel.send(notDMEmbed); + } else { + if(mainServerID == "empty" || threadServerID == "empty"){ + return message.channel.send(noServerEmbed); + } else if (categoryID == "empty" || logChannelID == "empty"){ + return message.channel.send(noChannelEmbed); + } else { + return newThread.execute(param, message, args); + } + } + + } +}; diff --git a/commands/ping.js b/commands/ping.js new file mode 100644 index 0000000..4fb22f5 --- /dev/null +++ b/commands/ping.js @@ -0,0 +1,30 @@ +module.exports = { + name: 'ping', + aliases: false, + level: 'User', + guildOnly: false, + args: false, + usage: false, + description: 'Calculate bot latency.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + + if(config.mainServerID != "empty" && config.threadServerID != "empty"){ + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } + } + } + + + let pingEmbed = getEmbed.execute(param, config.info_color, "Pong", "Ping?"); + + message.channel.send(pingEmbed).then((msg) => { + let editEmbed = getEmbed.execute(param, config.info_color, "Pong", `**Response time** : **${msg.createdTimestamp - message.createdTimestamp}** ms\n**API latency** : **${Math.round(param.client.ping)}** ms`); + msg.edit(editEmbed); + }); + } +}; diff --git a/commands/reload.js b/commands/reload.js new file mode 100644 index 0000000..829bda2 --- /dev/null +++ b/commands/reload.js @@ -0,0 +1,43 @@ +module.exports = { + name: 'reload', + aliases: false, + level: 'Owner', + guildOnly: false, + args: true, + usage: '[command name]', + description: 'Reload a command.', + note: false, + async execute(param, message, args){ + const client = param.client; + const config = param.config; + const getEmbed = param.getEmbed; + + const commandName = args.shift().toLowerCase(); + const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); + + const successEmbed = getEmbed.execute(param, config.info_color, "Success", `Command \`${command.name}\` was reloaded.`); + const notCmdEmbed = getEmbed.execute(param, config.error_color, "Not a Command", `That\'s not a valid command name or alias.\nUse \`${config.prefix}commands\` to show available commands.`); + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + + if (message.author.id === config.botOwnerID) { + //bot owner + if(!command){ + return message.channel.send(notCmdEmbed); + } + console.log(`Deleting ${command.name} cache.`); + delete require.cache[require.resolve(`./${command.name}.js`)]; + + console.log(`Loading ${command.name}...`) + const newCommand = require(`./${command.name}.js`); + client.commands.set(newCommand.name, newCommand); + + return message.channel.send(successEmbed); + } else { + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } +}; diff --git a/commands/reply.js b/commands/reply.js new file mode 100644 index 0000000..e02733f --- /dev/null +++ b/commands/reply.js @@ -0,0 +1,70 @@ +module.exports = { + name: 'reply', + aliases: false, + level: 'Moderator', + guildOnly: true, + args: false,//in case only attachment no message + usage: '[reply message]', + description: 'Reply to a user thread.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const reply = param.reply; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noChannelEmbed = getEmbed.execute(param, config.error_color, "Configuration Needed", "\`categoryID\` and/or \`logChannelID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` and/or \`modRoleID\` value is empty."); + const notChannelEmbed = getEmbed.execute(param, config.error_color, "Invalid Channel", `This isn\'t thread channel.`); + const noArgsEmbed = param.getEmbed.execute(param, config.warning_color, "Missing Arguments", `You didn\'t provide any arguments nor attachments.`); + + //Yes i know it's nasty to look at that many nested if else but it's needed @,@ + if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + return message.channel.send(noServerEmbed); + } else { + if(message.guild.id == config.threadServerID){ + //inside thread server + if (config.adminRoleID == "empty" || config.modRoleID == "empty"){ + //adminRoleID or modRoleID empty + return message.channel.send(noAdminEmbed); + } else if(config.categoryID == "empty" || config.logChannelID == "empty"){ + //categoryID or logChannelID empty + return message.channel.send(noChannelEmbed); + } else { + //adminRoleID, modRoleID, categoryID and logChannelID not empty + if (message.channel.parentID != config.categoryID || message.channel.id == config.logChannelID || message.channel.id == config.botChannelID) { + //the channel isn't under modmail category or it's a log channel or it's bot channel -_- + return message.channel.send(notChannelEmbed); + } else { + //the channel is under modmail category, it's not a log channel, and it's not bot channel + if(!args.length && message.attachments.size == 0){ + return message.channel.send(noArgsEmbed); + } else if(message.author.id == config.botOwnerID){ + return reply.execute(param, message, args); + } else if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return reply.execute(param, message, args); + } else if (await param.roleCheck.execute(message, config.modRoleID)){ + //user has moderator role + return reply.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + + } + } + + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/reset.js b/commands/reset.js new file mode 100644 index 0000000..38cd222 --- /dev/null +++ b/commands/reset.js @@ -0,0 +1,67 @@ +module.exports = { + name: 'reset', + aliases: false, + level: 'Admin', + guildOnly: true, + args: false, + usage: false, + description: 'Reset all configuration values.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const reset = param.reset; + + const successEmbed = getEmbed.execute(param, config.info_color, "Success", `All configuration value have been reset to default.`); + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` value is empty."); + + if (message.author.id === config.botOwnerID) { + //bot owner + console.log("Resetting bot configuration..."); + await reset.execute(param).then(()=>{ + message.channel.send(successEmbed).then(() =>{ + process.exit(1); + }); + }); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + //reset and restart the bot + console.log("Resetting bot configuration..."); + await reset.execute(param).then(()=>{ + message.channel.send(successEmbed).then(() =>{ + process.exit(1); + }); + }); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + console.log("Resetting bot configuration..."); + await reset.execute(param).then(()=>{ + message.channel.send(successEmbed).then(() =>{ + process.exit(1); + }); + }); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/restart.js b/commands/restart.js new file mode 100644 index 0000000..b3f4941 --- /dev/null +++ b/commands/restart.js @@ -0,0 +1,59 @@ +module.exports = { + name: 'restart', + aliases: ['reboot'], + level: 'Admin', + guildOnly: true, + args: false, + usage: false, + description: 'Restart the bot.', + note: false, + async execute(param, message, args) { + const config = param.config; + const getEmbed = param.getEmbed; + + const successEmbed = getEmbed.execute(param, config.info_color, "Restarting", `**Restarting in** : **${Math.round(param.client.ping)}** ms`); + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` value is empty."); + + if (message.author.id === config.botOwnerID) { + //bot owner + console.log("Restarting bot..."); + message.channel.send(successEmbed).then(() => { + process.exit(1); + }); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + console.log("Restarting bot..."); + message.channel.send(successEmbed).then(() => { + process.exit(1); + }); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + console.log("Restarting bot..."); + message.channel.send(successEmbed).then(() => { + process.exit(1); + }); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/set.js b/commands/set.js new file mode 100644 index 0000000..4dfd8d5 --- /dev/null +++ b/commands/set.js @@ -0,0 +1,50 @@ +module.exports = { + name: 'set', + aliases: false, + level: 'Admin', + guildOnly: true, + args: true, + usage: '[config name] [value]', + description: 'Set specific configuration value.', + note: 'Config name case is sensitive (upper case and lower case are different).', + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const set = param.set; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` value is empty."); + + if (message.author.id === config.botOwnerID) { + //bot owner + return await set.execute(param, message, args); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return await set.execute(param, message, args); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return await set.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/threadinfo.js b/commands/threadinfo.js new file mode 100644 index 0000000..e905773 --- /dev/null +++ b/commands/threadinfo.js @@ -0,0 +1,55 @@ +module.exports = { + name: 'threadinfo', + aliases: false, + level: 'Moderator', + guildOnly: true, + args: true, + usage: '[<userID> or <channelID>]', + description: 'Show a user thread information.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const threadInfo = param.threadInfo; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noChannelEmbed = getEmbed.execute(param, config.error_color, "Configuration Needed", "\`categoryID\` and/or \`logChannelID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` and/or \`modRoleID\` value is empty."); + const notChannelEmbed = getEmbed.execute(param, config.error_color, "Invalid Channel", `This isn\'t thread channel.`); + + if (message.author.id === config.botOwnerID) { + //bot owner + return threadInfo.execute(param, message, args); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return threadInfo.execute(param, message, args); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty" || config.modRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return threadInfo.execute(param, message, args); + } else if (await param.roleCheck.execute(message, config.modRoleID)){ + //user has moderator role + return threadInfo.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/commands/unblock.js b/commands/unblock.js new file mode 100644 index 0000000..febd103 --- /dev/null +++ b/commands/unblock.js @@ -0,0 +1,53 @@ +module.exports = { + name: 'unblock', + aliases: false, + level: 'Moderator', + guildOnly: true, + args: true, + usage: '<userID>', + description: 'Unblock user from creating new thread.', + note: false, + async execute(param, message, args){ + const config = param.config; + const getEmbed = param.getEmbed; + const unblock = param.unblock; + + const noPermEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", "You don\'t have permission to run this command."); + const noServerEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noAdminEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", "\`adminRoleID\` and/or \`modRoleID\` value is empty."); + + if (message.author.id === config.botOwnerID) { + //bot owner + return unblock.execute(param, message, args); + } else if (config.mainServerID == "empty" && config.threadServerID == "empty" && message.member.hasPermission("ADMINISTRATOR")) { + //mainServerID and threadServerID empty and user has ADMINISTRATOR permission + message.channel.send(noServerEmbed); + return unblock.execute(param, message, args); + } else { + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside main server or thread server + if (config.adminRoleID == "empty" || config.modRoleID == "empty"){ + //adminRoleID empty + message.channel.send(noAdminEmbed); + } + if (message.member.hasPermission("ADMINISTRATOR") || await param.roleCheck.execute(message, config.adminRoleID)){ + //user has ADMINISTRATOR permission or has admin role + return unblock.execute(param, message, args); + } else if (await param.roleCheck.execute(message, config.modRoleID)){ + //user has moderator role + return unblock.execute(param, message, args); + } else { + //user didn't have ADMINISTRATOR permission nor has admin role + if (config.botChannelID != "empty" && message.channel.id != config.botChannelID) { + return; + } else { + return message.channel.send(noPermEmbed); + }; + } + } else { + //outside main server and thread server + return message.channel.send(noPermEmbed); + } + }; + } +}; diff --git a/config.json b/config.json index 53caf73..ac52a5b 100644 --- a/config.json +++ b/config.json @@ -1,12 +1,14 @@ { "prefix" : "=", - "botOwnerID" : "", - "serverID" : "", + "botOwnerID" : "384304943516876801", + "mainServerID" : "", + "threadServerID" : "", "categoryID" : "", "logChannelID" : "", "adminRoleID" : "", "modRoleID" : "", "mentionedRoleID" : "here", + "botChannelID" : "", "maintenance" : "0", "info_color" : "#add8e6", "warning_color" : "#ffff00", diff --git a/functions/aclose.js b/functions/aclose.js new file mode 100644 index 0000000..9a3f3db --- /dev/null +++ b/functions/aclose.js @@ -0,0 +1,73 @@ +module.exports = { + name: "aclose", + async execute(param, message, args){ + const Discord = param.Discord; + const client = param.client; + const getEmbed = param.getEmbed; + const config = param.config; + const ThreadDB = param.ThreadDB; + + const mainServerID = config.mainServerID; + const mainServer = await client.guilds.get(mainServerID); + const threadServerID = config.threadServerID; + const threadServer = await client.guilds.get(threadServerID); + const categoryID = config.categoryID; + const logChannelID = config.logChannelID; + const logChannel = await threadServer.channels.get(logChannelID); + const author = message.author; + const channel = message.channel; + + const isThread = await ThreadDB.findOne({where: {channelID: channel.id}}); + let addSpace = args.join(' '); + let deleteSeparator = addSpace.split(/-+/); + const reason = deleteSeparator.shift(); + const note = deleteSeparator.shift() || "empty"; + + const noThreadEmbed = getEmbed.execute(param, config.error_color, "Not Found", `Couldn\'t find any thread asociated with this channel.`); + + if (!isThread) { + return channel.send(noThreadEmbed); + } else { + const user = await client.users.get(isThread.userID); + const logDescription = `${isThread.threadTitle}\n**Reason** : ${reason}\n**Note** : ${note}`; + const userDescription = `${isThread.threadTitle}\n**Reason** : ${reason}`; + + var logEmbed; + const userDMEmbed = new Discord.RichEmbed() + .setColor(config.warning_color) + .setAuthor("[Anonymous]") + .setTitle("Thread Closed") + .setDescription(userDescription) + .setFooter(mainServer.name, mainServer.avatarURL) + .setTimestamp(); + + if (user) { + logEmbed = new Discord.RichEmbed() + .setColor(config.warning_color) + .setAuthor(`[Anonymous] | ${author.tag}`, author.avatarURL) + .setTitle("Thread Closed") + .setDescription(logDescription) + .setFooter(`${user.tag} | ${user.id}`, user.avatarURL) + .setTimestamp(); + await user.send(userDMEmbed); + await logChannel.send(logEmbed); + } else { + logEmbed = new Discord.RichEmbed() + .setColor(config.warning_color) + .setAuthor(`[Anonymous] | ${author.tag}`, author.avatarURL) + .setTitle("Thread Closed") + .setDescription(logDescription) + .setFooter(`Can\'t find user | ${isThread.userID}`) + .setTimestamp(); + await logChannel.send(logEmbed); + } + + const rowCount = await ThreadDB.destroy({ where: {userID: isThread.userID} }); + if (rowCount > 0) { + console.log(`Closing Thread.`); + } + return channel.delete(); + }; + + } +}; diff --git a/functions/areply.js b/functions/areply.js new file mode 100644 index 0000000..a11c5c5 --- /dev/null +++ b/functions/areply.js @@ -0,0 +1,85 @@ +module.exports = { + name: "areply", + async execute(param, message, args){ + const Discord = param.Discord; + const Attachment = param.Attachment; + const client = param.client; + const getEmbed = param.getEmbed; + const config = param.config; + const ThreadDB = param.ThreadDB; + const isMember = param.isMember; + const isBlocked = param.isBlocked; + + const mainServerID = config.mainServerID; + const mainServer = await client.guilds.get(mainServerID); + const threadServerID = config.threadServerID; + const threadServer = await client.guilds.get(threadServerID); + const categoryID = config.categoryID; + const author = message.author; + const channel = message.channel; + + const isThread = await ThreadDB.findOne({where: {channelID: channel.id}}); + const checkIsBlocked = await isBlocked.execute(param, author.id); + + const blockedEmbed = getEmbed.execute(param, config.error_color, "Blocked", `User blocked.`); + const noDMEmbed = getEmbed.execute(param, config.error_color, "Not Sent", `User disabled Direct Message.`); + const noUserEmbed = getEmbed.execute(param, config.error_color, "Not Found", `Couldn\'t find user in my collection.`); + const noThreadEmbed = getEmbed.execute(param, config.error_color, "Not Found", `Couldn\'t find any thread asociated with this channel.`); + + if (!isThread) { + return channel.send(noThreadEmbed); + } else { + const checkIsMember = await isMember.execute(param, author.id); + const notMemberEmbed = getEmbed.execute(param, config.error_color, "Not a Member", `User aren\'t inside [**${mainServer.name}**] guild.`); + + if (!checkIsMember) { + return channel.send(notMemberEmbed); + } else if (checkIsBlocked){ + return channel.send(blockedEmbed); + } else { + const userID = isThread.userID; + const member = await mainServer.members.get(userID); + + if (!member) { + return channel.send(noUserEmbed); + } else { + const user = member.user; + const description = args.join(' '); + const userDMEmbed = new Discord.RichEmbed() + .setColor(config.sent_color) + .setAuthor("[Anonymous]") + .setTitle("Message Received") + .setDescription(description) + .setFooter(mainServer.name, mainServer.avatarURL) + .setTimestamp(); + const threadChannelEmbed = new Discord.RichEmbed() + .setColor(config.sent_color) + .setAuthor(`[Anonymous] | ${author.tag}`, author.avatarURL) + .setTitle("Message Sent") + .setDescription(description) + .setFooter(`${user.tag} | ${user.id}`, user.avatarURL) + .setTimestamp(); + + try{ + await user.send(userDMEmbed); + } catch (error){ + if(error.message == "Cannot send messages to this user"){ + return channel.send(noDMEmbed); + } + } + await channel.send(threadChannelEmbed); + if (message.attachments.size > 0) { + await message.attachments.forEach(async atch => { + let attachment = new Attachment(atch.url); + await user.send(attachment); + await channel.send(attachment); + }); + } + return message.delete(); + } + + }; + }; + + } +}; diff --git a/functions/bind.js b/functions/bind.js new file mode 100644 index 0000000..5ce9621 --- /dev/null +++ b/functions/bind.js @@ -0,0 +1,43 @@ +module.exports = { + name: "bind", + async execute(param, message, args){ + const Discord = param.Discord; + const moment = param.moment; + const client = param.client; + const getEmbed = param.getEmbed; + const config = param.config; + const ThreadDB = param.ThreadDB; + const bind = param.bind; + + const mainServerID = config.mainServerID; + const mainServer = await client.guilds.get(mainServerID); + const threadServerID = config.threadServerID; + const threadServer = await client.guilds.get(threadServerID); + + const userID = args.shift(); + const channelID = args.shift(); + const isThread = await ThreadDB.findOne({where: {userID: userID}}); + const isSame = await ThreadDB.findOne({where: {channelID: channelID}}); + + const successEmbed = getEmbed.execute(param, config.info_color, "Success", `Binded <@${userID}> (\`${userID}\`) thread to <#${channelID}>.`); + const sameChannelEmbed = getEmbed.execute(param, config.error_color, "Failed", `Channel <#${channelID}> binded with a thread already.`); + + if (isSame) { + return message.channel.send(sameChannelEmbed); + } else if(!isThread){ + const newThread = await ThreadDB.create({ + userID: userID, + channelID: channelID, + threadTitle: "empty" + }); + return message.channel.send(successEmbed); + } else { + await ThreadDB.update( + { channelID: channelID }, + { where: { userID: userID } } + ); + return message.channel.send(successEmbed); + }; + + } +}; diff --git a/functions/block.js b/functions/block.js new file mode 100644 index 0000000..5cd46fa --- /dev/null +++ b/functions/block.js @@ -0,0 +1,33 @@ +module.exports = { + name: "block", + async execute(param, message, args){ + const client = param.client; + const config = param.config; + const BlockedDB = param.BlockedDB; + const getEmbed = param.getEmbed; + + const modID = message.author.id; + const userID = args.shift(); + const reason = args.join(' ') || "empty"; + + const duplicatedEmbed = getEmbed.execute(param, config.error_color, "Duplicated", `<@${userID}> (\`${userID}\`) already blocked.`); + const successEmbed = getEmbed.execute(param, config.info_color, "Success", `Succesfully block <@${userID}> (\`${userID}\`).`); + + try{ + const blockThis = await BlockedDB.create({ + userID: userID, + modID: modID, + reason: reason + }); + if(blockThis){ + console.log(`Blocked [${userID}]`); + return message.channel.send(successEmbed); + } + } catch (error) { + if(error.name == "SequelizeUniqueConstraintError"){ + return message.channel.send(duplicatedEmbed); + } + }; + + } +}; diff --git a/functions/blockinfo.js b/functions/blockinfo.js new file mode 100644 index 0000000..32c7951 --- /dev/null +++ b/functions/blockinfo.js @@ -0,0 +1,30 @@ +module.exports = { + name: "blockinfo", + async execute(param, message, args){ + const moment = param.moment; + const client = param.client; + const config = param.config; + const BlockedDB = param.BlockedDB; + const getEmbed = param.getEmbed; + + const userID = args.shift(); + + const notFoundEmbed = getEmbed.execute(param, config.error_color, "Not Found", `<@${userID}> (\`${userID}\`) isn\'t blocked.`); + + const findUser = await BlockedDB.findOne({where: {userID: userID}}); + if(findUser){ + const data = []; + data.push(`**User** : <@${findUser.userID}>`); + data.push(`**User ID** : \`${findUser.userID}\``); + data.push(`**Blocked at** : ${moment(findUser.createdAt).format("D MMMM YYYY, **HH:mm:ss** UTC")}`); + data.push(`**Moderator** : <@${findUser.modID}>`); + data.push(`**Moderator ID** : \`${findUser.modID}\``); + data.push(`**Reason** : ${findUser.reason}`); + const infoEmbed = getEmbed.execute(param, config.info_color, "Block Info", data.join('\n')); + return message.channel.send(infoEmbed); + } else { + return message.channel.send(notFoundEmbed); + } + + } +}; diff --git a/functions/blocklist.js b/functions/blocklist.js new file mode 100644 index 0000000..f05549c --- /dev/null +++ b/functions/blocklist.js @@ -0,0 +1,41 @@ +module.exports = { + name: "blocklist", + async execute(param, message, args){ + const moment = param.moment; + const client = param.client; + const config = param.config; + const BlockedDB = param.BlockedDB; + const getEmbed = param.getEmbed; + + var pageNumber = args.shift(); + + const blocklist = await BlockedDB.findAll({ attributes: ["userID", "createdAt"] }); + var pages = Math.floor(blocklist.length / 20); + if (blocklist.length % 20 != 0) { + //add 1 number of pages if residual quotient is not 0 (15%10=5 -> 5 > 0) + pages += 1; + } + if (blocklist.length == 0) { + pageNumber = 0; + } else if(!pageNumber || isNaN(pageNumber) || pageNumber <= 0) { + //user didn't gave input or input is not a number or input is below or same as 0 + pageNumber = 1; + } else if(pageNumber > pages){ + //input is higher than the number of pages + pageNumber = pages; + } + + const listArray = blocklist.map(block =>`**[${moment(block.createdAt).format("D MMM YYYY")}]** <@${block.userID}> \`(${block.userID})\``); + const firstIndex = Math.abs((pageNumber-1) * 20); + let listString = listArray.slice(firstIndex, firstIndex + 20).join("\n") || `\`List empty.\``; + if (pages > 1) { + listString += `\n\`Page ${pageNumber} from ${pages} pages\``; + } else { + listString += `\n\`Page ${pageNumber} from ${pages} page\``; + } + + const listEmbed = getEmbed.execute(param, config.info_color, "Blocked Users", listString); + return message.channel.send(listEmbed); + + } +}; diff --git a/functions/close.js b/functions/close.js new file mode 100644 index 0000000..7cbe8dd --- /dev/null +++ b/functions/close.js @@ -0,0 +1,73 @@ +module.exports = { + name: "close", + async execute(param, message, args){ + const Discord = param.Discord; + const client = param.client; + const getEmbed = param.getEmbed; + const config = param.config; + const ThreadDB = param.ThreadDB; + + const mainServerID = config.mainServerID; + const mainServer = await client.guilds.get(mainServerID); + const threadServerID = config.threadServerID; + const threadServer = await client.guilds.get(threadServerID); + const categoryID = config.categoryID; + const logChannelID = config.logChannelID; + const logChannel = await threadServer.channels.get(logChannelID); + const author = message.author; + const channel = message.channel; + + const isThread = await ThreadDB.findOne({where: {channelID: channel.id}}); + let addSpace = args.join(' '); + let deleteSeparator = addSpace.split(/-+/); + const reason = deleteSeparator.shift(); + const note = deleteSeparator.shift() || "empty"; + + const noThreadEmbed = getEmbed.execute(param, config.error_color, "Not Found", `Couldn\'t find any thread asociated with this channel.`); + + if (!isThread) { + return channel.send(noThreadEmbed); + } else { + const user = await client.users.get(isThread.userID); + const logDescription = `${isThread.threadTitle}\n**Reason** : ${reason}\n**Note** : ${note}`; + const userDescription = `${isThread.threadTitle}\n**Reason** : ${reason}`; + + var logEmbed; + const userDMEmbed = new Discord.RichEmbed() + .setColor(config.warning_color) + .setAuthor(author.tag, author.avatarURL) + .setTitle("Thread Closed") + .setDescription(userDescription) + .setFooter(mainServer.name, mainServer.avatarURL) + .setTimestamp(); + + if (user) { + logEmbed = new Discord.RichEmbed() + .setColor(config.warning_color) + .setAuthor(author.tag, author.avatarURL) + .setTitle("Thread Closed") + .setDescription(logDescription) + .setFooter(`${user.tag} | ${user.id}`, user.avatarURL) + .setTimestamp(); + await user.send(userDMEmbed); + await logChannel.send(logEmbed); + } else { + logEmbed = new Discord.RichEmbed() + .setColor(config.warning_color) + .setAuthor(author.tag, author.avatarURL) + .setTitle("Thread Closed") + .setDescription(logDescription) + .setFooter(`Can\'t find user | ${isThread.userID}`) + .setTimestamp(); + await logChannel.send(logEmbed); + } + + const rowCount = await ThreadDB.destroy({ where: {userID: isThread.userID} }); + if (rowCount > 0) { + console.log(`Closing Thread.`); + } + return channel.delete(); + }; + + } +}; diff --git a/functions/configInfo.js b/functions/configInfo.js new file mode 100644 index 0000000..a157714 --- /dev/null +++ b/functions/configInfo.js @@ -0,0 +1,96 @@ +module.exports = { + name: "configInfo", + async execute(param, message, args){ + const Discord = param.Discord; + const moment = param.moment; + const client = param.client; + const getEmbed = param.getEmbed; + const config = param.config; + const ConfigDB = param.ConfigDB; + + const configName = args.shift(); + const isConfig = await ConfigDB.findOne({where: {name: configName}}); + const configCollection = await ConfigDB.findAll({ attributes: ["name"] }); + const configList = configCollection.map(conf => `\`${conf.name}\``).join(', '); + + const noConfigEmbed = getEmbed.execute(param, config.error_color, "Not Found", `Couldn\'t find config named \`${configName}\`.\nAvailable names : ${configList}`); + + var configData = []; + if (configName == "prefix") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : To differentiate between a command and non command.`); + configData.push(`**Requirements** : \n\`> Any input that didn\'t have [space] as it\'ll be ignored.\``); + } else if(configName == "botOwnerID") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : An owner of this bot can use any commands anywhere.`); + configData.push(`**Requirements** : \n\`> Only bot owner can change this value.\n> Input can\'t be empty.\``); + } else if(configName == "mainServerID") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : The server that is used by users who will use this bot to ask moderators.`); + configData.push(`**Requirements** : \n\`> Any server that have this bot.\n> Value can be same as [threadServerID].\``); + } else if(configName == "threadServerID") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : The server where thread channels will be on.`); + configData.push(`**Requirements** : \n\`> Any server that have this bot.\n> Value can be same as [mainServerID].\``); + } else if(configName == "categoryID") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Category channel where thread channels will be created.`); + configData.push(`**Requirements** : \n\`> Any category channel that are inside thread server.\n> [threadServerID] value can\'t be empty.\``); + configData.push(`**Note** : To understand what category channel is, check (<https://support.discordapp.com/hc/en-us/articles/115001580171-Channel-Categories-101>).`); + configData.push(`\`ps. Discord.js treat it as channel that\'s why i use this term too.\``); + } else if(configName == "logChannelID") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Channel where thread logs will be sent.`); + configData.push(`**Requirements** : \n\`> Any channel inside thread server.\n> [threadServerID] value can\'t be empty.\``); + } else if(configName == "adminRoleID") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Role that will have administrator permission level.`); + configData.push(`**Requirements** : \n\`> Any role inside thread server.\n> [threadServerID] value can\'t be empty.\``); + } else if(configName == "modRoleID") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Role that will have moderator permission level.`); + configData.push(`**Requirements** : \n\`> Any role inside thread server.\n> [threadServerID] value can\'t be empty.\``); + } else if(configName == "mentionedRoleID") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : The role that will be mentioned on new thread.`); + configData.push(`**Requirements** : \n\`> Can be empty (no one mentioned).\n> Any role at thread server including here and everyone [set mentionedRoleID everyone].\``); + } else if(configName == "botChannelID") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Channel where user can only use to execute commands (any commands in other channels will be ignored except help commands).`); + configData.push(`**Requirements** : \n\`> Can be empty (everyone can use any commands anywhere).\n> Any channels inside main server.\n> Should\'t be a category channel (Discord.js treat categories as a channel too).\``); + } else if(configName == "maintenance") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Maintenance mode toggle. Config changed according previous value.`); + } else if(configName == "info_color") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Color used for any information related embeds.`); + configData.push(`**Requirements** : \n\`> Hex code color input.\``); + } else if(configName == "warning_color") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Color used for any warning related embeds.`); + configData.push(`**Requirements** : \`.\``); + } else if(configName == "error_color") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Color used for any error related embeds.`); + configData.push(`**Requirements** : \`.\``); + } else if(configName == "sent_color") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Color used for any message sent on threads related embeds.`); + configData.push(`**Requirements** : \`.\``); + } else if(configName == "received_color") { + configData.push(`**Name** : ${configName}`); + configData.push(`**Description** : Color used for any message received on threads related embeds.`); + configData.push(`**Requirements** : \`.\``); + } else { + configData.push(`\`Information is still not available.\``); + } + const dataEmbed = await getEmbed.execute(param, config.info_color, "Configuration Information", configData.join('\n')); + + if (!isConfig) { + return message.channel.send(noConfigEmbed); + } else { + return message.channel.send(dataEmbed); + }; + + } +}; diff --git a/functions/configSync.js b/functions/configSync.js new file mode 100644 index 0000000..0314d9c --- /dev/null +++ b/functions/configSync.js @@ -0,0 +1,38 @@ +module.exports = { + name: "configSync", + async execute(param){ + const config = param.config; + const ConfigDB = param.ConfigDB; + const user = param.client.user; + + console.log("[Syncing Configuration]") + user.setActivity("Syncing...", { type: "WATCHING" }); + let configKeys = Object.keys(config); + var syncPromise = new Promise(resolve => { + try { + async function forLoop(){ + for (var i = 0; i < configKeys .length; i++) { + let getConfig = await ConfigDB.findOne({ where: { name: configKeys[i] } }); + if(getConfig){ + console.log(`Syncing ${getConfig.name}...`) + config[configKeys[i]] = getConfig.input || "empty"; + } else { + //resolved too cause im still confused with reject() + console.log("Calling reset function...") + await param.reset.execute(param); + break; + } + } + resolve(); + } + forLoop(); + } catch (error) { + return console.log(error); + } + }); + syncPromise.then(() => { + console.log("[Synced]"); + user.setActivity("[Ready]", { type: "WATCHING" }); + }); + } +}; diff --git a/functions/configuration.js b/functions/configuration.js new file mode 100644 index 0000000..3eb2cb3 --- /dev/null +++ b/functions/configuration.js @@ -0,0 +1,48 @@ +module.exports = { + name: "configuration", + async execute(param){ + const Discord = param.Discord; + const client = param.client; + const config = param.config; + const configKeys = Object.keys(config); //getting the name of each config (prefix, botOwnerID, etc) + let botConfig = []; + let serverConfig = []; + let embedColorConfig = []; + let botOwnerIDIndex = ""; //As separator for server related config and bot config. + let maintenanceIndex = ""; //As separator for server related config and embed color config. + + //getting the index first for separator + for (var i = 0; i < configKeys.length; i++) { + if(configKeys[i] == "botOwnerID"){ + botOwnerIDIndex = i; + } else if(configKeys[i] == "maintenance"){ + maintenanceIndex = i; + } + }; + + for (var i = 0; i < configKeys.length; i++) { + if(configKeys[i] == "prefix"){ + botConfig.push(`${configKeys[i]} : \`${config[configKeys[i]]}\``); + } else if(configKeys[i] == "botOwnerID"){ + botConfig.push(`${configKeys[i]} : \`${config[configKeys[i]]}\``); + } else if(i > botOwnerIDIndex && i < maintenanceIndex){ + serverConfig.push(`${configKeys[i]} : \`${config[configKeys[i]]}\``); + } else if(configKeys[i] == "maintenance"){ + botConfig.push(`${configKeys[i]} : \`${config[configKeys[i]]}\``); + } else if(i > maintenanceIndex && i < configKeys.length){ + embedColorConfig.push(`${configKeys[i]} : \`${config[configKeys[i]]}\``); + } + }; + + const configEmbed = new Discord.RichEmbed() + .setColor(config.info_color) + .setTitle("Configuration") + .addField("~ Bot ~", botConfig) + .addField("~ Server ~", serverConfig) + .addField("~ Embed Color ~", embedColorConfig) + .setThumbnail(client.user.avatarURL) + .setFooter(client.user.tag, client.user.avatarURL) + .setTimestamp(); + return configEmbed; + } +}; diff --git a/functions/getEmbed.js b/functions/getEmbed.js new file mode 100644 index 0000000..c4b5ecb --- /dev/null +++ b/functions/getEmbed.js @@ -0,0 +1,12 @@ +module.exports = { + name: "getEmbed", + execute(param, color, title, description){ + const embed = new param.Discord.RichEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter(param.client.user.tag, param.client.user.avatarURL) + .setTimestamp(); + return embed; + } +}; diff --git a/functions/isBlocked.js b/functions/isBlocked.js new file mode 100644 index 0000000..b1258c5 --- /dev/null +++ b/functions/isBlocked.js @@ -0,0 +1,13 @@ +module.exports = { + name: "isBlocked", + async execute(param, userID){ + const BlockedDB = param.BlockedDB; + const isBlocked = await BlockedDB.findOne({ where: {userID: userID} }); + + if(isBlocked){ + return true; + } else { + return false; + } + } +}; diff --git a/functions/isMember.js b/functions/isMember.js new file mode 100644 index 0000000..2f99878 --- /dev/null +++ b/functions/isMember.js @@ -0,0 +1,15 @@ +module.exports = { + name: "isMember", + async execute(param, userID){ + const client = param.client; + const mainServerID = param.config.mainServerID; + const mainServer = await client.guilds.get(mainServerID); + const isMember = await mainServer.members.get(userID); + + if(isMember){ + return true; + } else { + return false; + } + } +}; diff --git a/functions/newThread.js b/functions/newThread.js new file mode 100644 index 0000000..dcf6e85 --- /dev/null +++ b/functions/newThread.js @@ -0,0 +1,106 @@ +module.exports = { + name: "newThread", + async execute(param, message, args){ + const Discord = param.Discord; + const Attachment = param.Attachment; + const moment = param.moment; + const client = param.client; + const getEmbed = param.getEmbed; + const config = param.config; + const ThreadDB = param.ThreadDB; + const isMember = param.isMember; + const isBlocked = param.isBlocked; + + const mainServerID = config.mainServerID; + const mainServer = await client.guilds.get(mainServerID); + const threadServerID = config.threadServerID; + const threadServer = await client.guilds.get(threadServerID); + const categoryID = config.categoryID; + const categoryChannel = await threadServer.channels.get(categoryID); + const logChannelID = config.logChannelID; + const logChannel = await threadServer.channels.get(logChannelID); + const author = message.author; + const mentionedRoleID = config.mentionedRoleID; + + let mentionedRole = ""; + if (mentionedRoleID == "everyone" || mentionedRoleID == "here") { + mentionedRole = "@" + mentionedRoleID; + } else if (config.mentionedRoleID != null && config.mentionedRoleID != "empty") { + mentionedRole = "<@&" + mentionedRoleID + ">"; + } + + const isThread = await ThreadDB.findOne({where: {userID: author.id}}); + const checkIsMember = await isMember.execute(param, author.id); + const checkIsBlocked = await isBlocked.execute(param, author.id); + + const notMemberEmbed = getEmbed.execute(param, config.error_color, "Not a Member", `You aren\'t inside [**${mainServer.name}**] guild.`); + const blockedEmbed = getEmbed.execute(param, config.error_color, "Blocked", `You are blocked from creating new thread.`); + const isThreadEmbed = getEmbed.execute(param, config.error_color, "Thread Detected", `You still have open thread.`); + + if (isThread) { + return message.channel.send(isThreadEmbed); + } else { + if (!checkIsMember) { + return message.channel.send(notMemberEmbed); + } else if (checkIsBlocked){ + return message.channel.send(blockedEmbed); + } else { + const newChannel = await threadServer.createChannel(author.tag.replace("#", "-"), { type: "text" }); + await newChannel.setParent(categoryID); //move the channel under category channel + await newChannel.lockPermissions(); //inherit category channel permission + + let logEmbed = new Discord.RichEmbed() + .setColor(config.info_color) + .setTitle("New Thread") + .setDescription(`${args.join(' ')}`) + .setFooter(`${author.tag} | ${author.id}`, author.avatarURL) + .setTimestamp(); + logChannel.send(logEmbed); + + let dmEmbed = new Discord.RichEmbed() + .setColor(config.info_color) + .setTitle("Thread Created!") + .setDescription( + `**Title** : ${args.join(' ')}\n\`Please describe your issue. (No command needed.)\`` + ) + .setFooter(mainServer.name, mainServer.iconURL) + .setTimestamp(); + author.send(dmEmbed); + + const member = await mainServer.members.get(author.id); + const memberRoles = await member.roles.map(role => `${role.name}`).join(', '); + let userData = []; + userData.push(`**User Tag** : \`${author.tag}\``); + userData.push(`**User ID** : \`${author.id}\``); + userData.push(`**Created at** : ${moment(author.createdAt).format("D MMM YYYY, HH:mm")}`); + userData.push(`**Joined at** : ${moment(member.joinedAt).format("D MMM YYYY, HH:mm")}`); + userData.push(`**Roles** : ${memberRoles}`); + let newThreadEmbed = new Discord.RichEmbed() + .setColor(config.info_color) + .setTitle("New Thread") + .setDescription(args.join(' ')) + .addField("User Info", userData.join('\n')) + .setThumbnail(author.avatarURL) + .setFooter(`${author.tag} | ${author.id}`, author.avatarURL) + .setTimestamp(); + newChannel.send(newThreadEmbed); + + if (message.attachments.size > 0) { + await message.attachments.forEach(async atch => { + let attachment = new Attachment(atch.url); + await newChannel.send(attachment); + }); + } + + const newThread = await ThreadDB.create({ + userID: author.id, + channelID: newChannel.id, + threadTitle: args.join(' ') + }); + console.log(`${author.tag} created thread.`); + + } + }; + + } +}; diff --git a/functions/reply.js b/functions/reply.js new file mode 100644 index 0000000..6d1c261 --- /dev/null +++ b/functions/reply.js @@ -0,0 +1,85 @@ +module.exports = { + name: "reply", + async execute(param, message, args){ + const Discord = param.Discord; + const Attachment = param.Attachment; + const client = param.client; + const getEmbed = param.getEmbed; + const config = param.config; + const ThreadDB = param.ThreadDB; + const isMember = param.isMember; + const isBlocked = param.isBlocked; + + const mainServerID = config.mainServerID; + const mainServer = await client.guilds.get(mainServerID); + const threadServerID = config.threadServerID; + const threadServer = await client.guilds.get(threadServerID); + const categoryID = config.categoryID; + const author = message.author; + const channel = message.channel; + + const isThread = await ThreadDB.findOne({where: {channelID: channel.id}}); + const checkIsBlocked = await isBlocked.execute(param, author.id); + + const blockedEmbed = getEmbed.execute(param, config.error_color, "Blocked", `User blocked.`); + const noDMEmbed = getEmbed.execute(param, config.error_color, "Not Sent", `User disabled Direct Message.`); + const noUserEmbed = getEmbed.execute(param, config.error_color, "Not Found", `Couldn\'t find user in my collection.`); + const noThreadEmbed = getEmbed.execute(param, config.error_color, "Not Found", `Couldn\'t find any thread asociated with this channel.`); + + if (!isThread) { + return channel.send(noThreadEmbed); + } else { + const checkIsMember = await isMember.execute(param, author.id); + const notMemberEmbed = getEmbed.execute(param, config.error_color, "Not a Member", `User aren\'t inside [**${mainServer.name}**] guild.`); + + if (!checkIsMember) { + return channel.send(notMemberEmbed); + } else if (checkIsBlocked){ + return channel.send(blockedEmbed); + } else { + const userID = isThread.userID; + const member = await mainServer.members.get(userID); + + if (!member) { + return channel.send(noUserEmbed); + } else { + const user = member.user; + const description = args.join(' '); + const userDMEmbed = new Discord.RichEmbed() + .setColor(config.sent_color) + .setAuthor(author.tag, author.avatarURL) + .setTitle("Message Received") + .setDescription(description) + .setFooter(mainServer.name, mainServer.avatarURL) + .setTimestamp(); + const threadChannelEmbed = new Discord.RichEmbed() + .setColor(config.sent_color) + .setAuthor(author.tag, author.avatarURL) + .setTitle("Message Sent") + .setDescription(description) + .setFooter(`${user.tag} | ${user.id}`, user.avatarURL) + .setTimestamp(); + + try{ + await user.send(userDMEmbed); + } catch (error){ + if(error.message == "Cannot send messages to this user"){ + return channel.send(noDMEmbed); + } + } + await channel.send(threadChannelEmbed); + if (message.attachments.size > 0) { + await message.attachments.forEach(async atch => { + let attachment = new Attachment(atch.url); + await user.send(attachment); + await channel.send(attachment); + }); + } + return message.delete(); + } + + }; + }; + + } +}; diff --git a/functions/reset.js b/functions/reset.js new file mode 100644 index 0000000..90e2fd4 --- /dev/null +++ b/functions/reset.js @@ -0,0 +1,27 @@ +module.exports = { + name: "reset", + async execute(param){ + const defConfig = param.defConfig; + const ConfigDB = param.ConfigDB; + const configKeys = Object.keys(param.config); + + configKeys.forEach(async aKey => { + try { + //Create new row on config.sqlite + const newConfig = await ConfigDB.create({ + name: aKey, + input: defConfig[aKey] + }); + } catch (error) { + //Edit the value in config.sqlite with the one from config.js + if (error.name === "SequelizeUniqueConstraintError") { + await ConfigDB.update( + { input: defConfig[aKey] }, + { where: { name: aKey } } + ); + } + } + }); + return param.configSync.execute(param); + } +}; diff --git a/functions/roleCheck.js b/functions/roleCheck.js new file mode 100644 index 0000000..408f838 --- /dev/null +++ b/functions/roleCheck.js @@ -0,0 +1,12 @@ +module.exports = { + name: "roleCheck", + async execute(message, roleID){ + const isRole = message.member.roles.get(roleID); + + if(isRole){ + return true; + } else { + return false; + } + } +}; diff --git a/functions/set.js b/functions/set.js new file mode 100644 index 0000000..47b88a0 --- /dev/null +++ b/functions/set.js @@ -0,0 +1,119 @@ +module.exports = { + name: "set", + async execute(param, message, args){ + const client = param.client; + const config = param.config; + const getEmbed = param.getEmbed; + const configSync = param.configSync; + const ConfigDB = param.ConfigDB; + const configName = args.shift(); + var inputValue = args.shift() || "empty"; + + //manual toggle since i set database to String, can't store boolean for maintenance config. + if(configName == "maintenance"){ + if(config.maintenance == "0"){ + inputValue = "1"; + } else { + inputValue = "0"; + } + } + + const notOwnerEmbed = getEmbed.execute(param, config.warning_color, "Missing Permission", `Only bot owner [<@${config.botOwnerID}>] can change this value.`); + const successEmbed = getEmbed.execute(param, config.info_color, "Success", `The value of \`${configName}\` changed to \`${inputValue}\``); + const notSetEmbed = getEmbed.execute(param, config.warning_color, "Configuration Needed", `Please set \`threadServerID\` to change this config.`); + const emptyValueEmbed = getEmbed.execute(param, config.warning_color, "Invalid Value", "This config value can\'t be empty."); + const invalidUserEmbed = getEmbed.execute(param, config.warning_color, "Invalid User", `Can\'t find that user.`); + const invalidServerEmbed = getEmbed.execute(param, config.warning_color, "Invalid Server", `Can\'t find that server.\n\`Make sure the bot joined the server already\``); + const invalidChannelMainEmbed = getEmbed.execute(param, config.warning_color, "Invalid Channel", `Can\'t find that channel.\n\`Make sure the channel is inside Main Server.\``); + const invalidChannelThreadEmbed = getEmbed.execute(param, config.warning_color, "Invalid Channel", `Can\'t find that channel.\n\`Make sure the channel is inside Thread Server.\``); + const invalidRoleEmbed = getEmbed.execute(param, config.warning_color, "Invalid Role", `Can\'t find that role.\n\`Make sure the role is inside Thread Server.\``); + const invalidColorEmbed = getEmbed.execute(param, config.warning_color, "Invalid Color", `Use hex code for input.\nCheck : <https://html-color.codes/>`); + + //elimination for invalid input + if(configName == "botOwnerID"){ + + if(message.author.id != config.botOwnerID){ + return message.channel.send(notOwnerEmbed); + } else if(inputValue == "empty"){ + return message.channel.send(emptyValueEmbed); + } else if(!client.users.get(inputValue)){ + return message.channel.send(invalidUserEmbed); + }; + + } else if(configName == "mainServerID" && inputValue != "empty"){ + + if(!client.guilds.get(inputValue)) { + return message.channel.send(invalidServerEmbed); + }; + + } else if(configName == "threadServerID" && inputValue != "empty"){ + + if(!client.guilds.get(inputValue)) { + return message.channel.send(invalidServerEmbed); + }; + + } else if((configName == "categoryID" || configName == "logChannelID") && inputValue != "empty"){ + + if(config.threadServerID == "empty"){ + return message.channel.send(notSetEmbed); + } else if(!client.guilds.get(config.threadServerID).channels.get(inputValue)){ + return message.channel.send(invalidChannelThreadEmbed); + }; + + } else if(configName == "botChannelID" && inputValue != "empty"){ + + if(config.mainServerID == "empty"){ + return message.channel.send(notSetEmbed); + } else if(!client.guilds.get(config.mainServerID).channels.get(inputValue)){ + return message.channel.send(invalidChannelMainEmbed); + }; + + } else if((configName == "adminRoleID" || configName == "modRoleID") && inputValue != "empty"){ + + if(config.threadServerID == "empty"){ + return message.channel.send(notSetEmbed); + } else if(!client.guilds.get(config.threadServerID).roles.get(inputValue)){ + return message.channel.send(invalidRoleEmbed); + }; + + } else if(configName == "mentionedRoleID" && inputValue != "empty" && inputValue != "everyone" && inputValue != "here"){ + + if(config.threadServerID == "empty"){ + return message.channel.send(notSetEmbed); + } else if(!client.guilds.get(config.threadServerID).roles.get(inputValue)){ + return message.channel.send(invalidRoleEmbed); + } + + } else if(configName == "info_color" || configName == "warning_color" || configName == "error_color" || configName == "sent_color" || configName == "received_color"){ + + const colorTest = /^#[0-9A-F]{6}$/i; + if(inputValue == "empty"){ + return message.channel.send(emptyValueEmbed); + } else if(colorTest.test(inputValue) == false){ + return message.channel.send(invalidColorEmbed); + } + + } + + //getting all the config name from Database + const configCollection = await ConfigDB.findAll({ attributes: ["name"] }); + const configList = configCollection.map(conf => `\`${conf.name}\``).join(', '); + + //trying to edit the Database + const affectedRows = await ConfigDB.update({input: inputValue}, {where: {name:configName}}); + if(affectedRows > 0){ + console.log(`[${configName}] value changed to [${inputValue}]`); + await message.channel.send(successEmbed).then(async () => { + if(configName == "maintenance" || configName == "prefix"){ + process.exit(1); + } else { + return await configSync.execute(param); + } + }); + } else { + const notFoundEmbed = getEmbed.execute(param, config.error_color, "Failed", `Can\'t find config named \`${configName}\`.\nAvailable names : ${configList}`); + return message.channel.send(notFoundEmbed) + } + + } +}; diff --git a/functions/threadInfo.js b/functions/threadInfo.js new file mode 100644 index 0000000..6261419 --- /dev/null +++ b/functions/threadInfo.js @@ -0,0 +1,52 @@ +module.exports = { + name: "threadInfo", + async execute(param, message, args){ + const Discord = param.Discord; + const moment = param.moment; + const client = param.client; + const getEmbed = param.getEmbed; + const config = param.config; + const ThreadDB = param.ThreadDB; + + const mainServerID = config.mainServerID; + const mainServer = await client.guilds.get(mainServerID); + const threadServerID = config.threadServerID; + const threadServer = await client.guilds.get(threadServerID); + + const input = args.shift(); + const isThreadUser = await ThreadDB.findOne({where: {userID: input}}); + const isThreadChannel = await ThreadDB.findOne({where: {channelID: input}}); + let isThread = false; + + var noThreadEmbed = getEmbed.execute(param, config.error_color, "Not Found", `Couldn\'t find any thread asociated with that user id or channel id.`); + + if (isThreadUser) { + isThread = isThreadUser; + } else if(isThreadChannel){ + isThread = isThreadChannel; + } + + if (!isThread) { + return message.channel.send(noThreadEmbed); + } else { + let threadData = []; + const member = mainServer.members.get(isThread.userID); + + threadData.push(`${isThread.threadTitle}`); + if (member) { + threadData.push(`**User Tag** : \`${member.user.tag}\``); + } else { + threadData.push(`**User Tag** : \`Couldn\'t find user at main server.\``); + } + threadData.push(`**User ID** : \`${isThread.userID}\``); + threadData.push(`**Thread Channel** : <#${isThread.channelID}>`); + threadData.push(`**Created at** : ${moment(isThread.createdAt).format("D MMMM YYYY, **HH:mm:ss** UTC")}`); + threadData.push(`**Updated at** : ${moment(isThread.updatedAt).format("D MMMM YYYY, **HH:mm:ss** UTC")}`); + + const threadInfoEmbed = getEmbed.execute(param, config.info_color, "Thread Information", threadData.join('\n')); + return message.channel.send(threadInfoEmbed); + + }; + + } +}; diff --git a/functions/unblock.js b/functions/unblock.js new file mode 100644 index 0000000..1d5c2da --- /dev/null +++ b/functions/unblock.js @@ -0,0 +1,24 @@ +module.exports = { + name: "unblock", + async execute(param, message, args){ + const moment = param.moment; + const client = param.client; + const config = param.config; + const BlockedDB = param.BlockedDB; + const getEmbed = param.getEmbed; + + const userID = args.shift(); + + const notFoundEmbed = getEmbed.execute(param, config.error_color, "Not Found", `<@${userID}> (\`${userID}\`) isn\'t blocked.`); + const successEmbed = getEmbed.execute(param, config.info_color, "Success", `Succesfully unblock <@${userID}> (\`${userID}\`).`); + + const rowCount = await BlockedDB.destroy({ where: {userID: userID} }); + if (rowCount > 0) { + console.log(`Unblocked ${userID}`); + return message.channel.send(successEmbed); + } else { + return message.channel.send(notFoundEmbed); + } + + } +}; diff --git a/functions/userReply.js b/functions/userReply.js new file mode 100644 index 0000000..a99f5d4 --- /dev/null +++ b/functions/userReply.js @@ -0,0 +1,64 @@ +module.exports = { + name: "userReply", + async execute(param, message, thread){ + const Discord = param.Discord; + const Attachment = param.Attachment; + const client = param.client; + const getEmbed = param.getEmbed; + const config = param.config; + const isMember = param.isMember; + const isBlocked = param.isBlocked; + + const mainServerID = config.mainServerID; + const mainServer = await client.guilds.get(mainServerID); + const threadServerID = config.threadServerID; + const threadServer = await client.guilds.get(threadServerID); + const author = message.author; + + const checkIsBlocked = await isBlocked.execute(param, author.id); + + const blockedEmbed = getEmbed.execute(param, config.error_color, "Blocked", `You are blocked from replying to a thread.`); + const noServerEmbed = getEmbed.execute(param, config.error_color, "Contact Admin", "\`mainServerID\` and/or \`threadServerID\` value is empty."); + const noChannelEmbed = getEmbed.execute(param, config.error_color, "Channel Not Found", `Couldn\'t find your thread channel, ask admin to use \`${config.prefix}bind\` command.`); + + if(checkIsBlocked){ + return message.channel.send(blockedEmbed); + } else if (!mainServer || !threadServer) { + //Can't find main server or thread server + return message.channel.send(noServerEmbed); + } else { + const checkIsMember = await isMember.execute(param, author.id); + const notMemberEmbed = getEmbed.execute(param, config.error_color, "Not a Member", `User aren\'t inside [**${mainServer.name}**] guild.`); + const threadChannel = await threadServer.channels.get(thread.channelID); + + if(!checkIsMember){ + return message.channel.send(notMemberEmbed); + } else { + if(!threadChannel){ + return message.channel.send(noChannelEmbed); + } else { + const sendPromise = new Promise(async resolve => { + let userReplyEmbed = new Discord.RichEmbed() + .setColor(config.received_color) + .setTitle("Message Received") + .setDescription(message.content) + .setFooter(`${author.tag} | ${author.id}`, author.avatarURL) + .setTimestamp(); + await threadChannel.send(userReplyEmbed); + + if (message.attachments.size > 0) { + await message.attachments.forEach(async atch => { + let attachment = new Attachment(atch.url); + await threadChannel.send(attachment); + }); + } + resolve(); + }); + sendPromise.then(message.react("✅")); + + } + } + }; + + } +}; diff --git a/index.js b/index.js index 14c6586..20fa4b1 100644 --- a/index.js +++ b/index.js @@ -1,1820 +1,325 @@ -/* - -*/ - -//===============================DEPENDECIES==================================== - -//#dependencies -console.log("Loading Dependencies"); -const Discord = require("discord.js"); -const { Util, Attachment } = require("discord.js"); -const client = new Discord.Client(); -const server = require("./server.js"); -const Sequelize = require("sequelize"); -const fs = require("fs"); -const moment = require("moment"); -const defConfig = require("./config.json"); -require("dotenv").config(); - -//============================================================================== -//================================VARIABLES===================================== - -console.log("Loading Variables"); -//#config -//Config used by bot (synced from database everytime bot ready). -//Use same variable name on config.json or it won't be able to reseted on reset. -var config = { - prefix: "", - botOwnerID: "", - serverID: "", - categoryID: "", - logChannelID: "", - adminRoleID: "", - modRoleID: "", - mentionedRoleID: "", - maintenance: "", - info_color: "", - warning_color: "", - error_color: "", - received_color: "", - sent_color: "" -}; - -//----Activity List---- -//#activities -var activities = [ - `Glitch.com | ${defConfig.prefix}commands`, - `DM to contact Staff | ${defConfig.prefix}help`, - `DM, um Mitarbeiter zu kontaktieren | ${defConfig.prefix}helpDE`, - `Personel ile irtibata geçmek için DM | ${defConfig.prefix}helpTR`, - `직원에게 연락하는 DM | ${defConfig.prefix}helpKO`, - `DM para entrar em contato com a equipe | ${defConfig.prefix}helpPT`, - `DM contacte le personnel | ${defConfig.prefix}helpFR`, - `DM связаться с персоналом | ${defConfig.prefix}helpRU`, - `DM 与官方人员联系 | ${defConfig.prefix}helpCHS`, - `DM 與官方人員聯繫 | ${defConfig.prefix}helpCHT`, - `DM para contactar al personal | ${defConfig.prefix}helpES` -]; - -//----Database---- -//#db -const blockedDB = new Sequelize("database", "user", "password", { - host: "localhost", - dialect: "sqlite", - logging: false, - // SQLite only - storage: "blocked.sqlite" -}); -const BlockedDB = blockedDB.define("blocked", { - name: { - type: Sequelize.STRING, - unique: true - } -}); - -const configDB = new Sequelize("database", "user", "password", { - host: "localhost", - dialect: "sqlite", - logging: false, - // SQLite only - storage: "config.sqlite" -}); -const ConfigDB = configDB.define("config", { - name: { - type: Sequelize.STRING, - unique: true - }, - input: Sequelize.STRING -}); - -//============================================================================== -//===============================FUNCTIONS====================================== - -console.log("Loading Functions"); - -//----------------------------------Get Embed----------------------------------- -//#embed -function getEmbed(color, title, description) { - var embed = new Discord.RichEmbed() - .setColor(color) - .setTitle(title) - .setDescription(description) - .setFooter(client.user.tag, client.user.avatarURL) - .setTimestamp(); - return embed; -} - -//------------------------------Guild Member Check------------------------------ -//#isMemberFn -async function isMember(msg) { - if ( - config.serverID == "empty" || - config.categoryID == "empty" || - config.logChannelID == "empty" - ) { - msg.channel.send( - getEmbed( - config.error_color, - "Error!", - "Bot configuration has not been set. Use =setup command." - ) - ); - return false; - } - let searchMember = - (await client.guilds.get(config.serverID).members.get(msg.author.id)) || - false; - if (searchMember) { - return true; - } else { - await msg.channel.send( - getEmbed( - config.error_color, - "Not Member!", - `You aren't member of **${ - client.guilds.get(config.serverID).name - }** server.` - ) - ); - return false; - } -} - -//------------------------------Blocked User Check------------------------------ -//#isBlockedFn -async function isBlocked(msg) { - if ( - config.serverID == "empty" || - config.categoryID == "empty" || - config.logChannelID == "empty" - ) { - msg.channel.send( - getEmbed( - config.error_color, - "Error!", - "Bot configuration has not been set. Use =setup command." - ) - ); - return false; - } - let findInBlock = await BlockedDB.findOne({ where: { name: msg.author.id } }); - if (!findInBlock) { - return false; - } else { - return await msg.channel.send( - getEmbed( - config.error_color, - "Blocked!", - `You are blocked in **${ - client.guilds.get(config.serverID).name - }** server.` - ) - ); - return true; - } -} - -//-------------------------------Permission Check------------------------------- -//#permissionCheckFn -async function permissionCheck(msg, permission) { - let result = false; - if (msg.member.hasPermission(permission)) { - result = true; - } else { - result = false; - } - return result; -} - -//---------------------------------Role Check----------------------------------- -//#roleCheckFn -async function roleCheck(msg, roleID) { - let result = false; - if (roleID == "empty") { - if (config.adminRoleID == "empty" && config.modRoleID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - `Value of \`adminRoleID\` and \`modRoleID\` is empty. Use =setup to change it.` - ) - ); - return result; - } else if (config.adminRoleID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - `Value of \`adminRoleID\` is empty. Use =setup to change it.` - ) - ); - return result; - } else if (config.modRoleID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - `Value of \`modRoleID\` is empty. Use =setup to change it.` - ) - ); - return result; - } - } - let role = msg.guild.roles.get(roleID); - if (msg.member.roles.find(r => r.id == roleID)) { - result = true; - } else { - result = false; - } - return result; -} - -//++++++++++++++++++++++++++++++Command Functions+++++++++++++++++++++++++++++++ -//-----------------------------New Thread Function------------------------------ -//#newThreadFn -async function newThread(msg, args) { - if ( - config.serverID == "empty" || - config.categoryID == "empty" || - config.logChannelID == "empty" - ) { - return msg.channel.send( - getEmbed( - config.error_color, - "Error!", - "Bot configuration has not been set. Use =setup command." - ) - ); - } - let IsMember = await isMember(msg); - let IsBlocked = await isBlocked(msg); - let HaveThread = await client.guilds - .get(config.serverID) - .channels.find(ch => ch.name == msg.author.id); - let MentionedRole = ""; - if ( - config.mentionedRoleID == "everyone" || - config.mentionedRoleID == "here" - ) { - MentionedRole = "@" + config.mentionedRoleID; - } else if ( - config.mentionedRoleID != null && - config.mentionedRoleID != "empty" - ) { - MentionedRole = "<@&" + config.mentionedRoleID + ">"; - } - if (HaveThread) { - return await msg.channel.send( - getEmbed( - config.warning_color, - "Open Thread Exist!", - `You still have open thread.` - ) - ); - } - if (IsMember && !IsBlocked && !HaveThread) { - let newChannel = await client.guilds - .get(config.serverID) - .createChannel(msg.author.id, { type: "text" }); - await newChannel.setParent(config.categoryID); - await newChannel.lockPermissions().catch(console.error); - - let user = client.users.get(msg.author.id); - let memberRoles = await client.guilds - .get(config.serverID) - .members.get(msg.author.id) - .roles.filter(r => r.name !== "@everyone") - .map(role => `<@&${role.id}>`) - .join(", "); - let description = `**Nickname** : \`${user.tag}\`\n**ID** : \`${ - user.id - }\`\n**Created at** : ${moment(user.createdAt).format( - "DD MMM YYYY, HH:mm" - )}\n**Joined at** : ${moment( - client.guilds.get(config.serverID).members.get(msg.author.id).joinedAt - ).format("DD MMM YYYY, HH:mm")}\n**Roles** : ${memberRoles}`; - let newThreadEmbed = new Discord.RichEmbed() - .setColor(config.info_color) - .setAuthor("New Thread!") - .setTitle(`"${args}"`) - .setDescription(description) - .setThumbnail(msg.author.avatarURL) - .setFooter(`${msg.author.tag} | ${msg.author.id}`, msg.author.avatarURL) - .setTimestamp(); - newChannel.send(`${MentionedRole}`, newThreadEmbed); - - let logEmbed = new Discord.RichEmbed() - .setColor(config.info_color) - .setAuthor("New Thread!") - .setTitle(`"${args}"`) - .setFooter(`${msg.author.tag} | ${msg.author.id}`, msg.author.avatarURL) - .setTimestamp(); - let logChannel = await client.guilds - .get(config.serverID) - .channels.get(config.logChannelID); - logChannel.send(logEmbed); - - let mainServer = client.guilds.get(config.serverID); - let dmEmbed = new Discord.RichEmbed() - .setColor(config.info_color) - .setTitle("Thread Created!") - .setDescription( - `**Title : "${args}"**\n\n\`Please describe your issue. (No command needed.)\`` - ) - .setFooter(mainServer.name, mainServer.iconURL) - .setTimestamp(); - msg.channel.send(dmEmbed); - } -} - -//----------------------------User Response Function---------------------------- -//#userResponseFn -async function userResponse(msg, channel) { - let chatEmbed = new Discord.RichEmbed() - .setColor(config.received_color) - .setTitle("Message Received") - .setDescription(msg.content) - .setFooter(`${msg.author.tag} | ${msg.author.id}`, msg.author.avatarURL) - .setTimestamp(); - if (msg.attachments.size == 0) { - channel.send(chatEmbed).then(msg.react("✅")); - } else if (msg.attachments.size == 1) { - await msg.attachments.forEach(a => { - let attachment = new Attachment(a.url); - channel.send(chatEmbed.attachFile(attachment)).then(msg.react("✅")); - }); - } else { - await msg.attachments.forEach(a => { - let attachment = new Attachment(a.url); - channel.send(attachment); - }); - channel.send(chatEmbed).then(msg.react("✅")); - } -} - -//------------------------------User Block Function----------------------------- -//#blockFn -async function block(msg, arg) { - if (!arg) { - msg.channel.send( - getEmbed( - config.warning_color, - "Missing Argument", - "**Usage** : `block [user-id]`\n\n`Note : The bot didn't check user existence to enable blocking someone outside the server. Please double check the ID before using this command.`" - ) - ); - } else { - try { - const block = await BlockedDB.create({ - name: arg - }); - return msg.channel.send( - getEmbed( - config.error_color, - "Blocked!", - `<@${block.name}> (${block.name}) has been blocked.` - ) - ); - } catch (e) { - if (e.name === "SequelizeUniqueConstraintError") { - return msg.channel.send( - getEmbed( - config.warning_color, - "Duplicated!", - `<@${arg}> (${arg}) already blocked.` - ) - ); - } else { - return msg.channel.send( - getEmbed(config.error_color, "Error", `${e.name}`) - ); - } - } - } -} - -//----------------------------Users Blocklist Function-------------------------- -//#blockListFn -async function blocklist(msg, arg) { - const list = await BlockedDB.findAll({ attributes: ["name", "createdAt"] }); - var pages = Math.floor(list.length / 20); - if (list.length % 20 != 0) { - pages += 1; - } - if (!arg || isNaN(arg) || arg < 0) { - arg = 1; - } - if (list.length == 0) { - arg = 0; - } - const string = - list - .map( - b => - `**[${moment(b.createdAt).format("DD/MM/YYYY")}]** <@${b.name}> \`(${ - b.name - })\`` - ) - .slice(Math.abs((arg - 1) * 20)) - .slice(0, 20) - .join("\n") || "Blocklist empty."; - return msg.channel.send( - getEmbed( - config.info_color, - "**List of blocked user :**", - `${string}\n\n\`Page ${arg} from ${pages} pages.\`` - ) - ); -} - -//----------------------------User Unblock Function---------------------------- -//#unblockFn -async function unblock(msg, arg) { - if (!arg) { - msg.channel.send( - getEmbed( - config.warning_color, - "Missing Argument", - "**Usage** : `unblock [user-id]`" - ) - ); - } else { - const rowCount = await BlockedDB.destroy({ where: { name: arg } }); - if (!rowCount) - return msg.channel.send( - getEmbed(config.warning_color, "Not Found!", "That user isn't blocked.") - ); - - return msg.channel.send( - getEmbed(config.info_color, "Success!", `<@${arg}> (${arg}) unblocked.`) - ); - } -} - -//-----------------------------Thread Reply Function---------------------------- -//#replyFn -async function reply(msg, arg) { - if ( - config.serverID == "empty" || - config.categoryID == "empty" || - config.logChannelID == "empty" - ) { - return msg.channel.send( - getEmbed( - config.error_color, - "Error!", - "Bot configuration has not been set. Use =setup command." - ) - ); - } - if (!arg && msg.attachments.size == 0) { - let embed = getEmbed( - config.warning_color, - "Missing Argument", - `**Usage** : \`reply [reply message]\`` - ); - return msg.channel.send(embed); - } else { - let text = msg.content - .split(/ +/) - .slice(1) - .join(" "); - let channelName = await msg.channel.name; - let user - try{ - user = await client.guilds.get(config.serverID).members.get(channelName).user; - }catch(e){ - if(e.message == "Cannot read property 'user' of undefined"){ - return msg.channel.send( - getEmbed( - config.warning_color, - "User Not Found!", - `Can\'t find <@${channelName}>.` - ) - ); - } else { - return msg.channel.send( - getEmbed( - config.warning_color, - "Error", - e.message - ) - ); - } - } - let moderator = msg.author; - - let mainServer = client.guilds.get(config.serverID); - let chatGuildEmbed = new Discord.RichEmbed() - .setColor(config.sent_color) - .setAuthor(moderator.tag, moderator.avatarURL) - .setTitle("Message sent") - .setDescription(text) - .setFooter(`${user.tag} | ${user.id}`, user.avatarURL) - .setTimestamp(); - let chatDMEmbed = new Discord.RichEmbed() - .setColor(config.sent_color) - .setAuthor(moderator.tag, moderator.avatarURL) - .setDescription(text) - .setFooter(mainServer.name, mainServer.iconURL) - .setTimestamp(); - let disabledDM = getEmbed(config.error_color, "Failed!", "User disabled Direct Message.") - if (msg.attachments.size == 0) { - try{ - await user.send(chatDMEmbed); - } catch (e){ - if(e.message == "Cannot send messages to this user"){ - return msg.channel.send(disabledDM); - } else { - return msg.channel.send(getEmbed(config.error_color, "Error!", e.message)) - } - } - msg.channel.send(chatGuildEmbed); - msg.delete(); - } else { - try { - await user.send(chatDMEmbed); - } catch (e){ - if(e.message == "Cannot send messages to this user"){ - return msg.channel.send(disabledDM); - } else { - return msg.channel.send(getEmbed(config.error_color, "Error!", e.message)) - } - } - msg.channel.send(chatGuildEmbed); - await msg.attachments.forEach(a => { - let attachment = new Attachment(a.url); - user.send(attachment).then(msg.channel.send(attachment)); - - }); - msg.delete(); - } - - } -} - -//----------------------------Thread Close Function----------------------------- -//#closeFn -async function close(msg, arg) { - if ( - config.serverID == "empty" || - config.categoryID == "empty" || - config.logChannelID == "empty" - ) { - return msg.channel.send( - getEmbed( - config.error_color, - "Error!", - "Bot configuration has not been set. Use =setup command." - ) - ); - } - if ( - msg.channel.parentID != config.categoryID || - msg.channel.id == config.logChannelID - ) { - let embed = getEmbed( - config.warning_color, - "Not Thread Channel", - "This is not thread channel." - ); - msg.channel.send(embed); - } else if (!arg) { - let embed = getEmbed( - config.warning_color, - "Missing Argument", - `**Usage** : \`close [reason] - [note]\`` - ); - return msg.channel.send(embed); - } else { - let temp = arg.split(/-+/); - let reason = temp[0]; - let note = temp[1] || "Empty"; - let logChannel = await client.guilds - .get(config.serverID) - .channels.get(config.logChannelID); - let channelName = await msg.channel.name; - let user = await client.guilds.get(config.serverID).members.get(channelName) - .user; - let moderator = msg.author; - - let logEmbed = new Discord.RichEmbed() - .setColor(config.error_color) - .setAuthor(moderator.tag, moderator.avatarURL) - .setTitle("Thread closed!") - .setDescription(`**Reason** : ${reason}\n**Note** : ${note}`) - .setFooter(`${user.tag} | ${user.id}`, user.avatarURL) - .setTimestamp(); - let dmEmbed = new Discord.RichEmbed() - .setColor(config.error_color) - .setAuthor( - client.guilds.get(config.serverID).name, - client.guilds.get(config.serverID).iconURL - ) - .setTitle("Thread closed!") - .setDescription(`**Reason** : ${reason}`) - .setFooter(`${user.tag} | ${user.id}`, user.avatarURL) - .setTimestamp(); - msg.channel.delete().catch(console.error); - logChannel.send(logEmbed); - user.send(dmEmbed).catch(console.error.message); - } -} - -//-----------------------------Reset Config Function---------------------------- -//#resetFn -//Using variables at config.js as default. -//I've tried to reverse this to (update > error > create) it can't find the row, didn't throw any error, and keep searching indefinitely. -async function resetConfig() { - let configKeys = Object.keys(config); - configKeys.forEach(async aKey => { - try { - //Create new row on config.sqlite - const newConfig = await ConfigDB.create({ - name: aKey, - input: defConfig[aKey] - }); - } catch (e) { - //Edit the value in config.sqlite with the one from config.js - if (e.name === "SequelizeUniqueConstraintError") { - await ConfigDB.update( - { input: defConfig[aKey] }, - { where: { name: aKey } } - ); - } else { - console.log(e); - } - } - }); - return await configSync(); -} - -//-----------------------------Config Setup Function---------------------------- -//#setupFn -async function setup(msg, configName, configValue) { - if (configName == "botOwnerID") { - if (msg.author.id != config.botOwnerID) { - return msg.channel.send( - getEmbed( - config.warning_color, - "Missing Permission", - "Only bot owner can change this value." - ) - ); - } else if (!client.users.get(configValue)) { - return msg.channel.send( - getEmbed(config.warning_color, "Not Found!", "Can't find that user") - ); - } - } else if (configName == "serverID" && configValue != "empty") { - if (!client.guilds.get(configValue)) - return msg.channel.send( - getEmbed(config.warning_color, "Not Found!", "Cannot find that server.") - ); - } else if (!config.serverID || config.serverID == "empty") { - return msg.channel.send( - getEmbed( - config.error_color, - "Cannot find ServerID!", - "Please set `serverID` to change this value. `setup serverID [serverID]`" - ) - ); - } else if (configName == "categoryID" && configValue != "empty") { - if (!client.guilds.get(config.serverID).channels.get(configValue)) - return msg.channel.send( - getEmbed( - config.warning_color, - "Not Found", - "Can't find that category channel." - ) - ); - } else if (configName == "logChannelID" && configValue != "empty") { - if (!client.guilds.get(config.serverID).channels.get(configValue)) - return msg.channel.send( - getEmbed(config.warning_color, "Not Found", "Can't find that channel.") - ); - } else if (configName == "adminRoleID" && configValue != "empty") { - if (!client.guilds.get(config.serverID).roles.get(configValue)) - return msg.channel.send( - getEmbed(config.warning_color, "Not Found", "Can't find that role.") - ); - } else if (configName == "modRoleID" && configValue != "empty") { - if (!client.guilds.get(config.serverID).roles.get(configValue)) - return msg.channel.send( - getEmbed(config.warning_color, "Not Found", "Can't find that role.") - ); - } else if ( - configName == "mentionedRoleID" && - configValue != "everyone" && - configValue != "here" && - configValue != "empty" - ) { - if (!client.guilds.get(config.serverID).roles.get(configValue)) - return msg.channel.send( - getEmbed(config.warning_color, "Not Found", "Can't find that role.") - ); - } else if (configName == "maintenance") { - if (config.maintenance == "0") { - configValue = "1"; - } else { - configValue = "0"; - } - } else if ( - configName == "info_color" || - configName == "warning_color" || - configName == "error_color" || - configName == "received_color" || - configName == "sent_color" - ) { - var colorTest = /^#[0-9A-F]{6}$/i; //check if input is a hex color code. Search "JavaScript how to check hex code" for explanation. - if (colorTest.test(configValue) == false) { - return msg.channel.send( - getEmbed( - config.warning_color, - "Invalid Input", - "Use hex code for input.\n\nExample : `#ffffff`, `#000000`\n\nColor picker site will be helpful https://html-color.codes/" - ) - ); - } - } - let checkDB = await ConfigDB.findOne({ where: { name: configName } }); - if (!checkDB) { - const configList = await ConfigDB.findAll({ attributes: ["name"] }); - const configString = - configList.map(c => `\`${c.name}\``).join(", ") || - "Database empty, use =reset command."; - return msg.channel.send( - getEmbed( - config.warning_color, - "Failed", - `Could not find a config with name \`${configName}\`.\n\nAvailable config : ${configString}` - ) - ); - } else { - const affectedRows = await ConfigDB.update( - { input: configValue }, - { where: { name: configName } } - ); - if (affectedRows > 0) { - await configSync(); - await msg.channel.send( - getEmbed( - config.error_color, - "Success", - `Value of \`${configName}\` was edited to \`${configValue}\`.` - ) - ); - if (configName == "maintenance") { - process.exit(1); - } - } - } -} - -//-----------------------------Config List Function----------------------------- -//#configlistFn -async function configList(msg) { - let configKeys = Object.keys(config); - let serverSet = "", - colorSet = ""; - for (var i = 1; i < 8; i++) { - serverSet += `${configKeys[i]} : \`${config[configKeys[i]]}\`\n`; - } - for (var i = 9; i < 14; i++) { - colorSet += `${configKeys[i]} : \`${config[configKeys[i]]}\`\n`; - } - var embed = new Discord.RichEmbed() - .setColor(config.info_color) - .setTitle("Config List") - .addField( - configKeys[0][0].toUpperCase() + configKeys[0].slice(1), - config[configKeys[0]] - ) //Get config.prefix name and it's value - .addField("Server Config", serverSet) - .addField( - configKeys[8][0].toUpperCase() + configKeys[8].slice(1), - config[configKeys[8]] - ) //Get config.maintenance name and it's value - .addField("Color Config", colorSet) - .setFooter(client.user.tag, client.user.avatarURL) - .setTimestamp(); - return msg.channel.send(embed); -} - -//-----------------------------Server List Function----------------------------- -//#serverlistFn -async function serverList(msg) { - let list = - client.guilds.map(g => `**${g.name}** \`(${g.id})\``).join("\n") || - "The bot hasn't joined any server yet."; - return msg.channel.send(getEmbed(config.info_color, "Server List", list)); -} - -//----------------------------Leave Server Function----------------------------- -//#leaveFn -async function leaveServer(msg, server_ID) { - if (!server_ID) { - return msg.channel.send( - getEmbed( - config.warning_color, - "Missing Argument", - "Usage : `leave [serverID]`" - ) - ); - } - let server = client.guilds.get(server_ID); - if (!server) { - return msg.channel.send( - getEmbed( - config.warning_color, - "Unidentified!", - `The bot isn't inside the server with serverID of \`(${server_ID})\`.` - ) - ); - } else { - server.leave(); - return msg.channel.send( - getEmbed( - config.error_color, - "Leaving Server.", - `Leaving from **"${server.name}"** server.` - ) - ); - } -} - -//+++++++++++++++++++++++++++Config Sync Function+++++++++++++++++++++++++++++++ -//#configSyncFn -//syncing the variables value at #config with the database file -async function configSync() { - client.user.setActivity("Syncing...", { type: "WATCHING" }); - let configKeys = Object.keys(config); - var syncPromise = new Promise(resolve => { - configKeys.forEach(async aKey => { - try { - let getConfig = await ConfigDB.findOne({ where: { name: aKey } }).catch( - console.error - ); - config[aKey] = getConfig.input || "empty"; - resolve(); - } catch (e) { - if (e.message == "Cannot read property 'input' of null") { - await resetConfig(); - resolve(); - } - return console.log(e); - } - }); - }); - syncPromise.then(() => { - console.log("Sync done."); - }); -} - -//============================================================================== -//==================================READY======================================= -//#botReady -client.on("ready", async () => { - console.log("Syncing database...."); - await BlockedDB.sync(); - await ConfigDB.sync(); - await configSync(); - console.log(`Logged in as ${client.user.tag}!`); - client.user.setActivity("Ready.", { type: "WATCHING" }); - //when i use local variable (config.maintenance), the configSync() is still in process. - let getMT = await ConfigDB.findOne({ where: { name: "maintenance" } }).catch( - console.error - ); - if (getMT.input == "0") { - let index = 0; - setInterval(() => { - client.user.setActivity(activities[index], { type: "WATCHING" }); - index++; - if (index == activities.length) index = 0; - }, 7000); - } else { - client.user.setActivity("Under Maintenance.", { type: "WATCHING" }); - } -}); - -//============================================================================== -//=================================NEW GUILD==================================== -//#botJoin -client.on("guildCreate", async guild => { - client.users - .get(config.botOwnerID) - .send( - getEmbed( - config.info_color, - "Joined a Server", - `Joined \`${guild.name}\` server.\nServerID : \`${guild.id}\`` - ) - ); -}); - -//============================================================================== -//=================================MESSAGES===================================== -//#newMessage -client.on("message", async msg => { - if (msg.author.bot) return; - - //----------------------------Local Variables--------------------------------- - - let cmd = msg.content - .slice(config.prefix.length) - .split(/ +/, 1) - .join(" ") - .toLowerCase(); - let arg = msg.content - .split(/ +/) - .slice(1) - .join(" "); - - //------------------------Command Message Handler----------------------------- - //checking from default config first so that you can always use default prefix to run any commands - if ( - msg.content.indexOf(defConfig.prefix) == 0 || - msg.content.indexOf(config.prefix) == 0 - ) { - //-------------------------Restart Command---------------------------------- - //#restartCmd - if (cmd == "restart") { - const embed = new Discord.RichEmbed() - .setTitle("Done.") - .setDescription(`Restarted in **${Math.floor(client.ping)}**ms`); - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "Only Owner and Admin can use this command." - ); - if (msg.guild == null) { - if (msg.author.id === config.botOwnerID) { - msg.channel.send(embed).then(() => { - process.exit(1); - }); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (msg.author.id === config.botOwnerID) { - msg.channel.send(embed).then(() => { - process.exit(1); - }); - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - msg.channel.send(embed).then(() => { - process.exit(1); - }); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - - //--------------------------Server List Command----------------------------- - //#serverlistCmd - else if (cmd == "serverlist") { - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "Only Owner and Admin can use this command." - ); - if (msg.guild == null) { - if (msg.author.id === config.botOwnerID) { - await serverList(msg); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (msg.author.id === config.botOwnerID) { - await serverList(msg); - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - await serverList(msg); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - - //--------------------------Leave Server Command---------------------------- - //#leaveCmd - else if (cmd == "leave") { - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "Only Owner can use this command." - ); - if (msg.author.id === config.botOwnerID) { - await leaveServer(msg, arg); - } else { - return msg.channel.send(errorEmbed); - } - } - - //---------------------------Command list Command--------------------------- - //#cmdlistCmd - else if (cmd == "commands") { - let ownerLevel = "**leave** : Make the bot leave a specified server."; - let adminLevel = - "**restart** : Restart the bot.\n" + - "**reset** : Reset config values to default.\n" + - "**setup** : Setup config values.\n" + - "**configlist** : Show current config setting.\n" + - "**serverlist** : Show a list of servers that have this bot."; - let modLevel = - "**reply** : Reply to a user thread.\n" + - "**close** : Close a thread.\n" + - "**block** : Block a user.\n" + - "**blocklist** : Show list of blocked user.\n" + - "**unblock** : Remove a user from blocked list."; - let userLevel = - "**new** : Create a new thread.\n" + - "**help** : Show instruction about how to use the bot.\n" + - "**helpde** : Anleitung zur Verwendung des Bots anzeigen.\n" + - "**helptr** : Bot kullanımı hakkında talimat göster.\n" + - "**helpko** : 봇 사용 방법에 대한 지시 사항 표시.\n" + - "**helppt** : Mostrar instruções sobre como usar o bot.\n" + - "**helpfr** : Afficher les instructions sur l'utilisation du bot.\n" + - "**helpru** : Показать инструкцию о том, как использовать бот.\n" + - "**helpchs** : 显示如何使用操作这个系统的说明.\n" + - "**helpcht** : 顯示如何使用操作這個系統的說明.\n" + - "**helpes** : Mostrar instrucciones sobre cómo usar el bot."; - let ownerEmbed = new Discord.RichEmbed() - .setColor(config.info_color) - .setTitle("Command List") - .addField("Owner Level", ownerLevel) - .addField("Admin Level", adminLevel) - .addField("Moderator Level", modLevel) - .addField("User level", userLevel) - .setThumbnail(client.user.avatarURL) - .setFooter(client.user.tag, client.user.avatarURL) - .setTimestamp(); - let adminEmbed = new Discord.RichEmbed() - .setColor(config.info_color) - .setTitle("Command List") - .addField("Admin Level", adminLevel) - .addField("Moderator Level", modLevel) - .addField("User level", userLevel) - .setThumbnail(client.user.avatarURL) - .setFooter(client.user.tag, client.user.avatarURL) - .setTimestamp(); - let moderatorEmbed = new Discord.RichEmbed() - .setColor(config.info_color) - .setTitle("Command List") - .addField("Moderator Level", modLevel) - .addField("User level", userLevel) - .setThumbnail(client.user.avatarURL) - .setFooter(client.user.tag, client.user.avatarURL) - .setTimestamp(); - let userEmbed = new Discord.RichEmbed() - .setColor(config.info_color) - .setTitle("Command List") - .addField("User level", userLevel) - .setThumbnail(client.user.avatarURL) - .setFooter(client.user.tag, client.user.avatarURL) - .setTimestamp(); - if (msg.guild == null) { - if (msg.author.id === config.botOwnerID) { - msg.channel.send(ownerEmbed); - } else { - return msg.channel.send(userEmbed); - } - } else { - if (msg.author.id === config.botOwnerID) { - msg.channel.send(ownerEmbed); - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - msg.channel.send(adminEmbed); - } else if (await roleCheck(msg, config.modRoleID)) { - msg.channel.send(moderatorEmbed); - } else { - msg.channel.send(userEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - - //-------------------------------Help Commands------------------------------ - //#helpCmd - else if (cmd == "help") { - let embed = getEmbed( - config.info_color, - "Instruction", - "Use `=new Your thread title here` to create a new thread. You don't need to use any command after your thread created. Describe your issue afterward." - ); - msg.channel.send(embed); - } else if (cmd == "helpde") { - let embed = getEmbed( - config.info_color, - "Anweisung", - "Verwenden Sie `=new Dein Threadtitel hier`, um einen neuen Thread zu erstellen (es wird **Thread Created!** Angezeigt). Sie müssen nach dem Erstellen Ihres Threads keinen Befehl mehr verwenden. Beschreiben Sie anschließend Ihr Problem." - ); - msg.channel.send(embed); - } else if (cmd == "helptr") { - let embed = getEmbed( - config.info_color, - "Talimat", - "Yeni bir bilet oluşturmak için `=new konuyu buraya yazın` kullanın (şu mesajı alırsınız: **Thread Created!**). Konuyu oluşturduktan sonra herhangi bir komut kullanmanıza gerek yoktur. Daha sonra sorununuzu açıklayın." - ); - msg.channel.send(embed); - } else if (cmd == "helpko") { - let embed = getEmbed( - config.info_color, - "교수", - "`=new 스레드 제목을 여기에 사용하십시오` 새 스레드를 만들려면 **Thread Created!** 라고합니다. 스레드가 생성 된 후에는 명령을 사용할 필요가 없습니다. 나중에 문제를 설명하십시오." - ); - msg.channel.send(embed); - } else if (cmd == "helppt") { - let embed = getEmbed( - config.info_color, - "Instrução", - "Digite `=new O título do seu tópico aqui`. para criar um novo tópico (ele dirá **Thread Created!**). Você não precisa usar nenhum comando após a criação do seu thread. Descreva seu problema posteriormente." - ); - msg.channel.send(embed); - } else if (cmd == "helpfr") { - let embed = getEmbed( - config.info_color, - "Instruction", - "Taper `=new le titre de votre sujet de discussion ici` pour créer un nouveau sujet (ça va dire **Thread Created!**). Vous n'avez plus besoin d'utiliser de commande après la création du sujet. Décrivez simplement votre problème." - ); - msg.channel.send(embed); - } else if (cmd == "helpru") { - let embed = getEmbed( - config.info_color, - "инструкция", - "Введите `=new заголовок вашей темы здесь`. создать новую тему (будет сказано **Thread Created!**). Вам не нужно использовать какую-либо команду после создания вашего потока. Опишите вашу проблему позже." - ); - msg.channel.send(embed); - } else if (cmd == "helpchs") { - let embed = getEmbed( - config.info_color, - "指令", - "在此处输入`=new 您的线程标题`。 创建一个新线程(它将显示为 **Thread Created!**)。 创建线程后,无需使用任何命令。 之后描述您的问题。" - ); - msg.channel.send(embed); - } else if (cmd == "helpcht") { - let embed = getEmbed( - config.info_color, - "指令", - "在此處輸入 `=new 您的線程標題`。 創建一個新線程(它將顯示為 **Thread Created!**)。 創建線程後,無需使用任何命令。 之後描述您的問題。" - ); - msg.channel.send(embed); - } else if (cmd == "helpes") { - let embed = getEmbed( - config.info_color, - "Instrucción", - "Escribe `=new el título de su tema de discusión aquí` para crear un nuevo tema (esto mostrará **Thread Created!**). Ya no necesita usar un comando después de crear el asunto. Sólo tiene que describir su problema." - ); - msg.channel.send(embed); - } - - //----------------------------New Thread Command---------------------------- - //#newThreadCmd - else if (cmd == "new") { - if (msg.guild == null) { - if (!arg) { - let embed = getEmbed( - config.warning_color, - "Missing Argument", - "Usage : `new [Thread Title]`" - ); - return msg.channel.send(embed); - } else { - await newThread(msg, arg); - } - } else { - msg.channel.send( - getEmbed( - config.error_color, - "Command Unavailable", - "This command can only be used in Direct Message." - ) - ); - } - } - - //----------------------------Thred Reply Command--------------------------- - //#replyCmd - else if (cmd == "reply") { - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "You need to have moderator role to use this command." - ); - if (msg.guild == null) { - return msg.channel.send( - getEmbed( - config.warning_color, - "Command Unavailable", - "You can't use this command in DM." - ) - ); - } else { - if (msg.author.id === config.botOwnerID) { - await reply(msg, arg); - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.modRoleID)) || - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - await reply(msg, arg); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - - //---------------------------Thread Close Command--------------------------- - //#closeCmd - else if (cmd == "close") { - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "You need to have moderator role to use this command." - ); - if (msg.guild == null) { - return msg.channel.send( - getEmbed( - config.warning_color, - "Command Unavailable", - "You can't use this command in DM." - ) - ); - } else { - if (msg.author.id === config.botOwnerID) { - await close(msg, arg); - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.modRoleID)) || - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - await close(msg, arg); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - - //---------------------------User Blocklist Command------------------------- - //#blocklistCmd - else if (cmd == "blocklist") { - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "You need to have moderator role to use this command." - ); - if (msg.guild == null) { - if (msg.author.id === config.botOwnerID) { - await blocklist(msg, arg); - } else { - return msg.channel.send( - getEmbed( - config.warning_color, - "Command Unavailable", - "You can't use this command in DM." - ) - ); - } - } else { - if (msg.author.id === config.botOwnerID) { - await blocklist(msg, arg); - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.modRoleID)) || - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - await blocklist(msg, arg); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - - //---------------------------User Block Command----------------------------- - //#blockCmd - else if (cmd == "block") { - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "You need to have moderator role to use this command." - ); - if (msg.guild == null) { - if (msg.author.id === config.botOwnerID) { - await block(msg, arg); - } else { - return msg.channel.send( - getEmbed( - config.warning_color, - "Command Unavailable", - "You can't use this command in DM." - ) - ); - } - } else { - if (msg.author.id === config.botOwnerID) { - await block(msg, arg); - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.modRoleID)) || - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - await block(msg, arg); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - - //----------------------------Unblock Command------------------------------- - //#unblockCmd - else if (cmd == "unblock") { - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "You need to have moderator role to use this command." - ); - if (msg.guild == null) { - if (msg.author.id === config.botOwnerID) { - await unblock(msg, arg); - } else { - return msg.channel.send( - getEmbed( - config.warning_color, - "Command Unavailable", - "You can't use this command in DM." - ) - ); - } - } else { - if (msg.author.id === config.botOwnerID) { - await unblock(msg, arg); - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.modRoleID)) || - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - await unblock(msg, arg); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - - //-----------------------------Reset Config Command------------------------- - //#resetCmd - else if (cmd == "reset") { - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "Only Owner and Admin can use this command." - ); - if (msg.guild == null) { - if (msg.author.id === config.botOwnerID) { - await resetConfig(); - await configSync(); - msg.channel.send( - getEmbed( - config.error_color, - "Success", - "Config values has been reseted." - ) - ); - } else { - return msg.channel.send( - getEmbed( - config.warning_color, - "Command Unavailable", - "You can't use this command in DM." - ) - ); - } - } else { - if (msg.author.id === config.botOwnerID) { - await resetConfig(); - await configSync(); - msg.channel.send( - getEmbed( - config.error_color, - "Success", - "Config values has been reseted." - ) - ); - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - await resetConfig(); - await configSync(); - msg.channel.send( - getEmbed( - config.error_color, - "Success", - "Config values has been reseted." - ) - ); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - - //----------------------------Config Setup Command-------------------------- - //#setupCmd - else if (cmd == "setup") { - const noArgs = getEmbed( - config.warning_color, - "Missing Argument", - "Usage : `setup [config name] [config value]`\n\n`Note : The bot didn't check the value given please set correctly to avoid errors.`" - ); - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "Only Owner and Admin can use this command." - ); - let tempArg, - configName, - configValue = ""; - if (arg) { - tempArg = arg.split(/ +/); - configName = tempArg[0]; - configValue = tempArg[1] || "empty"; - configValue = configValue.toLowerCase(); - } - if (msg.guild == null) { - if (msg.author.id === config.botOwnerID) { - if (!arg || !configName || !configValue) { - msg.channel.send(noArgs); - } else { - await setup(msg, configName, configValue); - } - } else { - return msg.channel.send( - getEmbed( - config.warning_color, - "Command Unavailable", - "You can't use this command in DM." - ) - ); - } - } else { - if (msg.author.id === config.botOwnerID) { - if (!arg || !configName || !configValue) { - msg.channel.send(noArgs); - } else { - await setup(msg, configName, configValue); - } - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if (!arg || !configName || !configValue) { - msg.channel.send(noArgs); - } else { - await setup(msg, configName, configValue); - } - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - //----------------------------Config List Command--------------------------- - //#configlistCmd - else if (cmd == "configlist") { - const errorEmbed = getEmbed( - config.error_color, - "Missing Permission", - "Only Owner and Admin can use this command." - ); - if (msg.guild == null) { - if (msg.author.id === config.botOwnerID) { - await configList(msg); - } else { - return msg.channel.send( - getEmbed( - config.warning_color, - "Command Unavailable", - "You can't use this command in DM." - ) - ); - } - } else { - if (msg.author.id === config.botOwnerID) { - await configList(msg); - } else if ( - msg.guild.id == config.serverID || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - if ( - (await roleCheck(msg, config.adminRoleID)) || - (await permissionCheck(msg, "ADMINISTRATOR")) - ) { - await configList(msg); - } else { - return msg.channel.send(errorEmbed); - } - } else { - if (config.serverID == "empty") { - msg.channel.send( - getEmbed( - config.warning_color, - "Warning!", - "The `serverID` value has not been set." - ) - ); - } else { - let serverName = await client.guilds.get(config.serverID).name; - msg.channel.send( - getEmbed( - config.warning_color, - "Not Main Server!", - `You need to be in **${serverName}** to use this command.` - ) - ); - } - } - } - } - } - //---------------------------UserDM Message Handler--------------------------- - //#userDM - else if (msg.guild == null) { - try { - let getChannel = await client.guilds - .get(config.serverID) - .channels.find(ch => ch.name == msg.author.id); - if (getChannel) { - let IsMember = await isMember(msg); - let IsBlocked = await isBlocked(msg); - if (IsMember && !IsBlocked) { - userResponse(msg, getChannel); - } - } - } catch (e) { - if (e.message == "Cannot read property 'channels' of undefined") - return msg.channel.send( - getEmbed( - config.error_color, - "Error!", - "Bot configuration has not been set." - ) - ); - console.log(e); - } - } -}); - -//============================================================================== -//==================================LOGIN======================================= - -client.login(process.env.TOKEN); -require("http") - .createServer() - .listen(); - -//============================================================================== +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DEPENDENCIES~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +//#dependencies +console.log("[Loading Dependencies]"); +const Discord = require("discord.js"); +const { Util, Attachment } = require("discord.js"); +const client = new Discord.Client(); +const server = require("./server.js"); +const Sequelize = require("sequelize"); +const fs = require("fs"); +const moment = require("moment"); +const defConfig = require("./config.json"); +require("dotenv").config(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~VARIABLES~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +console.log("[Loading Variables]"); + +//#config (synced with database) +var config = { + prefix: "", + botOwnerID: "", + mainServerID: "", + threadServerID: "", + categoryID: "", + logChannelID: "", + botChannelID: "", + adminRoleID: "", + modRoleID: "", + mentionedRoleID: "", + maintenance: "", + info_color: "", + warning_color: "", + error_color: "", + received_color: "", + sent_color: "" +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DATABASE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +//#configDB +const configDB = new Sequelize("database", "user", "password", { + host: "localhost", + dialect: "sqlite", + logging: false, + storage: "config.sqlite" +}); +const ConfigDB = configDB.define("config", { + name: { + type: Sequelize.STRING, + unique: true + }, + input: Sequelize.STRING +}); + +//#blockedDB +const blockedDB = new Sequelize("database", "user", "password", { + host: "localhost", + dialect: "sqlite", + logging: false, + storage: "blocked.sqlite" +}); +const BlockedDB = blockedDB.define("blocked", { + userID: { + type: Sequelize.STRING, + unique: true + }, + modID: Sequelize.STRING, + reason: Sequelize.STRING +}); + +//#threadDB +const threadDB = new Sequelize("database", "user", "password", { + host: "localhost", + dialect: "sqlite", + logging: false, + storage: "thread.sqlite" +}); +const ThreadDB = configDB.define("thread", { + userID: { + type: Sequelize.STRING, + unique: true + }, + channelID: { + type: Sequelize.STRING, + unique: true + }, + threadTitle: Sequelize.STRING +}); + +//#commandsCollection +client.commands = new Discord.Collection(); +const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); +for (const file of commandFiles) { + const cmd = require(`./commands/${file}`); + client.commands.set(cmd.name, cmd); +} + +//#functionsCollection +client.functions = new Discord.Collection(); +const functionFiles = fs.readdirSync('./functions').filter(file => file.endsWith('.js')); +for (const file of functionFiles) { + const func = require(`./functions/${file}`); + client.functions.set(func.name, func); +} + +//#parameter +const param = { + Discord, + Attachment, + moment, + client, + ConfigDB, + ThreadDB, + BlockedDB, + config, + defConfig, + configSync: client.functions.get("configSync"), + getEmbed: client.functions.get("getEmbed"), + roleCheck: client.functions.get("roleCheck"), + isBlocked: client.functions.get("isBlocked"), + isMember: client.functions.get("isMember"), + reset: client.functions.get("reset"), + configuration: client.functions.get("configuration"), + configInfo: client.functions.get("configInfo"), + set: client.functions.get("set"), + bind: client.functions.get("bind"), + newThread: client.functions.get("newThread"), + threadInfo: client.functions.get("threadInfo"), + reply: client.functions.get("reply"), + areply: client.functions.get("areply"), + userReply: client.functions.get("userReply"), + close: client.functions.get("close"), + aclose: client.functions.get("aclose"), + block: client.functions.get("block"), + unblock: client.functions.get("unblock"), + blockinfo: client.functions.get("blockinfo"), + blocklist: client.functions.get("blocklist") +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~READY~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +client.on('ready', async () => { + console.log("[Syncing Database]"); + await BlockedDB.sync(); + await ConfigDB.sync(); + await ThreadDB.sync(); + await param.configSync.execute(param); //cant make the bot waiting this guy to finish pfft + + console.log(`Logged in as ${client.user.tag}!`); + //when i use local variable (config.maintenance), the configSync() is still in process that's why i use database value for this. + const getMaintenance = await ConfigDB.findOne({ where: { name: "maintenance" } }).catch( + error => {console.log(error)} + ); + const getPrefix = await ConfigDB.findOne({ where: { name: "prefix" } }).catch( + error => {console.log(error)} + ); + + let isMaintenance + if(!getMaintenance){ + isMaintenance = "0"; + } else { + isMaintenance = await getMaintenance.input; + } + + //#activities + let activities = [] + if(getPrefix){ + activities.push(`Glitch.com | ${getPrefix.input}commands`); + activities.push(`DM to contact Staff | ${getPrefix.input }help`); + activities.push(`DM, um Mitarbeiter zu kontaktieren | ${getPrefix.input}helpDE`); + activities.push(`Personel ile irtibata geçmek için DM | ${getPrefix.input}helpTR`); + activities.push(`직원에게 연락하는 DM | ${getPrefix.input}helpKR`); + activities.push(`DM para entrar em contato com a equipe | ${getPrefix.input}helpPT`); + activities.push(`DM contacte le personnel | ${getPrefix.input}helpFR`); + activities.push(`DM связаться с персоналом | ${getPrefix.input}helpRU`); + activities.push(`DM 与官方人员联系 | ${getPrefix.input}helpCHS`); + activities.push(`DM 與官方人員聯繫 | ${getPrefix.input}helpCHT`); + activities.push(`DM para contactar al personal | ${getPrefix.input}helpES`); + } else { + activities.push(`- Restart Me -`); + } + + if (isMaintenance == "0") { + let index = 0; + setInterval(() => { + client.user.setActivity(activities[index], { type: "WATCHING" }); + index++; + if (index == activities.length) index = 0; + }, 7000); + } else { + //using timeout since i can't make the bot wait for configSync() function to finish :( + setTimeout(()=> { + client.user.setActivity("~ Under Maintenance ~", { type: "STREAMING" }); + }, 10000); + } +}); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~NEW GUILD~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +client.on('guildCreate', async guild => { + const ownerID = config.botOwnerID; + if(ownerID){ + const newServerEmbed = param.getEmbed.execute(param, config.info_color, "Joined a Guild", `[**${guild.name}**] (\`${guild.id}\`)`); + client.users.get(ownerID).send(newServerEmbed); + } + console.log(`Joined [${guild.name}] guild.`); +}); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~MESSSAGES~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +client.on('message', async message => { + if(message.author.bot) return; + try { + //maintenance mode + if(config.maintenance == "1"){ + + const authorID = message.author.id; + const botOwnerID = config.botOwnerID; + const maintenanceEmbed = param.getEmbed.execute(param, config.error_color, "Maintenance", "All commands are disabled."); + + if(message.guild == null && authorID != botOwnerID){ + //in Direct Message and not bot owner + return message.channel.send(maintenanceEmbed); + } else if(config.mainServerID == "empty" && config.threadServerID == "empty") { + //the mainServerID and threadServerID empty + if(authorID != botOwnerID && !message.member.hasPermission('ADMINISTRATOR')){ + //not bot owner and doesn't have ADMINISTRATOR permission + return message.channel.send(maintenanceEmbed); + }; + } else if(config.mainServerID != "empty" && config.threadServerID != "empty"){ + //mainServerID and threadServerID isn't empty + if(message.guild.id == config.mainServerID || message.guild.id == config.threadServerID){ + //inside mainServerID or threadServerID + if(authorID != botOwnerID && !message.member.hasPermission('ADMINISTRATOR') && !param.roleCheck.execute(message, config.adminRoleID)){ + //not bot owner and user doesn't have ADMINISTRATOR permission nor have Admin role + return message.channel.send(maintenanceEmbed); + } + } else { + //outside mainServerID and threadServerID + if(authorID != botOwnerID){ + //not bot owner + return message.channel.send(maintenanceEmbed); + }; + }; + } + }; + + let args, commandName = ""; + + //checking wheter user use prefix or mention the bot + let prefixIndex = message.content.indexOf(config.prefix); + let botMentionIndex = message.content.indexOf("<@"+client.user.id+">"); + if (prefixIndex !== 0 && botMentionIndex !== 0){ + if(message.guild != null){ + return; + } else { + const isThread = await ThreadDB.findOne({where: {userID: message.author.id}}); + if(!isThread){ + return; + } else { + return param.userReply.execute(param, message, isThread); + } + } + } else if (prefixIndex === 0){ + args = message.content.slice(config.prefix.length).split(/ +/); + commandName = args.shift().toLowerCase(); + } else if (botMentionIndex === 0){ + args = message.content.slice(("<@"+client.user.id+">").length).split(/ +/); + commandName = args.shift().toLowerCase(); + } + + //finding command that was triggered + const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); + + //user using prefix or mention bot, command name is invalid + if ((prefixIndex == 0 || botMentionIndex == 0) && !command) return; + + //command is guildOnly, user trigger it inside Direct Message + if(command.guildOnly && message.channel.type !== 'text' && message.author.id != config.botOwnerID){ + let noDMEmbed = param.getEmbed.execute(param, config.error_color, "Command Unavailable", "This command can\'t be used inside Direct Message."); + return message.channel.send(noDMEmbed); + } + + //command need arguments to run, user did't gave any + if(command.args && !args.length){ + let description = "You didn\'t provide any arguments." + + if(command.usage) { + description += `\n**Usage** : \`${config.prefix}${command.name} ${command.usage}\``; + } + if(command.note){ + description += `\n**Note** : \`${command.note}\``; + } + + let noArgsEmbed = param.getEmbed.execute(param, config.warning_color, "Missing Arguments", description); + return message.channel.send(noArgsEmbed); + } + + //command handler + //trying to execute the command + await command.execute(param, message, args); + } catch (error) { + //catching error -> log it in console -> send error message to user + console.log(error); + let errorEmbed = param.getEmbed.execute(param, config.error_color, "An Error Occured.", `**Contact bot Owner** : <@${config.botOwnerID}>\n**Error Message** : \`${error.message}\``); + return message.channel.send(errorEmbed); + } + +}); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~LOGIN~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +client.login(process.env.TOKEN); +require("https") + .createServer() + .listen(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~