diff --git a/app.js b/app.js index b8727c9..6fefe86 100644 --- a/app.js +++ b/app.js @@ -3,15 +3,35 @@ const Discord = require("discord.js"); const client = new Discord.Client(); const setup = require("./setup.js"); -const fs = require("fs") var util = require("./src/util.js") var developer = false; module.exports = {}; module.exports.version = require("./package.json").version; module.exports.start = function(config) { console.log("Loading commands") - setup(fs, config, require("path").dirname(require.main.filename)).then((commands) => { - client.commanddata = commands; + setup(config, require("path").dirname(require.main.filename)).then((data) => { + client.commanddata = data.commands; + client.functions = data.functions + client.functions.types = { + messages: [], + commands: [] + } + client.data = {}; + client.data.version = module.exports.version; + client.data.util = util + + client.functions.messages.messagefuncs.forEach(i => { + i.type = i.type.map(i => (i.toLowerCase())) + if (i.type == "all" && i.type.length === 1) { + client.functions.types.commands.push(i.name); + client.functions.types.messages.push(i.name); + } else if (i.type == "messages") { + client.functions.types.messages.push(i.name); + } else if (i.type == "commands") { + client.functions.types.commands.push(i.name); + } + + }) client.config = config; start(client, client.config, client.commanddata) }).catch((err) => { @@ -45,13 +65,13 @@ function start(client, config, commanddata) { return console.warn("This wrapper doesn't support selfbots.") } client.fetchApplication().then((application) => { - if (application.owner == null){ + if (application.owner == null) { if (client.config.owner_id == null) { return console.error("Can't fetch the owner's id, please follow instructions here .") } else if (client.users.get(client.config.owner_id) == undefined) { return console.error("The bot can't find the owner_id set up inside your file, \nThis could be because it's not valid, or because you are not in a server with it, please invite it to a server where you are on.") } - }else{ + } else { client.config.owner_id = application.owner.id } @@ -65,13 +85,27 @@ function start(client, config, commanddata) { } }) + + client.functions.boot.bootfuncs.forEach((data) => { + + function returnfunction() { + return data.function(client) + } + + + setTimeout(function() { + if (data.time > 0) { + setInterval(returnfunction, data.time) + } + return returnfunction() + + }, data.delay); + }) + + + console.log(commanddata.commands.size + " commands | " + commanddata.aliases.size + " aliases, bot online") console.log("To add new commands, type \"" + config.prefix + "createcommand \" to generate a new template!") - util.checkUpdate(module.exports).then(update => { - console.log(update) - }).catch(err => { - console.warn(err) - }) @@ -84,16 +118,40 @@ function start(client, config, commanddata) { + // commands if (!message.content.startsWith(config.prefix)) { + dofuncs(client, message, "message").catch((data) => { + if (data) { + if (developer) { + return console.warn(data) + } + } + }) return } var content = message.content.replace(config.prefix, "") var command = content.split(" ")[0].toLowerCase(); if (commanddata.commands.has(command) === true) { - doCommand(command, client, message) + message.command = commanddata.commands.get(command) + dofuncs(client, message, "command").then(() => { + doCommand(command, client, message) + }).catch(data => { + if (data) { + if (developer) { + return console.warn(data) + } + } + }) } else if (commanddata.aliases.has(command) === true) { - doCommand(commanddata.aliases.get(command), client, message); + message.command = commanddata.commands.get(commanddata.aliases.get(command)) + dofuncs(client, message, "command").then(() => { + doCommand(commanddata.aliases.get(command), client, message); + }).catch(data => { + if (data) { + console.log(data) + } + }) } }) } @@ -120,6 +178,93 @@ function doCommand(command, client, message) { console.warn("Command: " + command.name + " | had an error. Show the developer of the command module that you are getting this error code: \n" + err) } } +} + +function dofuncs(client, message, type) { + return new Promise(function(resolve, reject) { + if (type == "message") { + var funcnumber = 0; + if (client.functions.types.messages.length == 0) { + return resolve() + } + client.functions.messages.messagefuncs.forEach(i => { + var num = client.functions.messages.messagefuncs.size + if (client.functions.types.messages.includes(i.name) == false) { + done(funcnumber, num) + } + var result = i.function(client, message, message.command) + if (result == undefined) { + return done(funcnumber, num) + } + if (typeof result.then == "function") { + result.then(data => { + if (data) { + if (typeof data == "string") { + message.channel.send(data) + } + return reject() + } + done(funcnumber, num) + }).catch(err => console.warn(i.name + " | Message function just stopped working correctly. | Error: \n", err)) + } else { + if (result) { + if (typeof result == "string") { + message.channel.send(result) + } + return reject() + } + done(funcnumber, num) + } + }) + + + } + if (type == "command") { + var number = 0; + if (client.functions.types.commands.length == 0) { + return resolve() + } + client.functions.messages.messagefuncs.forEach(i => { + var num = client.functions.messages.messagefuncs.size + if (client.functions.types.commands.includes(i.name) == false) { + done(number, num) + } + + var result = i.function(client, message, message.command) + if (result == undefined) { + return done(number, num) + } + if (typeof result.then == "function") { + result.then((data) => { + if (data) { + if (typeof data == "string") { + message.channel.send(data) + } + return reject() + } + done(number, num) + }).catch(err => console.warn(i.name + " | Message function just stopped working correctly. | Error: \n", err)) + } else { + if (result) { + if (typeof result == "string") { + message.channel.send(result) + } + return reject() + } + done(number, num) + } + }) + + } + + + function done(number, num) { + number = number + 1 + if (number == num) { + return resolve() + } + } + }); } diff --git a/commands/createcommand.js b/commands/createcommand.js index b824dfb..89ff896 100644 --- a/commands/createcommand.js +++ b/commands/createcommand.js @@ -2,12 +2,11 @@ var command = module.exports = {} var path = require("path") var fs = require("fs") command.name = "createcommand" - +// Owner only +command.level = 10; command.command = function(client, message) { var args = message.content.split(" "); - if (!message.author.id == client.config.owner_id) { - return - } + if (args[1] == null) { return message.channel.send("[EDB] Please specify the name for the command. If you want to use aliases, type them space-seperated behind the name."); @@ -17,7 +16,7 @@ command.command = function(client, message) { aliases: [], name: args[1] } - if (args[1].match(/[/\\<>:*|]/g)){ + if (args[1].match(/[/\\<>:*|]/g)) { return message.channel.send("[EDB] Filenames can't include one of these characters: ` / \\ < > : * | `, please try a different filename.") } if (args[2] != null) { @@ -32,7 +31,9 @@ command.command = function(client, message) { return message.channel.send("[EDB] This file does already exist. Please try a different name. ") } - fs.writeFile(path.resolve(path.dirname(require.main.filename), "commands/" + data.name + ".js"), "exports.name = \"" + data.name + "\" \nexports.aliases = " + JSON.stringify(data.aliases) + "\nexports.command = function(client, message){\n\n//Write your command functions here.\n\n} ", {options: "utf8"}, (err) => { + fs.writeFile(path.resolve(path.dirname(require.main.filename), "commands/" + data.name + ".js"), "exports.name = \"" + data.name + "\" \nexports.aliases = " + JSON.stringify(data.aliases) + "\nexports.command = function(client, message){\n\n//Write your command functions here.\n\n} ", { + options: "utf8" + }, (err) => { if (err) { return message.channel.send("[EDB] Failed to create this file, try to create it manually using this template: ```javascript\nexports.name = \"" + data.name + "\" \nexports.aliases = \"" + JSON.stringify(data.aliases) + "\"\nexports.command = function(client, message){\n\n//Write your command functions here.\n\n} \n```") } diff --git a/commands/reboot.js b/commands/reboot.js index 7d5d424..ce2fdf1 100644 --- a/commands/reboot.js +++ b/commands/reboot.js @@ -4,9 +4,11 @@ var command = module.exports = {} command.name = "reboot"; command.aliases = ["restart"]; +// Owner only +command.level = 10 + command.command = function(client, message) { - // needs to be replaced with command requirements when started working on! - if (client.config.owner_id !== message.author.id) {return} + message.channel.send("[EDB] Restarting bot...") diff --git a/commands/reload.js b/commands/reload.js index bc8a4e6..9a61065 100644 --- a/commands/reload.js +++ b/commands/reload.js @@ -1,15 +1,14 @@ var command = module.exports = {} command.name = "reload"; +// owner only +command.level = 10; const setup = require("../setup.js"); const fs = require("fs") command.command = function(client, message) { - // needs to be replaced with command requirements when started working on! - if (client.config.owner_id !== message.author.id) { - return - } + var args = message.content.split(" ") if (args[1] == null) { args[1] = "" diff --git a/functions/boot/checkUpdate.js b/functions/boot/checkUpdate.js new file mode 100644 index 0000000..2aafa09 --- /dev/null +++ b/functions/boot/checkUpdate.js @@ -0,0 +1,14 @@ +/* eslint no-console: 0 */ +exports.name = "checkUpdate"; +// Check update every every hour +exports.time = 3600000; +// Check on boot +exports.delay = 0; + +exports.function = function(client) { + client.data.util.checkUpdate(client.data.version).then(update => { + console.log(update) + }).catch(err => { + console.warn(err) + }) +} diff --git a/functions/messages/permissioncheck.js b/functions/messages/permissioncheck.js new file mode 100644 index 0000000..d040994 --- /dev/null +++ b/functions/messages/permissioncheck.js @@ -0,0 +1,13 @@ +exports.name = "permissioncheck" +exports.type = ["commands"]; +exports.function = function(client, message, command) { + switch (command.level) { + case 10: + if (message.author.id === client.config.owner_id) { + return false; + } + return true; + default: + return false; + } +} diff --git a/package-lock.json b/package-lock.json index b585df6..0ea852c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "easy-discord-bot", - "version": "0.0.2-beta.0", + "version": "0.0.2-beta.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 667c648..257f0e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "easy-discord-bot", - "version": "0.0.2-beta.0", + "version": "0.0.2-beta.3", "description": "An easy to use discord bot, which uses small modules for getting commands and messages. ", "main": "app.js", "dependencies": { diff --git a/setup.js b/setup.js index 0d82ea3..40c00d2 100644 --- a/setup.js +++ b/setup.js @@ -1,7 +1,7 @@ -/* eslint max-params: ["error", 4]*/ -module.exports = function(fs, config, local, reload) { - var util = require("./src/util.js") - const path = require("path"); +var fs = require("fs") +const path = require("path"); +var util = require("./src/util.js") +module.exports = function(config, local, reload) { return new Promise(function(resolve, reject) { if (parseInt(process.version.charAt(1) < 7)) { return reject("You need to update your node version to Node 7 or higher, go to https://nodejs.org/en/download/ for the latest versions.") @@ -20,7 +20,7 @@ module.exports = function(fs, config, local, reload) { fs.mkdir(path.resolve(local, "commands"), function() { util.load("cmds", __dirname).then((data) => { - return resolve(data) + return next(data, local, reload).then(data => resolve(data)).catch(err => reject(err)) }).catch(err => { return reject(err) }) @@ -28,11 +28,87 @@ module.exports = function(fs, config, local, reload) { } else { util.load("cmds", __dirname, reload).then((data) => { - return resolve(data) + return next(data, local, reload).then(data => resolve(data)).catch(err => reject(err)) }).catch(err => { return reject(err) }) } }); + + }); +} + + +function next(commands, local, reload) { + return new Promise(function(resolve, reject) { + + var data = {} + data.commands = commands + + fs.access(path.resolve(local, "functions"), fs.constants.R_OK, (err) => { + if (err) { + + fs.mkdir(path.resolve(local, "functions"), function() { + + functions(data, local, reload).then((functiondata) => { + data.functions = functiondata + resolve(data) + }).catch(err => reject(err)) + }) + } else { + functions(data, local, reload).then((functiondata) => { + data.functions = functiondata + resolve(data) + }).catch(err => reject(err)) + + + } + }); + }); + +} + + + +function functions(data, local, reload) { + + return new Promise(function(resolve, reject) { + var types = ["messages"] + + function done(data) { + if (Object.keys(data).length === 2) { + return true + } + + /* LENGTH NEEDS TO BE CHANGED WHEN NEW FUNCTIONS ARE ADDED! */ + } + types.forEach(i => { + fs.access(path.resolve(local, "functions/" + i), fs.constants.R_OK, (err) => { + if (err) { + fs.mkdir(path.resolve(local, "functions/" + i), function(err) { + if (err) { + return reject(err) + } + util.load("functions", __dirname, reload).then((data) => { + if (done(data) == true) { + resolve(data) + } + }).catch(err => { + return reject(err) + }) + + }) + } else { + util.load("functions", __dirname, reload).then((data) => { + + if (done(data) == true) { + return resolve(data) + } + }).catch(err => { + return reject(err) + }) + } + }); + }) }); } diff --git a/src/checkUpdate.js b/src/checkUpdate.js index b3c6691..b21acbd 100644 --- a/src/checkUpdate.js +++ b/src/checkUpdate.js @@ -1,21 +1,21 @@ const request = require("request"); -module.exports = function(edb) { +module.exports = function(version) { return new Promise(function(resolve, reject) { - request("https://easy-discord-bot.tk/update?currentversion=" + edb.version, + request("https://easy-discord-bot.tk/update?currentversion=" + version, function(error, response, body) { if (error) { return reject("Sorry, There was a issue whilst checking for a update, try again later.") } else if (response.statusCode == 200) { var data = JSON.parse(body) if (data.update_required) { - var version = null; - if (edb.version.includes("beta")) { - version = data.latest_beta + var newversion = null; + if (version.includes("beta")) { + newversion = data.latest_beta } else { - version = data.latest + newversion = data.latest } - return resolve("\nAn update is required, please type npm install easy-discord-bot \nto install the latest version ( v" + edb.version + " --> v" + version + ")") + return resolve("\nAn update is required, please type npm install easy-discord-bot \nto install the latest version ( v" + version + " --> v" + newversion + ")") } } diff --git a/src/loadCommands.js b/src/loadCommands.js index 5199c94..5a41955 100644 --- a/src/loadCommands.js +++ b/src/loadCommands.js @@ -1,4 +1,5 @@ /* eslint no-console: 0 */ +/* eslint complexity: ["error", 25]*/ var fs = require("fs") var path = require("path"); module.exports = function(dir, local, reload) { @@ -67,7 +68,6 @@ function commands(location, reload) { if (temp.conf.aliases != null) { temp.aliases = temp.conf.aliases } - } if (temp.help === null) { console.warn(path + " -- File isn't set up correctly, go to to learn more on how to set up commands. | code: komada_no_help") @@ -81,8 +81,6 @@ function commands(location, reload) { } temp.name = temp.help.name.toLowerCase() - - if (temp.run != null && typeof temp.run == "function") { temp.command = temp.run } else { @@ -123,6 +121,10 @@ function commands(location, reload) { } else if (temp.aliases.constructor != Array) { temp.aliases = [] } + + if (typeof temp.level != "number") { + temp.level = 0 + } temp.path = path data.names.push(temp.name) data.commands.set(temp.name, temp) diff --git a/src/loadFunctions.js b/src/loadFunctions.js new file mode 100644 index 0000000..01ce415 --- /dev/null +++ b/src/loadFunctions.js @@ -0,0 +1,252 @@ +/* eslint no-console: 0 */ +var fs = require("fs") +var path = require("path"); +module.exports = function(dir, local, reload) { + return new Promise(function(resolve, reject) { + + var functions = {}; + messages(dir, local, reload).then(data => { + functions.messages = data + if (done(functions) == true) { + resolve(functions) + } + }).catch(err => reject(err)) + + bootFuncs(dir, local, reload).then(data => { + functions.boot = data + if (done(functions) == true) { + resolve(functions) + } + }).catch(err => reject(err)) + + + + + }) +} + + +function done(data) { + if (Object.keys(data).length === 2) { + return true + } + +} + +function messages(dir, local, reload) { + return new Promise(function(resolve, reject) { + messagesLoad(dir, reload).then(data => { + if (data == false) { + return messages(dir, local, reload).then((data) => resolve(data)).catch(err => reject(err)) + } + if (dir == local) { + return resolve(data) + } + messagesLoad(local, reload).then(localdata => { + if (localdata == false) { + return messages(dir, local, reload).then((data) => resolve(data)).catch(err => reject(err)) + } + data.names.forEach(function(i, index) { + if (localdata.names.includes(i)) { + data.messagefuncs.delete(i) + } else { + localdata.messagefuncs.set(i, data.messagefuncs.get(i)) + } + if ((data.messagefuncs.size - 1) === index) { + if (reload) { + localdata.issues = localdata.issues + data.issues + } + return resolve(localdata) + } + }) + }).catch(err => reject(err)) + }).catch(err => reject(err)) + }); +} + +function bootFuncs(dir, local, reload) { + return new Promise(function(resolve, reject) { + bootLoad(dir, reload).then(data => { + if (data == false) { + return messages(dir, local, reload).then((data) => resolve(data)).catch(err => reject(err)) + } + if (dir == local) { + return resolve(data) + } + bootLoad(local, reload).then(localdata => { + if (localdata == false) { + return messages(dir, local, reload).then((data) => resolve(data)).catch(err => reject(err)) + } + data.names.forEach(function(i, index) { + if (localdata.names.includes(i)) { + data.bootfuncs.delete(i) + } else { + localdata.bootfuncs.set(i, data.bootfuncs.get(i)) + } + if ((data.bootfuncs.size - 1) === index) { + if (reload) { + localdata.issues = localdata.issues + data.issues + } + return resolve(localdata) + } + }) + }).catch(err => reject(err)) + }).catch(err => reject(err)) + }); +} + +function bootLoad(location, reload) { + return new Promise(function(resolve, reject) { + fs.readdir(path.resolve(location, "functions/boot/"), function(err, results) { + if (err) { + fs.mkdir(path.resolve(location, "functions/boot/"), function(err) { + if (err) { + return reject(err) + } + resolve(false) + }) + + } + if (!err) { + results = results.map(i => (path.resolve(location, "functions/boot/" + i))).filter((i) => { + return i.endsWith(".js") + }) + var data = { + bootfuncs: new Map(), + names: [], + issues: 0 + } + if (results.length === 0) { + return resolve(data) + } + var number = 0; + + results.forEach((path, num) => { + number = number + 1 + var mod = require.resolve(path); + if (mod !== undefined && (require.cache[mod] !== undefined)) { + delete require.cache[require.resolve(path)] + } + var temp = require(path); + if (typeof temp != "object") { + console.warn(path + " -- File isn't set up correctly, go to to learn more on how to set up boot functions. | code: msgfunc_no_object") + return done(number, num, reload) + + } else if (temp.name === null || typeof temp.name != "string") { + console.warn(path + " - File isn't set up correctly, go to to learn more on how to set up boot functions. | code: invalid_or_no_name") + return done(number, num, reload) + + } else if (temp.time == null || typeof temp.time != "number") { + temp.time = 0; + + } else if (temp.delay == null || typeof temp.delay != "number") { + temp.delay = 0; + + } else if (temp.function == null || typeof temp.function != "function") { + console.warn(path + " - File isn't set up correctly, go to to learn more on how to set up boot functions. | code: no_function_setup") + return done(number, num, reload) + + } + + + + data.bootfuncs.set(temp.name, temp) + data.names.push(temp.name) + return done(number, num) + + + function done(number, num, reload) { + if (reload) { + data.issues = data.issues + 1 + } + number = number - 1 + if (number === num) { + return resolve(data) + } + } + }) + } + }) + }) + +} + +function messagesLoad(location, reload) { + return new Promise(function(resolve, reject) { + fs.readdir(path.resolve(location, "functions/messages/"), function(err, results) { + if (err) { + fs.mkdir(path.resolve(location, "functions/messages/"), function(err) { + if (err) { + return reject(err) + } + return resolve(false) + }) + } + results = results.map(i => (path.resolve(location, "functions/messages/" + i))).filter((i) => { + return i.endsWith(".js") + }) + var data = { + messagefuncs: new Map(), + names: [], + issues: 0 + } + if (results.length === 0) { + return resolve(data) + } + var number = 0; + + results.forEach((path, num) => { + number = number + 1 + var mod = require.resolve(path); + if (mod !== undefined && (require.cache[mod] !== undefined)) { + delete require.cache[require.resolve(path)] + } + var temp = require(path); + if (typeof temp != "object") { + console.warn(path + " -- File isn't set up correctly, go to to learn more on how to set up message functions. | code: msgfunc_no_object") + return done(number, num, reload) + + } else if (temp.name === null || typeof temp.name != "string") { + console.warn(path + " - File isn't set up correctly, go to to learn more on how to set up message functions. | code: invalid_or_no_name") + return done(number, num, reload) + + } else if (temp.function == null || typeof temp.function != "function") { + console.warn(path + " - File isn't set up correctly, go to to learn more on how to set up message functions. | code: no_function_setup") + return done(number, num, reload) + + } + if (temp.type == null || temp.type.constructor != Array) { + temp.type = ["messages"] + } else { + + temp.type.forEach(i => { + i = i.toLowerCase() + if (i == "all" || i == "messages" || i == "commands") { + // empty block was the easiest thing i could think off :( + } else { + temp.type = ["messages"] + } + + }) + } + + + data.messagefuncs.set(temp.name, temp) + data.names.push(temp.name) + return done(number, num) + + + function done(number, num, reload) { + if (reload) { + data.issues = data.issues + 1 + } + number = number - 1 + if (number === num) { + return resolve(data) + } + } + }) + }) + }) + +} diff --git a/src/loaddata.js b/src/loaddata.js index e39bee7..429e876 100644 --- a/src/loaddata.js +++ b/src/loaddata.js @@ -9,10 +9,11 @@ module.exports = function(type, dir, reload) { resolve(commanddata) }).catch((err) => reject(err)); break; - // case "messages": - // messages(dir, local).then(() => {resolve(messagedata)}).catch(err => reject(err)); - // break; - // IDEA: To be done! + case "functions": + util.loadFunctions(dir, local, reload).then((functiondata) => { + resolve(functiondata) + }).catch((err) => reject(err)); + break; } diff --git a/src/util.js b/src/util.js index 047e70f..2d00a3b 100644 --- a/src/util.js +++ b/src/util.js @@ -6,3 +6,4 @@ module.exports = {}; module.exports.load = require("./loaddata.js"); module.exports.checkUpdate = require("./checkUpdate.js"); module.exports.loadCommands = require("./loadCommands.js"); +module.exports.loadFunctions = require("./loadFunctions.js");