Merged release/v1.3.0 into master

This commit is contained in:
benji7425 2017-01-22 18:57:02 +00:00
commit 3c8b45154a
10 changed files with 198 additions and 79 deletions

View file

@ -1,5 +1,20 @@
# Changelog # Changelog
## v1.3.0
### Added
- Deletion of "You have successfully subscribed" messages after a short delay (configurable)
- 'Developer' commands that can only be accessed by specified users
- !cacheList developer command to view the cached URLs
### Updated
- !logsplease is now a developer command
- Subscriptions are now done using a role
- !subscribe and !unsibscribe add and remove the user from the role
- !sublist command is now removed
- The role is mentioned when the link is posted, rather than a long chain of user IDs
## v1.2.1 ## v1.2.1
### Fixed ### Fixed

View file

@ -1,14 +1,24 @@
{ {
"feedUrl": "https://www.youtube.com/feeds/videos.xml?user=EthosLab", "feedUrl": "https://www.youtube.com/feeds/videos.xml?user=EthosLab",
"channelID": "264420391282409473", "channelID": "264420391282409473",
"serverID": "264420391282409473",
"pollingInterval": 5000, "pollingInterval": 5000,
"numLinksToCache": 10, "numLinksToCache": 10,
"messageDeleteDelay": 10000,
"youtubeMode": true, "youtubeMode": true,
"logRequestMessage": "!logsplease", "allowSubscriptions": true,
"subscribeRequestMessage": "!subscribe", "subscribersRoleID": "272788856447959040",
"unsubscribeRequestMessage": "!unsubscribe",
"subscribersListRequestMessage": "!sublist",
"helpRequestMessage": "!help",
"logFile": "./log", "logFile": "./log",
"subscribersFile": "./subscribers.json" "userCommands": {
"subscribe": "!subscribe",
"unsubscribe": "!unsubscribe",
"help": "!help"
},
"developerCommands": {
"logUpload": "!logsplease",
"cacheList": "!cacheList"
},
"developers": [
"117966411548196870"
]
} }

11
docs/.gitrepo Normal file
View file

@ -0,0 +1,11 @@
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
;
[subrepo]
remote = git@github.com:benji7425/discord-feed-bot.wiki.git
branch = master
commit = f70e48b91074ad051eec48679d013409a79ed53e
parent = 21bc8bdaeb42f8eca6218fbe1910ddcc75d56c3c
cmdver = 0.3.1

View file

@ -2,9 +2,18 @@
There is a very basic level of interaction with the bot available via chat commands, all of which are prefixed with an exclamation mark '!' There is a very basic level of interaction with the bot available via chat commands, all of which are prefixed with an exclamation mark '!'
## User commands
| command | action | | command | action |
|--------------|-----------------------------------------------------------------------------------------| |--------------|-----------------------------------------------------------------------------------------|
| !help | list available commands | | !help | list available commands |
| !subscribe | subscribe to feed notifications, so your username gets tagged when a new link is posted | | !subscribe | subscribe to feed notifications, so your username gets tagged when a new link is posted |
| !unsubscribe | unsubscribe from feed notifications | | !unsubscribe | unsubscribe from feed notifications |
| !sublist | view list of subscribed users |
## Developer commands
Requires your user ID to be specified in the developers list in config.json
| command | action |
|-------------|----------------------------|
| !logsplease | upload the log file |
| !cacheList | report all the cached URLs |

View file

@ -0,0 +1,31 @@
# Configuration
| parameter | description |
|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| feedUrl | the RSS feed to check |
| channelID | report all the cached URLs |
| serverID | id of the server the bot is installed on - require to use subscriptions |
| pollingInterval | interval in ms to check the RSS feed |
| numLinksToCache | number of posted links to cache and check against before posting - turn this up if users post a lot of links in the channel |
| messageDeleteDelay | time in ms to leave response messages before deleting (eg "You have successfully subscribed") |
| youtubeMode | whether or not to convert YouTube links to their short url - recommended if you are pulling links from a YouTube channel feed |
| allowSubscriptions | whether or not to have the bot mention a role when it posts a link |
| subscribersRoleID | the ID of the role to mention when posting a link - you can find this by typing \@role in discord and copying out just the numeric part |
| developers | array of developer IDs - add a new one by putting a comma at the end of the one above and putting the ID in double quotes |
## How to find IDs
- Make sure developer mode is turned on in discord
- User Settings > Appearance > Developer Mode
| id | how to find |
|----------------------------|-----------------------------------------------|
| channelID | right click on the channel > copy ID |
| serverID | right click on the server name > copy ID |
| subscribersRoleID | type \@role in discord, copy the numeric part |
| user ID (to add developer) | right click on user > copy ID |
## Note about subsriptions
For subscriptions to work the bot needs the "Manage roles" permission, and needs to be in a role *higher than* the subscribers role

View file

@ -4,9 +4,11 @@
2. Download the zip from [releases](https://github.com/benji7425/discord-feed-bot/releases) and extract 2. Download the zip from [releases](https://github.com/benji7425/discord-feed-bot/releases) and extract
3. Open a terminal in extracted folder 3. Open a terminal in extracted folder
4. Run `npm install` and wait for it to finish 4. Run `npm install` and wait for it to finish
5. Edit *config.json* to include your RSS feed and channel ID 5. Edit *config.json* to include your server/channel details (see configuration page for more info)
6. Create *bot-config.json* to include your bot token: 6. Create *bot-config.json* to include your bot token:
`{ `{
"token": "abc123blahblahblahyourtokengoeshere" "token": "abc123blahblahblahyourtokengoeshere"
}` }`
7. Run `node feed-bot.js` 7. Run `node feed-bot.js`
See configuration page for more detail on configuration options

View file

@ -0,0 +1,10 @@
# Troubleshooting
## Bot can't add users to role
- Make sure the bot's role has the "Manage Roles" permission
- Make sure the bot's role is higher than the subscribers role
## Other stuff
Feel free to contact me at the email on my GitHub profile :)

View file

@ -37,6 +37,7 @@ var DiscordClient = {
DiscordClient.checkPastMessagesForLinks(); //we need to check past messages for links on startup, but also on reconnect because we don't know what has happened during the downtime DiscordClient.checkPastMessagesForLinks(); //we need to check past messages for links on startup, but also on reconnect because we don't know what has happened during the downtime
//set the interval function to check the feed
intervalFunc = () => { intervalFunc = () => {
Feed.check((err, articles) => { Feed.check((err, articles) => {
Links.validate(err, articles, DiscordClient.post); Links.validate(err, articles, DiscordClient.post);
@ -61,36 +62,17 @@ var DiscordClient = {
}); });
} }
else { else {
switch (message) { //iterate over all of our message triggers to see if the message sent requires any action
case Config.subscribeRequestMessage: for (var i = 0; i < DiscordClient.messageTriggers.length; i++) {
Subscriptions.subscribe(channelID, userID, user); var messageTrigger = DiscordClient.messageTriggers[i];
break; if (message === messageTrigger.message) {
case Config.unsubscribeRequestMessage: //check if its locked to a channel or to a specific user
Subscriptions.unsubscribe(channelID, userID, user); if ((messageTrigger.channelID && messageTrigger.channelID === channelID) || (messageTrigger.userIDs && messageTrigger.userIDs.includes(userID)))
break; messageTrigger.action(user, userID, channelID, message);
case Config.subscribersListRequestMessage: }
DiscordClient.bot.sendMessage({
to: Config.channelID,
message: DiscordClient.bot.fixMessage("<@" + Subscriptions.subscribers.join("> <@") + ">")
});
break;
case Config.helpRequestMessage:
DiscordClient.bot.sendMessage({
to: Config.channelID,
message: Config.subscribeRequestMessage + ", " + Config.unsubscribeRequestMessage + ", " + Config.subscribersListRequestMessage
});
} }
} }
} }
else if (message === Config.logRequestMessage) {
DiscordClient.bot.uploadFile({
to: channelID,
file: Config.logFile
}, (err, message) => {
if (err) Log.error("Failed to upload log file: " + message, err);
else Log.event("Uploaded log file for user " + user + "(" + userID + ")");
});
}
}, },
checkPastMessagesForLinks: function () { checkPastMessagesForLinks: function () {
var limit = 100; var limit = 100;
@ -121,58 +103,100 @@ var DiscordClient = {
}); });
}, },
post: function (link) { post: function (link) {
var tags = "";
for (var userID in Subscriptions.subscribers)
tags += "<@" + Subscriptions.subscribers[userID] + "> ";
//send a messsage containing the new feed link to our discord channel //send a messsage containing the new feed link to our discord channel
DiscordClient.bot.sendMessage({ DiscordClient.bot.sendMessage({
to: Config.channelID, to: Config.channelID,
message: tags + link message: Subscriptions.mention() + link
}, function (err, message) {
if (err) {
Log.error("ERROR: Failed to send message" + message ? message : "", err);
//if there is an error posting the message, check if it is because the bot isn't connected
if (!DiscordClient.bot.connected) DiscordClient.onDisconnect();
}
}); });
} },
//actions to perform when certain messages are detected, along with channel or user requirements
messageTriggers: [
{
message: Config.userCommands.subscribe,
action: (user, userID, channelID, message) => { if (Config.allowSubscriptions) Subscriptions.subscribe(user, userID, channelID, message); },
channelID: Config.channelID
},
{
message: Config.userCommands.unsubscribe,
action: (user, userID, channelID, message) => { if (Config.allowSubscriptions) Subscriptions.unsubscribe(user, userID, channelID, message); },
channelID: Config.channelID
},
{
message: Config.userCommands.help,
action: (user, userID, channelID, message) => {
DiscordClient.bot.sendMessage({
to: Config.channelID,
message: Config.userCommands.join(" + ")
});
},
channelID: Config.channelID
},
{
message: Config.developerCommands.logUpload,
action: (user, userID, channelID, message) => {
DiscordClient.bot.uploadFile({
to: channelID,
file: Config.logFile
});
},
userIDs: Config.developers
},
{
message: Config.developerCommands.cacheList,
action: (user, userID, channelID, message) => {
DiscordClient.bot.sendMessage({
to: channelID,
message: Links.cached.join(", ")
});
},
userIDs: Config.developers
}
]
}; };
var Subscriptions = { var Subscriptions = {
subscribers: [], subscribe: function (user, userID, channelID, message) {
parse: function () { DiscordClient.bot.addToRole({
JsonFile.readFile(Config.subscribersFile, (err, obj) => { serverID: Config.serverID,
if (err) Log.error("Unable to parse json subscribers file", err); userID: userID,
this.subscribers = obj || []; roleID: Config.subscribersRoleID
}); },
}, (err) => {
subscribe: function (channelID, userID, user) { if (err) Log.raw(err); //log the error if there is an error
if (this.subscribers.indexOf(userID) === -1) { else { //else go ahead and confirm subscription
this.subscribers.push(userID); //subscribe the user if they aren't already subscribed Log.event("Subscribed user " + (user ? user + "(" + userID + ")" : userID));
this.writeToFile();
Log.event("Subscribed user " + (user ? user + "(" + userID + ")" : userID));
DiscordClient.bot.sendMessage({ DiscordClient.bot.sendMessage({
to: channelID, to: channelID,
message: "You have successfully subscribed" message: "You have successfully subscribed"
}, (err, response) => { setTimeout(() => { DiscordClient.bot.deleteMessage({ channelID: channelID, messageID: response.id }); }, Config.messageDeleteDelay); }); //delete the subscription confirmation message after a delay
}
}); });
}
},
unsubscribe: function (channelID, userID, user) {
if (this.subscribers.indexOf(userID) > -1) {
this.subscribers.splice(this.subscribers.indexOf(userID), 1);
this.writeToFile();
Log.event("Unsubscribed user " + (user ? user + "(" + userID + ")" : userID));
DiscordClient.bot.sendMessage({
to: channelID,
message: "You have successfully unsubscribed"
});
}
}, },
writeToFile: function () {
JsonFile.writeFile(Config.subscribersFile, this.subscribers, (err) => { if (err) Log.error("Unable to write subscribers to json file", err); }); unsubscribe: function (user, userID, channelID, message) {
DiscordClient.bot.removeFromRole({
serverID: Config.serverID,
userID: userID,
roleID: Config.subscribersRoleID
},
(err) => {
if (err) Log.raw(err); //log the error if there is an error
else { //else go ahead and confirm un-subscription
Log.event("Unsubscribed user " + (user ? user + "(" + userID + ")" : userID));
DiscordClient.bot.sendMessage({
to: channelID,
message: "You have successfully unsubscribed"
}, (err, response) => { setTimeout(() => { DiscordClient.bot.deleteMessage({ channelID: channelID, messageID: response.id }); }, Config.messageDeleteDelay); }); //delete the un-subscription confirmation message after a delay
}
});
},
mention: function () {
return Config.allowSubscriptions ? "<@&" + Config.subscribersRoleID + "> " : "";
} }
}; };
@ -265,7 +289,6 @@ var intervalFunc = () => { }; //do nothing by default
//IIFE to kickstart the bot when the app loads //IIFE to kickstart the bot when the app loads
(function () { (function () {
Subscriptions.parse();
DiscordClient.startup(); DiscordClient.startup();
setInterval(() => { intervalFunc(); }, Config.pollingInterval); setInterval(() => { intervalFunc(); }, Config.pollingInterval);
})(); })();

7
log.js
View file

@ -20,6 +20,10 @@ function log(message) {
} }
} }
function logRaw(obj) {
Console.log(obj);
}
module.exports = { module.exports = {
info: function (message) { info: function (message) {
if (message) if (message)
@ -36,5 +40,8 @@ module.exports = {
//log the message, attach innerEx information if it was passed //log the message, attach innerEx information if it was passed
log("[ERROR] " + message + (innerEx ? ". Inner exception details: " + (innerEx.message || innerEx) : "")); log("[ERROR] " + message + (innerEx ? ". Inner exception details: " + (innerEx.message || innerEx) : ""));
} }
},
raw: function (obj) {
if (obj) logRaw(obj);
} }
}; };

View file

@ -1,9 +1,10 @@
{ {
"name": "discord-feed-bot", "name": "discord-feed-bot",
"version": "1.0.0", "version": "1.3.0",
"description": "discord-feed-bot", "description": "discord-feed-bot",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "node feed-bot.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"repository": { "repository": {