Merge branch 'wrapper-update'

This commit is contained in:
benji7425 2017-05-17 19:00:04 +01:00
commit 097ad48e95
5 changed files with 52 additions and 16 deletions

View File

@ -6,6 +6,6 @@
[subrepo] [subrepo]
remote = git@github.com:benji7425/shell-discord-bot.git remote = git@github.com:benji7425/shell-discord-bot.git
branch = master branch = master
commit = 4946884723f9c66d3c2713f109aab2cf60bd81f4 commit = 59528679ea56f0a82b4564fe19b57229925f2e5a
parent = 258eff2d63b5804e1e423e9418b117ad4212d8ff parent = 56afc197bc59785baf2fa97bd6b6220cd238cceb
cmdver = 0.3.1 cmdver = 0.3.1

View File

@ -3,7 +3,8 @@
The purpose of this is to act as a shell for other bot modules, so that a single bot user account can be used for a multi-function bot. The purpose of this is to act as a shell for other bot modules, so that a single bot user account can be used for a multi-function bot.
## Setup ## Setup
- Fork/clone/merge this repo into a new one - Clone this as a submodule/subtree/subrepo into another repo as "wrapper" (or a folder name of your choice)
- Use *app/index.js* as your bot entry point, or change the reference in this index.js
- `npm install --save discord.io` - `npm install --save discord.io`
- `npm shrinkwrap --dev` - `npm shrinkwrap --dev`
- `shrinkpack .` - `shrinkpack .`
@ -15,7 +16,7 @@ Interfacing with each bot module is done by the properties in its module.exports
| property | property type | parameters | description | | property | property type | parameters | description |
|--------------|---------------|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------| |--------------|---------------|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
| onReady | method | none | called on the bot ready event | | onReady | method | bot | called on the bot ready event |
| onDisconnect | method | none | called when the bot disconnects | | onDisconnect | method | none | called when the bot disconnects |
| onMessage | method | bot, user, userID, channelID, message | called when the bot receives a message - identical to the 'action' property of a command, but triggered on every message (see below) | | onMessage | method | bot, user, userID, channelID, message | called when the bot receives a message - identical to the 'action' property of a command, but triggered on every message (see below) |
| commands | array | N/A | commands a user can invoke - like the onMessage event, but only triggered on expected commands (see below) | | commands | array | N/A | commands a user can invoke - like the onMessage event, but only triggered on expected commands (see below) |
@ -25,13 +26,22 @@ Interfacing with each bot module is done by the properties in its module.exports
A command object contains a command, and an action to invoke if the message contains that command. Each command object needs a certain set of properties: A command object contains a command, and an action to invoke if the message contains that command. Each command object needs a certain set of properties:
| property | optional? | value | description | | property | optional? | value | description |
|------------|-----------|--------------------------|----------------------------------------------------------------------------------------------------| |------------|-----------|--------------------------|-----------------------------------------------------------------------------------------------------------|
| command | required | string | Command to look for in the message | | command | required | string | Command to look for in the message |
| type | required | "equals" or "startsWith" | Describes whether we are looking for the message to be the exact command, or just to start with it | | type | required | "equals" or "startsWith" | Describes whether we are looking for the message to be the exact command, or just to start with it |
| action | required | function | Callback to invoke if the command is matched (see below) | | action | required | function | Callback to invoke if the command is matched (see below) |
| channelIDs | optional | array of strings | If this property is present, the command will only be triggered if sent in one of these channels | | channelIDs | optional | array of strings | If this property is present, the command will only be triggered if sent in one of these channels |
| userIDs | optional | array of strings | If this property is present, the command will only be triggered if made by one of these users | | roleIDs | optional | array of strings | If this property is present, the command will only be triggered if send by a user with one of these roles |
| userIDs | optional | array of strings | If this property is present, the command will only be triggered if sent by one of these users |
**Permission heirarchy**
channelIDs > roleIDs > userIDs
Examples of commands that *won't* be triggered:
- channelIDs *contains* the channel, but userIDs *doesn't* - channelID check will pass, userID check subsequently won't
- channelIDs *doesn't contain* the channel, roleIDs or userIDs *contain* the user - channelID check will block the command, regardless of other permissions
- channelIDs *contains* the channel, roleIDs *doesn't* contain the user's roles, userIDs *contains* the user - channelID check will pass, roleID check will block
#### Actions #### Actions
@ -80,4 +90,4 @@ Example 2:
``` ```
The above example expects the user to type '!define something', ie only checking for the message to start with '!define'. You are still passed the full message, so can split it up and read it however you want. The above example expects the user to type '!define something', ie only checking for the message to start with '!define'. You are still passed the full message, so can split it up and read it however you want.
*action* will only be called if the message begins with '!define', but has no restrictions on which channel(s) or user(s) use it *action* will only be called if the message begins with '!define', but has no restrictions on which channel(s) or user(s) use it

View File

@ -4,7 +4,7 @@ const Console = require("console");
//external module imports //external module imports
var Discord = require("discord.io"); var Discord = require("discord.io");
var BotModules = [require("../index.js")]; var BotModules = [require("../app/index.js")];
var bot; var bot;
@ -35,9 +35,7 @@ var EventHandlers = {
for (let j = 0, jLen = botModule.commands.length; j < jLen; j++) { for (let j = 0, jLen = botModule.commands.length; j < jLen; j++) {
let messageTrigger = botModule.commands[j]; let messageTrigger = botModule.commands[j];
if ((!messageTrigger.channelIDs && !messageTrigger.userIDs) //if we have neither channel nor user restraint, pass if (commandIsAllowed(messageTrigger, user, userID, channelID))
|| (messageTrigger.channelIDs && messageTrigger.channelIDs.includes(channelID)) //otherwise, if we have a channel constraint, pass if we're allowed to respond in this channel
|| (messageTrigger.userIDs && messageTrigger.userIDs.includes(userID))) //otherwise, if we have a user constraint, pass if we're allowed to respond to this user
switch (messageTrigger.type) { switch (messageTrigger.type) {
case "startsWith": case "startsWith":
if (message.startsWith(messageTrigger.command)) if (message.startsWith(messageTrigger.command))
@ -55,6 +53,34 @@ var EventHandlers = {
} }
}; };
var commandIsAllowed = (messageTrigger, user, userID, channelID) => {
//if we aren't allowed this command in this channel, disallow the command
if (messageTrigger.channelIDs && !messageTrigger.channelIDs.includes(channelID))
return false;
if (messageTrigger.roleIDs) { //check if we have a role constraint
var userHasPermissiveRole = false;
messageTrigger.roleIDs.forEach((element) => { //iterate over all the allowed role IDs
if (userHasRole(userID, channelID, element)) userHasPermissiveRole = true; //check if the user has this role
});
if (!userHasPermissiveRole) return false; //disallow the command if the user doesn't have one of these role IDs
}
//if this user isn't allowed, disallow the command
if (messageTrigger.userIDs && !messageTrigger.userIDs.includes(userID))
return false;
//if we haven't returned false by now, then the command is allowed
return true;
};
var userHasRole = (userID, channelID, roleID) => {
var userRoles = bot.servers[bot.channels[channelID].guild_id].members[userID].roles;
return userRoles.includes(roleID);
};
(() => { (() => {
bot = new Discord.Client({ bot = new Discord.Client({
token: require("./token.json").token, token: require("./token.json").token,