From b4050001f3bee05043f507290820f069dd138708 Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 04:03:20 -0500 Subject: [PATCH 01/46] Removes config.json from repo --- config.json | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 config.json diff --git a/config.json b/config.json deleted file mode 100644 index e848e53..0000000 --- a/config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "port": 8421, - "logs": "logs", - "token": { - "api": "Set your API token here", - "robot": "Set your access token for your robot user here.", - "webhook": "Set your incoming webhook token here" - }, - "domain": "SlackTeam", - "hostname": "https://SlackTeam.slack.com", - "path": "/services/hooks/incoming-webhook?token=[REDACTED]", - "keys": [ - "Create a unique access key and make sure to set it as a URL parameter in your Slack outgoing-webhook URL" - ], - "timeout": 8000 -} From 50a8e9cfa963e0250c4b3bec76edc5fdf0020384 Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:25:13 -0500 Subject: [PATCH 02/46] Fixes setup functions not running. --- bot.js | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/bot.js b/bot.js index c9c87fb..cce1ace 100644 --- a/bot.js +++ b/bot.js @@ -19,17 +19,19 @@ var slack = { exports.actions = []; -exports.setup = function (callback) { +exports.setup = function setup (callback) { var setup; var x; + fs.readdir(__dirname + '/actions', function (error, files) { var errors = []; if (error) return callback(error, files); - + _.each(files, function (file) { - var action = require(__dirname + '/actions/' + file); - if (!action) return true; - // exports.actions.push(action); + require(__dirname + '/actions/' + file); + }); + + _.each(exports.actions, function runSetup (action) { setup = action.setup; if (setup && _.isFunction(setup)) setup(function (error, data) { console.log('Running setup of ' + file); @@ -40,6 +42,7 @@ exports.setup = function (callback) { log.info('Success running setup function of action' + data.name); } }); + }); log.info('bot setup complete'); @@ -47,12 +50,24 @@ exports.setup = function (callback) { }); }; -exports.processRequest = function (request, response) { - var actionFound, commands, input, outgoingData, pipedResponse, regex, requestText, responseMethod, responseText, VARIABLES; - +exports.processRequest = function processRequest (request, response) { + var + actionFound, + commands, + input, + outgoingData, + pipedResponse, + regex, + requestText, + responseMethod, + responseText, + VARIABLES + ; + input = request.body.text; - // The keys on this object will + // The keys on this object will be replaced with their corresponding values + // at runtime. VARIABLES = { 'HERE': '#' + request.body.channel_name, 'ME': '@' + request.body.user_name, @@ -152,11 +167,11 @@ exports.processRequest = function (request, response) { break; case 'channel': - exports.sendMessage(responseText, '#' + redirect.name); + exports.sendMessage(responseText, '#' + redirect.name); break; case 'group': - exports.sendMessage(responseText, '#' + redirect.name); + exports.sendMessage(responseText, '#' + redirect.name); break; case 'file': @@ -182,7 +197,7 @@ exports.processRequest = function (request, response) { function formatResponse (response) { return (request.body.trigger_word) ? JSON.stringify({text: response}) : response; - } + } }; exports.addAction = function (action) { @@ -213,7 +228,7 @@ exports.sendMessage = function (message, channel, callback) { https.get('https://slack.com/api/chat.postMessage?' + querystring.stringify(messageData), function (response) { response.on('end', function () { - callback(response.error, response); + callback(response.error, response); }); }).end(); }; From ac483fac32d1521adc25d90946e144b358632f40 Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:25:42 -0500 Subject: [PATCH 03/46] Minor style changes --- library/parse.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/library/parse.js b/library/parse.js index 7c4d6a0..ab3fc11 100644 --- a/library/parse.js +++ b/library/parse.js @@ -15,7 +15,7 @@ var slackEncoding = { } var slackChars = Object.keys(slackEncoding) -exports.httpParameters = function(parameters) { +exports.httpParameters = function httpParameters (parameters) { var parameters = parameters.split('&') var parametersObject = {} @@ -27,7 +27,7 @@ exports.httpParameters = function(parameters) { return parametersObject } -exports.slackText = function(encodedText) { +exports.slackText = function slackText (encodedText) { var decodedText = '' while (encodedText) { @@ -45,7 +45,7 @@ exports.slackText = function(encodedText) { if (encodedText[0] === '%') { try { decodedText += decodeURIComponent(encodedText.substring(0, 3)) - encodedText = encodedText.substring(3, encodedText.length) + encodedText = encodedText.substring(3, encodedText.length) } catch (exception) { decodedText += encodedText[0] encodedText = encodedText.substring(1, encodedText.length) @@ -66,7 +66,7 @@ exports.slackText = function(encodedText) { * @param {String} input String of commands * @return {Array} Array of tokens, including commands, arguments, switches, resources, etc. */ -function commands (tokens, input) { + exports.commands = function commands (tokens, input) { var commandId = ''; if (typeof tokens === 'string') { input = tokens; @@ -89,7 +89,7 @@ function commands (tokens, input) { } else if (quotes === 'single') { boundary = true; quotes = ''; - } + } break; case '"': @@ -98,7 +98,7 @@ function commands (tokens, input) { } else if (quotes === 'double') { boundary = true; quotes = ''; - } + } break; case '\\': @@ -135,7 +135,7 @@ function commands (tokens, input) { if (tokens.length === 0) state = 'command'; else if(tokens[tokens.length - 1].value === '>') state = 'resource'; else state = 'command'; - } + } break; } @@ -152,7 +152,7 @@ function commands (tokens, input) { index++; } return normalize(tokens); -} +}; function normalize (commands) { var normalizedCommands = []; @@ -176,7 +176,7 @@ function normalize (commands) { pipe: false, redirectTo: [] }; - + normalizedCommands.push(command); thisCommand = _.find(normalizedCommands, {id: token.id}); break; @@ -203,7 +203,7 @@ function normalize (commands) { case 'resource': if (resourceTypes[token.value.substring(0,1)]) thisCommand.redirectTo.push({type: resourceTypes[token.value.substring(0,1)] , name: token.value.substring(1)}); - else + else thisCommand.redirectTo.push({type: 'file' , name: token.value}); break; @@ -216,7 +216,7 @@ function normalize (commands) { return normalizedCommands; } -/** +/** * Creates a parsing Error and associated formatted message * @param {String} error Error message to be displayed to the user * @param {String} input String that was to be parsed when the error was thrown @@ -238,5 +238,3 @@ function throwParseError (error, input, index) { throw new Error(errorText); } - -exports.commands = commands; From f01d93125f70778e0f9331c3e1871483e8efde85 Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:26:09 -0500 Subject: [PATCH 04/46] Pass arguments on to node --- Slacker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Slacker b/Slacker index aaac5aa..b42bd95 100755 --- a/Slacker +++ b/Slacker @@ -6,4 +6,4 @@ rm -rf logs/*.log clear -node master.js +node master.js $1 $2 $3 $4 $5 $6 $7 $8 $9 From 50141627d643ea64b9d5ab07085ffda99e9fe83a Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:26:40 -0500 Subject: [PATCH 05/46] Updates help action --- actions/help.js | 50 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/actions/help.js b/actions/help.js index 692bad5..c89c85c 100644 --- a/actions/help.js +++ b/actions/help.js @@ -1,37 +1,57 @@ var bot = require(__dirname + '/../bot.js') var fs = require('fs') +var _ = require('lodash'); var action = { name: 'help', - trigger: /^help.*/, - description: 'Display information on how to user Slacker.', helpText: 'help.md has not loaded yet, try again.', setup: function() { fs.readFile(__dirname + '/../action_data/help.md', function(error, data) { - if (error) - throw error + if (error) { + throw error; + } - action.helpText = data.toString() + action.helpText = data.toString(); }) }, execute: function(data, callback) { - var components = data.text.split(' ') - - if (components.length === 1) - callback(this.helpText) - - for (var x = 0; x < bot.actions.length; x++) - if (bot.actions[x].name === components[1]) - callback(bot.actions[x].trigger) + var args, action, helpText, helpTitle; + + args = data.command.arguments; + helpText = ''; + helpTitle = ''; + + if (args.length === 0) { + + helpTitle = this.name; + helpText = this.helpText; + } else if (args.length >= 1) { + action = _.find(bot.actions, {name: data.command.arguments[0]}); + helpTitle = args[0]; + + if (!action) { + console.log('No action.'); + helpText = 'Command, `' + args[0] + '`, not found. Did you mistype it?'; + } else if (!action.helpText && !action.description) { + helpText = 'No help information found.'; + } else if (!action.helpText && action.description) { + helpText = action.description; + } else if (typeof action.helpText === 'string') { + helpText = action.helpText; + } else if (typeof action.helpText === 'function') { + helpText = action.helpText(); + } + } + + callback('*' + helpTitle.toUpperCase() + '*\n' + helpText.replace(/^/g, '> ')); - callback('Action "' + components[1] + '" not found.') } } -bot.addAction(action) +bot.addAction(action); From f9918eefcd9409779366d6d025ec2cec570783a5 Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:28:08 -0500 Subject: [PATCH 06/46] Trims unnecessary code. --- actions/list.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/actions/list.js b/actions/list.js index 16e03c8..b9e1272 100644 --- a/actions/list.js +++ b/actions/list.js @@ -3,8 +3,6 @@ var bot = require(__dirname + '/../bot.js') var action = { name: 'list', - trigger: /^list$/, - description: 'List all availble actions.', execute: function(data, callback) { @@ -14,6 +12,6 @@ var action = { callback(output) } -} +}; -bot.addAction(action) +bot.addAction(action); From fd5faf7e73a8484675bc12b3e84e791d3bb6f1a1 Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:38:51 -0500 Subject: [PATCH 07/46] Improves format of multi-line help. --- actions/help.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/help.js b/actions/help.js index c89c85c..61e5300 100644 --- a/actions/help.js +++ b/actions/help.js @@ -49,7 +49,7 @@ var action = { } } - callback('*' + helpTitle.toUpperCase() + '*\n' + helpText.replace(/^/g, '> ')); + callback('*' + helpTitle.toUpperCase() + '*\n' + '> ' + helpText.replace(/\n/g, '\n> ')); } } From 086da19c58b8ac7e732af1c9f7a428588a37e710 Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:39:33 -0500 Subject: [PATCH 08/46] Removes unnecessary code and adds helpText. --- actions/talky.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/actions/talky.js b/actions/talky.js index ddea747..9a86516 100644 --- a/actions/talky.js +++ b/actions/talky.js @@ -5,10 +5,16 @@ var id = require('../library/id.js'); var action = { name: 'talky', - trigger: /^talky\s*(['"]?)(.*?)(\1)$/, - description: 'Create a talky room for video conferencing and video chatting.', + helpText: '' + + 'Create a talky room for video conferencing and video chatting.\n\n' + + + '`/slacker talky [room_name]`\n\n' + + + 'If the optional `room_name` is inlcuded, then it will be used in the form of `http://talky.io/room_name`. If not a random one will be chosen.' + , + execute: function(data, callback) { var match = data.text.match(this.trigger); var room = (match && match[1]) ? encodeURI(data.text.replace(this.trigger, '$2')) : id(); @@ -18,7 +24,7 @@ var action = { text: 'Join the conference: .' }; - // Once bot supports formatted responses, replace the following with `callback(payload);` + // TODO: Once bot supports formatted responses, replace the following with `callback(payload);` callback(payload.text); } }; From 0c41c847e53bf372235523fd0afc105706eb93b4 Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:44:41 -0500 Subject: [PATCH 09/46] Improves help formatting. --- actions/talky.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/talky.js b/actions/talky.js index 9a86516..724088d 100644 --- a/actions/talky.js +++ b/actions/talky.js @@ -8,10 +8,10 @@ var action = { description: 'Create a talky room for video conferencing and video chatting.', helpText: '' + - 'Create a talky room for video conferencing and video chatting.\n\n' + - - '`/slacker talky [room_name]`\n\n' + - + 'Create a talky room for video conferencing and video chatting.\n' + + '```' + + '/slacker talky [room_name]' + + '```\n' + 'If the optional `room_name` is inlcuded, then it will be used in the form of `http://talky.io/room_name`. If not a random one will be chosen.' , From 843ffcdd184ca32d49c9688eb6303bd57fbd64fc Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:49:53 -0500 Subject: [PATCH 10/46] Adds help text for gif action. --- actions/gif.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/actions/gif.js b/actions/gif.js index fb81d10..55242b7 100644 --- a/actions/gif.js +++ b/actions/gif.js @@ -6,9 +6,15 @@ var https = require('https') var action = { name: 'gif', - trigger: /^gif ".*"$/, + description: 'Displays animated GIFs from Giphy.', - description: 'Display a random GIF from Giphy.', + helpText: '' + + 'Displays animated GIFs from Giphy.\n' + + '```' + + '/slacker gif [tag] [...]' + + '```\n' + + 'If no tag is supplied, then `gif` will return a completely random gif. If one or more tags are provided, `gif` will return a random result from a search for all of the tags on Giphy.' + , apiKey: 'dc6zaTOxFJmzC', From a28db5f9de88193373ff9bc78e8149e496627ee3 Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:50:44 -0500 Subject: [PATCH 11/46] Tweaks output format. --- actions/btc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/btc.js b/actions/btc.js index 1ae189b..b4f96ec 100644 --- a/actions/btc.js +++ b/actions/btc.js @@ -21,7 +21,7 @@ var action = { }); response.on('end', function() { try { - callback(JSON.parse(responseText).ask + ' USD'); + callback('1 BTC = ' + JSON.parse(responseText).ask + ' USD'); } catch (exception) { throw exception; } From 87aedbdcc76dc96a93f034ebb6a8b2a47b86c295 Mon Sep 17 00:00:00 2001 From: Ustice Date: Wed, 17 Dec 2014 23:50:59 -0500 Subject: [PATCH 12/46] Title for help text is now included in the action. --- action_data/help.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/action_data/help.md b/action_data/help.md index 297eeb3..45250f5 100644 --- a/action_data/help.md +++ b/action_data/help.md @@ -1,3 +1 @@ -*Help* - -Try `list` to see available actions, or try `help action` for help with a specific action. +Try `list` to see available actions, or try `help ` for help with a specific action. From f18386d76fcab28b29b4a59c552aa17dcefb6e2d Mon Sep 17 00:00:00 2001 From: Ustice Date: Thu, 18 Dec 2014 00:30:18 -0500 Subject: [PATCH 13/46] Add support for Heroku --- master.js | 2 +- worker.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/master.js b/master.js index ca3da7e..e3e5729 100644 --- a/master.js +++ b/master.js @@ -14,7 +14,7 @@ if (cluster.isMaster) { } log.info('application started') - console.log('application started on port:', config.port) + console.log('application started on port:', process.env.PORT || config.port) var cores = os.cpus().length for (var x = 0; x < cores; x++) diff --git a/worker.js b/worker.js index a718988..8187af5 100644 --- a/worker.js +++ b/worker.js @@ -114,9 +114,9 @@ module.exports = function() { }) }) }) - - server.listen(config.port, function() { - log.info('listening on port ' + config.port) + + server.listen(process.env.PORT || config.port, function() { + log.info('listening on port ' + process.env.PORT || config.port) }) }) } From 45c1f582e5ab026c340a2cd821ef61485231bfc6 Mon Sep 17 00:00:00 2001 From: Ustice Date: Thu, 18 Dec 2014 00:30:34 -0500 Subject: [PATCH 14/46] Remove dead code. --- bot.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bot.js b/bot.js index cce1ace..262ee4f 100644 --- a/bot.js +++ b/bot.js @@ -5,18 +5,12 @@ var _ = require('lodash'); var fs = require('fs'); var https = require('https'); var querystring = require('querystring'); -var Slack = require('slack-node'); // Libraries var config = require(__dirname + '/config.json'); var log = require(__dirname + '/library/log.js'); var parse = require(__dirname + '/library/parse.js'); -var slack = { - webhook: new Slack(config.token.webhook, config.domain), - api: new Slack(config.token.api) -}; - exports.actions = []; exports.setup = function setup (callback) { From 6503c56c5f19a0bdf7885397a76ad503383d89b7 Mon Sep 17 00:00:00 2001 From: Ustice Date: Thu, 18 Dec 2014 00:30:56 -0500 Subject: [PATCH 15/46] Rename config.token elements to be more clear. --- bot.js | 2 +- worker.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.js b/bot.js index 262ee4f..ca13faf 100644 --- a/bot.js +++ b/bot.js @@ -215,7 +215,7 @@ exports.addAction = function (action) { exports.sendMessage = function (message, channel, callback) { callback = callback || function () {}; var messageData = { - token: config.token.robot, + token: config.token.bot, channel: channel, text: message }; diff --git a/worker.js b/worker.js index 8187af5..672c542 100644 --- a/worker.js +++ b/worker.js @@ -88,7 +88,7 @@ module.exports = function() { if (request.body.token) { if ( (request.body.trigger_word && request.body.token === config.token.webhook ) || - (request.body.command && request.body.token === config.token.api) + (request.body.command && request.body.token === config.token.slashCommand) ) router(request, response) else { From ead1c9a5c12cb280a77f8c2f4e35fe73a6a60010 Mon Sep 17 00:00:00 2001 From: Ustice Date: Thu, 18 Dec 2014 01:10:31 -0500 Subject: [PATCH 16/46] Removes the need for keys, adds sample config The Slash Command token takes care of the authentication. --- sample-config.json | 9 ++++++++ worker.js | 56 +++++++++++++++++----------------------------- 2 files changed, 29 insertions(+), 36 deletions(-) create mode 100644 sample-config.json diff --git a/sample-config.json b/sample-config.json new file mode 100644 index 0000000..d9fb106 --- /dev/null +++ b/sample-config.json @@ -0,0 +1,9 @@ +{ + "port": 80, + "logs": "logs", + "token": { + "slashCommand": "[Enter your Slash Command token here.]", + "bot": "[Enter your Bot token here.]" + }, + "timeout": 8000 +} diff --git a/worker.js b/worker.js index 672c542..331f095 100644 --- a/worker.js +++ b/worker.js @@ -69,46 +69,30 @@ module.exports = function() { log.info('headers', request.headers, request.id) - var key = request.url.parameters.key; - if (key) { - if (~config.keys.indexOf(key)) { - if (request.body) { - try { - request.body = parse.httpParameters(request.body) - log.info('body', request.body, request.id) - } catch (exception) { - log.error('failed to parse request body', exception, request.id) - response.statusCode = 415 - response.end() - return - } - } - request.data = {} - - if (request.body.token) { - if ( - (request.body.trigger_word && request.body.token === config.token.webhook ) || - (request.body.command && request.body.token === config.token.slashCommand) - ) - router(request, response) - else { - log.error('invalid token', request.body.token, request.id) - response.statusCode = 403 - response.end() - } - } else { - log.error('missing token', {}, request.id) - response.statusCode = 403 - response.end() - } + if (request.body) { + try { + request.body = parse.httpParameters(request.body) + log.info('body', request.body, request.id) + } catch (exception) { + log.error('failed to parse request body', exception, request.id) + response.statusCode = 415 + response.end() + return + } + } + request.data = {} + + if (request.body.token) { + if (request.body.command && request.body.token === config.token.slashCommand) { + router(request, response); } else { - log.error('invalid key', key, request.id) - response.statusCode = 401 + log.error('invalid token', request.body.token, request.id) + response.statusCode = 403 response.end() } } else { - log.error('missing key', {}, request.id) - response.statusCode = 401 + log.error('missing token', {}, request.id) + response.statusCode = 403 response.end() } }) From 1599fd41114377c1bdeb9b70883638f10257b4bc Mon Sep 17 00:00:00 2001 From: Ustice Date: Thu, 18 Dec 2014 01:48:21 -0500 Subject: [PATCH 17/46] Updates documentation. --- README.md | 141 +++++++++++++++++++++++++++++++++++++----------- actions/echo.js | 13 +++-- 2 files changed, 120 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 928ad46..0d468a9 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,16 @@ .d8888b. 888 888 d88P Y88b 888 888 Y88b. 888 888 - "Y888b. 888 d888b. .d8888b 888 .888 .d88b. 888d88b + "Y888b. 888 d888b. .d8888b 888 .888 .d88b. 888d88b "Y88b. 888 "88b d88P" 888 .88P d8P Y8b 888P" - "888 888 .d888888 888 888888K 88888888 888 + "888 888 .d888888 888 888888K 88888888 888 Y88b d88P 888 888 888 Y88b. 888 "88b Y8b. 888 "Y8888P" 888 "Y888888 "Y8888P 888 .888 "Y888P 888 ```` ### Slacker is a bot for [Slack](https://slack.com) built on the Node.js platform. - Slacker processes Slack WebHook requests and executes pre-defined actions before responding to Slack. It deals with the networking aspects of your bot so you can focus on functionality. + Slacker processes Slack Slash Command requests and executes pre-defined actions before responding to Slack. It deals with the networking aspects of your bot so you can focus on functionality. ## Setup @@ -25,25 +25,92 @@ 3. Set Slack Integrations. - * Create a Outgoing WebHook in Slack and point it to your instance of Slacker. + * Create a Slash Command integration in Slack and point it to your instance of Slacker. * Slacker expects to receive requests directly to the server's root URL. - * Be sure to include a valid `key` URL parameter on your outgoing-webhook URL when you set it in Slack. + * Be sure to note the token for this Slash Command, as you will need it for the configuration file. - * Create an Incoming WebHook in Slack. + * Create an Bot integration in Slack. - * Be sure to update `hostname` and `path` in `config.json` in match your incoming-webhook. + 4. Create a `config.json` file. Note that a `sample-config.json` is included in this package. You can simply copy this, and replace the two token values with the tokens that you noted above. - 4. Start Slacker. + ````json + { + "port": 80, + "logs": "logs", + "token": { + "slashCommand": "[Enter your Slash Command token here.]", + "bot": "[Enter your Bot token here.]" + }, + "timeout": 8000 + } + ```` + + 5. Start Slacker. + + ```` + ➜ ~ sh Slacker + ```` +## Using Slacker + + Slacker uses a command-line-like syntax. To interact with Slacker, use the Slash Command that you previously set up. For demonstration purposes, we'll assume that you named it `/slacker`. + + One of the most basic uses of Slacker is to get a list of commands. To do this, on an empty input line in Slack, type + + ```` + ➜ /slacker list + ```` + + Assuming that everything is set up correctly, you should now see a list of commands. Note that these are returned to you through Slackbot, which only you can see. + + Another useful action is __help__. If you wanted to learn how to use the `gif` action, for instance, you could use the following command. + + ```` + ➜ /slacker help gif + ```` + + This time, we sent 'gif' as an argument for __help__. Beware that different actions may use arguments differently, so pay attention to their help. If you want to send multiple words as single argument, simply wrap them in quotes like so. ```` - ➜ ~ sh Slacker + ➜ /slacker gif "Homer Simpson" ```` + Alternately, you can escape a space like so. + + ```` + ➜ /slacker gif Peter/ Griffin + ```` + + If you want to pass in quotes as part of an argument, you can escape them as well. + + ```` + ➜ /slacker echo "The worm looked up at me and said, \"I'd like to poison your mind.\"" + ```` + + You can also redirect where the output goes through the use of the `>` character, which is often used to redirect output on a terminal to a file. Valid targets include rooms, + + ```` + ➜ /slacker gif daily kitten > #general + ```` + + and users. + + ```` + ➜ /slacker btc > @stewie_griffin + ```` + + One of the more powerful features of Slacker is the user of pipes (`|`), where you can pipe the output of one action into the input of the next. + + ```` + ➜ /slacker btc | echo + ```` + + (Yes, I know that example is lame, but our actions catalogue is a bit light at the moment.) + ## Actions - Actions are script files located in the `actions/` directory. When Slacker receives a request from Slack it will check for and execute the appropriate action. Actions receive a `data` object with relevant information about the request from Slack, process the data and then return a response string. Slacker facilitates the response process. + Actions are script files located in the `actions/` directory. When Slacker receives a request from Slack it will check for and execute the appropriate action. Actions receive a `data` object with relevant information about the request from Slack and the command that triggered it, process the data and then return a response string. Slacker facilitates the response process. ### Creating an Action @@ -57,36 +124,38 @@ ### A Sample Action - ```` - var bot = require(__dirname + '/../bot.js') + ````javascript + // Loads all of the bot functionality. + var bot = require(__dirname + '/../bot.js'); var action = { + // This is the string that will name: 'echo', - trigger: /^echo \".*\"$/, - + // Used for the `list` action. description: 'Echo a string to Slack.', + // Used for the `help` action. + helpText: 'Echo a string to Slack.', + setup: function() { // This method will be run at server start up. }, execute: function(data, callback) { - callback(data.text.split('\"')[1]) + // If piped data is provided, send that, otherwise send any text passed in. + callback( data.pipedResponse || data.command.arguments.join(' ') ); } - } + }; - bot.addAction(action) + // Adds this action to the action list. + bot.addAction(action); ```` #### Name The `name` attribute defines your action. It is used by the __help__ and __list__ actions to inform users about your action. `name` attributes must be unique; Slacker will ignore actions if their `name` has already been defined by another action. This attribute is required on all actions. -#### Trigger - - Your action's `trigger` attribute is a regular expression which defines when it will be exectued. If a Slack user activates your bot and his message text matches your action's `trigger` then Slacker will perform your action. `trigger` attributes should be unique; Slacker will ignore actions if their `trigger` attributes have already been defined by another action. This attribute is required on all actions. - #### Description The `description` attribute is a string used to describe your action when a user triggers the __list__ action. This attribute is required on all actions. @@ -101,16 +170,26 @@ ##### The `data` Object - ```` - var data = { - team_id: 'T028JNZFM', - team_domain: 'mobdev', - channel_id: 'C02DCNQRN', - channel_name: 'slacker-testing', - timestamp: '1405215092.000210', - user_id: 'U02A1R3PM', - user_name: 'chris_young', - text: 'echo foo' + ````javascript + data === { + "channel_id": "D02DVPT67", + "channel_name": "directmessage", + "team_domain": "ustice", + "team_id": "T02DVPT63", + "text": "echo \"This is a test of the Emergency Broadcast System.\"", + "user_id": "U02DVPT65", + "user_name": "ustice", + "command": { + "name": "echo", + "id": "A230317A-82C7-4FA5-91A8-92DFEFB49C06", + "arguments": [ + "This is a test of the Emergency Broadcast System." + ], + "switches": [], + "pipe": false, + "redirectTo": [] + }, + "pipedResponse": null } ```` diff --git a/actions/echo.js b/actions/echo.js index 49131c2..2790c42 100644 --- a/actions/echo.js +++ b/actions/echo.js @@ -1,19 +1,26 @@ +// Loads all of the bot functionality. var bot = require(__dirname + '/../bot.js'); var action = { + // This is the string that will name: 'echo', - trigger: /^echo \".*\"$/, - + // Used for the `list` action. description: 'Echo a string to Slack.', + // Used for the `help` action. + helpText: 'Echo a string to Slack.', + setup: function() { // This method will be run at server start up. }, execute: function(data, callback) { - callback( data.pipedResponse || data.command.arguments.join(' ') ); + console.log(JSON.stringify(data, null, ' ')); + // If piped data is provided, send that, otherwise send any text passed in. + callback( data.pipedResponse || data.command.arguments.join(' ') ); } }; +// Adds this action to the action list. bot.addAction(action); From ada7685cc28f91ee4043782be904028d7e2c0f98 Mon Sep 17 00:00:00 2001 From: Ustice Date: Thu, 18 Dec 2014 03:06:25 -0500 Subject: [PATCH 18/46] Updates documentation with user not bot --- README.md | 4 ++-- bot.js | 2 +- sample-config.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0d468a9..3de334e 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ * Be sure to note the token for this Slash Command, as you will need it for the configuration file. - * Create an Bot integration in Slack. + * Get your admin user token. The easiest way is to use the (API explorer)[https://api.slack.com/methods/emoji.list/test], and grab it off the url. 4. Create a `config.json` file. Note that a `sample-config.json` is included in this package. You can simply copy this, and replace the two token values with the tokens that you noted above. @@ -41,7 +41,7 @@ "logs": "logs", "token": { "slashCommand": "[Enter your Slash Command token here.]", - "bot": "[Enter your Bot token here.]" + "user": "[Enter your User token here.]" }, "timeout": 8000 } diff --git a/bot.js b/bot.js index ca13faf..00ba71f 100644 --- a/bot.js +++ b/bot.js @@ -215,7 +215,7 @@ exports.addAction = function (action) { exports.sendMessage = function (message, channel, callback) { callback = callback || function () {}; var messageData = { - token: config.token.bot, + token: config.token.user, channel: channel, text: message }; diff --git a/sample-config.json b/sample-config.json index d9fb106..ef94d9b 100644 --- a/sample-config.json +++ b/sample-config.json @@ -3,7 +3,7 @@ "logs": "logs", "token": { "slashCommand": "[Enter your Slash Command token here.]", - "bot": "[Enter your Bot token here.]" + "user": "[Enter your User token here.]" }, "timeout": 8000 } From 40a0bd7fb89c2d7fb2f19544d90c6de1b7fb24bb Mon Sep 17 00:00:00 2001 From: Ustice Date: Thu, 18 Dec 2014 03:07:46 -0500 Subject: [PATCH 19/46] Allows users to end commands with > Outputs to current room. --- bot.js | 8 +++++++- library/parse.js | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/bot.js b/bot.js index 00ba71f..53d41a4 100644 --- a/bot.js +++ b/bot.js @@ -152,6 +152,11 @@ exports.processRequest = function processRequest (request, response) { pipedResponse = null; } + // User is ending their command with the `>`. Assume current room. + if (command.redirects && !command.redirectTo.length) { + command.redirectTo.push({ type: 'channel', name: request.body.channel_name }); + } + // If the response should be redirected, then do so if (command.redirectTo.length > 0) { _.each(command.redirectTo, function (redirect) { @@ -220,7 +225,8 @@ exports.sendMessage = function (message, channel, callback) { text: message }; - https.get('https://slack.com/api/chat.postMessage?' + querystring.stringify(messageData), function (response) { + var url = 'https://slack.com/api/chat.postMessage?' + querystring.stringify(messageData); + https.get(url, function (response) { response.on('end', function () { callback(response.error, response); }); diff --git a/library/parse.js b/library/parse.js index ab3fc11..3b3307c 100644 --- a/library/parse.js +++ b/library/parse.js @@ -174,6 +174,7 @@ function normalize (commands) { arguments: [], switches: [], pipe: false, + redirects: false, redirectTo: [] }; @@ -198,6 +199,7 @@ function normalize (commands) { case 'operator': if (token.value === '|') thisCommand.pipe = true; + if (token.value === '>') thisCommand.redirects = true; break; case 'resource': From f560db5deac0a8bd6f91779da9108ee883e9e889 Mon Sep 17 00:00:00 2001 From: Ustice Date: Thu, 18 Dec 2014 03:08:00 -0500 Subject: [PATCH 20/46] Fixes youtube --- actions/youtube.js | 67 +++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/actions/youtube.js b/actions/youtube.js index 7efa76f..13e95e4 100644 --- a/actions/youtube.js +++ b/actions/youtube.js @@ -5,48 +5,47 @@ var https = require('https'); var action = { name: "youtube", - trigger: /^youtube ".*"$/, - description: "Display a random YouTube video similar to the way the 'gif' command does.", api_key: "AIzaSyAHD4juIcaWTRC-sDhspzbPYh-GQ5BXkbs", execute: function(data, callback) { - - var query_param = data.text.substring(data.text.indexOf('\"') + 1, data.text.length - 1).replace(/ /g,"+"); - - var options = { - hostname: "www.googleapis.com", - path : "/youtube/v3/search?part=snippet&q=" + query_param + "&key=" + this.api_key, - port: 443, - method: "GET" - }; - - var request = https.request(options, function(response) { - var responseText = ""; - response.on("data", function(data) { - responseText += data.toString(); - }); - response.on("end", function() { - var videoArray = JSON.parse(responseText).items; - if (videoArray.length > 0) { - var random_int = Math.floor(Math.random() * videoArray.length); - var videoID = videoArray[random_int].id.videoId; - var videoURL = "http://www.youtube.com/watch?v=" + videoID; - callback(videoURL); - } - else { - callback("No Videos Today :disappointed:"); - } - }); + var input = data.pipedResponse || data.command.arguments.join(' '); + var query_param = input.replace(/ /g,"+"); + + var options = { + hostname: "www.googleapis.com", + path : "/youtube/v3/search?part=snippet&q=" + query_param + "&key=" + this.api_key, + port: 443, + method: "GET" + }; + + var request = https.request(options, function(response) { + var responseText = ""; + response.on("data", function(data) { + responseText += data.toString(); }); - - request.on("error", function(error) { - callback("Something wasn't right. :disappointed:"); - throw error; + response.on("end", function() { + var videoArray = JSON.parse(responseText).items; + if (videoArray.length > 0) { + var random_int = Math.floor(Math.random() * videoArray.length); + var videoID = videoArray[random_int].id.videoId; + var videoURL = "http://www.youtube.com/watch?v=" + videoID; + + callback(videoURL); + } + else { + callback("No Videos Today :disappointed:"); + } }); + }); + + request.on("error", function(error) { + callback("Something wasn't right. :disappointed:"); + throw error; + }); - request.end(); + request.end(); } }; From d738d6d61a070bfdc0105c651099de045fbfe15b Mon Sep 17 00:00:00 2001 From: Ustice Date: Thu, 18 Dec 2014 03:08:08 -0500 Subject: [PATCH 21/46] Remove console log --- actions/echo.js | 1 - 1 file changed, 1 deletion(-) diff --git a/actions/echo.js b/actions/echo.js index 2790c42..ac8cbfd 100644 --- a/actions/echo.js +++ b/actions/echo.js @@ -16,7 +16,6 @@ var action = { }, execute: function(data, callback) { - console.log(JSON.stringify(data, null, ' ')); // If piped data is provided, send that, otherwise send any text passed in. callback( data.pipedResponse || data.command.arguments.join(' ') ); } From 539e84e6b65397279452174214342fdb0f55789f Mon Sep 17 00:00:00 2001 From: Ustice Date: Fri, 19 Dec 2014 13:15:25 -0500 Subject: [PATCH 22/46] Adds npm start script --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index 5a8cb78..bd7e445 100644 --- a/package.json +++ b/package.json @@ -34,5 +34,8 @@ }, "devDependencies": { "mocha": "~1.20.1" + }, + "scripts": { + "start": "./Slacker" } } From 3f9ab580fd85bbd91b5a466c05a6e8cbc304b088 Mon Sep 17 00:00:00 2001 From: Ustice Date: Fri, 19 Dec 2014 13:26:07 -0500 Subject: [PATCH 23/46] Adds default confirmation response. --- worker.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/worker.js b/worker.js index 331f095..e2d525f 100644 --- a/worker.js +++ b/worker.js @@ -79,6 +79,8 @@ module.exports = function() { response.end() return } + } else if(request.method.toLowerCase() === 'get') { + response.end('Slacker is running.'); } request.data = {} From 1a4fe0302204402356f411627d4c1f2636498148 Mon Sep 17 00:00:00 2001 From: Ustice Date: Fri, 19 Dec 2014 13:39:34 -0500 Subject: [PATCH 24/46] Sets node to start directly for Heroku --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bd7e445..2ab09ad 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,6 @@ "mocha": "~1.20.1" }, "scripts": { - "start": "./Slacker" + "start": "node master.js" } } From 6a49f604114212e0fd88e0dd0c57b5decb8a20d6 Mon Sep 17 00:00:00 2001 From: Ustice Date: Fri, 19 Dec 2014 13:42:50 -0500 Subject: [PATCH 25/46] Adds Heroku Procfile --- Procfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 Procfile diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..063b78f --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: npm start From c6ba803c500f43abdf37d5b96d8684159a8e88a0 Mon Sep 17 00:00:00 2001 From: Ustice Date: Fri, 19 Dec 2014 13:46:46 -0500 Subject: [PATCH 26/46] Update Procfile --- Procfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Procfile b/Procfile index 063b78f..1b1cdf7 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: npm start +web: node master.js From 2896fd35dbf66ae18630d54b1a6c66ddebac46ea Mon Sep 17 00:00:00 2001 From: Ustice Date: Fri, 19 Dec 2014 13:51:54 -0500 Subject: [PATCH 27/46] Adds install script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ab09ad..1e2cbf8 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "mocha": "~1.20.1" }, "scripts": { - "start": "node master.js" + "start": "node master.js", + "install": "npm install" } } From 7f35e02e83629380e9af0ac397438207a299b1f3 Mon Sep 17 00:00:00 2001 From: Ustice Date: Fri, 19 Dec 2014 13:54:38 -0500 Subject: [PATCH 28/46] Oops, that was a bad idea... --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 1e2cbf8..2ab09ad 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "mocha": "~1.20.1" }, "scripts": { - "start": "node master.js", - "install": "npm install" + "start": "node master.js" } } From 5a7f1b5c8ff1d9c2e3c806cfc2c0415f2afb4333 Mon Sep 17 00:00:00 2001 From: Ustice Date: Fri, 19 Dec 2014 15:47:24 -0500 Subject: [PATCH 29/46] Adds Heroku-compatible configuration --- bot.js | 2 +- library/config.js | 22 ++++++++++++++++++++++ library/log.js | 2 +- master.js | 2 +- worker.js | 2 +- 5 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 library/config.js diff --git a/bot.js b/bot.js index 53d41a4..633d43e 100644 --- a/bot.js +++ b/bot.js @@ -7,7 +7,7 @@ var https = require('https'); var querystring = require('querystring'); // Libraries -var config = require(__dirname + '/config.json'); +var config = require(__dirname + '/library/config'); var log = require(__dirname + '/library/log.js'); var parse = require(__dirname + '/library/parse.js'); diff --git a/library/config.js b/library/config.js new file mode 100644 index 0000000..7784015 --- /dev/null +++ b/library/config.js @@ -0,0 +1,22 @@ +"use strict"; + +var fs = require('fs'); +var config; + +var configExists = fs.existsSync(__dirname + '/../config.json'); + +if (!configExists) { + config = { + "port": 8421, + "logs": "logs", + "token": { + "slashCommand": process.env.TOKEN_SLASH_COMMAND, + "user": process.env.USER + }, + "timeout": 8000 + }; +} else { + config = require(__dirname + '/../config.json'); +} + +module.exports = config; diff --git a/library/log.js b/library/log.js index 8a56f38..4835fd0 100644 --- a/library/log.js +++ b/library/log.js @@ -1,7 +1,7 @@ var cluster = require('cluster') var fs = require('fs') -var config = require(__dirname + '/../config.json') +var config = require(__dirname + '/config') function format(type, message, data, id) { var speaker = cluster.isMaster ? 'master' : 'worker' + process.pid diff --git a/master.js b/master.js index e3e5729..05bf903 100644 --- a/master.js +++ b/master.js @@ -1,7 +1,7 @@ var cluster = require('cluster') var os = require('os') -var config = require(__dirname + '/config.json') +var config = require(__dirname + '/library/config') var worker = require(__dirname + '/worker.js') var log = require(__dirname + '/library/log.js') diff --git a/worker.js b/worker.js index e2d525f..7aed061 100644 --- a/worker.js +++ b/worker.js @@ -3,7 +3,7 @@ var http = require('http') var domain = require('domain') var url = require('url') -var config = require(__dirname + '/config.json') +var config = require(__dirname + '/library/config') var router = require(__dirname + '/router.js') var bot = require(__dirname + '/bot.js') From 4b871138a863619a400091d65b5e811c669aaf1d Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 01:56:22 -0500 Subject: [PATCH 30/46] Logs errors to the console for better debugging --- worker.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/worker.js b/worker.js index 7aed061..45f5f14 100644 --- a/worker.js +++ b/worker.js @@ -26,6 +26,7 @@ module.exports = function() { serverDomain.on('error', function(error) { log.error('uncaught exception', error, response.id) + console.error(error.stack); try { var kill = setTimeout(function() { @@ -39,6 +40,7 @@ module.exports = function() { response.end() } catch (exception) { log.error('failed to respond after uncaught exception', exception, response.id) + console.error(exception.stack); } }) @@ -48,6 +50,7 @@ module.exports = function() { request.on('error', function(error) { log.error('request error', error, request.id) + console.error(error); response.statusCode = 500 response.end() From 16a7357e9feb9042d8d5a9d624ee8885739779d5 Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 01:56:37 -0500 Subject: [PATCH 31/46] No double stringifying --- library/log.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/log.js b/library/log.js index 4835fd0..5b410a8 100644 --- a/library/log.js +++ b/library/log.js @@ -25,7 +25,7 @@ function format(type, message, data, id) { stringifiedData = JSON.stringify(dataObject); } - return JSON.stringify(stringifiedData) + return stringifiedData } function writeToFile(fileName, dataString) { From 71e0bd2ba7e7721851f301f4b5b74793f6ba9479 Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 01:57:02 -0500 Subject: [PATCH 32/46] BTC action was failing. fixed. --- actions/btc.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/actions/btc.js b/actions/btc.js index b4f96ec..e1553ff 100644 --- a/actions/btc.js +++ b/actions/btc.js @@ -26,11 +26,13 @@ var action = { throw exception; } }); - }).end(); + }); request.on('error', function(error) { throw error; }); + + request.end(); } }; From e8e3cd34184ae081fc3535550d93d61b62e7e7e0 Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 02:09:21 -0500 Subject: [PATCH 33/46] Log redirects. --- bot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/bot.js b/bot.js index 633d43e..8c907b4 100644 --- a/bot.js +++ b/bot.js @@ -160,6 +160,7 @@ exports.processRequest = function processRequest (request, response) { // If the response should be redirected, then do so if (command.redirectTo.length > 0) { _.each(command.redirectTo, function (redirect) { + console.log('Redirecting to: ', redirect.name); switch (redirect.type) { case 'user': exports.sendMessage(responseText, '@' + redirect.name); From db5bd615824c4759c8a91f17c789ae5b02cc75aa Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 02:16:51 -0500 Subject: [PATCH 34/46] Debugging --- router.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/router.js b/router.js index b78a1c4..c7f3a9f 100644 --- a/router.js +++ b/router.js @@ -3,6 +3,7 @@ var log = require(__dirname + '/library/log.js') var bot = require(__dirname + '/bot.js') function route(request, response) { + console.log(request.method + ' ' + JSON.stringify(request.body, null, ' ')); if (request.method === 'POST') bot.processRequest(request, response) else { @@ -25,7 +26,7 @@ module.exports = function(request, response) { default: response.statusCode = 404 response.end() - + log.error('resource not found', request.url.pathname, request.id) } } From b23d356232acdf025b18719a04f76689cdbb928e Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 02:22:00 -0500 Subject: [PATCH 35/46] Debugging --- bot.js | 2 ++ router.js | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bot.js b/bot.js index 8c907b4..d4e2248 100644 --- a/bot.js +++ b/bot.js @@ -226,9 +226,11 @@ exports.sendMessage = function (message, channel, callback) { text: message }; + console.log('Sending message: ', JSON.stringify(messageData)); var url = 'https://slack.com/api/chat.postMessage?' + querystring.stringify(messageData); https.get(url, function (response) { response.on('end', function () { + console.log('Message sent'); callback(response.error, response); }); }).end(); diff --git a/router.js b/router.js index c7f3a9f..a0702bb 100644 --- a/router.js +++ b/router.js @@ -3,7 +3,6 @@ var log = require(__dirname + '/library/log.js') var bot = require(__dirname + '/bot.js') function route(request, response) { - console.log(request.method + ' ' + JSON.stringify(request.body, null, ' ')); if (request.method === 'POST') bot.processRequest(request, response) else { From 7c67cdbdc0c4280c3aba214b332e26d1199d556e Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 02:24:34 -0500 Subject: [PATCH 36/46] Debugging --- bot.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bot.js b/bot.js index d4e2248..b62a572 100644 --- a/bot.js +++ b/bot.js @@ -233,5 +233,9 @@ exports.sendMessage = function (message, channel, callback) { console.log('Message sent'); callback(response.error, response); }); + + response.on('error', function (error) { + console.error(error); + }) }).end(); }; From 962e8f5b781a3eb1b3874cded6a05a0a8a38138c Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 02:32:22 -0500 Subject: [PATCH 37/46] Debugging --- bot.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bot.js b/bot.js index b62a572..a203edf 100644 --- a/bot.js +++ b/bot.js @@ -163,7 +163,9 @@ exports.processRequest = function processRequest (request, response) { console.log('Redirecting to: ', redirect.name); switch (redirect.type) { case 'user': - exports.sendMessage(responseText, '@' + redirect.name); + exports.sendMessage(responseText, '@' + redirect.name, function (error, data) { + console.log('After redirecting to ' + redirect.name + ': error: ' + JSON.stringify(error, null, ' ') + ' data: ' + JSON.stringify(data, null, ' ')); + }); break; case 'channel': From 92d2fffd0f3747f3e035d25b4b864b68c4bb5cd1 Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 02:35:04 -0500 Subject: [PATCH 38/46] Debugging --- bot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.js b/bot.js index a203edf..76464c1 100644 --- a/bot.js +++ b/bot.js @@ -232,7 +232,7 @@ exports.sendMessage = function (message, channel, callback) { var url = 'https://slack.com/api/chat.postMessage?' + querystring.stringify(messageData); https.get(url, function (response) { response.on('end', function () { - console.log('Message sent'); + console.log('Message sent: ' + url); callback(response.error, response); }); From 06ae65bdf3f4bc162108344b8c1409d7632ca822 Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 02:36:58 -0500 Subject: [PATCH 39/46] Debugging --- bot.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bot.js b/bot.js index 76464c1..b6dec44 100644 --- a/bot.js +++ b/bot.js @@ -228,11 +228,10 @@ exports.sendMessage = function (message, channel, callback) { text: message }; - console.log('Sending message: ', JSON.stringify(messageData)); var url = 'https://slack.com/api/chat.postMessage?' + querystring.stringify(messageData); + console.log('Sending message: ', JSON.stringify(url)); https.get(url, function (response) { response.on('end', function () { - console.log('Message sent: ' + url); callback(response.error, response); }); From 06a5b8abdd4df257116bd049e32533c67b451e1f Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 02:41:16 -0500 Subject: [PATCH 40/46] Debugging --- library/config.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/config.js b/library/config.js index 7784015..21a959d 100644 --- a/library/config.js +++ b/library/config.js @@ -19,4 +19,6 @@ if (!configExists) { config = require(__dirname + '/../config.json'); } +console.log('Using config:' + JSON.stringify(config)); + module.exports = config; From 4d81e6474887f6150bd5a9970aa22054ad449de9 Mon Sep 17 00:00:00 2001 From: Ustice Date: Sat, 20 Dec 2014 02:46:00 -0500 Subject: [PATCH 41/46] Config was missing user token for Heroku. --- bot.js | 6 +----- library/config.js | 4 +--- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/bot.js b/bot.js index b6dec44..33d68f2 100644 --- a/bot.js +++ b/bot.js @@ -160,12 +160,9 @@ exports.processRequest = function processRequest (request, response) { // If the response should be redirected, then do so if (command.redirectTo.length > 0) { _.each(command.redirectTo, function (redirect) { - console.log('Redirecting to: ', redirect.name); switch (redirect.type) { case 'user': - exports.sendMessage(responseText, '@' + redirect.name, function (error, data) { - console.log('After redirecting to ' + redirect.name + ': error: ' + JSON.stringify(error, null, ' ') + ' data: ' + JSON.stringify(data, null, ' ')); - }); + exports.sendMessage(responseText, '@' + redirect.name); break; case 'channel': @@ -229,7 +226,6 @@ exports.sendMessage = function (message, channel, callback) { }; var url = 'https://slack.com/api/chat.postMessage?' + querystring.stringify(messageData); - console.log('Sending message: ', JSON.stringify(url)); https.get(url, function (response) { response.on('end', function () { callback(response.error, response); diff --git a/library/config.js b/library/config.js index 21a959d..0b820f5 100644 --- a/library/config.js +++ b/library/config.js @@ -11,7 +11,7 @@ if (!configExists) { "logs": "logs", "token": { "slashCommand": process.env.TOKEN_SLASH_COMMAND, - "user": process.env.USER + "user": process.env.TOKEN_USER }, "timeout": 8000 }; @@ -19,6 +19,4 @@ if (!configExists) { config = require(__dirname + '/../config.json'); } -console.log('Using config:' + JSON.stringify(config)); - module.exports = config; From 6620857dd767b2ca56520c7eda2b7747551e6f8d Mon Sep 17 00:00:00 2001 From: Ustice Date: Mon, 22 Dec 2014 11:59:47 -0500 Subject: [PATCH 42/46] Adds github contacts to contributors. --- package.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 2ab09ad..5fbef10 100644 --- a/package.json +++ b/package.json @@ -7,23 +7,27 @@ "node": "~0.10.28" }, "scripts": { - "test": "mocha tests" + "start": "node master.js" }, "author": { "name": "Chris Young", + "github": "https://github.com/chris--young", "email": "cyoung@mobiquityinc.com" }, "contributors": [ { "name": "Jason Kleinberg", - "email": "jkleinberg@mobiquityinc.com" + "github": "https://github.com/Ustice", + "email": "ustice@gmail.com" }, { "name": "Firoze Rakib", + "github": "https://github.com/firoze", "email": "frakib@mobiquityinc.com" }, { "name": "Andrew Crites", + "github": "https://github.com/ajcrites", "email": "acrites@mobiquityinc.com" } ], @@ -34,8 +38,5 @@ }, "devDependencies": { "mocha": "~1.20.1" - }, - "scripts": { - "start": "node master.js" } } From 6bd9aa44eeebacea9da901b0436bb6a8c3921c46 Mon Sep 17 00:00:00 2001 From: Ustice Date: Mon, 22 Dec 2014 12:00:27 -0500 Subject: [PATCH 43/46] Ignore OS X .DS_Store files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0abd9d3..c273066 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ logs/ config.json node_modules/ config.json +.DS_Store From 1a304912f29d97da6b3a9c97c0bb2d0651757634 Mon Sep 17 00:00:00 2001 From: Ustice Date: Mon, 22 Dec 2014 12:01:02 -0500 Subject: [PATCH 44/46] Fix: Slacker not parsing `-` correctly. --- library/parse.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/parse.js b/library/parse.js index 3b3307c..57fbe84 100644 --- a/library/parse.js +++ b/library/parse.js @@ -125,8 +125,9 @@ exports.slackText = function slackText (encodedText) { break; case '-': - boundary = (state !== 'switch'); - state = 'switch'; + if (boundary) { + state = 'switch'; + } break; default: From 95cf8b01485795ecd47c36c8b776299887c33501 Mon Sep 17 00:00:00 2001 From: Firoze Rakib Date: Mon, 12 Jan 2015 11:23:15 -0500 Subject: [PATCH 45/46] new action commitmsg --- actions/commitmsg.js | 25 +++++++++++++++++++++++++ package.json | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 actions/commitmsg.js diff --git a/actions/commitmsg.js b/actions/commitmsg.js new file mode 100644 index 0000000..d7d2fd4 --- /dev/null +++ b/actions/commitmsg.js @@ -0,0 +1,25 @@ +var bot = require(__dirname + '/../bot.js'); +var $ = require('jquerygo'); + +var action = { + name: "commitmsg", + + trigger: /^commitmsg ".*"$/, + + description: "Display a message from http://whatthecommit.com/", + + execute: function(data, callback) { + $.visit("http://whatthecommit.com/", function() { + $("#content p:first-child").text(function(text) { + if (text) { + callback(text); + } else { + callback("Sorry. Something went wrong :disappointed:"); + } + $.close(); + }); + }); + } +}; + +bot.addAction(action); \ No newline at end of file diff --git a/package.json b/package.json index 5fbef10..2981b45 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "license": "ISC", "dependencies": { "lodash": "~2.4.1", - "slack-node": "0.0.9" + "slack-node": "0.0.9", + "jquerygo": "0.0.16" }, "devDependencies": { "mocha": "~1.20.1" From 15fa43ea770affa5bcee740590a66b34b982567c Mon Sep 17 00:00:00 2001 From: Firoze Rakib Date: Mon, 12 Jan 2015 11:32:58 -0500 Subject: [PATCH 46/46] Remove trigger, add helptext --- actions/commitmsg.js | 4 ++-- actions/weather.js | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/actions/commitmsg.js b/actions/commitmsg.js index d7d2fd4..a898ff3 100644 --- a/actions/commitmsg.js +++ b/actions/commitmsg.js @@ -4,10 +4,10 @@ var $ = require('jquerygo'); var action = { name: "commitmsg", - trigger: /^commitmsg ".*"$/, - description: "Display a message from http://whatthecommit.com/", + helpText: "Display a random message from http://whatthecommit.com/", + execute: function(data, callback) { $.visit("http://whatthecommit.com/", function() { $("#content p:first-child").text(function(text) { diff --git a/actions/weather.js b/actions/weather.js index cc435a4..33be6be 100644 --- a/actions/weather.js +++ b/actions/weather.js @@ -5,10 +5,11 @@ var http = require('http'); var action = { name: "weather", - trigger: /^weather ".*"$/, - description: "Display weather based on City or ZIP", + helpText: "Get weather from openweathermap.org by Zip or City and State + \n" + + "```" + "/slacker weather \"19102\" \n /slacker weather \"Philadelphia, PA\"" + "```", + execute: function(data, callback) { var query_param = data.text.substring(data.text.indexOf('\"') + 1, data.text.length - 1).replace(/ /g,"+"); @@ -61,11 +62,11 @@ var action = { callback(callback_data_str); } else { - callback("Something wasn't right :disappointed:"); + callback("Something wasn't right :disappointed: try again, please."); } } else { - callback("Where you at, bruh? Try `looking out the window` to get a read on the situation..."); + callback("Something wasn't right :disappointed: try again, please."); } }); });