From 04e068777d2eef17b651a012aaad0472bb73ea58 Mon Sep 17 00:00:00 2001 From: Mike Brevoort Date: Fri, 22 Jul 2016 15:43:56 -0600 Subject: [PATCH 1/5] Adding generated documentation --- README.md | 470 +++++++++++++++++++++++++++++++ src/conversation_store/index.js | 4 + src/conversation_store/memory.js | 1 + src/index.js | 11 - src/message.js | 64 +++-- src/receiver.js | 4 + src/slackapp.js | 125 ++++---- 7 files changed, 583 insertions(+), 96 deletions(-) diff --git a/README.md b/README.md index 8d3211df4..3a683baf8 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,473 @@ # slackapp-js A node.js module for Slack App integrations + +# slackapp + +[src/slackapp.js:24-487](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L24-L487 "Source code on GitHub") + +`slackapp` exposes a factory that takes an options object. + + var SlackApp = require('slackapp') + var slackapp = SlackApp(opts) + +**Parameters** + +- `opts` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** + - `opts.app_token` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Slack App token override + - `opts.app_user_id` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Slack App User ID (who installed the app) + - `opts.bot_token` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Slack App Bot token + - `opts.bot_user_id` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Slack App Bot ID + - `opts.convo_store` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Implementation of ConversationStore, defaults to memory + - `opts.error` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Error handler function `(error) => {}` + +Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** SlackApp + +## use + +[src/slackapp.js:124-126](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L124-L126 "Source code on GitHub") + +Register a new middleware, considered in order of registration + +**Parameters** + +- `fn` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (msg, next) => { } + - `fn.msg` **[message](#message)** instance of message + - `fn.next` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** next callback + +## attachToExpress + +[src/slackapp.js:180-182](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L180-L182 "Source code on GitHub") + +Attach HTTP routes to an [Express](https://expressjs.com/) app and registers the following routes: + +- `POST` `/slack-event` +- `POST` `/slack-command` +- `POST` `/slack-action` + +**Parameters** + +- `app` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** instance of an express app + +## route + +[src/slackapp.js:192-194](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L192-L194 "Source code on GitHub") + +Register a new function route + +**Parameters** + +- `fnKey` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** unique function key +- `fn` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** callback (msg) => {} + - `fn.msg` **[message](#message)** instance of message + +## getRoute + +[src/slackapp.js:202-204](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L202-L204 "Source code on GitHub") + +Return a registered route + +**Parameters** + +- `fnKey` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** unique function key + +## match + +[src/slackapp.js:225-227](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L225-L227 "Source code on GitHub") + +Register a custom Match function (fn) + +$eturns `true` if there is a match AND you handled the msg. +Return `false` if there is not a match and you pass on the message. + +All of the higher level matching convenience functions +generate a match function and call match to register it. + +Only one matcher can return true and they are executed in the order they are +defined. Match functions should return as fast as possible because it's important +that they are efficient. However you may do asyncronous tasks within to +your hearts content. + +**Parameters** + +- `fn` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** match function `(msg) => { return bool }` + - `fn.msg` **[message](#message)** instance of Message + +Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** was a match found and the message handled (otherwise continue looking) + +## message + +[src/slackapp.js:264-286](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L264-L286 "Source code on GitHub") + +Register a new message handler function for the provided criteria. Types should be one or +more of: + +- `direct_message` +- `direct_mention` +- `mention` +- `ambient` +- default: matches all if none provided + +**Parameters** + +- `criteria` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp))** string of a regular expression or RexExp object +- `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (msg) => {} + - `callback.msg` **[message](#message)** instance of Message +- `typeFilter` + +**Examples** + +```javascript +`msg` object: + + { + "token":"dxxxxxxxxxxxxxxxxxxxx", + "team_id":"TXXXXXXXX", + "api_app_id":"AXXXXXXXX", + "event":{ + "type":"message", + "user":"UXXXXXXXX", + "text":"hello!", + "ts":"1469130107.000088", + "channel":"DXXXXXXXX" + }, + "event_ts":"1469130107.000088", + "type":"event_callback", + "authed_users":[ + "UXXXXXXXX" + ] + } +``` + +## event + +[src/slackapp.js:318-330](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L318-L330 "Source code on GitHub") + +Register a new event handler for an actionName + +**Parameters** + +- `criteria` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp))** type of event or RegExp for more flexible matching +- `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (msg) => {} + - `callback.msg` **[message](#message)** instance of Message + +**Examples** + +```javascript +`msg` object: + + { + "token":"dxxxxxxxxxxxxxxxxxxxx", + "team_id":"TXXXXXXXX", + "api_app_id":"AXXXXXXXX", + "event":{ + "type":"reaction_added", + "user":"UXXXXXXXX", + "item":{ + "type":"message", + "channel":"DXXXXXXXX", + "ts":"1469130181.000096" + }, + "reaction":"grinning" + }, + "event_ts":"1469131201.822817", + "type":"event_callback", + "authed_users":[ + "UXXXXXXXX" + ] + } +``` + +## action + +[src/slackapp.js:407-430](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L407-L430 "Source code on GitHub") + +Register a new action handler for an actionNameCriteria + +**Parameters** + +- `callbackId` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Slack interactive message callback_id +- `actionNameCriteria` **\[([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp))]** type of action or RegExp for more flexible matching +- `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (msg) => {} + - `callback.msg` **[message](#message)** instance of Message + +**Examples** + +```javascript +`msg` object: + +{ + "actions":[ + { + "name":"answer", + "value":":wine_glass:" + } + ], + "callback_id":"in_or_out_callback", + "team":{ + "id":"TXXXXXXXX", + "domain":"companydomain" + }, + "channel":{ + "id":"DXXXXXXXX", + "name":"directmessage" + }, + "user":{ + "id":"UXXXXXXXX", + "name":"mike.brevoort" + }, + "action_ts":"1469129995.067370", + "message_ts":"1469129988.000084", + "attachment_id":"1", + "token":"dxxxxxxxxxxxxxxxxxxxx", + "original_message":{ + "text":"What?", + "username":"In or Out", + "bot_id":"BXXXXXXXX", + "attachments":[ + { + "callback_id":"in_or_out_callback", + "fallback":"Pick one", + "id":1, + "actions":[ + { + "id":"1", + "name":"answer", + "text":":beer:", + "type":"button", + "value":":beer:", + "style":"" + }, + { + "id":"2", + "name":"answer", + "text":":beers:", + "type":"button", + "value":":wine:", + "style":"" + }, + ] + }, + { + "text":":beers: • mike.brevoort", + "id":2, + "fallback":"who picked beers" + } + ], + "type":"message", + "subtype":"bot_message", + "ts":"1469129988.000084" + }, + "response_url":"https://hooks.slack.com/actions/TXXXXXXXX/111111111111/txxxxxxxxxxxxxxxxxxxx" +``` + +## command + +[src/slackapp.js:469-486](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L469-L486 "Source code on GitHub") + +Register a new slash command handler + +**Parameters** + +- `command` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the slash command (e.g. "/doit") +- `criteria` **\[([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp))]** matching criteria for slash command name (e.g "/^create.\*$/") +- `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (msg) => {} + - `callback.msg` **[message](#message)** instance of Message + +**Examples** + +```javascript +`msg` object: + + { + "type":"command", + "body":{ + "token":"xxxxxxxxxxxxxxxxxxx", + "team_id":"TXXXXXXXX", + "team_domain":"teamxxxxxxx", + "channel_id":"Dxxxxxxxx", + "channel_name":"directmessage", + "user_id":"Uxxxxxxxx", + "user_name":"xxxx.xxxxxxxx", + "command":"/doit", + "text":"whatever was typed after command", + "response_url":"https://hooks.slack.com/commands/TXXXXXXXX/111111111111111111111111111" + }, + "resource":{ + "app_token":"xoxp-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX", + "app_user_id":"UXXXXXXXX", + "bot_token":"xoxb-XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXX", + "bot_user_id":"UXXXXXXXX" + }, + "meta":{ + "user_id":"UXXXXXXXX", + "channel_id":"DXXXXXXXX", + "team_id":"TXXXXXXXX" + }, + } +``` + +# message + +[src/message.js:8-340](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L8-L340 "Source code on GitHub") + +Message + +## route + +[src/message.js:45-59](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L45-L59 "Source code on GitHub") + +Register the next function to route to in a conversation. The route should +be registered already through `slackapp.route` + +**Parameters** + +- `fnKey` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** unique key to register function +- `state` +- `secondsToExpire` + +## cancel + +[src/message.js:65-67](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L65-L67 "Source code on GitHub") + +Explicity cancel `route` registration. + +## say + +[src/message.js:83-95](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L83-L95 "Source code on GitHub") + +Send a message through `chat.postmessage` that defaults to current channel and tokens + +`input` may be one of: + +- type `object`: raw object that would be past to `chat.postmessage` +- type `string`: text of a message that will be used to construct object sent to `chat.postmessage` +- type `Array`: of strings or objects above to be picked randomly (can be mixed!) + +**Parameters** + +- `input` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array))** +- `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (err, data) => {} + - `callback.err` **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** error object + - `callback.data` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** data returned from call + +## respond + +[src/message.js:112-140](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L112-L140 "Source code on GitHub") + +Use a `response_url` from a Slash command or interactive message action + +`input` may be one of: + +- type `object`: raw object that would be past to `chat.postmessage` +- type `string`: text of a message that will be used to construct object sent to `chat.postmessage` +- type `Array`: of strings or objects above to be picked randomly (can be mixed!) + +**Parameters** + +- `responseUrl` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** URL provided by a Slack interactive message action or slash command +- `input` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array))** +- `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (err, data) => {} + - `callback.err` **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** error object + - `callback.data` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** data returned from call + +## isMessage + +[src/message.js:146-148](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L146-L148 "Source code on GitHub") + +Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Is this an `event` of type `message`? + +## isDirectMention + +[src/message.js:154-156](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L154-L156 "Source code on GitHub") + +Is this a message that is a direct mention ("@botusername: hi there", "@botusername goodbye!") + +## isDirectMessage + +[src/message.js:162-164](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L162-L164 "Source code on GitHub") + +Is this a message in a direct message channel (one on one) + +## isMention + +[src/message.js:171-173](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L171-L173 "Source code on GitHub") + +Is this a message where the bot user mentioned anywhere in the message. +This only checks for the bot user and does not consider any other users + +## isAmbient + +[src/message.js:180-182](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L180-L182 "Source code on GitHub") + +Is this a message that's not a direct message or that mentions that bot at +all (other users could be mentioned) + +## isAnyOf + +[src/message.js:191-202](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L191-L202 "Source code on GitHub") + +Is this a message that matches any one of these filter types + +Parameters: + +- `messageFilters` Array - any of direct_message, direct_mention, mention or ambient + +**Parameters** + +- `messageFilters` + +## usersMentioned + +[src/message.js:210-212](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L210-L212 "Source code on GitHub") + +Users mentioned in the message + +Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** array of user IDs + +## channelsMentioned + +[src/message.js:220-222](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L220-L222 "Source code on GitHub") + +Channels mentioned in the message + +Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** array of channel IDs + +## subteamGroupsMentioned + +[src/message.js:229-231](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L229-L231 "Source code on GitHub") + +Subteams (groups) mentioned in the message + +Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** array of subteam IDs + +## everyoneMentioned + +[src/message.js:237-239](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L237-L239 "Source code on GitHub") + +Was "@everyone" mentioned in the message + +## channelMentioned + +[src/message.js:245-247](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L245-L247 "Source code on GitHub") + +Was the current "@channel" mentioned in the message + +## hereMentioned + +[src/message.js:253-255](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L253-L255 "Source code on GitHub") + +Was the current "@channel" mentioned in the message + +## linksMentioned + +[src/message.js:261-276](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L261-L276 "Source code on GitHub") + +Return the URLs of any links mentioned in the message + +## stripDirectMention + +[src/message.js:283-293](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L283-L293 "Source code on GitHub") + +Strip the direct mention prefix from the message text and return it. The +original text is not modified diff --git a/src/conversation_store/index.js b/src/conversation_store/index.js index 197a7c0ee..e2b43c0fd 100644 --- a/src/conversation_store/index.js +++ b/src/conversation_store/index.js @@ -2,6 +2,10 @@ const MemoryStore = require('./memory') +/** + * Conversation store + * @private + */ module.exports = (opts) => { opts = opts || {} let storage diff --git a/src/conversation_store/memory.js b/src/conversation_store/memory.js index 08b5b5aaa..d060c3224 100644 --- a/src/conversation_store/memory.js +++ b/src/conversation_store/memory.js @@ -2,6 +2,7 @@ /** * In memory implementation of a ConversationStore, primarily for testing + * @private */ module.exports = class MemoryStore { diff --git a/src/index.js b/src/index.js index 0fbb31982..de99044d7 100644 --- a/src/index.js +++ b/src/index.js @@ -1,16 +1,5 @@ const SlackApp = require('./slackapp') -/** - * Initialize a SlackApp, accepts an options object - * - * Options: - * - `app_token` Slack App token - * - `app_user_id` Slack App User ID (who installed the app) - * - `bot_token` Slack App Bot token - * - `bot_user_id` Slack App Bot ID - * - `convo_store` `string` of type of Conversation store (`memory`, etc.) or `object` implementation - * - `error` Error handler function `(error) => {}` - */ module.exports = (opts) => { let app = new SlackApp(opts) diff --git a/src/message.js b/src/message.js index 8d718e11e..a867be847 100644 --- a/src/message.js +++ b/src/message.js @@ -3,6 +3,10 @@ const request = require('request') const slack = require('slack') +/** + * Message + * @class + */ module.exports = class Message { constructor (type, body, meta) { this.type = type @@ -32,14 +36,12 @@ module.exports = class Message { } /** - * Register the next function to route to in a conversation. + * Register the next function to route to in a conversation. The route should + * be registered already through `slackapp.route` * - * The route should be registered already through `slackapp.route` - * - * Parameters - * - `fnKey` `string` - * - `state` `object` arbitrary data to be passed back to your function [optional] - * - `secondsToExpire` `number` - number of seconds to wait for the next message in the conversation before giving up. Default 60 minutes [optional] + * @param {string} fnKey - unique key to register function + * @param {Object={}} state - arbitrary data to be passed back to your function [optional] + * @param {number=3600} secondsToExpire - seconds to wait for the next message in the conversation before giving up. Default 60 minutes [optional] */ route (fnKey, state, secondsToExpire) { @@ -69,13 +71,15 @@ module.exports = class Message { /** * Send a message through `chat.postmessage` that defaults to current channel and tokens * - * Parameters - * - `input` `string` or `object` or `Array` - * * type `object`: raw object that would be past to `chat.postmessage` - * * type `string`: text of a message that will be used to construct object sent to `chat.postmessage` - * * type `Array`: of strings or objects above to be picked randomly (can be mixed!) + * `input` may be one of: + * - type `object`: raw object that would be past to `chat.postmessage` + * - type `string`: text of a message that will be used to construct object sent to `chat.postmessage` + * - type `Array`: of strings or objects above to be picked randomly (can be mixed!) * - * - `callback` string - (err, data) => {} + * @param {string|Object|Array} input + * @param {function} callback - (err, data) => {} + * @param {Error} callback.err - error object + * @param {Object} callback.data - data returned from call */ say (input, callback) { @@ -95,14 +99,16 @@ module.exports = class Message { /** * Use a `response_url` from a Slash command or interactive message action * - * Parameters - * - `responseUrl` string - URL provided by a Slack interactive message action or slash command - * - `input` string or object or Array - * * type `object`: raw object that would be past to `chat.postmessage` - * * type `string`: text of a message that will be used to construct object sent to `chat.postmessage` - * * type `Array`: of strings or objects above to be picked randomly (can be mixed!) + * `input` may be one of: + * - type `object`: raw object that would be past to `chat.postmessage` + * - type `string`: text of a message that will be used to construct object sent to `chat.postmessage` + * - type `Array`: of strings or objects above to be picked randomly (can be mixed!) * - * - `callback` string - (err, data) => {} + * @param {string} responseUrl - URL provided by a Slack interactive message action or slash command + * @param {string|Object|Array} input + * @param {function} callback - (err, data) => {} + * @param {Error} callback.err - error object + * @param {Object} callback.data - data returned from call */ respond (responseUrl, input, callback) { @@ -136,7 +142,7 @@ module.exports = class Message { } /** - * Is this an `event` of type `message`? + * @return {boolean} Is this an `event` of type `message`? */ isMessage () { @@ -197,9 +203,9 @@ module.exports = class Message { } /** - * Return the user IDs of any users mentioned in the message + * Users mentioned in the message * - * Returns an Array of IDs + * @return {Array} array of user IDs */ usersMentioned () { @@ -207,9 +213,9 @@ module.exports = class Message { } /** - * Return the channel IDs of any channels mentioned in the message + * Channels mentioned in the message * - * Returns an Array of IDs + * @return {Array} array of channel IDs */ channelsMentioned () { @@ -217,9 +223,9 @@ module.exports = class Message { } /** - * Return the IDs of any subteams (groups) mentioned in the message + * Subteams (groups) mentioned in the message * - * Returns an Array of IDs + * @return {Array} array of subteam IDs */ subteamGroupsMentioned () { return this._regexMentions(new RegExp(']+>', 'g')) @@ -290,7 +296,7 @@ module.exports = class Message { /** * Returns array of regex matches from the text of a message * - * @api private + * @private */ _regexMentions (re) { @@ -314,7 +320,7 @@ module.exports = class Message { * If an array, pick a random item of the array. * If a string, wrap in a `chat.postmessage` params object * - * @api private + * @private */ _processInput (input) { diff --git a/src/receiver.js b/src/receiver.js index fdf1a7ed0..604364b67 100644 --- a/src/receiver.js +++ b/src/receiver.js @@ -5,6 +5,10 @@ const bodyParser = require('body-parser') const fs = require('fs') const Message = require('./message') +/** + * Receives HTTP requests with Events, Slash Commands, and Actions + * @private + */ module.exports = class Receiver extends EventEmitter { constructor (opts) { super() diff --git a/src/slackapp.js b/src/slackapp.js index 33957adb1..9c99e73f1 100644 --- a/src/slackapp.js +++ b/src/slackapp.js @@ -5,20 +5,31 @@ const conversationStore = require('./conversation_store') const Receiver = require('./receiver') /** - * SlackApp module + * `slackapp` exposes a factory that takes an options object. + * + * ``` + * var SlackApp = require('slackapp') + * var slackapp = SlackApp(opts) + * ``` + * + * @class + * @param {Object} opts + * @param {string} opts.app_token - Slack App token override + * @param {string} opts.app_user_id - Slack App User ID (who installed the app) + * @param {string} opts.bot_token - Slack App Bot token + * @param {string} opts.bot_user_id - Slack App Bot ID + * @param {Object} opts.convo_store - Implementation of ConversationStore, defaults to memory + * @param {string} opts.error - Error handler function `(error) => {}` + * @returns {Object} SlackApp */ + module.exports = class SlackApp { /** - * Initialize a SlackApp, accepts an options object + * SlackApp constructor * - * Options: - * - `app_token` Slack App token - * - `app_user_id` Slack App User ID (who installed the app) - * - `bot_token` Slack App Bot token - * - `bot_user_id` Slack App Bot ID - * - `convo_store` `string` of type of Conversation store (`memory`, etc.) or `object` implementation - * - `error` Error handler function `(error) => {}` + * Documented in index.js + * @private */ constructor (opts) { @@ -53,6 +64,8 @@ module.exports = class SlackApp { /** * Initialize app w/ default middleware and receiver listener + * + * @private */ init () { // call `handle` for each new request @@ -68,7 +81,7 @@ module.exports = class SlackApp { * Middleware that gets an existing conversation from the conversation store * or initialize a new one. * - * @api private + * @private */ preprocessConversationMiddleware () { @@ -90,7 +103,7 @@ module.exports = class SlackApp { /** * Middleware that ignores messages from any bot user when we can tell * - * @api private + * @private */ ignoreBotsMiddleware () { @@ -103,11 +116,12 @@ module.exports = class SlackApp { } } + /** - * Register a new middleware - * - * Middleware is processed in the order registered. - * `fn` : (msg, next) => { } + * Register a new middleware, considered in order of registration + * @param {function} fn - (msg, next) => { } + * @param {message} fn.msg - instance of message + * @param {function} fn.next - next callback */ use (fn) { @@ -122,7 +136,7 @@ module.exports = class SlackApp { * - `msg` `Message` * - `done` `function(err, bool)` Callback called once complete, called with error and boolean indicating message was handled [optional] * - * @api private + * @private */ _handle (msg, done) { @@ -171,12 +185,13 @@ module.exports = class SlackApp { } /** - * Attach HTTP routes to an Express app + * Attach HTTP routes to an [Express](https://expressjs.com/) app and registers the following routes: + * - `POST` `/slack-event` + * - `POST` `/slack-command` + * - `POST` `/slack-action` + * + * @param {Object} app - instance of an express app * - * Routes are: - * - POST `/slack-event` - * - POST `/slack-command` - * - POST `/slack-action` */ attachToExpress (app) { @@ -186,9 +201,9 @@ module.exports = class SlackApp { /** * Register a new function route * - * Parameters - * - `fnKey` string - unique key to refer to function - * - `fn` function - `(msg) => {}` + * @param {string} fnKey - unique function key + * @param {function} fn - callback (msg) => {} + * @param {message} fn.msg - instance of message */ route (fnKey, fn) { @@ -200,8 +215,7 @@ module.exports = class SlackApp { /** * Return a registered route * - * Parameters - * - `fnKey` string - unique key to refer to function + * @param {string} fnKey - unique function key */ getRoute (fnKey) { @@ -222,8 +236,9 @@ module.exports = class SlackApp { * that they are efficient. However you may do asyncronous tasks within to * your hearts content. * - * Parameters - * - `fn` function - match function `(msg) => { return bool }` + * @param {function} fn - match function `(msg) => { return bool }` + * @param {message} fn.msg - instance of Message + * @return {boolean} - was a match found and the message handled (otherwise continue looking) */ match (fn) { @@ -233,19 +248,20 @@ module.exports = class SlackApp { } /** - * Register a new message handler function for the criteria + * Register a new message handler function for the provided criteria. Types should be one or + * more of: * - * Parameters: - * - `criteria` string or RegExp - message is string or match RegExp - * - `typeFilter` Array for list of values or string for one value [optional] - * * `direct_message` - * * `direct_mention` - * * `mention` - * * `ambient` - * * default: matches all if none provided - * - `callback` function - `(msg) => {}` + * - `direct_message` + * - `direct_mention` + * - `mention` + * - `ambient` + * - default: matches all if none provided * - * Example `msg` object: + * @param {(string|RegExp)} criteria - string of a regular expression or RexExp object + * @param {(string=|Array=)} typeFilter - list of types or string if just one + * @param {function} callback - (msg) => {} + * @param {message} callback.msg - instance of Message + * @example `msg` object: * * { * "token":"dxxxxxxxxxxxxxxxxxxxx", @@ -293,11 +309,10 @@ module.exports = class SlackApp { /** * Register a new event handler for an actionName * - * Parameters: - * - `criteria` string or RegExp - the type of event - * - `callback` function - `(msg) => {}` - * - * Example `msg` object: + * @param {(string|RegExp)} criteria - type of event or RegExp for more flexible matching + * @param {function} callback - (msg) => {} + * @param {message} callback.msg - instance of Message + * @example `msg` object: * * { * "token":"dxxxxxxxxxxxxxxxxxxxx", @@ -338,12 +353,11 @@ module.exports = class SlackApp { /** * Register a new action handler for an actionNameCriteria * - * Parameters: - * - `callbackId` string - * - `actionNameCriteria` string or RegExp - the name of the action [optional] - * - `callback` function - `(msg) => {}` - * - * Example `msg` object: + * @param {string} callbackId - Slack interactive message callback_id + * @param {(string|RegExp)=} actionNameCriteria - type of action or RegExp for more flexible matching + * @param {function} callback - (msg) => {} + * @param {message} callback.msg - instance of Message + * @example `msg` object: * * { * "actions":[ @@ -439,12 +453,11 @@ module.exports = class SlackApp { /** * Register a new slash command handler * - * Parameters: - * - `command` string - the slash command (e.g. "/doit") - * - `criteria` string or RegExp (e.g "/^create.*$/") [optional] - * - `callback` function - `(msg) => {}` - * - * Example `msg` object: + * @param {string} command - the slash command (e.g. "/doit") + * @param {(string|RegExp)=} criteria - matching criteria for slash command name (e.g "/^create.*$/") + * @param {function} callback - (msg) => {} + * @param {message} callback.msg - instance of Message + * @example `msg` object: * * { * "type":"command", From 96390487df71765eb8f277a7a6a3859b54c18f28 Mon Sep 17 00:00:00 2001 From: Mike Brevoort Date: Sat, 23 Jul 2016 10:23:33 -0600 Subject: [PATCH 2/5] Docs updating readme --- README.md | 530 ++++++++++++++---------------------------------- package.json | 1 + scripts/docs.js | 36 ++++ src/message.js | 8 +- src/slackapp.js | 125 +++++------- 5 files changed, 250 insertions(+), 450 deletions(-) create mode 100644 scripts/docs.js diff --git a/README.md b/README.md index 3a683baf8..9f72e6073 100644 --- a/README.md +++ b/README.md @@ -3,472 +3,248 @@ # slackapp-js A node.js module for Slack App integrations -# slackapp -[src/slackapp.js:24-487](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L24-L487 "Source code on GitHub") -`slackapp` exposes a factory that takes an options object. - var SlackApp = require('slackapp') - var slackapp = SlackApp(opts) +# API -**Parameters** +## undefined -- `opts` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** - - `opts.app_token` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Slack App token override - - `opts.app_user_id` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Slack App User ID (who installed the app) - - `opts.bot_token` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Slack App Bot token - - `opts.bot_user_id` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Slack App Bot ID - - `opts.convo_store` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Implementation of ConversationStore, defaults to memory - - `opts.error` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Error handler function `(error) => {}` +### SlackApp.module.exports -Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** SlackApp +

SlackApp module

-## use +### SlackApp.constructor() -[src/slackapp.js:124-126](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L124-L126 "Source code on GitHub") +

Initialize a SlackApp, accepts an options object

Options:

    +
  • app_token Slack App token
  • +
  • app_user_id Slack App User ID (who installed the app)
  • +
  • bot_token Slack App Bot token
  • +
  • bot_user_id Slack App Bot ID
  • +
  • convo_store string of type of Conversation store (memory, etc.) or object implementation
  • +
  • error Error handler function (error) => {}
  • +
-Register a new middleware, considered in order of registration -**Parameters** +### SlackApp.init() -- `fn` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (msg, next) => { } - - `fn.msg` **[message](#message)** instance of message - - `fn.next` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** next callback +

Initialize app w/ default middleware and receiver listener

-## attachToExpress +### SlackApp.preprocessConversationMiddleware() -[src/slackapp.js:180-182](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L180-L182 "Source code on GitHub") +

Middleware that gets an existing conversation from the conversation store
or initialize a new one.

-Attach HTTP routes to an [Express](https://expressjs.com/) app and registers the following routes: +### SlackApp.ignoreBotsMiddleware() -- `POST` `/slack-event` -- `POST` `/slack-command` -- `POST` `/slack-action` +

Middleware that ignores messages from any bot user when we can tell

-**Parameters** +### SlackApp.use() -- `app` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** instance of an express app +

Register a new middleware

Middleware is processed in the order registered.
fn : (msg, next) => { }

-## route +### SlackApp._handle() -[src/slackapp.js:192-194](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L192-L194 "Source code on GitHub") +

Handle new events (slack events, commands, actions, webhooks, etc.)

-Register a new function route +### SlackApp.attachToExpress() -**Parameters** +

Attach HTTP routes to an Express app

Routes are:

    +
  • POST /slack-event
  • +
  • POST /slack-command
  • +
  • POST /slack-action
  • +
-- `fnKey` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** unique function key -- `fn` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** callback (msg) => {} - - `fn.msg` **[message](#message)** instance of message -## getRoute +### SlackApp.route() -[src/slackapp.js:202-204](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L202-L204 "Source code on GitHub") +

Register a new function route

Parameters

    +
  • fnKey string - unique key to refer to function
  • +
  • fn function - (msg) => {}
  • +
-Return a registered route -**Parameters** +### SlackApp.getRoute() -- `fnKey` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** unique function key +

Return a registered route

Parameters

    +
  • fnKey string - unique key to refer to function
  • +
-## match -[src/slackapp.js:225-227](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L225-L227 "Source code on GitHub") +### SlackApp.match() -Register a custom Match function (fn) +

Register a custom Match function (fn)

$eturns true if there is a match AND you handled the msg.
Return false if there is not a match and you pass on the message.

All of the higher level matching convenience functions
generate a match function and call match to register it.

Only one matcher can return true and they are executed in the order they are
defined. Match functions should return as fast as possible because it's important
that they are efficient. However you may do asyncronous tasks within to
your hearts content.

Parameters

    +
  • fn function - match function (msg) => { return bool }
  • +
-$eturns `true` if there is a match AND you handled the msg. -Return `false` if there is not a match and you pass on the message. -All of the higher level matching convenience functions -generate a match function and call match to register it. +### SlackApp.message() -Only one matcher can return true and they are executed in the order they are -defined. Match functions should return as fast as possible because it's important -that they are efficient. However you may do asyncronous tasks within to -your hearts content. +

Register a new message handler function for the criteria

Parameters:

    +
  • criteria string or RegExp - message is string or match RegExp
  • +
  • typeFilter Array for list of values or string for one value [optional]
      +
    • direct_message
    • +
    • direct_mention
    • +
    • mention
    • +
    • ambient
    • +
    • default: matches all if none provided
    • +
    +
  • +
  • callback function - (msg) => {}
  • +
+

Example msg object:

{
"token":"dxxxxxxxxxxxxxxxxxxxx",
"team_id":"TXXXXXXXX",
"api_app_id":"AXXXXXXXX",
"event":{
"type":"message",
"user":"UXXXXXXXX",
"text":"hello!",
"ts":"1469130107.000088",
"channel":"DXXXXXXXX"
},
"event_ts":"1469130107.000088",
"type":"event_callback",
"authed_users":[
"UXXXXXXXX"
]
}

-**Parameters** +### SlackApp.event() -- `fn` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** match function `(msg) => { return bool }` - - `fn.msg` **[message](#message)** instance of Message +

Register a new event handler for an actionName

Parameters:

    +
  • criteria string or RegExp - the type of event
  • +
  • callback function - (msg) => {}
  • +
+

Example msg object:

{
"token":"dxxxxxxxxxxxxxxxxxxxx",
"team_id":"TXXXXXXXX",
"api_app_id":"AXXXXXXXX",
"event":{
"type":"reaction_added",
"user":"UXXXXXXXX",
"item":{
"type":"message",
"channel":"DXXXXXXXX",
"ts":"1469130181.000096"
},
"reaction":"grinning"
},
"event_ts":"1469131201.822817",
"type":"event_callback",
"authed_users":[
"UXXXXXXXX"
]
}

-Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** was a match found and the message handled (otherwise continue looking) +### SlackApp.action() -## message +

Register a new action handler for an actionNameCriteria

Parameters:

    +
  • callbackId string
  • +
  • actionNameCriteria string or RegExp - the name of the action [optional]
  • +
  • callback function - (msg) => {}
  • +
+

Example msg object:

{
"actions":[
{
"name":"answer",
"value":":wine_glass:"
}
],
"callback_id":"in_or_out_callback",
"team":{
"id":"TXXXXXXXX",
"domain":"companydomain"
},
"channel":{
"id":"DXXXXXXXX",
"name":"directmessage"
},
"user":{
"id":"UXXXXXXXX",
"name":"mike.brevoort"
},
"action_ts":"1469129995.067370",
"message_ts":"1469129988.000084",
"attachment_id":"1",
"token":"dxxxxxxxxxxxxxxxxxxxx",
"original_message":{
"text":"What?",
"username":"In or Out",
"bot_id":"BXXXXXXXX",
"attachments":[
{
"callback_id":"in_or_out_callback",
"fallback":"Pick one",
"id":1,
"actions":[
{
"id":"1",
"name":"answer",
"text":":beer:",
"type":"button",
"value":":beer:",
"style":""
},
{
"id":"2",
"name":"answer",
"text":":beers:",
"type":"button",
"value":":wine:",
"style":""
},
]
},
{
"text":":beers: • mike.brevoort",
"id":2,
"fallback":"who picked beers"
}
],
"type":"message",
"subtype":"bot_message",
"ts":"1469129988.000084"
},
"response_url":"https://hooks.slack.com/actions/TXXXXXXXX/111111111111/txxxxxxxxxxxxxxxxxxxx"

-[src/slackapp.js:264-286](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L264-L286 "Source code on GitHub") +### SlackApp.command() -Register a new message handler function for the provided criteria. Types should be one or -more of: - -- `direct_message` -- `direct_mention` -- `mention` -- `ambient` -- default: matches all if none provided - -**Parameters** - -- `criteria` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp))** string of a regular expression or RexExp object -- `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (msg) => {} - - `callback.msg` **[message](#message)** instance of Message -- `typeFilter` - -**Examples** - -```javascript -`msg` object: - - { - "token":"dxxxxxxxxxxxxxxxxxxxx", - "team_id":"TXXXXXXXX", - "api_app_id":"AXXXXXXXX", - "event":{ - "type":"message", - "user":"UXXXXXXXX", - "text":"hello!", - "ts":"1469130107.000088", - "channel":"DXXXXXXXX" - }, - "event_ts":"1469130107.000088", - "type":"event_callback", - "authed_users":[ - "UXXXXXXXX" - ] - } -``` - -## event - -[src/slackapp.js:318-330](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L318-L330 "Source code on GitHub") - -Register a new event handler for an actionName - -**Parameters** - -- `criteria` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp))** type of event or RegExp for more flexible matching -- `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (msg) => {} - - `callback.msg` **[message](#message)** instance of Message - -**Examples** - -```javascript -`msg` object: - - { - "token":"dxxxxxxxxxxxxxxxxxxxx", - "team_id":"TXXXXXXXX", - "api_app_id":"AXXXXXXXX", - "event":{ - "type":"reaction_added", - "user":"UXXXXXXXX", - "item":{ - "type":"message", - "channel":"DXXXXXXXX", - "ts":"1469130181.000096" - }, - "reaction":"grinning" - }, - "event_ts":"1469131201.822817", - "type":"event_callback", - "authed_users":[ - "UXXXXXXXX" - ] - } -``` - -## action - -[src/slackapp.js:407-430](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L407-L430 "Source code on GitHub") - -Register a new action handler for an actionNameCriteria - -**Parameters** - -- `callbackId` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Slack interactive message callback_id -- `actionNameCriteria` **\[([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp))]** type of action or RegExp for more flexible matching -- `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (msg) => {} - - `callback.msg` **[message](#message)** instance of Message - -**Examples** - -```javascript -`msg` object: - -{ - "actions":[ - { - "name":"answer", - "value":":wine_glass:" - } - ], - "callback_id":"in_or_out_callback", - "team":{ - "id":"TXXXXXXXX", - "domain":"companydomain" - }, - "channel":{ - "id":"DXXXXXXXX", - "name":"directmessage" +

Register a new slash command handler

Parameters:

    +
  • command string - the slash command (e.g. "/doit")
  • +
  • criteria string or RegExp (e.g "/^create.*$/") [optional]
  • +
  • callback function - (msg) => {}
  • +
+

Example msg object:

{
+   "type":"command",
+   "body":{
+      "token":"xxxxxxxxxxxxxxxxxxx",
+      "team_id":"TXXXXXXXX",
+      "team_domain":"teamxxxxxxx",
+      "channel_id":"Dxxxxxxxx",
+      "channel_name":"directmessage",
+      "user_id":"Uxxxxxxxx",
+      "user_name":"xxxx.xxxxxxxx",
+      "command":"/doit",
+      "text":"whatever was typed after command",
+      "response_url":"https://hooks.slack.com/commands/TXXXXXXXX/111111111111111111111111111"
    },
-   "user":{
-      "id":"UXXXXXXXX",
-      "name":"mike.brevoort"
+   "resource":{
+      "app_token":"xoxp-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX",
+      "app_user_id":"UXXXXXXXX",
+      "bot_token":"xoxb-XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXX",
+      "bot_user_id":"UXXXXXXXX"
    },
-   "action_ts":"1469129995.067370",
-   "message_ts":"1469129988.000084",
-   "attachment_id":"1",
-   "token":"dxxxxxxxxxxxxxxxxxxxx",
-   "original_message":{
-      "text":"What?",
-      "username":"In or Out",
-      "bot_id":"BXXXXXXXX",
-      "attachments":[
-         {
-            "callback_id":"in_or_out_callback",
-            "fallback":"Pick one",
-            "id":1,
-            "actions":[
-               {
-                  "id":"1",
-                  "name":"answer",
-                  "text":":beer:",
-                  "type":"button",
-                  "value":":beer:",
-                  "style":""
-               },
-               {
-                  "id":"2",
-                  "name":"answer",
-                  "text":":beers:",
-                  "type":"button",
-                  "value":":wine:",
-                  "style":""
-               },
-            ]
-         },
-         {
-            "text":":beers: • mike.brevoort",
-            "id":2,
-            "fallback":"who picked beers"
-         }
-      ],
-      "type":"message",
-      "subtype":"bot_message",
-      "ts":"1469129988.000084"
+   "meta":{
+      "user_id":"UXXXXXXXX",
+      "channel_id":"DXXXXXXXX",
+      "team_id":"TXXXXXXXX"
    },
-   "response_url":"https://hooks.slack.com/actions/TXXXXXXXX/111111111111/txxxxxxxxxxxxxxxxxxxx"
-```
-
-## command
-
-[src/slackapp.js:469-486](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/slackapp.js#L469-L486 "Source code on GitHub")
-
-Register a new slash command handler
-
-**Parameters**
-
--   `command` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the slash command (e.g. "/doit")
--   `criteria` **\[([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp))]** matching criteria for slash command name (e.g "/^create.\*$/")
--   `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (msg) => {}
-    -   `callback.msg` **[message](#message)** instance of Message
-
-**Examples**
-
-```javascript
-`msg` object:
-
-    {
-       "type":"command",
-       "body":{
-          "token":"xxxxxxxxxxxxxxxxxxx",
-          "team_id":"TXXXXXXXX",
-          "team_domain":"teamxxxxxxx",
-          "channel_id":"Dxxxxxxxx",
-          "channel_name":"directmessage",
-          "user_id":"Uxxxxxxxx",
-          "user_name":"xxxx.xxxxxxxx",
-          "command":"/doit",
-          "text":"whatever was typed after command",
-          "response_url":"https://hooks.slack.com/commands/TXXXXXXXX/111111111111111111111111111"
-       },
-       "resource":{
-          "app_token":"xoxp-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX",
-          "app_user_id":"UXXXXXXXX",
-          "bot_token":"xoxb-XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXX",
-          "bot_user_id":"UXXXXXXXX"
-       },
-       "meta":{
-          "user_id":"UXXXXXXXX",
-          "channel_id":"DXXXXXXXX",
-          "team_id":"TXXXXXXXX"
-       },
-    }
-```
-
-# message
-
-[src/message.js:8-340](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L8-L340 "Source code on GitHub")
-
-Message
-
-## route
-
-[src/message.js:45-59](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L45-L59 "Source code on GitHub")
-
-Register the next function to route to in a conversation. The route should
-be registered already through `slackapp.route`
-
-**Parameters**
-
--   `fnKey` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** unique key to register function
--   `state`  
--   `secondsToExpire`  
-
-## cancel
-
-[src/message.js:65-67](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L65-L67 "Source code on GitHub")
-
-Explicity cancel `route` registration.
-
-## say
-
-[src/message.js:83-95](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L83-L95 "Source code on GitHub")
-
-Send a message through `chat.postmessage` that defaults to current channel and tokens
-
-`input` may be one of:
-
--   type `object`: raw object that would be past to `chat.postmessage`
--   type `string`: text of a message that will be used to construct object sent to `chat.postmessage`
--   type `Array`: of strings or objects above to be picked randomly (can be mixed!)
-
-**Parameters**
-
--   `input` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array))**
--   `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (err, data) => {}
-    -   `callback.err` **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** error object
-    -   `callback.data` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** data returned from call
-
-## respond
-
-[src/message.js:112-140](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L112-L140 "Source code on GitHub")
-
-Use a `response_url` from a Slash command or interactive message action
-
-`input` may be one of:
-
--   type `object`: raw object that would be past to `chat.postmessage`
--   type `string`: text of a message that will be used to construct object sent to `chat.postmessage`
--   type `Array`: of strings or objects above to be picked randomly (can be mixed!)
-
-**Parameters**
+}
+
-- `responseUrl` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** URL provided by a Slack interactive message action or slash command -- `input` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array))** -- `callback` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** (err, data) => {} - - `callback.err` **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** error object - - `callback.data` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** data returned from call +## undefined -## isMessage +### Message.module.exports -[src/message.js:146-148](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L146-L148 "Source code on GitHub") +

Message

-Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Is this an `event` of type `message`? +### Message.route() -## isDirectMention +

Register the next function to route to in a conversation. The route should
be registered already through slackapp.route

-[src/message.js:154-156](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L154-L156 "Source code on GitHub") +### Message.cancel() -Is this a message that is a direct mention ("@botusername: hi there", "@botusername goodbye!") +

Explicity cancel route registration.

-## isDirectMessage +### Message.say() -[src/message.js:162-164](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L162-L164 "Source code on GitHub") +

Send a message through chat.postmessage that defaults to current channel and tokens

input may be one of:

    +
  • type object: raw object that would be past to chat.postmessage
  • +
  • type string: text of a message that will be used to construct object sent to chat.postmessage
  • +
  • type Array: of strings or objects above to be picked randomly (can be mixed!)
  • +
-Is this a message in a direct message channel (one on one) -## isMention +### Message.respond() -[src/message.js:171-173](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L171-L173 "Source code on GitHub") +

Use a response_url from a Slash command or interactive message action

input may be one of:

    +
  • type object: raw object that would be past to chat.postmessage
  • +
  • type string: text of a message that will be used to construct object sent to chat.postmessage
  • +
  • type Array: of strings or objects above to be picked randomly (can be mixed!)
  • +
-Is this a message where the bot user mentioned anywhere in the message. -This only checks for the bot user and does not consider any other users -## isAmbient +### Message.isMessage() -[src/message.js:180-182](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L180-L182 "Source code on GitHub") -Is this a message that's not a direct message or that mentions that bot at -all (other users could be mentioned) -## isAnyOf +### Message.isDirectMention() -[src/message.js:191-202](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L191-L202 "Source code on GitHub") +

Is this a message that is a direct mention ("@botusername: hi there", "@botusername goodbye!")

-Is this a message that matches any one of these filter types +### Message.isDirectMessage() -Parameters: +

Is this a message in a direct message channel (one on one)

-- `messageFilters` Array - any of direct_message, direct_mention, mention or ambient +### Message.isMention() -**Parameters** +

Is this a message where the bot user mentioned anywhere in the message.
This only checks for the bot user and does not consider any other users

-- `messageFilters` +### Message.isAmbient() -## usersMentioned +

Is this a message that's not a direct message or that mentions that bot at
all (other users could be mentioned)

-[src/message.js:210-212](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L210-L212 "Source code on GitHub") +### Message.isAnyOf() -Users mentioned in the message +

Is this a message that matches any one of these filter types

Parameters:

    +
  • messageFilters Array - any of direct_message, direct_mention, mention or ambient
  • +
-Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** array of user IDs -## channelsMentioned +### Message.usersMentioned() -[src/message.js:220-222](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L220-L222 "Source code on GitHub") +

Users mentioned in the message

-Channels mentioned in the message +### Message.channelsMentioned() -Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** array of channel IDs +

Channels mentioned in the message

-## subteamGroupsMentioned +### Message.subteamGroupsMentioned() -[src/message.js:229-231](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L229-L231 "Source code on GitHub") +

Subteams (groups) mentioned in the message

-Subteams (groups) mentioned in the message +### Message.everyoneMentioned() -Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** array of subteam IDs +

Was "@everyone" mentioned in the message

-## everyoneMentioned +### Message.channelMentioned() -[src/message.js:237-239](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L237-L239 "Source code on GitHub") +

Was the current "@channel" mentioned in the message

-Was "@everyone" mentioned in the message +### Message.hereMentioned() -## channelMentioned +

Was the current "@channel" mentioned in the message

-[src/message.js:245-247](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L245-L247 "Source code on GitHub") +### Message.linksMentioned() -Was the current "@channel" mentioned in the message +

Return the URLs of any links mentioned in the message

-## hereMentioned +### Message.stripDirectMention() -[src/message.js:253-255](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L253-L255 "Source code on GitHub") +

Strip the direct mention prefix from the message text and return it. The
original text is not modified

-Was the current "@channel" mentioned in the message +### Message._regexMentions() -## linksMentioned +

Returns array of regex matches from the text of a message

-[src/message.js:261-276](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L261-L276 "Source code on GitHub") +### Message._processInput() -Return the URLs of any links mentioned in the message +

Preprocess chat.postmessage input.

If an array, pick a random item of the array.
If a string, wrap in a chat.postmessage params object

-## stripDirectMention +# Contributing -[src/message.js:283-293](https://github.com/BeepBoopHQ/slackapp-js/blob/59256077fb3b9c34ad8e767105d6a80219b260cb/src/message.js#L283-L293 "Source code on GitHub") -Strip the direct mention prefix from the message text and return it. The -original text is not modified +# License diff --git a/package.json b/package.json index 87366182e..372909415 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "ava": "^0.15.2", "nyc": "^7.0.0", "sinon": "^1.17.4", + "dox": "^0.8.1", "standard": "^7.1.2" } } diff --git a/scripts/docs.js b/scripts/docs.js new file mode 100644 index 000000000..0b89d66fd --- /dev/null +++ b/scripts/docs.js @@ -0,0 +1,36 @@ +const dox = require('dox') +const fs = require('fs') + +// read source +const src = [ + { + name: 'SlackApp', + src: fs.readFileSync(__dirname + '/../src/slackapp.js', { encoding: 'utf8' }) + }, + { + name: 'Message', + src: fs.readFileSync(__dirname + '/../src/message.js', { encoding: 'utf8' }) + } +] + +let apiLines = [] + +src.forEach((item) => { + const comments = dox.parseComments(item.src) + + apiLines.push('## ' + src.name) + comments.forEach((i) => { + apiLines.push('### ' + item.name + '.' + i.ctx.string) + apiLines.push(i.description.full) + }) +}) + +let api = apiLines.join('\n\n') +let readme = fs.readFileSync(__dirname + '/../README.md', { encoding: 'utf8' }) +let parts = readme.split('# API\n') +let preamble = parts[0] +parts = parts[1].split('# Contributing\n') +let postamble = parts[1] + +let updatedReadme = [preamble, "# API", api, '# Contributing', postamble].join('\n\n') +fs.writeFileSync(__dirname + '/../README.md', updatedReadme) diff --git a/src/message.js b/src/message.js index a867be847..2c9f07248 100644 --- a/src/message.js +++ b/src/message.js @@ -40,8 +40,8 @@ module.exports = class Message { * be registered already through `slackapp.route` * * @param {string} fnKey - unique key to register function - * @param {Object={}} state - arbitrary data to be passed back to your function [optional] - * @param {number=3600} secondsToExpire - seconds to wait for the next message in the conversation before giving up. Default 60 minutes [optional] + * @param {Object=} state - arbitrary data to be passed back to your function [optional] + * @param {number} secondsToExpire - seconds to wait for the next message in the conversation before giving up. Default 60 minutes [optional] */ route (fnKey, state, secondsToExpire) { @@ -296,7 +296,7 @@ module.exports = class Message { /** * Returns array of regex matches from the text of a message * - * @private + * @api private */ _regexMentions (re) { @@ -320,7 +320,7 @@ module.exports = class Message { * If an array, pick a random item of the array. * If a string, wrap in a `chat.postmessage` params object * - * @private + * @api private */ _processInput (input) { diff --git a/src/slackapp.js b/src/slackapp.js index 9c99e73f1..33957adb1 100644 --- a/src/slackapp.js +++ b/src/slackapp.js @@ -5,31 +5,20 @@ const conversationStore = require('./conversation_store') const Receiver = require('./receiver') /** - * `slackapp` exposes a factory that takes an options object. - * - * ``` - * var SlackApp = require('slackapp') - * var slackapp = SlackApp(opts) - * ``` - * - * @class - * @param {Object} opts - * @param {string} opts.app_token - Slack App token override - * @param {string} opts.app_user_id - Slack App User ID (who installed the app) - * @param {string} opts.bot_token - Slack App Bot token - * @param {string} opts.bot_user_id - Slack App Bot ID - * @param {Object} opts.convo_store - Implementation of ConversationStore, defaults to memory - * @param {string} opts.error - Error handler function `(error) => {}` - * @returns {Object} SlackApp + * SlackApp module */ - module.exports = class SlackApp { /** - * SlackApp constructor + * Initialize a SlackApp, accepts an options object * - * Documented in index.js - * @private + * Options: + * - `app_token` Slack App token + * - `app_user_id` Slack App User ID (who installed the app) + * - `bot_token` Slack App Bot token + * - `bot_user_id` Slack App Bot ID + * - `convo_store` `string` of type of Conversation store (`memory`, etc.) or `object` implementation + * - `error` Error handler function `(error) => {}` */ constructor (opts) { @@ -64,8 +53,6 @@ module.exports = class SlackApp { /** * Initialize app w/ default middleware and receiver listener - * - * @private */ init () { // call `handle` for each new request @@ -81,7 +68,7 @@ module.exports = class SlackApp { * Middleware that gets an existing conversation from the conversation store * or initialize a new one. * - * @private + * @api private */ preprocessConversationMiddleware () { @@ -103,7 +90,7 @@ module.exports = class SlackApp { /** * Middleware that ignores messages from any bot user when we can tell * - * @private + * @api private */ ignoreBotsMiddleware () { @@ -116,12 +103,11 @@ module.exports = class SlackApp { } } - /** - * Register a new middleware, considered in order of registration - * @param {function} fn - (msg, next) => { } - * @param {message} fn.msg - instance of message - * @param {function} fn.next - next callback + * Register a new middleware + * + * Middleware is processed in the order registered. + * `fn` : (msg, next) => { } */ use (fn) { @@ -136,7 +122,7 @@ module.exports = class SlackApp { * - `msg` `Message` * - `done` `function(err, bool)` Callback called once complete, called with error and boolean indicating message was handled [optional] * - * @private + * @api private */ _handle (msg, done) { @@ -185,13 +171,12 @@ module.exports = class SlackApp { } /** - * Attach HTTP routes to an [Express](https://expressjs.com/) app and registers the following routes: - * - `POST` `/slack-event` - * - `POST` `/slack-command` - * - `POST` `/slack-action` - * - * @param {Object} app - instance of an express app + * Attach HTTP routes to an Express app * + * Routes are: + * - POST `/slack-event` + * - POST `/slack-command` + * - POST `/slack-action` */ attachToExpress (app) { @@ -201,9 +186,9 @@ module.exports = class SlackApp { /** * Register a new function route * - * @param {string} fnKey - unique function key - * @param {function} fn - callback (msg) => {} - * @param {message} fn.msg - instance of message + * Parameters + * - `fnKey` string - unique key to refer to function + * - `fn` function - `(msg) => {}` */ route (fnKey, fn) { @@ -215,7 +200,8 @@ module.exports = class SlackApp { /** * Return a registered route * - * @param {string} fnKey - unique function key + * Parameters + * - `fnKey` string - unique key to refer to function */ getRoute (fnKey) { @@ -236,9 +222,8 @@ module.exports = class SlackApp { * that they are efficient. However you may do asyncronous tasks within to * your hearts content. * - * @param {function} fn - match function `(msg) => { return bool }` - * @param {message} fn.msg - instance of Message - * @return {boolean} - was a match found and the message handled (otherwise continue looking) + * Parameters + * - `fn` function - match function `(msg) => { return bool }` */ match (fn) { @@ -248,20 +233,19 @@ module.exports = class SlackApp { } /** - * Register a new message handler function for the provided criteria. Types should be one or - * more of: + * Register a new message handler function for the criteria * - * - `direct_message` - * - `direct_mention` - * - `mention` - * - `ambient` - * - default: matches all if none provided + * Parameters: + * - `criteria` string or RegExp - message is string or match RegExp + * - `typeFilter` Array for list of values or string for one value [optional] + * * `direct_message` + * * `direct_mention` + * * `mention` + * * `ambient` + * * default: matches all if none provided + * - `callback` function - `(msg) => {}` * - * @param {(string|RegExp)} criteria - string of a regular expression or RexExp object - * @param {(string=|Array=)} typeFilter - list of types or string if just one - * @param {function} callback - (msg) => {} - * @param {message} callback.msg - instance of Message - * @example `msg` object: + * Example `msg` object: * * { * "token":"dxxxxxxxxxxxxxxxxxxxx", @@ -309,10 +293,11 @@ module.exports = class SlackApp { /** * Register a new event handler for an actionName * - * @param {(string|RegExp)} criteria - type of event or RegExp for more flexible matching - * @param {function} callback - (msg) => {} - * @param {message} callback.msg - instance of Message - * @example `msg` object: + * Parameters: + * - `criteria` string or RegExp - the type of event + * - `callback` function - `(msg) => {}` + * + * Example `msg` object: * * { * "token":"dxxxxxxxxxxxxxxxxxxxx", @@ -353,11 +338,12 @@ module.exports = class SlackApp { /** * Register a new action handler for an actionNameCriteria * - * @param {string} callbackId - Slack interactive message callback_id - * @param {(string|RegExp)=} actionNameCriteria - type of action or RegExp for more flexible matching - * @param {function} callback - (msg) => {} - * @param {message} callback.msg - instance of Message - * @example `msg` object: + * Parameters: + * - `callbackId` string + * - `actionNameCriteria` string or RegExp - the name of the action [optional] + * - `callback` function - `(msg) => {}` + * + * Example `msg` object: * * { * "actions":[ @@ -453,11 +439,12 @@ module.exports = class SlackApp { /** * Register a new slash command handler * - * @param {string} command - the slash command (e.g. "/doit") - * @param {(string|RegExp)=} criteria - matching criteria for slash command name (e.g "/^create.*$/") - * @param {function} callback - (msg) => {} - * @param {message} callback.msg - instance of Message - * @example `msg` object: + * Parameters: + * - `command` string - the slash command (e.g. "/doit") + * - `criteria` string or RegExp (e.g "/^create.*$/") [optional] + * - `callback` function - `(msg) => {}` + * + * Example `msg` object: * * { * "type":"command", From 3ca7883aca85107a28adbd39ddd817ad2411a70c Mon Sep 17 00:00:00 2001 From: Mike Brevoort Date: Sat, 23 Jul 2016 16:19:52 -0600 Subject: [PATCH 3/5] revert message.js --- scripts/docs.js | 13 +++++++---- src/message.js | 61 ++++++++++++++++++++++--------------------------- 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/scripts/docs.js b/scripts/docs.js index 0b89d66fd..e940de6a6 100644 --- a/scripts/docs.js +++ b/scripts/docs.js @@ -1,15 +1,18 @@ const dox = require('dox') const fs = require('fs') +const path = require('path') + +const readmePath = path.join(__dirname, '/../README.md') // read source const src = [ { name: 'SlackApp', - src: fs.readFileSync(__dirname + '/../src/slackapp.js', { encoding: 'utf8' }) + src: fs.readFileSync(path.join(__dirname, '/../src/slackapp.js', { encoding: 'utf8' })) }, { name: 'Message', - src: fs.readFileSync(__dirname + '/../src/message.js', { encoding: 'utf8' }) + src: fs.readFileSync(path.join(__dirname, '/../src/message.js', { encoding: 'utf8' })) } ] @@ -26,11 +29,11 @@ src.forEach((item) => { }) let api = apiLines.join('\n\n') -let readme = fs.readFileSync(__dirname + '/../README.md', { encoding: 'utf8' }) +let readme = fs.readFileSync(readmePath, { encoding: 'utf8' }) let parts = readme.split('# API\n') let preamble = parts[0] parts = parts[1].split('# Contributing\n') let postamble = parts[1] -let updatedReadme = [preamble, "# API", api, '# Contributing', postamble].join('\n\n') -fs.writeFileSync(__dirname + '/../README.md', updatedReadme) +let updatedReadme = [preamble, '# API', api, '# Contributing', postamble].join('\n\n') +fs.writeFileSync(readmePath, updatedReadme) diff --git a/src/message.js b/src/message.js index 2c9f07248..edd32a828 100644 --- a/src/message.js +++ b/src/message.js @@ -1,12 +1,7 @@ 'use strict' - const request = require('request') const slack = require('slack') -/** - * Message - * @class - */ module.exports = class Message { constructor (type, body, meta) { this.type = type @@ -36,12 +31,14 @@ module.exports = class Message { } /** - * Register the next function to route to in a conversation. The route should - * be registered already through `slackapp.route` + * Register the next function to route to in a conversation. + * + * The route should be registered already through `slackapp.route` * - * @param {string} fnKey - unique key to register function - * @param {Object=} state - arbitrary data to be passed back to your function [optional] - * @param {number} secondsToExpire - seconds to wait for the next message in the conversation before giving up. Default 60 minutes [optional] + * Parameters + * - `fnKey` `string` + * - `state` `object` arbitrary data to be passed back to your function [optional] + * - `secondsToExpire` `number` - number of seconds to wait for the next message in the conversation before giving up. Default 60 minutes [optional] */ route (fnKey, state, secondsToExpire) { @@ -71,15 +68,13 @@ module.exports = class Message { /** * Send a message through `chat.postmessage` that defaults to current channel and tokens * - * `input` may be one of: - * - type `object`: raw object that would be past to `chat.postmessage` - * - type `string`: text of a message that will be used to construct object sent to `chat.postmessage` - * - type `Array`: of strings or objects above to be picked randomly (can be mixed!) + * Parameters + * - `input` `string` or `object` or `Array` + * * type `object`: raw object that would be past to `chat.postmessage` + * * type `string`: text of a message that will be used to construct object sent to `chat.postmessage` + * * type `Array`: of strings or objects above to be picked randomly (can be mixed!) * - * @param {string|Object|Array} input - * @param {function} callback - (err, data) => {} - * @param {Error} callback.err - error object - * @param {Object} callback.data - data returned from call + * - `callback` string - (err, data) => {} */ say (input, callback) { @@ -99,16 +94,14 @@ module.exports = class Message { /** * Use a `response_url` from a Slash command or interactive message action * - * `input` may be one of: - * - type `object`: raw object that would be past to `chat.postmessage` - * - type `string`: text of a message that will be used to construct object sent to `chat.postmessage` - * - type `Array`: of strings or objects above to be picked randomly (can be mixed!) + * Parameters + * - `responseUrl` string - URL provided by a Slack interactive message action or slash command + * - `input` string or object or Array + * * type `object`: raw object that would be past to `chat.postmessage` + * * type `string`: text of a message that will be used to construct object sent to `chat.postmessage` + * * type `Array`: of strings or objects above to be picked randomly (can be mixed!) * - * @param {string} responseUrl - URL provided by a Slack interactive message action or slash command - * @param {string|Object|Array} input - * @param {function} callback - (err, data) => {} - * @param {Error} callback.err - error object - * @param {Object} callback.data - data returned from call + * - `callback` string - (err, data) => {} */ respond (responseUrl, input, callback) { @@ -142,7 +135,7 @@ module.exports = class Message { } /** - * @return {boolean} Is this an `event` of type `message`? + * Is this an `event` of type `message`? */ isMessage () { @@ -203,9 +196,9 @@ module.exports = class Message { } /** - * Users mentioned in the message + * Return the user IDs of any users mentioned in the message * - * @return {Array} array of user IDs + * Returns an Array of IDs */ usersMentioned () { @@ -213,9 +206,9 @@ module.exports = class Message { } /** - * Channels mentioned in the message + * Return the channel IDs of any channels mentioned in the message * - * @return {Array} array of channel IDs + * Returns an Array of IDs */ channelsMentioned () { @@ -223,9 +216,9 @@ module.exports = class Message { } /** - * Subteams (groups) mentioned in the message + * Return the IDs of any subteams (groups) mentioned in the message * - * @return {Array} array of subteam IDs + * Returns an Array of IDs */ subteamGroupsMentioned () { return this._regexMentions(new RegExp(']+>', 'g')) From e224cc07dd815042fa1fea0076b85489eb0432d5 Mon Sep 17 00:00:00 2001 From: Mike Brevoort Date: Sat, 23 Jul 2016 17:12:35 -0600 Subject: [PATCH 4/5] README update, `npm run docs` to update API docs --- README.md | 775 ++++++++++++++++++++++++++++++++++-------------- package.json | 3 +- scripts/docs.js | 125 +++++++- src/index.js | 34 ++- src/message.js | 152 ++++++++-- src/slackapp.js | 328 ++++++++++++-------- 6 files changed, 1034 insertions(+), 383 deletions(-) mode change 100644 => 100755 scripts/docs.js diff --git a/README.md b/README.md index 9f72e6073..d56a34962 100644 --- a/README.md +++ b/README.md @@ -3,248 +3,579 @@ # slackapp-js A node.js module for Slack App integrations - - - # API -## undefined - -### SlackApp.module.exports - -

SlackApp module

- -### SlackApp.constructor() - -

Initialize a SlackApp, accepts an options object

Options:

    -
  • app_token Slack App token
  • -
  • app_user_id Slack App User ID (who installed the app)
  • -
  • bot_token Slack App Bot token
  • -
  • bot_user_id Slack App Bot ID
  • -
  • convo_store string of type of Conversation store (memory, etc.) or object implementation
  • -
  • error Error handler function (error) => {}
  • -
- - -### SlackApp.init() - -

Initialize app w/ default middleware and receiver listener

- -### SlackApp.preprocessConversationMiddleware() - -

Middleware that gets an existing conversation from the conversation store
or initialize a new one.

- -### SlackApp.ignoreBotsMiddleware() - -

Middleware that ignores messages from any bot user when we can tell

- -### SlackApp.use() - -

Register a new middleware

Middleware is processed in the order registered.
fn : (msg, next) => { }

- -### SlackApp._handle() - -

Handle new events (slack events, commands, actions, webhooks, etc.)

- -### SlackApp.attachToExpress() - -

Attach HTTP routes to an Express app

Routes are:

    -
  • POST /slack-event
  • -
  • POST /slack-command
  • -
  • POST /slack-action
  • -
- - -### SlackApp.route() - -

Register a new function route

Parameters

    -
  • fnKey string - unique key to refer to function
  • -
  • fn function - (msg) => {}
  • -
- - -### SlackApp.getRoute() - -

Return a registered route

Parameters

    -
  • fnKey string - unique key to refer to function
  • -
- - -### SlackApp.match() - -

Register a custom Match function (fn)

$eturns true if there is a match AND you handled the msg.
Return false if there is not a match and you pass on the message.

All of the higher level matching convenience functions
generate a match function and call match to register it.

Only one matcher can return true and they are executed in the order they are
defined. Match functions should return as fast as possible because it's important
that they are efficient. However you may do asyncronous tasks within to
your hearts content.

Parameters

    -
  • fn function - match function (msg) => { return bool }
  • -
- - -### SlackApp.message() - -

Register a new message handler function for the criteria

Parameters:

    -
  • criteria string or RegExp - message is string or match RegExp
  • -
  • typeFilter Array for list of values or string for one value [optional]
      -
    • direct_message
    • -
    • direct_mention
    • -
    • mention
    • -
    • ambient
    • -
    • default: matches all if none provided
    • -
    -
  • -
  • callback function - (msg) => {}
  • -
-

Example msg object:

{
"token":"dxxxxxxxxxxxxxxxxxxxx",
"team_id":"TXXXXXXXX",
"api_app_id":"AXXXXXXXX",
"event":{
"type":"message",
"user":"UXXXXXXXX",
"text":"hello!",
"ts":"1469130107.000088",
"channel":"DXXXXXXXX"
},
"event_ts":"1469130107.000088",
"type":"event_callback",
"authed_users":[
"UXXXXXXXX"
]
}

- -### SlackApp.event() - -

Register a new event handler for an actionName

Parameters:

    -
  • criteria string or RegExp - the type of event
  • -
  • callback function - (msg) => {}
  • -
-

Example msg object:

{
"token":"dxxxxxxxxxxxxxxxxxxxx",
"team_id":"TXXXXXXXX",
"api_app_id":"AXXXXXXXX",
"event":{
"type":"reaction_added",
"user":"UXXXXXXXX",
"item":{
"type":"message",
"channel":"DXXXXXXXX",
"ts":"1469130181.000096"
},
"reaction":"grinning"
},
"event_ts":"1469131201.822817",
"type":"event_callback",
"authed_users":[
"UXXXXXXXX"
]
}

- -### SlackApp.action() +# slackapp + + - [slackapp()](#slackappoptsobject) + +## slackapp(opts:Object) + + Create a new SlackApp, accepts an options object + + Parameters + - `opts.app_token` Slack App token override + - `opts.app_user_id` Slack App User ID (who installed the app) + - `opts.bot_token` Slack App Bot token + - `opts.bot_user_id` Slack App Bot ID + - `opts.convo_store` Implementation of ConversationStore, defaults to memory + - `opts.error` Error handler function `(error) => {}` + + Example + + +```js + var SlackApp = require('slackapp') + var BeepBoopConvoStore = require('slackapp-convo-beepboop') + var slackapp = SlackApp({ + debug: true, + record: 'out.jsonl', + convo_store: BeepBoopConvoStore({ debug: true }), + error: (err) => { console.error('Error: ', err) } + }) +``` + + + +# SlackApp + + - [SlackApp.use()](#slackappusefnfunction) + - [Parameters](#parameters) + - [Returns](#returns) + - [SlackApp.attachToExpress()](#slackappattachtoexpressappobject) + - [Parameters](#parameters) + - [Returns](#returns) + - [SlackApp.route()](#slackapproutefnkeystringfnfunction) + - [Parameters](#parameters) + - [Returns](#returns) + - [SlackApp.getRoute()](#slackappgetroutefnkeystring) + - [Parameters](#parameters) + - [Returns](#returns) + - [SlackApp.match()](#slackappmatchfnfunction) + - [Returns `true` if there is a match AND you handled the msg.](#returnstrueifthereisamatchandyouhandledthemsg) + - [Parameters](#parameters) + - [Returns](#returns) + - [SlackApp.message()](#slackappmessagecriteriastringtypefilterstringarray) + - [Parameters](#parameters) + - [Returns](#returns) + - [SlackApp.event()](#slackappeventcriteriastringregexpcallbackfunction) + - [Parameters](#parameters) + - [Returns](#returns) + - [SlackApp.action()](#slackappactioncallbackidstringactionnamecriteriastringregexpcallbackfunction) + - [Parameters](#parameters) + - [Returns](#returns) + - [SlackApp.command()](#slackappcommandcommandstringcriteriastringregexpcallbackfunction) + - [Parameters](#parameters) + - [Returns](#returns) + +## SlackApp.use(fn:function) + + Register a new middleware, processed in the order registered. + +#### Parameters + - `fn`: middleware function `(msg, next) => { }` + + +#### Returns + - `this` (chainable) + +## SlackApp.attachToExpress(app:Object) + + Attach HTTP routes to an Express app + + Routes are: + - POST `/slack-event` + - POST `/slack-command` + - POST `/slack-action` + +#### Parameters + - `app` instance of Express app + + +#### Returns + - `app` reference to Express app passed in + +## SlackApp.route(fnKey:string, fn:function) + + Register a new function route + +#### Parameters + - `fnKey` unique key to refer to function + - `fn` `(msg, state) => {}` + + +#### Returns + - `this` (chainable) + +## SlackApp.getRoute(fnKey:string) + + Return a registered route + +#### Parameters + - `fnKey` string - unique key to refer to function + + +#### Returns + - `(msg, state) => {}` + +## SlackApp.match(fn:function) + + Register a custom Match function (fn) + +#### Returns `true` if there is a match AND you handled the msg. + Return `false` if there is not a match and you pass on the message. + + All of the higher level matching convenience functions + generate a match function and call `match` to register it. + + Only one matcher can return true, and they are executed in the order they are + defined. Match functions should return as fast as possible because it's important + that they are efficient. However you may do asyncronous tasks within to + your hearts content. + +#### Parameters + - `fn` function - match function `(msg) => { return bool }` + + +#### Returns + - `this` (chainable) + +## SlackApp.message(criteria:string, typeFilter:string|Array) + + Register a new message handler function for the criteria + +#### Parameters + - `criteria` text that message contains or regex (e.g. "^hi") + - `typeFilter` [optional] Array for multiple values or string for one value. Valid values are `direct_message`, `direct_mention`, `mention`, `ambient` + - `callback` function - `(msg) => {}` + + +#### Returns + - `this` (chainable) + + + Example `msg` object: + +```js + { + "token":"dxxxxxxxxxxxxxxxxxxxx", + "team_id":"TXXXXXXXX", + "api_app_id":"AXXXXXXXX", + "event":{ + "type":"message", + "user":"UXXXXXXXX", + "text":"hello!", + "ts":"1469130107.000088", + "channel":"DXXXXXXXX" + }, + "event_ts":"1469130107.000088", + "type":"event_callback", + "authed_users":[ + "UXXXXXXXX" + ] + } +``` + +## SlackApp.event(criteria:string|RegExp, callback:function) + + Register a new event handler for an actionName + +#### Parameters + - `criteria` the type of event + - `callback` `(msg) => {}` + + +#### Returns + - `this` (chainable) + + + Example `msg` object: + +```js + { + "token":"dxxxxxxxxxxxxxxxxxxxx", + "team_id":"TXXXXXXXX", + "api_app_id":"AXXXXXXXX", + "event":{ + "type":"reaction_added", + "user":"UXXXXXXXX", + "item":{ + "type":"message", + "channel":"DXXXXXXXX", + "ts":"1469130181.000096" + }, + "reaction":"grinning" + }, + "event_ts":"1469131201.822817", + "type":"event_callback", + "authed_users":[ + "UXXXXXXXX" + ] + } +``` + +## SlackApp.action(callbackId:string, actionNameCriteria:string|RegExp, callback:function) + + Register a new action handler for an actionNameCriteria + +#### Parameters + - `callbackId` string + - `actionNameCriteria` string or RegExp - the name of the action [optional] + - `callback` function - `(msg) => {}` + + +#### Returns + - `this` (chainable) + + + Example `msg` object: + +```js + { + "actions":[ + { + "name":"answer", + "value":":wine_glass:" + } + ], + "callback_id":"in_or_out_callback", + "team":{ + "id":"TXXXXXXXX", + "domain":"companydomain" + }, + "channel":{ + "id":"DXXXXXXXX", + "name":"directmessage" + }, + "user":{ + "id":"UXXXXXXXX", + "name":"mike.brevoort" + }, + "action_ts":"1469129995.067370", + "message_ts":"1469129988.000084", + "attachment_id":"1", + "token":"dxxxxxxxxxxxxxxxxxxxx", + "original_message":{ + "text":"What?", + "username":"In or Out", + "bot_id":"BXXXXXXXX", + "attachments":[ + { + "callback_id":"in_or_out_callback", + "fallback":"Pick one", + "id":1, + "actions":[ + { + "id":"1", + "name":"answer", + "text":":beer:", + "type":"button", + "value":":beer:", + "style":"" + }, + { + "id":"2", + "name":"answer", + "text":":beers:", + "type":"button", + "value":":wine:", + "style":"" + }, + ] + }, + { + "text":":beers: • mike.brevoort", + "id":2, + "fallback":"who picked beers" + } + ], + "type":"message", + "subtype":"bot_message", + "ts":"1469129988.000084" + }, + "response_url":"https://hooks.slack.com/actions/TXXXXXXXX/111111111111/txxxxxxxxxxxxxxxxxxxx" + } +``` + +## SlackApp.command(command:string, criteria:string|RegExp, callback:function) + + Register a new slash command handler + +#### Parameters + - `command` string - the slash command (e.g. "/doit") + - `criteria` string or RegExp (e.g "/^create.+$/") [optional] + - `callback` function - `(msg) => {}` + + +#### Returns + - `this` (chainable) + + + Example `msg` object: + +```js + { + "type":"command", + "body":{ + "token":"xxxxxxxxxxxxxxxxxxx", + "team_id":"TXXXXXXXX", + "team_domain":"teamxxxxxxx", + "channel_id":"Dxxxxxxxx", + "channel_name":"directmessage", + "user_id":"Uxxxxxxxx", + "user_name":"xxxx.xxxxxxxx", + "command":"/doit", + "text":"whatever was typed after command", + "response_url":"https://hooks.slack.com/commands/TXXXXXXXX/111111111111111111111111111" + }, + "resource":{ + "app_token":"xoxp-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX", + "app_user_id":"UXXXXXXXX", + "bot_token":"xoxb-XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXX", + "bot_user_id":"UXXXXXXXX" + }, + "meta":{ + "user_id":"UXXXXXXXX", + "channel_id":"DXXXXXXXX", + "team_id":"TXXXXXXXX" + }, + } +``` + + + +# Message + + +A Message object is created for every incoming Slack event, slash command, and interactive message action. +It is generally always passed as `msg`. + +`msg` has three main top level properties +- `type` - one of `event`, `command`, `action` +- `body` - the unmodified payload of the original event +- `meta` - derived or normalized properties and anything appended by middleware. + + +`meta` should at least have these properties +- `` +- `app_token` - token for the user for the app +- `app_user_id` - userID for the user who install ed the app +- `bot_token` - token for a bot user of the app +- `bot_user_id` - userID of the bot user of the app + + + - [Message.constructor()](#messageconstructortypestringbodyobjectmetaobject) + - [Parameters](#parameters) + - [Message.route()](#messageroutefnkeystringstateobjectsecondstoexpirenumber) + - [Parameters](#parameters) + - [Returns](#returns) + - [Message.cancel()](#messagecancel) + - [Message.say()](#messagesayinputstringobjectarraycallbackfunction) + - [Parameters](#parameters) + - [Returns](#returns) + - [Message.respond()](#messagerespondresponseurlstringinputstringobjectarraycallbackfunction) + - [Parameters](#parameters) + - [Returns](#returns) + - [Message.isMessage()](#messageismessage) + - [Returns `bool` true if `this` is a message event type](#returnsbooltrueifthisisamessageeventtype) + - [Message.isDirectMention()](#messageisdirectmention) + - [Returns `bool` true if `this` is a direct mention](#returnsbooltrueifthisisadirectmention) + - [Message.isDirectMessage()](#messageisdirectmessage) + - [Returns `bool` true if `this` is a direct message](#returnsbooltrueifthisisadirectmessage) + - [Message.isMention()](#messageismention) + - [Returns `bool` true if `this` mentions the bot user](#returnsbooltrueifthismentionsthebotuser) + - [Message.isAmbient()](#messageisambient) + - [Returns `bool` true if `this` is an ambient message](#returnsbooltrueifthisisanambientmessage) + - [Message.isAnyOf()](#messageisanyofofarray) + - [Parameters](#parameters) + - [Returns `bool` true if `this` is a message that matches any of the filters](#returnsbooltrueifthisisamessagethatmatchesanyofthefilters) + - [Message.usersMentioned()](#messageusersmentioned) + - [Returns an Array of user IDs](#returnsanarrayofuserids) + - [Message.channelsMentioned()](#messagechannelsmentioned) + - [Returns an Array of channel IDs](#returnsanarrayofchannelids) + - [Message.subteamGroupsMentioned()](#messagesubteamgroupsmentioned) + - [Returns an Array of subteam IDs](#returnsanarrayofsubteamids) + - [Message.everyoneMentioned()](#messageeveryonementioned) + - [Returns `bool` true if `@everyone` was mentioned](#returnsbooltrueifeveryonewasmentioned) + - [Message.channelMentioned()](#messagechannelmentioned) + - [Returns `bool` true if `@channel` was mentioned](#returnsbooltrueifchannelwasmentioned) + - [Message.hereMentioned()](#messageherementioned) + - [Returns `bool` true if `@here` was mentioned](#returnsbooltrueifherewasmentioned) + - [Message.linksMentioned()](#messagelinksmentioned) + - [Returns `Array:string` of URLs of links mentioned in the message](#returnsarraystringofurlsoflinksmentionedinthemessage) + - [Message.stripDirectMention()](#messagestripdirectmention) + - [Returns `string` original `text` of message with a direct mention of the bot](#returnsstringoriginaltextofmessagewithadirectmentionofthebot) + +## Message.constructor(type:string, body:Object, meta:Object) + + Construct a new Message + +#### Parameters + - `type` the type of message (event, command, action, etc.) + +## Message.route(fnKey:string, state:Object, secondsToExpire:number) + + Register the next function to route to in a conversation. + + The route should be registered already through `slackapp.route` + +#### Parameters + - `fnKey` `string` + - `state` `object` arbitrary data to be passed back to your function [optional] + - `secondsToExpire` `number` - number of seconds to wait for the next message in the conversation before giving up. Default 60 minutes [optional] + + +#### Returns + - `this` (chainable) + +## Message.cancel() + + Explicity cancel pending `route` registration. + +## Message.say(input:string|Object|Array, callback:function) + + Send a message through [`chat.postmessage`](https://api.slack.com/methods/chat.postMessage). + + The current channel and inferred tokens are used as defaults. `input` maybe a + `string`, `Object` or mixed `Array` of `strings` and `Objects`. If a string, + the value will be set to `text` of the `chat.postmessage` object. Otherwise pass + a [`chat.postmessage`](https://api.slack.com/methods/chat.postMessage) `Object`. + + If `input` is an `Array`, a random value in the array will be selected. + +#### Parameters + - `input` the payload to send, maybe a string, Object or Array. + - `callback` (err, data) => {} + + +#### Returns + - `this` (chainable) + +## Message.respond(responseUrl:string, input:string|Object|Array, callback:function) + + Use a `response_url` from a Slash command or interactive message action with + a [`chat.postmessage`](https://api.slack.com/methods/chat.postMessage) payload. + `input` options are the same as [`say`](#messagesay) + +#### Parameters + - `responseUrl` string - URL provided by a Slack interactive message action or slash command + - `input` the payload to send, maybe a string, Object or Array. + - `callback` (err, data) => {} + + +#### Returns + - `this` (chainable) + +## Message.isMessage() + + Is this an `event` of type `message`? + + +#### Returns `bool` true if `this` is a message event type + +## Message.isDirectMention() + + Is this a message that is a direct mention ("@botusername: hi there", "@botusername goodbye!") + + +#### Returns `bool` true if `this` is a direct mention + +## Message.isDirectMessage() + + Is this a message in a direct message channel (one on one) + + +#### Returns `bool` true if `this` is a direct message + +## Message.isMention() + + Is this a message where the bot user mentioned anywhere in the message. + Only checks for mentions of the bot user and does not consider any other users. + + +#### Returns `bool` true if `this` mentions the bot user + +## Message.isAmbient() + + Is this a message that's not a direct message or that mentions that bot at + all (other users could be mentioned) + + +#### Returns `bool` true if `this` is an ambient message + +## Message.isAnyOf(of:Array) -

Register a new action handler for an actionNameCriteria

Parameters:

    -
  • callbackId string
  • -
  • actionNameCriteria string or RegExp - the name of the action [optional]
  • -
  • callback function - (msg) => {}
  • -
-

Example msg object:

{
"actions":[
{
"name":"answer",
"value":":wine_glass:"
}
],
"callback_id":"in_or_out_callback",
"team":{
"id":"TXXXXXXXX",
"domain":"companydomain"
},
"channel":{
"id":"DXXXXXXXX",
"name":"directmessage"
},
"user":{
"id":"UXXXXXXXX",
"name":"mike.brevoort"
},
"action_ts":"1469129995.067370",
"message_ts":"1469129988.000084",
"attachment_id":"1",
"token":"dxxxxxxxxxxxxxxxxxxxx",
"original_message":{
"text":"What?",
"username":"In or Out",
"bot_id":"BXXXXXXXX",
"attachments":[
{
"callback_id":"in_or_out_callback",
"fallback":"Pick one",
"id":1,
"actions":[
{
"id":"1",
"name":"answer",
"text":":beer:",
"type":"button",
"value":":beer:",
"style":""
},
{
"id":"2",
"name":"answer",
"text":":beers:",
"type":"button",
"value":":wine:",
"style":""
},
]
},
{
"text":":beers: • mike.brevoort",
"id":2,
"fallback":"who picked beers"
}
],
"type":"message",
"subtype":"bot_message",
"ts":"1469129988.000084"
},
"response_url":"https://hooks.slack.com/actions/TXXXXXXXX/111111111111/txxxxxxxxxxxxxxxxxxxx"

+ Is this a message that matches any one of the filters + +#### Parameters + - `messageFilters` Array - any of `direct_message`, `direct_mention`, `mention` and `ambient` + + +#### Returns `bool` true if `this` is a message that matches any of the filters -### SlackApp.command() +## Message.usersMentioned() + + Return the user IDs of any users mentioned in the message + +#### Returns an Array of user IDs + +## Message.channelsMentioned() -

Register a new slash command handler

Parameters:

    -
  • command string - the slash command (e.g. "/doit")
  • -
  • criteria string or RegExp (e.g "/^create.*$/") [optional]
  • -
  • callback function - (msg) => {}
  • -
-

Example msg object:

{
-   "type":"command",
-   "body":{
-      "token":"xxxxxxxxxxxxxxxxxxx",
-      "team_id":"TXXXXXXXX",
-      "team_domain":"teamxxxxxxx",
-      "channel_id":"Dxxxxxxxx",
-      "channel_name":"directmessage",
-      "user_id":"Uxxxxxxxx",
-      "user_name":"xxxx.xxxxxxxx",
-      "command":"/doit",
-      "text":"whatever was typed after command",
-      "response_url":"https://hooks.slack.com/commands/TXXXXXXXX/111111111111111111111111111"
-   },
-   "resource":{
-      "app_token":"xoxp-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX",
-      "app_user_id":"UXXXXXXXX",
-      "bot_token":"xoxb-XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXX",
-      "bot_user_id":"UXXXXXXXX"
-   },
-   "meta":{
-      "user_id":"UXXXXXXXX",
-      "channel_id":"DXXXXXXXX",
-      "team_id":"TXXXXXXXX"
-   },
-}
-
+ Return the channel IDs of any channels mentioned in the message + +#### Returns an Array of channel IDs -## undefined +## Message.subteamGroupsMentioned() -### Message.module.exports + Return the IDs of any subteams (groups) mentioned in the message + +#### Returns an Array of subteam IDs -

Message

+## Message.everyoneMentioned() -### Message.route() + Was "@everyone" mentioned in the message + +#### Returns `bool` true if `@everyone` was mentioned -

Register the next function to route to in a conversation. The route should
be registered already through slackapp.route

+## Message.channelMentioned() -### Message.cancel() + Was the current "@channel" mentioned in the message + +#### Returns `bool` true if `@channel` was mentioned -

Explicity cancel route registration.

+## Message.hereMentioned() -### Message.say() + Was the "@here" mentioned in the message + +#### Returns `bool` true if `@here` was mentioned -

Send a message through chat.postmessage that defaults to current channel and tokens

input may be one of:

    -
  • type object: raw object that would be past to chat.postmessage
  • -
  • type string: text of a message that will be used to construct object sent to chat.postmessage
  • -
  • type Array: of strings or objects above to be picked randomly (can be mixed!)
  • -
+## Message.linksMentioned() + Return the URLs of any links mentioned in the message + +#### Returns `Array:string` of URLs of links mentioned in the message -### Message.respond() +## Message.stripDirectMention() -

Use a response_url from a Slash command or interactive message action

input may be one of:

    -
  • type object: raw object that would be past to chat.postmessage
  • -
  • type string: text of a message that will be used to construct object sent to chat.postmessage
  • -
  • type Array: of strings or objects above to be picked randomly (can be mixed!)
  • -
+ Strip the direct mention prefix from the message text and return it. The + original text is not modified + + +#### Returns `string` original `text` of message with a direct mention of the bot + user removed. For example, `@botuser hi` or `@botuser: hi` would produce `hi`. + `@notbotuser hi` would produce `@notbotuser hi` -### Message.isMessage() - - - -### Message.isDirectMention() - -

Is this a message that is a direct mention ("@botusername: hi there", "@botusername goodbye!")

- -### Message.isDirectMessage() - -

Is this a message in a direct message channel (one on one)

- -### Message.isMention() - -

Is this a message where the bot user mentioned anywhere in the message.
This only checks for the bot user and does not consider any other users

- -### Message.isAmbient() - -

Is this a message that's not a direct message or that mentions that bot at
all (other users could be mentioned)

- -### Message.isAnyOf() - -

Is this a message that matches any one of these filter types

Parameters:

    -
  • messageFilters Array - any of direct_message, direct_mention, mention or ambient
  • -
- - -### Message.usersMentioned() - -

Users mentioned in the message

- -### Message.channelsMentioned() - -

Channels mentioned in the message

- -### Message.subteamGroupsMentioned() - -

Subteams (groups) mentioned in the message

- -### Message.everyoneMentioned() - -

Was "@everyone" mentioned in the message

- -### Message.channelMentioned() - -

Was the current "@channel" mentioned in the message

- -### Message.hereMentioned() - -

Was the current "@channel" mentioned in the message

- -### Message.linksMentioned() - -

Return the URLs of any links mentioned in the message

- -### Message.stripDirectMention() - -

Strip the direct mention prefix from the message text and return it. The
original text is not modified

- -### Message._regexMentions() - -

Returns array of regex matches from the text of a message

- -### Message._processInput() - -

Preprocess chat.postmessage input.

If an array, pick a random item of the array.
If a string, wrap in a chat.postmessage params object

- # Contributing +We adore contributions. Please include the details of the proposed changes in a Pull Request and ensure `npm run test` pass. 👻 + +### Scripts +- `npm test` - runs linter and tests with coverage +- `npm run unit` - runs unit tests without coverage +- `npm run lint` - just runs JS standard linter +- `npm run coverage` - runs tests with coverage +- `npm run docs` - regenerates API docs in this README.md # License +MIT Copyright (c) 2016 Beep Boop, Robots & Pencils diff --git a/package.json b/package.json index 372909415..95b321ddd 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "test": "npm run lint && npm run coverage", "lint": "standard", "unit": "ava --verbose", - "coverage": "nyc ava --verbose" + "coverage": "nyc ava --verbose", + "docs": "node scripts/docs.js" }, "repository": { "type": "git", diff --git a/scripts/docs.js b/scripts/docs.js old mode 100644 new mode 100755 index e940de6a6..f881c72b3 --- a/scripts/docs.js +++ b/scripts/docs.js @@ -1,3 +1,4 @@ +'use strict' const dox = require('dox') const fs = require('fs') const path = require('path') @@ -6,26 +7,42 @@ const readmePath = path.join(__dirname, '/../README.md') // read source const src = [ + { + name: 'slackapp', + src: fs.readFileSync(path.join(__dirname, '/../src/index.js'), { encoding: 'utf8' }) + }, { name: 'SlackApp', - src: fs.readFileSync(path.join(__dirname, '/../src/slackapp.js', { encoding: 'utf8' })) + src: fs.readFileSync(path.join(__dirname, '/../src/slackapp.js'), { encoding: 'utf8' }) }, { name: 'Message', - src: fs.readFileSync(path.join(__dirname, '/../src/message.js', { encoding: 'utf8' })) + description: ` +A Message object is created for every incoming Slack event, slash command, and interactive message action. +It is generally always passed as \`msg\`. + +\`msg\` has three main top level properties +- \`type\` - one of \`event\`, \`command\`, \`action\` +- \`body\` - the unmodified payload of the original event +- \`meta\` - derived or normalized properties and anything appended by middleware. + +\`meta\` should at least have these properties +- \`app_token\` - token for the user for the app +- \`app_user_id\` - userID for the user who install ed the app +- \`bot_token\` - token for a bot user of the app +- \`bot_user_id\` - userID of the bot user of the app + `, + src: fs.readFileSync(path.join(__dirname, '/../src/message.js'), { encoding: 'utf8' }) } ] let apiLines = [] src.forEach((item) => { - const comments = dox.parseComments(item.src) - - apiLines.push('## ' + src.name) - comments.forEach((i) => { - apiLines.push('### ' + item.name + '.' + i.ctx.string) - apiLines.push(i.description.full) - }) + const comments = dox.parseComments(item.src, { raw: true }) + apiLines.push('# ' + item.name) + if (item.description) apiLines.push(item.description) + apiLines.push(formatDoxComments(comments)) }) let api = apiLines.join('\n\n') @@ -35,5 +52,93 @@ let preamble = parts[0] parts = parts[1].split('# Contributing\n') let postamble = parts[1] -let updatedReadme = [preamble, '# API', api, '# Contributing', postamble].join('\n\n') +let updatedReadme = [preamble, '# API\n\n', api, '\n\n# Contributing\n', postamble].join('') fs.writeFileSync(readmePath, updatedReadme) + +/** + * Adapted from dox source + */ + +function formatDoxComments (comments) { + var buf = [] + console.log(JSON.stringify(comments)) + + comments.forEach(function (comment) { + if (comment.isPrivate) return + if (comment.ignore) return + var ctx = comment.ctx + var desc = comment.description + if (!ctx) return + if (~desc.full.indexOf('Module dependencies')) return + if (!ctx.string.indexOf('module.exports')) return + buf.push('### ' + context(comment)) + buf.push('') + buf.push(desc.full.trim().replace(/^/gm, ' ')) + buf.push('') + }) + + buf = buf + .join('\n') + .replace(/^ *#/gm, '') + + var code = buf.match(/^( {4}[^\n]+\n*)+/gm) || [] + + code.forEach(function (block) { + var code = block.replace(/^ {4}/gm, '') + buf = buf.replace(block, '```js\n' + code.trimRight() + '\n```\n\n') + }) + + return toc(buf) + '\n\n' + buf +} + +function toc (str) { + return headings(str).map(function (h) { + var clean = h.title.replace(/\(.*?\)/, '()') + return ' - [' + clean + '](#' + slug(h.title) + ')' + }).join('\n') +} + +function slug (str) { + return str.replace(/\W+/g, '').toLowerCase() +} + +function headings (str) { + return (str.match(/^#+ *([^\n]+)/gm) || []).map(function (str) { + str = str.replace(/^(#+) */, '') + return { + title: str, + level: RegExp.$1.length + } + }) +} + +function context (comment) { + var ctx = comment.ctx + var tags = comment.tags + + var alias = tags.map(function (tag) { + return tag.type === 'alias' && tag.string + }).filter(Boolean) + + let name + + switch (ctx.type) { + case 'function': + name = alias.pop() || ctx.name + return name + '(' + params(tags) + ')' + case 'method': + case 'constructor': + name = alias.pop() || (ctx.cons || ctx.receiver) + '.' + ctx.name + return name + '(' + params(tags) + ')' + default: + return alias.pop() || ctx.string + } +} + +function params (tags) { + return tags.filter(function (tag) { + return tag.type === 'param' + }).map(function (param) { + return param.name + ':' + param.types.join('|') + }).join(', ') +} diff --git a/src/index.js b/src/index.js index de99044d7..c65382916 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,39 @@ const SlackApp = require('./slackapp') -module.exports = (opts) => { +/** + * Create a new SlackApp, accepts an options object + * + * Parameters + * - `opts.app_token` Slack App token override + * - `opts.app_user_id` Slack App User ID (who installed the app) + * - `opts.bot_token` Slack App Bot token + * - `opts.bot_user_id` Slack App Bot ID + * - `opts.convo_store` Implementation of ConversationStore, defaults to memory + * - `opts.error` Error handler function `(error) => {}` + * + * Example + * + * + * var SlackApp = require('slackapp') + * var BeepBoopConvoStore = require('slackapp-convo-beepboop') + * var slackapp = SlackApp({ + * debug: true, + * record: 'out.jsonl', + * convo_store: BeepBoopConvoStore({ debug: true }), + * error: (err) => { console.error('Error: ', err) } + * }) + * + * + * @param {Object} opts + * @returns {Object} SlackApp + * @function slackapp + * @alias slackapp + */ + +function factory (opts) { let app = new SlackApp(opts) return app.init() } + +module.exports = factory diff --git a/src/message.js b/src/message.js index edd32a828..c86d1bff7 100644 --- a/src/message.js +++ b/src/message.js @@ -2,7 +2,24 @@ const request = require('request') const slack = require('slack') -module.exports = class Message { +/** + * A Slack event message (command, action, event, etc.) + * @class Message + * @api private + */ +class Message { + + /** + * Construct a new Message + * + * ##### Parameters + * - `type` the type of message (event, command, action, etc.) + * + * @param {string} type + * @param {Object} body + * @param {Object} meta + * @constructor + */ constructor (type, body, meta) { this.type = type this.body = body @@ -12,10 +29,34 @@ module.exports = class Message { this._slackapp = null } + /** + * Attach a SlackApp reference + * + * ##### Parameters + * - `slackapp` instance of SlackApp + * + * @param {SlackApp} slackapp + * @api private + */ attachSlackApp (slackapp) { this._slackapp = slackapp } + /** + * Attach override handler in a conversation + * + * ##### Parameters + * - `fnKey` function key + * - `state` saved state to be passed onto router handler + * + * + * ##### Returns + * - `this` (chainable) + * + * @param {string} fnKey + * @param {Object} state + * @api private + */ attachOverrideRoute (fnKey, state) { let fn = this._slackapp.getRoute(fnKey) @@ -35,10 +76,18 @@ module.exports = class Message { * * The route should be registered already through `slackapp.route` * - * Parameters + * ##### Parameters * - `fnKey` `string` * - `state` `object` arbitrary data to be passed back to your function [optional] * - `secondsToExpire` `number` - number of seconds to wait for the next message in the conversation before giving up. Default 60 minutes [optional] + * + * + * ##### Returns + * - `this` (chainable) + * + * @param {string} fnKey + * @param {Object} state + * @param {number} secondsToExpire */ route (fnKey, state, secondsToExpire) { @@ -58,7 +107,7 @@ module.exports = class Message { } /** - * Explicity cancel `route` registration. + * Explicity cancel pending `route` registration. */ cancel () { @@ -66,15 +115,25 @@ module.exports = class Message { } /** - * Send a message through `chat.postmessage` that defaults to current channel and tokens + * Send a message through [`chat.postmessage`](https://api.slack.com/methods/chat.postMessage). + * + * The current channel and inferred tokens are used as defaults. `input` maybe a + * `string`, `Object` or mixed `Array` of `strings` and `Objects`. If a string, + * the value will be set to `text` of the `chat.postmessage` object. Otherwise pass + * a [`chat.postmessage`](https://api.slack.com/methods/chat.postMessage) `Object`. + * + * If `input` is an `Array`, a random value in the array will be selected. + * + * ##### Parameters + * - `input` the payload to send, maybe a string, Object or Array. + * - `callback` (err, data) => {} + * * - * Parameters - * - `input` `string` or `object` or `Array` - * * type `object`: raw object that would be past to `chat.postmessage` - * * type `string`: text of a message that will be used to construct object sent to `chat.postmessage` - * * type `Array`: of strings or objects above to be picked randomly (can be mixed!) + * ##### Returns + * - `this` (chainable) * - * - `callback` string - (err, data) => {} + * @param {(string|Object|Array)} input + * @param {function} callback */ say (input, callback) { @@ -92,16 +151,22 @@ module.exports = class Message { } /** - * Use a `response_url` from a Slash command or interactive message action + * Use a `response_url` from a Slash command or interactive message action with + * a [`chat.postmessage`](https://api.slack.com/methods/chat.postMessage) payload. + * `input` options are the same as [`say`](#messagesay) * - * Parameters + * ##### Parameters * - `responseUrl` string - URL provided by a Slack interactive message action or slash command - * - `input` string or object or Array - * * type `object`: raw object that would be past to `chat.postmessage` - * * type `string`: text of a message that will be used to construct object sent to `chat.postmessage` - * * type `Array`: of strings or objects above to be picked randomly (can be mixed!) + * - `input` the payload to send, maybe a string, Object or Array. + * - `callback` (err, data) => {} * - * - `callback` string - (err, data) => {} + * + * ##### Returns + * - `this` (chainable) + * + * @param {string} responseUrl + * @param {(string|Object|Array)} input + * @param {function} callback */ respond (responseUrl, input, callback) { @@ -136,6 +201,9 @@ module.exports = class Message { /** * Is this an `event` of type `message`? + * + * + * ##### Returns `bool` true if `this` is a message event type */ isMessage () { @@ -144,6 +212,9 @@ module.exports = class Message { /** * Is this a message that is a direct mention ("@botusername: hi there", "@botusername goodbye!") + * + * + * ##### Returns `bool` true if `this` is a direct mention */ isDirectMention () { @@ -152,6 +223,9 @@ module.exports = class Message { /** * Is this a message in a direct message channel (one on one) + * + * + * ##### Returns `bool` true if `this` is a direct message */ isDirectMessage () { @@ -160,7 +234,10 @@ module.exports = class Message { /** * Is this a message where the bot user mentioned anywhere in the message. - * This only checks for the bot user and does not consider any other users + * Only checks for mentions of the bot user and does not consider any other users. + * + * + * ##### Returns `bool` true if `this` mentions the bot user */ isMention () { @@ -170,6 +247,9 @@ module.exports = class Message { /** * Is this a message that's not a direct message or that mentions that bot at * all (other users could be mentioned) + * + * + * ##### Returns `bool` true if `this` is an ambient message */ isAmbient () { @@ -177,10 +257,15 @@ module.exports = class Message { } /** - * Is this a message that matches any one of these filter types + * Is this a message that matches any one of the filters * - * Parameters: - * - `messageFilters` Array - any of direct_message, direct_mention, mention or ambient + * ##### Parameters + * - `messageFilters` Array - any of `direct_message`, `direct_mention`, `mention` and `ambient` + * + * + * ##### Returns `bool` true if `this` is a message that matches any of the filters + * + * @param {Array} of {string} messageFilters */ isAnyOf (messageFilters) { @@ -198,7 +283,7 @@ module.exports = class Message { /** * Return the user IDs of any users mentioned in the message * - * Returns an Array of IDs + * ##### Returns an Array of user IDs */ usersMentioned () { @@ -208,7 +293,7 @@ module.exports = class Message { /** * Return the channel IDs of any channels mentioned in the message * - * Returns an Array of IDs + * ##### Returns an Array of channel IDs */ channelsMentioned () { @@ -218,7 +303,7 @@ module.exports = class Message { /** * Return the IDs of any subteams (groups) mentioned in the message * - * Returns an Array of IDs + * ##### Returns an Array of subteam IDs */ subteamGroupsMentioned () { return this._regexMentions(new RegExp(']+>', 'g')) @@ -226,6 +311,8 @@ module.exports = class Message { /** * Was "@everyone" mentioned in the message + * + * ##### Returns `bool` true if `@everyone` was mentioned */ everyoneMentioned () { @@ -234,6 +321,8 @@ module.exports = class Message { /** * Was the current "@channel" mentioned in the message + * + * ##### Returns `bool` true if `@channel` was mentioned */ channelMentioned () { @@ -241,7 +330,9 @@ module.exports = class Message { } /** - * Was the current "@channel" mentioned in the message + * Was the "@here" mentioned in the message + * + * ##### Returns `bool` true if `@here` was mentioned */ hereMentioned () { @@ -250,6 +341,8 @@ module.exports = class Message { /** * Return the URLs of any links mentioned in the message + * + * ##### Returns `Array:string` of URLs of links mentioned in the message */ linksMentioned () { @@ -272,6 +365,11 @@ module.exports = class Message { /** * Strip the direct mention prefix from the message text and return it. The * original text is not modified + * + * + * ##### Returns `string` original `text` of message with a direct mention of the bot + * user removed. For example, `@botuser hi` or `@botuser: hi` would produce `hi`. + * `@notbotuser hi` would produce `@notbotuser hi` */ stripDirectMention () { @@ -287,7 +385,7 @@ module.exports = class Message { } /** - * Returns array of regex matches from the text of a message + * ##### Returns array of regex matches from the text of a message * * @api private */ @@ -332,3 +430,5 @@ module.exports = class Message { } } + +module.exports = Message diff --git a/src/slackapp.js b/src/slackapp.js index 33957adb1..fd0109593 100644 --- a/src/slackapp.js +++ b/src/slackapp.js @@ -5,20 +5,27 @@ const conversationStore = require('./conversation_store') const Receiver = require('./receiver') /** - * SlackApp module + * A Slack App + * @class SlackApp + * @api private */ -module.exports = class SlackApp { +class SlackApp { /** - * Initialize a SlackApp, accepts an options object - * - * Options: - * - `app_token` Slack App token - * - `app_user_id` Slack App User ID (who installed the app) - * - `bot_token` Slack App Bot token - * - `bot_user_id` Slack App Bot ID - * - `convo_store` `string` of type of Conversation store (`memory`, etc.) or `object` implementation - * - `error` Error handler function `(error) => {}` + * Construct a SlackApp, accepts an options object + * + * ##### Parameters + * - `opts.app_token` Slack App token override + * - `opts.app_user_id` Slack App User ID (who installed the app) + * - `opts.bot_token` Slack App Bot token + * - `opts.bot_user_id` Slack App Bot ID + * - `opts.convo_store` Implementation of ConversationStore, defaults to memory + * - `opts.error` Error handler function `(error) => {}` + * + * @api private + * @constructor + * @param {Object} opts + * @returns {Object} SlackApp */ constructor (opts) { @@ -53,6 +60,12 @@ module.exports = class SlackApp { /** * Initialize app w/ default middleware and receiver listener + * + * + * ##### Returns + * - `this` (chainable) + * + * @api private */ init () { // call `handle` for each new request @@ -104,10 +117,17 @@ module.exports = class SlackApp { } /** - * Register a new middleware + * Register a new middleware, processed in the order registered. + * + * ##### Parameters + * - `fn`: middleware function `(msg, next) => { }` + * * - * Middleware is processed in the order registered. - * `fn` : (msg, next) => { } + * ##### Returns + * - `this` (chainable) + * + * @param {function} fn + * @api public */ use (fn) { @@ -118,10 +138,13 @@ module.exports = class SlackApp { /** * Handle new events (slack events, commands, actions, webhooks, etc.) - * Parameters + * + * ##### Parameters * - `msg` `Message` * - `done` `function(err, bool)` Callback called once complete, called with error and boolean indicating message was handled [optional] * + * @param {Message} msg + * @param {function} done * @api private */ @@ -177,6 +200,15 @@ module.exports = class SlackApp { * - POST `/slack-event` * - POST `/slack-command` * - POST `/slack-action` + * + * ##### Parameters + * - `app` instance of Express app + * + * + * ##### Returns + * - `app` reference to Express app passed in + * + * @param {Object} app - instance of Express app */ attachToExpress (app) { @@ -186,9 +218,16 @@ module.exports = class SlackApp { /** * Register a new function route * - * Parameters - * - `fnKey` string - unique key to refer to function - * - `fn` function - `(msg) => {}` + * ##### Parameters + * - `fnKey` unique key to refer to function + * - `fn` `(msg, state) => {}` + * + * + * ##### Returns + * - `this` (chainable) + * + * @param {string} fnKey + * @param {function} fn */ route (fnKey, fn) { @@ -200,8 +239,14 @@ module.exports = class SlackApp { /** * Return a registered route * - * Parameters + * ##### Parameters * - `fnKey` string - unique key to refer to function + * + * + * ##### Returns + * - `(msg, state) => {}` + * + * @param {string} fnKey */ getRoute (fnKey) { @@ -210,20 +255,26 @@ module.exports = class SlackApp { /** * Register a custom Match function (fn) - - * $eturns `true` if there is a match AND you handled the msg. + * + * ##### Returns `true` if there is a match AND you handled the msg. * Return `false` if there is not a match and you pass on the message. - + * * All of the higher level matching convenience functions - * generate a match function and call match to register it. + * generate a match function and call `match` to register it. * - * Only one matcher can return true and they are executed in the order they are + * Only one matcher can return true, and they are executed in the order they are * defined. Match functions should return as fast as possible because it's important * that they are efficient. However you may do asyncronous tasks within to * your hearts content. * - * Parameters + * ##### Parameters * - `fn` function - match function `(msg) => { return bool }` + * + * + * ##### Returns + * - `this` (chainable) + * + * @param {function} fn */ match (fn) { @@ -235,16 +286,16 @@ module.exports = class SlackApp { /** * Register a new message handler function for the criteria * - * Parameters: - * - `criteria` string or RegExp - message is string or match RegExp - * - `typeFilter` Array for list of values or string for one value [optional] - * * `direct_message` - * * `direct_mention` - * * `mention` - * * `ambient` - * * default: matches all if none provided + * ##### Parameters + * - `criteria` text that message contains or regex (e.g. "^hi") + * - `typeFilter` [optional] Array for multiple values or string for one value. Valid values are `direct_message`, `direct_mention`, `mention`, `ambient` * - `callback` function - `(msg) => {}` * + * + * ##### Returns + * - `this` (chainable) + * + * * Example `msg` object: * * { @@ -264,6 +315,9 @@ module.exports = class SlackApp { * "UXXXXXXXX" * ] * } + * + * @param {(string)} criteria + * @param {(string|Array)} typeFilter */ message (criteria, typeFilter, callback) { @@ -287,38 +341,47 @@ module.exports = class SlackApp { } } } - return this.match(fn) + this.match(fn) + return this } /** * Register a new event handler for an actionName * - * Parameters: - * - `criteria` string or RegExp - the type of event - * - `callback` function - `(msg) => {}` + * ##### Parameters + * - `criteria` the type of event + * - `callback` `(msg) => {}` + * + * + * ##### Returns + * - `this` (chainable) + * * * Example `msg` object: * - * { - * "token":"dxxxxxxxxxxxxxxxxxxxx", - * "team_id":"TXXXXXXXX", - * "api_app_id":"AXXXXXXXX", - * "event":{ - * "type":"reaction_added", - * "user":"UXXXXXXXX", - * "item":{ - * "type":"message", - * "channel":"DXXXXXXXX", - * "ts":"1469130181.000096" - * }, - * "reaction":"grinning" - * }, - * "event_ts":"1469131201.822817", - * "type":"event_callback", - * "authed_users":[ - * "UXXXXXXXX" - * ] - * } + * { + * "token":"dxxxxxxxxxxxxxxxxxxxx", + * "team_id":"TXXXXXXXX", + * "api_app_id":"AXXXXXXXX", + * "event":{ + * "type":"reaction_added", + * "user":"UXXXXXXXX", + * "item":{ + * "type":"message", + * "channel":"DXXXXXXXX", + * "ts":"1469130181.000096" + * }, + * "reaction":"grinning" + * }, + * "event_ts":"1469131201.822817", + * "type":"event_callback", + * "authed_users":[ + * "UXXXXXXXX" + * ] + * } + * + * @param {(string|RegExp)} criteria + * @param {function} callback */ event (criteria, callback) { @@ -338,77 +401,86 @@ module.exports = class SlackApp { /** * Register a new action handler for an actionNameCriteria * - * Parameters: + * ##### Parameters * - `callbackId` string * - `actionNameCriteria` string or RegExp - the name of the action [optional] * - `callback` function - `(msg) => {}` * + * + * ##### Returns + * - `this` (chainable) + * + * * Example `msg` object: * - * { - * "actions":[ - * { - * "name":"answer", - * "value":":wine_glass:" - * } - * ], - * "callback_id":"in_or_out_callback", - * "team":{ - * "id":"TXXXXXXXX", - * "domain":"companydomain" - * }, - * "channel":{ - * "id":"DXXXXXXXX", - * "name":"directmessage" - * }, - * "user":{ - * "id":"UXXXXXXXX", - * "name":"mike.brevoort" - * }, - * "action_ts":"1469129995.067370", - * "message_ts":"1469129988.000084", - * "attachment_id":"1", - * "token":"dxxxxxxxxxxxxxxxxxxxx", - * "original_message":{ - * "text":"What?", - * "username":"In or Out", - * "bot_id":"BXXXXXXXX", - * "attachments":[ - * { - * "callback_id":"in_or_out_callback", - * "fallback":"Pick one", - * "id":1, - * "actions":[ - * { - * "id":"1", - * "name":"answer", - * "text":":beer:", - * "type":"button", - * "value":":beer:", - * "style":"" - * }, - * { - * "id":"2", - * "name":"answer", - * "text":":beers:", - * "type":"button", - * "value":":wine:", - * "style":"" - * }, - * ] - * }, - * { - * "text":":beers: • mike.brevoort", - * "id":2, - * "fallback":"who picked beers" - * } - * ], - * "type":"message", - * "subtype":"bot_message", - * "ts":"1469129988.000084" - * }, - * "response_url":"https://hooks.slack.com/actions/TXXXXXXXX/111111111111/txxxxxxxxxxxxxxxxxxxx" + * { + * "actions":[ + * { + * "name":"answer", + * "value":":wine_glass:" + * } + * ], + * "callback_id":"in_or_out_callback", + * "team":{ + * "id":"TXXXXXXXX", + * "domain":"companydomain" + * }, + * "channel":{ + * "id":"DXXXXXXXX", + * "name":"directmessage" + * }, + * "user":{ + * "id":"UXXXXXXXX", + * "name":"mike.brevoort" + * }, + * "action_ts":"1469129995.067370", + * "message_ts":"1469129988.000084", + * "attachment_id":"1", + * "token":"dxxxxxxxxxxxxxxxxxxxx", + * "original_message":{ + * "text":"What?", + * "username":"In or Out", + * "bot_id":"BXXXXXXXX", + * "attachments":[ + * { + * "callback_id":"in_or_out_callback", + * "fallback":"Pick one", + * "id":1, + * "actions":[ + * { + * "id":"1", + * "name":"answer", + * "text":":beer:", + * "type":"button", + * "value":":beer:", + * "style":"" + * }, + * { + * "id":"2", + * "name":"answer", + * "text":":beers:", + * "type":"button", + * "value":":wine:", + * "style":"" + * }, + * ] + * }, + * { + * "text":":beers: • mike.brevoort", + * "id":2, + * "fallback":"who picked beers" + * } + * ], + * "type":"message", + * "subtype":"bot_message", + * "ts":"1469129988.000084" + * }, + * "response_url":"https://hooks.slack.com/actions/TXXXXXXXX/111111111111/txxxxxxxxxxxxxxxxxxxx" + * } * + * @param {string} callbackId + * @param {(string|RegExp)} actionNameCriteria + * @param {function} callback */ action (callbackId, actionNameCriteria, callback) { @@ -439,11 +511,16 @@ module.exports = class SlackApp { /** * Register a new slash command handler * - * Parameters: + * ##### Parameters * - `command` string - the slash command (e.g. "/doit") - * - `criteria` string or RegExp (e.g "/^create.*$/") [optional] + * - `criteria` string or RegExp (e.g "/^create.+$/") [optional] * - `callback` function - `(msg) => {}` * + * + * ##### Returns + * - `this` (chainable) + * + * * Example `msg` object: * * { @@ -472,6 +549,9 @@ module.exports = class SlackApp { * "team_id":"TXXXXXXXX" * }, * } + * @param {string} command + * @param {(string|RegExp)} criteria + * @param {function} callback */ command (command, criteria, callback) { @@ -493,3 +573,5 @@ module.exports = class SlackApp { return this.match(fn) } } + +module.exports = SlackApp From 63fee7dda76c62fccaaff1ed549850235d224d2b Mon Sep 17 00:00:00 2001 From: Mike Brevoort Date: Sun, 24 Jul 2016 22:58:15 -0600 Subject: [PATCH 5/5] Add Slack notification --- .travis.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b29cf66a2..c0019d1d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,7 @@ language: node_js node_js: - - "4" - - "6" +- '4' +- '6' +notifications: + slack: + secure: KF6oKsIXnFym5rbJ8tt5Nq3flha8xaOLvu0SkFMjpC9oqRd9y8h/AM2BdUU2gVUUy28VuZeYKKL0BEA2X6dHiG9NLabFUlwefoiQLD5CjKVNIYOkG18hN98ijeCM+VwFy8Lj50xxaCpvy7y+sVcCjPuH9ZAboLFiZ7/0nx1uwGkTJDFCGDb+8NIGWsvpKlCbNBjkQblw7GdLegCCZiZuEa1H029eTQtSCKpdViCnWRFO9YKSO6gmsVWdTeRDdbWEbC6tfVBzt8s18o+38ZtdillZNMEW0+XX/hakRFTAP5A5Druhdp+Wpe1cTVPnTdFCNIKifnHFHShS07THv1e07KzYtvxAOvZmdLA4ptjBIHL17+2UYQ5vZ8tWrxNGEb7KhnmJ2Jw2o6/F35AxEt+osJ7/CaJI5jShu8k8j2NM7YyuYMIrwlo0vwK6bOQbF/V3kQue7WaP/5noBQzCCH5d9UpsoaO5CoMlnp0uvAD8qZ+hpOX/zcwATT0nll8w/oWM87AVzne86703r4vpDM6zuo2P+cUBf/XBV83sXujgPro7Gcb/wJQlWfXM2xX73iyuNXZi8rW+ODRTFAz8YSzNa4jgwz8u+5RHyGxIouFWaVnjedv1hkkigmneuERQX/8dWwHsbnvs5V/rr0o4Q+FQBn/I4SC72ae8/Ge+nz74n4A=