From 288e166f20318541f7f62d587c210a1f015b6a25 Mon Sep 17 00:00:00 2001 From: Fillerino Date: Wed, 25 Oct 2017 21:31:42 +0200 Subject: [PATCH] Uploaded the main code! Uploaded the main sourcecode and some unfinished commands! --- .babelrc | 3 + .gitignore | 63 ++ README.md | 26 +- bot/bot.js | 193 ++++ bot/helpers.js | 11 + bot/modules/example.js | 22 + bot/modules/moderation.js | 15 + bot/modules/reminder.js | 21 + bot/modules/speech.js | 18 + bot/modules/tipbot.js | 17 + bot/plugins.js | 47 + config/default.json.example | 20 + package.json | 32 + yarn.lock | 1776 +++++++++++++++++++++++++++++++++++ 14 files changed, 2263 insertions(+), 1 deletion(-) create mode 100644 .babelrc create mode 100644 .gitignore create mode 100644 bot/bot.js create mode 100644 bot/helpers.js create mode 100644 bot/modules/example.js create mode 100644 bot/modules/moderation.js create mode 100644 bot/modules/reminder.js create mode 100644 bot/modules/speech.js create mode 100644 bot/modules/tipbot.js create mode 100644 bot/plugins.js create mode 100644 config/default.json.example create mode 100644 package.json create mode 100644 yarn.lock diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..7219679 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["node8"] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..08f6d4e --- /dev/null +++ b/.gitignore @@ -0,0 +1,63 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# dist +dist/* +#configuration +config/default.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env \ No newline at end of file diff --git a/README.md b/README.md index b3662e4..07c5563 100644 --- a/README.md +++ b/README.md @@ -1 +1,25 @@ -Will be updated with the new wunderbot when changes have been reviewed. \ No newline at end of file +# Bot for [LBRY's Discord](https://discord.gg/tgnNHf5) +(This README will be updated along with bot updates) +Features: + +- Tipbot for LBC. Responds to `!tip`. +- Dynamic plugin loading with permission support. + + + +## Requirements + +- node > 8.0.0 +- npm > 0.12.x + + +## Installation + +Create a bot and get the bot's API Token: https://discordapp.com/developers/applications/me + +Edit and rename default.json.example in /config, then run: + +``` +npm install +node bot.js +``` \ No newline at end of file diff --git a/bot/bot.js b/bot/bot.js new file mode 100644 index 0000000..942238d --- /dev/null +++ b/bot/bot.js @@ -0,0 +1,193 @@ +'use strict'; + +// Load up libraries +const Discord = require("discord.js"); +// Load config! +let config = require('config'); +config = config.get('bot'); + +var aliases; +try { + aliases = require("./alias.json"); +} catch (e) { + //No aliases defined + aliases = { + "test": { + process: function(bot,msg){ + msg.channel.send('test'); + } + } +} +} +var commands = { + ping: { + description: "responds pong, useful for checking if bot is alive", + process: async function(bot, msg, suffix) { + let m = await msg.channel.send(msg.author + " Ping?"); + m.edit( + `Pong! Latency is ${m.createdTimestamp - + msg.createdTimestamp}ms. API Latency is ${Math.round(bot.ping)}ms` + ); + if (suffix) { + msg.channel.send("note that !ping takes no arguments!"); + } + } + } +}; + +var bot = new Discord.Client(); + +bot.on("ready", function() { + console.log( + "Logged in! Serving in " + bot.guilds.array().length + " servers" + ); + require("./plugins.js").init(); + console.log("type " + config.prefix + "help in Discord for a commands list."); + bot.user.setGame( + config.prefix + "help | Tipping not available" + ); +}); + +bot.on("disconnected", function() { + console.log("Disconnected!"); + process.exit(1); //exit node.js with an error +}); + +function checkMessageForCommand(msg, isEdit) { + //check if message is a command + if (msg.author.id != bot.user.id && msg.content.startsWith(config.prefix)) { + console.log( + "treating " + msg.content + " from " + msg.author + " as command" + ); + var cmdTxt = msg.content.split(" ")[0].substring(config.prefix.length); + var suffix = msg.content.substring( + cmdTxt.length + config.prefix.length + 1 + ); //add one for the ! and one for the space + if (msg.isMentioned(bot.user)) { + try { + cmdTxt = msg.content.split(" ")[1]; + suffix = msg.content.substring( + bot.user.mention().length + cmdTxt.length + config.prefix.length + 1 + ); + } catch (e) { + //no command + msg.channel.send("Yes?"); + return; + } + } + let alias = aliases[cmdTxt]; + if (alias) { + var cmd = alias; + } else { + var cmd = commands[cmdTxt]; + } + if (cmdTxt === "help") { + //help is special since it iterates over the other commands + if (suffix) { + var cmds = suffix.split(" ").filter(function(cmd) { + return commands[cmd]; + }); + var info = ""; + for (var i = 0; i < cmds.length; i++) { + var cmd = cmds[i]; + info += "**" + config.prefix + cmd + "**"; + var usage = commands[cmd].usage; + if (usage) { + info += " " + usage; + } + var description = commands[cmd].description; + if (description instanceof Function) { + description = description(); + } + if (description) { + info += "\n\t" + description; + } + info += "\n"; + } + msg.channel.send(info); + } else { + msg.author.send("**Available Commands:**").then(function() { + var batch = ""; + var sortedCommands = Object.keys(commands).sort(); + for (var i in sortedCommands) { + var cmd = sortedCommands[i]; + var info = "**" + config.prefix + cmd + "**"; + var usage = commands[cmd].usage; + if (usage) { + info += " " + usage; + } + var description = commands[cmd].description; + if (description instanceof Function) { + description = description(); + } + if (description) { + info += "\n\t" + description; + } + var newBatch = batch + "\n" + info; + if (newBatch.length > 1024 - 8) { + //limit message length + msg.author.send(batch); + batch = info; + } else { + batch = newBatch; + } + } + if (batch.length > 0) { + msg.author.send(batch); + } + }); + } + } else if (cmd) { + // Add permission check here later on ;) + try { + cmd.process(bot, msg, suffix, isEdit); + } catch (e) { + var msgTxt = "command " + cmdTxt + " failed :("; + if (config.debug) { + msgTxt += "\n" + e.stack; + } + msg.channel.send(msgTxt); + } + } else { + msg.channel + .send(cmdTxt + " not recognized as a command!") + .then(message => message.delete(5000)); + } + } else { + //message isn't a command or is from us + //drop our own messages to prevent feedback loops + if (msg.author == bot.user) { + return; + } + + if (msg.author != bot.user && msg.isMentioned(bot.user)) { + msg.channel.send("yes?"); //using a mention here can lead to looping + } else { + } + } +} + +bot.on("message", msg => checkMessageForCommand(msg, false)); +bot.on("messageUpdate", (oldMessage, newMessage) => { + checkMessageForCommand(newMessage, true); +}); + +exports.addCommand = function(commandName, commandObject) { + try { + commands[commandName] = commandObject; + } catch (err) { + console.log(err); + } +}; +exports.addCustomFunc = function(customFunc) { + try { + customFunc(bot); + } catch (err) { + console.log(err); + } +} +exports.commandCount = function() { + return Object.keys(commands).length; +}; + +bot.login(config.token); diff --git a/bot/helpers.js b/bot/helpers.js new file mode 100644 index 0000000..e631e62 --- /dev/null +++ b/bot/helpers.js @@ -0,0 +1,11 @@ +let config = require('config'); +let permRanks = config.get('moderation'); + +// Checks if user is allowed to use a command only for mods/team members +exports.hasPerms = function(msg){ +if(message.member.roles.some(r=>permRanks.perms.includes(r.name)) ) { + return true; +} else { + return false; +} +} \ No newline at end of file diff --git a/bot/modules/example.js b/bot/modules/example.js new file mode 100644 index 0000000..e9fc41a --- /dev/null +++ b/bot/modules/example.js @@ -0,0 +1,22 @@ +/* +exports.commands = [ + "demo" // command that is in this file, every command needs it own export as shown below +] + +exports.custom = [ + "initFunction" +] + +exports.demo = { + usage: "", + description: 'description of command', + process: function(bot,msg,suffix){ + // Here the bot,msg and suffix is avaible, this function can be async if needed. + } +} + +exports.initFunction = function(bot) { + // Other functions that needs to be ran once on bootup! + // For example a timed function and or some init stuff.. +} +*/ \ No newline at end of file diff --git a/bot/modules/moderation.js b/bot/modules/moderation.js new file mode 100644 index 0000000..7da331a --- /dev/null +++ b/bot/modules/moderation.js @@ -0,0 +1,15 @@ +/*'use strict'; +// Moderation module, handles banning and kicking and more... +let hasPerms = require('../helpers.js').hasPerms; + +exports.commands = [ + "m" +] + +exports.m = { + usage: " ", + description: 'ban: bans the user with the reason\n kick: get adress for your deposits\n', + process: function(bot,msg,suffix){ + console.log(msg.member.user); + } +}*/ \ No newline at end of file diff --git a/bot/modules/reminder.js b/bot/modules/reminder.js new file mode 100644 index 0000000..45e44ee --- /dev/null +++ b/bot/modules/reminder.js @@ -0,0 +1,21 @@ +/*exports.commands = [ + "remind" // command that is in this file, every command needs it own export as shown below +] + +exports.custom = [ + "checkReminders" +] + +exports.remind = { + usage: "