From 269c1f99545d7ca3088b31a691ccb14e7dd2e348 Mon Sep 17 00:00:00 2001 From: benji7425 Date: Fri, 1 Sep 2017 15:51:05 +0100 Subject: [PATCH 2/8] Squash merge v2 template code --- .gitignore | 79 +++++++++++++++++++++++++ .npmrc | 3 + .vscode/launch.json | 14 +++++ .vscode/settings.json | 9 +++ CHANGELOG.md | 3 + app/bot.js | 13 +++++ app/config.json | 22 +++++++ app/index.js | 121 +++++++++++++++++++++++++++++++++++++++ app/models/guild-data.js | 7 +++ bootstrap.js | 20 +++++++ package.json | 12 ++++ 11 files changed, 303 insertions(+) create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 CHANGELOG.md create mode 100644 app/bot.js create mode 100644 app/config.json create mode 100644 app/index.js create mode 100644 app/models/guild-data.js create mode 100644 bootstrap.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..00b213c --- /dev/null +++ b/.gitignore @@ -0,0 +1,79 @@ +### Discord bots #### +guilds.json +token.json +log + + +# Created by https://www.gitignore.io/api/node,visualstudiocode + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# 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 (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_cache +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 + + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history + +# End of https://www.gitignore.io/api/node,visualstudiocode diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..799e6bc --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +save=true +save-exact=true +cache=node_cache diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..120515c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible Node.js debug attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "program": "${workspaceRoot}/bootstrap.js" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..728ef00 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.exclude": { + "log": true, + ".npmrc": true, + "node_modules": true, + "node_cache": true, + "token.json": true + } +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8deb76e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +## Unreleased \ No newline at end of file diff --git a/app/bot.js b/app/bot.js new file mode 100644 index 0000000..ff81e7d --- /dev/null +++ b/app/bot.js @@ -0,0 +1,13 @@ +const GuildData = require("./models/guild-data.js"); + +module.exports = { + onCommand(commandObj, commandsObj, params, guildData, message) { + switch (commandObj.command) { + case commandsObj.commandName.command: + return; //return promise! + } + }, + onNonCommandMsg(message, guildData) { + return; + } +}; \ No newline at end of file diff --git a/app/config.json b/app/config.json new file mode 100644 index 0000000..e4c69c2 --- /dev/null +++ b/app/config.json @@ -0,0 +1,22 @@ +{ + "generic": { + "saveFile": "./guilds.json", + "saveIntervalSec": 60, + "website": "https://benji7425.github.io", + "discordInvite": "https://discord.gg/SSkbwSJ", + "defaultDMResponse": "This bot does not have any handling for direct messages. To learn more or get help please visit %s, or join my Discord server here: %s" }, + "commands": { + "version": { + "command": "version", + "description": "Returns the bot version", + "syntax": "version", + "admin": false + }, + "help": { + "command": "help", + "description": "Display information about commands available to you", + "syntax": "help", + "admin": false + } + } +} \ No newline at end of file diff --git a/app/index.js b/app/index.js new file mode 100644 index 0000000..759e2b7 --- /dev/null +++ b/app/index.js @@ -0,0 +1,121 @@ +//node imports +const FileSystem = require("fs"); //manage files +const Util = require("util"); //various node utilities + +//external lib imports +const Discord = require("discord.js"); +const JsonFile = require("jsonfile"); //save/load data to/from json + +//my imports +const DiscordUtil = require("discordjs-util"); //some discordjs helper functions of mine + +//app components +const GuildData = require("./models/guild-data.js"); //data structure for guilds +const PackageJSON = require("../package.json"); //used to provide some info about the bot +const Bot = require("./bot.js"); + +//global vars +let writeFile = null; + +//use module.exports as a psuedo "onready" function +module.exports = (client, config = null) => { + config = config || require("./config.json"); //load config file + const guildsData = FileSystem.existsSync(config.generic.saveFile) ? fromJSON(JsonFile.readFileSync(config.generic.saveFile)) : {}; //read data from file, or generate new one if file doesn't exist + + //create our writeFile function that will allow other functions to save data to json without needing access to the full guildsData or config objects + //then set an interval to automatically save data to file + writeFile = () => JsonFile.writeFile(config.generic.saveFile, guildsData, err => { if (err) DiscordUtil.dateError("Error writing file", err); }); + setInterval(() => writeFile(), config.generic.saveIntervalSec * 1000); + + //handle messages + client.on("message", message => { + if (message.author.id !== client.user.id) { //check the bot isn't triggering itself + + //check whether we need to use DM or text channel handling + if (message.channel.type === "dm") + HandleMessage.dm(client, config, message); + else if (message.channel.type === "text" && message.member) + HandleMessage.text(client, config, message, guildsData); + } + }); +}; + +const HandleMessage = { + dm: (client, config, message) => { + message.reply(Util.format(config.generic.defaultDMResponse, config.generic.website, config.generic.discordInvite)); + }, + text: (client, config, message, guildsData) => { + const isCommand = message.content.startsWith(message.guild.me.toString()); + let guildData = guildsData[message.guild.id]; + + if (!guildData) + guildData = guildsData[message.guild.id] = new GuildData({ id: message.guild.id }); + + if (isCommand) { + const userIsAdmin = message.member.permissions.has("ADMINISTRATOR"); + const botName = "@" + (message.guild.me.nickname || client.user.username); + + const split = message.content.toLowerCase().split(/\ +/); //split the message at whitespace + const command = split[1]; //extract the command used + const commandObj = config.commands[Object.keys(config.commands).find(x => config.commands[x].command.toLowerCase() === command)]; //find the matching command object + + if (!commandObj || (!commandObj.admin && !userIsAdmin)) + return; + + const params = split.slice(2, split.length); //extract the parameters passed for the command + const expectedParamCount = commandObj.syntax.split(/\ +/).length - 1; //calculate the number of expected command params + + let finalisedParams; + if (params.length > expectedParamCount) //if we have more params than needed + finalisedParams = params.slice(0, expectedParamCount - 1).concat([params.slice(expectedParamCount - 1, params.length).join(" ")]); + else //else we either have exactly the right amount, or not enough + finalisedParams = params; + + //find which command was used and handle it + switch (command) { + case config.commands.version.command: + message.reply(`${PackageJSON.name} v${PackageJSON.version}`); + break; + case config.commands.help.command: + message.channel.send(createHelpEmbed(botName, config, userIsAdmin)); + break; + default: + if (finalisedParams.length >= expectedParamCount) + Bot.onCommand(commandObj, config.commands, finalisedParams, guildData, message) + .then(msg => { + message.reply(msg); + writeFile(); + }) + .catch(err => { + message.reply(err); + DiscordUtil.dateError(err); + }); + else + message.reply(`Incorrect syntax!\n**Expected:** *${botName} ${commandObj.syntax}*\n**Need help?** *${botName} ${config.commands.help.command}*`); + break; + } + } + else + Bot.onNonCommandMsg(message, guildData); + } +}; + +function fromJSON(json) { + const guildsData = Object.keys(json); + guildsData.forEach(guildID => { json[guildID] = new GuildData(json[guildID]); }); + return json; +} + +function createHelpEmbed(name, config, userIsAdmin) { + const commandsArr = Object.keys(config.commands).map(x => config.commands[x]).filter(x => userIsAdmin || !x.admin); + + const embed = new Discord.RichEmbed().setTitle("__Help__"); + + commandsArr.forEach(command => { + embed.addField(command.command, `${command.description}\n**Usage:** *${name} ${command.syntax}*${userIsAdmin && command.admin ? "\n***Admin only***" : ""}`); + }); + + embed.addField("__Need more help?__", `[Visit my website](${config.generic.website}) or [Join my Discord](${config.generic.discordInvite})`, true); + + return { embed }; +} \ No newline at end of file diff --git a/app/models/guild-data.js b/app/models/guild-data.js new file mode 100644 index 0000000..2060d58 --- /dev/null +++ b/app/models/guild-data.js @@ -0,0 +1,7 @@ +const DiscordUtil = require("discordjs-util"); + +module.exports = class GuildData { + constructor({ id }) { + this.id = id; + } +}; \ No newline at end of file diff --git a/bootstrap.js b/bootstrap.js new file mode 100644 index 0000000..a78913e --- /dev/null +++ b/bootstrap.js @@ -0,0 +1,20 @@ +const Discord = require("discord.js"); +const DiscordUtil = require("discordjs-util"); + +const client = new Discord.Client(); + +process.on("uncaughtException", (err) => { + DiscordUtil.dateError("Uncaught exception!", err); +}); + +client.login(require("./token.json").token); + +client.on("ready", () => { + DiscordUtil.dateLog("Registered bot " + client.user.username); + require("./app/index.js")(client); + client.user.setPresence({ game: { name: "benji7425.github.io", type: 0 } }); +}); + +client.on("disconnect", eventData => { + DiscordUtil.dateError("Bot was disconnected!", eventData.code, eventData.reason); +}); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..329536c --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "version": "0.1.0", + "main": "app/index.js", + "scripts": { + "start": "node bootstrap.js" + }, + "dependencies": { + "discord.js": "11.1.0", + "discordjs-util": "git+https://github.com/benji7425/discordjs-util.git", + "jsonfile": "3.0.1" + } +} \ No newline at end of file From 939e6f5946309b76304c9601ba88e3bb95c31b79 Mon Sep 17 00:00:00 2001 From: benji7425 Date: Fri, 1 Sep 2017 18:19:48 +0100 Subject: [PATCH 3/8] Add commands to config --- app/bot.js | 21 ++++++++++++++++++--- app/config.json | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/app/bot.js b/app/bot.js index ff81e7d..ac2f13e 100644 --- a/app/bot.js +++ b/app/bot.js @@ -3,11 +3,26 @@ const GuildData = require("./models/guild-data.js"); module.exports = { onCommand(commandObj, commandsObj, params, guildData, message) { switch (commandObj.command) { - case commandsObj.commandName.command: - return; //return promise! + case commandsObj.addFeed.command: + return addFeed(); + case commandsObj.removeFeed.command: + return removeFeed(); + case commandsObj.viewFeeds.command: + return viewFeeds(); } }, onNonCommandMsg(message, guildData) { return; } -}; \ No newline at end of file +}; + +function addFeed() { + //todo +} + +function removeFeed() { + //todo +} +function viewFeeds() { + //todo +} \ No newline at end of file diff --git a/app/config.json b/app/config.json index e4c69c2..34468f9 100644 --- a/app/config.json +++ b/app/config.json @@ -17,6 +17,24 @@ "description": "Display information about commands available to you", "syntax": "help", "admin": false + }, + "addFeed": { + "command": "add-feed", + "description": "Add an RSS feed to be posted in a channel, with an optional role to tag", + "syntax": "add-feed <#channel> [@role]", + "admin": true + }, + "removeFeed": { + "command": "remove-feed", + "description": "Remove an RSS feed by it's ID", + "syntax": "remove-feed ", + "admin": true + }, + "viewFeeds": { + "command": "view-feeds", + "description": "View a list of configured feeds and their associated details", + "syntax": "view-feed", + "admin": true } } } \ No newline at end of file From d22c9b91dcb85b1abc9ef8951d3db004b447b6d2 Mon Sep 17 00:00:00 2001 From: benji7425 Date: Sat, 9 Sep 2017 20:25:50 +0100 Subject: [PATCH 4/8] Add onReady function in bot.js --- app/bot.js | 7 +++++++ app/index.js | 2 ++ 2 files changed, 9 insertions(+) diff --git a/app/bot.js b/app/bot.js index ac2f13e..30ef1cd 100644 --- a/app/bot.js +++ b/app/bot.js @@ -1,6 +1,13 @@ const GuildData = require("./models/guild-data.js"); module.exports = { + onReady(client, guildsData, config) { + return new Promise((resolve, reject) => { + parseLinksInGuilds(client.guilds, guildsData) + .then(() => checkFeedsInGuilds(client.guilds, guildsData)) + .then(() => setInterval(() => checkFeedsInGuilds(client.guilds, guildsData), config.feedCheckIntervalSec * 1000)); //set up an interval to check all the feeds + }); + }, onCommand(commandObj, commandsObj, params, guildData, message) { switch (commandObj.command) { case commandsObj.addFeed.command: diff --git a/app/index.js b/app/index.js index 759e2b7..ebd686f 100644 --- a/app/index.js +++ b/app/index.js @@ -38,6 +38,8 @@ module.exports = (client, config = null) => { HandleMessage.text(client, config, message, guildsData); } }); + + Bot.onReady(client, guildsData, config).then(() => writeFile).catch(err => DiscordUtil.dateError(err)); }; const HandleMessage = { From c79267845230774680844dc1ae84231697833e31 Mon Sep 17 00:00:00 2001 From: benji7425 Date: Sat, 9 Sep 2017 20:26:04 +0100 Subject: [PATCH 5/8] Add v2 functionality --- app/bot.js | 88 +++++++++++++++++++++++++++++++++++---- app/config.json | 4 +- app/models/feed-data.js | 89 ++++++++++++++++++++++++++++++++++++++++ app/models/guild-data.js | 20 ++++++++- 4 files changed, 191 insertions(+), 10 deletions(-) create mode 100644 app/models/feed-data.js diff --git a/app/bot.js b/app/bot.js index 30ef1cd..3cc2706 100644 --- a/app/bot.js +++ b/app/bot.js @@ -1,4 +1,12 @@ +//external lib imports +const GetUrls = require("get-urls"); //for extracting urls from messages + +//my imports +const DiscordUtil = require("discordjs-util"); + +//app component imports const GuildData = require("./models/guild-data.js"); +const FeedData = require("./models/feed-data.js"); module.exports = { onReady(client, guildsData, config) { @@ -19,17 +27,83 @@ module.exports = { } }, onNonCommandMsg(message, guildData) { - return; + guildData.feeds.forEach(feedData => { + if (message.channel.name === feedData.channelName) + feedData.cachedLinks.push(...GetUrls(message.content)); //spread the urlSet returned by GetUrls into the cache array + }); } }; -function addFeed() { - //todo +function addFeed(client, guildsData, message, maxCacheSize) { + return new Promise((resolve, reject) => { + const feedUrl = [...GetUrls(message.content)][0]; + const channel = message.mentions.channels.first(); + + if (!feedUrl || !channel) + reject("Please provide both a channel and an RSS feed URL. You can optionally @mention a role also."); + + const role = message.mentions.roles.first(); + + const feedData = new FeedData({ + url: feedUrl, + channelName: channel.name, + roleName: role ? role.name : null, + maxCacheSize: maxCacheSize + }); + + //ask the user if they're happy with the details they set up, save if yes, don't if no + DiscordUtil.ask(client, message.channel, message.member, "Are you happy with this?\n" + feedData.toString()) + .then(responseMessage => { + + //if they responded yes, save the feed and let them know, else tell them to start again + if (responseMessage.content.toLowerCase() === "yes") { + if (!guildsData[message.guild.id]) + guildsData[message.guild.id] = new GuildData({ id: message.guild.id, feeds: [] }); + + guildsData[message.guild.id].feeds.push(feedData); + resolve("Your new feed has been saved!"); + } + else + reject("Your feed has not been saved, please add it again with the correct details"); + }); + }); } -function removeFeed() { - //todo +function removeFeed(guildsData, message, botName) { + return new Promise((resolve, reject) => { + const parameters = message.content.split(" "); + if (parameters.length !== 3) + resolve(`Please use the command as such:\n\`\`\` ${botName} remove-feed feedid\`\`\``); + else { + const guildData = guildsData[message.guild.id]; + const idx = guildData.feeds.findIndex(feed => feed.id === parameters[2]); + if (!Number.isInteger(idx)) + reject("Can't find feed with id " + parameters[2]); + else { + guildData.feeds.splice(idx, 1); + reject("Feed removed!"); + } + } + }); } -function viewFeeds() { - //todo + +function viewFeeds(guildData) { + if (!guildData) + return Promise.reject("Guild not setup"); + + return Promise.resolve(guildData.feeds.map(f => f.toString()).join("\n")); +} + +function checkFeedsInGuilds(guilds, guildsData) { + Object.keys(guildsData).forEach(key => guildsData[key].checkFeeds(guilds)); +} + +function parseLinksInGuilds(guilds, guildsData) { + const promises = []; + for (let guildId of guilds.keys()) { + const guildData = guildsData[guildId]; + if (guildData) + promises.push(guildData.cachePastPostedLinks(guilds.get(guildId))); + } + return Promise.all(promises); } \ No newline at end of file diff --git a/app/config.json b/app/config.json index 34468f9..b1fd888 100644 --- a/app/config.json +++ b/app/config.json @@ -4,7 +4,9 @@ "saveIntervalSec": 60, "website": "https://benji7425.github.io", "discordInvite": "https://discord.gg/SSkbwSJ", - "defaultDMResponse": "This bot does not have any handling for direct messages. To learn more or get help please visit %s, or join my Discord server here: %s" }, + "defaultDMResponse": "This bot does not have any handling for direct messages. To learn more or get help please visit %s, or join my Discord server here: %s" + }, + "feedCheckIntervalSec": 30, "commands": { "version": { "command": "version", diff --git a/app/models/feed-data.js b/app/models/feed-data.js new file mode 100644 index 0000000..da5a90c --- /dev/null +++ b/app/models/feed-data.js @@ -0,0 +1,89 @@ +//my imports +const DiscordUtil = require("discordjs-util"); + +//external lib imports +const Dns = require("dns"); //for host resolution checking +const Url = require("url"); //for url parsing +const FeedRead = require("feed-read"); //for extracing new links from RSS feeds +const GetUrls = require("get-urls"); //for extracting urls from messages +const ShortID = require("shortid"); //to provide ids for each feed, allowing guilds to remove them + +module.exports = class FeedData { + constructor({ id, url, channelName, roleName, cachedLinks, maxCacheSize }) { + this.id = id || ShortID.generate(); + this.url = url; + this.channelName = channelName; + this.roleName = roleName; + this.cachedLinks = cachedLinks || []; + this.maxCacheSize = maxCacheSize || 10; + + this.cachedLinks.push = (...elements) => { + const unique = elements + .map(el => normaliseUrl(el)) //normalise all the urls + .filter(el => !this.cachedLinks.includes(el)); //filter out any already cached + Array.prototype.push.apply(this.cachedLinks, unique); + + if (this.cachedLinks.length > this.maxCacheSize) + this.cachedLinks.splice(0, this.cachedLinks.length - this.maxCacheSize); //remove the # of elements above the max from the beginning + }; + } + + /** + * Returns a promise providing all the links posted in the last 100 messages + * @param {Discord.Guild} guild The guild this feed belongs to + * @returns {Promise} Links posted in last 100 messages + */ + updatePastPostedLinks(guild) { + const channel = guild.channels.find(ch => ch.type === "text" && ch.name === this.channelName); + + return new Promise((resolve, reject) => { + channel.fetchMessages({ limit: 100 }) + .then(messages => { + new Map([...messages].reverse()).forEach(m => this.cachedLinks.push(...GetUrls(m.content))); //push all the links in each message into our links array + resolve(this); + }) + .catch(reject); + }); + } + + check(guild) { + Dns.resolve(Url.parse(this.url).host || "", err => { //check we can resolve the host, so we can throw an appropriate error if it fails + if (err) + DiscordUtil.dateError("Connection Error: Can't resolve host", err); //log our error if we can't resolve the host + else + FeedRead(this.url, (err, articles) => { //check the feed + if (err) + DiscordUtil.dateError(err); + else { + let latest = articles[0].link; //extract the latest link + latest = normaliseUrl(latest); //standardise it a bit + + //if we don't have it cached already, cache it and callback + if (!this.cachedLinks.includes(latest)) { + this.cachedLinks.push(latest); + + const channel = guild.channels.find(ch => ch.type === "text" && ch.name.toLowerCase() === this.channelName.toLowerCase()); + const role = this.roleName ? guild.roles.find(role => role.name.toLowerCase() === this.roleName.toLowerCase()) : null; + channel.send((role ? role + " " : "") + latest); + } + } + }); + }); + } + + toString() { + const blacklist = ["cachedLinks", "maxCacheSize"]; + return `\`\`\`JavaScript\n ${JSON.stringify(this, (k, v) => !blacklist.includes(k) ? v : undefined, "\t")} \`\`\``; + } +}; + +function normaliseUrl(url) { + url = url.replace("https://", "http://"); //cheaty way to get around http and https not matching + + if (Url.parse(url).host.includes("youtu")) //detect youtu.be and youtube.com - yes I know it's hacky + url = url.split("&")[0]; //quick way to chop off stuff like &feature=youtube + + url = url.replace(/(www.)?youtube.com\/watch\?v=/, "youtu.be/"); //turn full url into share url + + return url; +} \ No newline at end of file diff --git a/app/models/guild-data.js b/app/models/guild-data.js index 2060d58..d1ea352 100644 --- a/app/models/guild-data.js +++ b/app/models/guild-data.js @@ -1,7 +1,23 @@ -const DiscordUtil = require("discordjs-util"); +const FeedData = require("./feed-data.js"); +const Util = require("discordjs-util"); module.exports = class GuildData { - constructor({ id }) { + constructor({ id, feeds }) { this.id = id; + this.feeds = feeds.map(feed => new FeedData(feed)); + } + + cachePastPostedLinks(guild) { + const promises = []; + + this.feeds.forEach(feed => { + promises.push(feed.updatePastPostedLinks(guild).catch(Util.dateError)); + }); + + return Promise.all(promises); + } + + checkFeeds(guilds) { + this.feeds.forEach(feed => feed.check(guilds.get(this.id))); } }; \ No newline at end of file From 049ce4d2a8d52ae35a83e344a24198439661f381 Mon Sep 17 00:00:00 2001 From: benji7425 Date: Sat, 9 Sep 2017 20:32:51 +0100 Subject: [PATCH 6/8] Add extra parameters to be passed to bot onCommand method --- app/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/index.js b/app/index.js index ebd686f..594819a 100644 --- a/app/index.js +++ b/app/index.js @@ -83,7 +83,7 @@ const HandleMessage = { break; default: if (finalisedParams.length >= expectedParamCount) - Bot.onCommand(commandObj, config.commands, finalisedParams, guildData, message) + Bot.onCommand(commandObj, config.commands, finalisedParams, guildData, message, config, client, botName) .then(msg => { message.reply(msg); writeFile(); From e6b2ed52efea0f212b6b78075c27c22d80b946ad Mon Sep 17 00:00:00 2001 From: benji7425 Date: Sat, 9 Sep 2017 20:52:27 +0100 Subject: [PATCH 7/8] Add passing of parameters to commands Fix a couple of issues --- app/bot.js | 21 ++++++++++----------- app/config.json | 1 + 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/bot.js b/app/bot.js index 3cc2706..fe185a3 100644 --- a/app/bot.js +++ b/app/bot.js @@ -16,14 +16,14 @@ module.exports = { .then(() => setInterval(() => checkFeedsInGuilds(client.guilds, guildsData), config.feedCheckIntervalSec * 1000)); //set up an interval to check all the feeds }); }, - onCommand(commandObj, commandsObj, params, guildData, message) { + onCommand(commandObj, commandsObj, params, guildData, message, config, client, botName) { switch (commandObj.command) { case commandsObj.addFeed.command: - return addFeed(); + return addFeed(client, guildData, message, config.maxCacheSize); case commandsObj.removeFeed.command: - return removeFeed(); + return removeFeed(guildData, message, botName); case commandsObj.viewFeeds.command: - return viewFeeds(); + return viewFeeds(guildData); } }, onNonCommandMsg(message, guildData) { @@ -34,7 +34,7 @@ module.exports = { } }; -function addFeed(client, guildsData, message, maxCacheSize) { +function addFeed(client, guildData, message, maxCacheSize) { return new Promise((resolve, reject) => { const feedUrl = [...GetUrls(message.content)][0]; const channel = message.mentions.channels.first(); @@ -57,10 +57,10 @@ function addFeed(client, guildsData, message, maxCacheSize) { //if they responded yes, save the feed and let them know, else tell them to start again if (responseMessage.content.toLowerCase() === "yes") { - if (!guildsData[message.guild.id]) - guildsData[message.guild.id] = new GuildData({ id: message.guild.id, feeds: [] }); + if (!guildData) + guildData = new GuildData({ id: message.guild.id, feeds: [] }); - guildsData[message.guild.id].feeds.push(feedData); + guildData.feeds.push(feedData); resolve("Your new feed has been saved!"); } else @@ -69,19 +69,18 @@ function addFeed(client, guildsData, message, maxCacheSize) { }); } -function removeFeed(guildsData, message, botName) { +function removeFeed(guildData, message, botName) { return new Promise((resolve, reject) => { const parameters = message.content.split(" "); if (parameters.length !== 3) resolve(`Please use the command as such:\n\`\`\` ${botName} remove-feed feedid\`\`\``); else { - const guildData = guildsData[message.guild.id]; const idx = guildData.feeds.findIndex(feed => feed.id === parameters[2]); if (!Number.isInteger(idx)) reject("Can't find feed with id " + parameters[2]); else { guildData.feeds.splice(idx, 1); - reject("Feed removed!"); + resolve("Feed removed!"); } } }); diff --git a/app/config.json b/app/config.json index b1fd888..e10434f 100644 --- a/app/config.json +++ b/app/config.json @@ -6,6 +6,7 @@ "discordInvite": "https://discord.gg/SSkbwSJ", "defaultDMResponse": "This bot does not have any handling for direct messages. To learn more or get help please visit %s, or join my Discord server here: %s" }, + "maxCacheSize": 100, "feedCheckIntervalSec": 30, "commands": { "version": { From e7e0bba1057c54bcaf2e7bee5c4dab81bb03019c Mon Sep 17 00:00:00 2001 From: benji7425 Date: Sat, 9 Sep 2017 21:01:07 +0100 Subject: [PATCH 8/8] Initialise npm and add required packages --- package.json | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 329536c..6ce6ffc 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,28 @@ { - "version": "0.1.0", - "main": "app/index.js", - "scripts": { - "start": "node bootstrap.js" - }, - "dependencies": { - "discord.js": "11.1.0", - "discordjs-util": "git+https://github.com/benji7425/discordjs-util.git", - "jsonfile": "3.0.1" - } -} \ No newline at end of file + "version": "3.0.0-b1", + "main": "app/index.js", + "scripts": { + "start": "node bootstrap.js" + }, + "dependencies": { + "discord.js": "11.1.0", + "discordjs-util": "git+https://github.com/benji7425/discordjs-util.git", + "feed-read": "0.0.1", + "get-urls": "7.0.0", + "jsonfile": "3.0.1", + "shortid": "2.2.8" + }, + "name": "discord-bot-rss-feed", + "devDependencies": {}, + "repository": { + "type": "git", + "url": "git+https://github.com/benji7425/discord-bot-rss-feed.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/benji7425/discord-bot-rss-feed/issues" + }, + "homepage": "https://github.com/benji7425/discord-bot-rss-feed#readme", + "description": "" +}