From b2a7b466a3553355fe4c9715190521165d80860e Mon Sep 17 00:00:00 2001 From: Ben Brown Date: Fri, 26 Oct 2018 10:27:08 -0500 Subject: [PATCH] Apply more stringent linter rules --- .eslintrc.json | 16 ++- lib/BotFramework.js | 20 +-- lib/ConsoleBot.js | 3 +- lib/CoreBot.js | 233 ++++++++++++++++++++------------ lib/Facebook.js | 68 ++++++---- lib/GoogleHangoutsBot.js | 6 +- lib/JabberBot.js | 15 +- lib/JabberGroupManager.js | 55 +++----- lib/SlackBot.js | 191 ++++++++++++++++---------- lib/Slack_web_api.js | 10 +- lib/Slackbot_worker.js | 40 +++--- lib/Studio.js | 81 ++++++----- lib/Teams.js | 54 ++++---- lib/TeamsAPI.js | 8 +- lib/TwilioIPMBot.js | 50 ++++--- lib/TwilioSMSBot.js | 3 - lib/Web.js | 36 +++-- lib/WebexBot.js | 45 +++--- lib/storage/simple_storage.js | 44 +++--- tests/lib/Slack_web_api.test.js | 20 +-- tests/lib/Teams.test.js | 1 - tests/unit/storage.test.js | 24 ++-- 22 files changed, 599 insertions(+), 424 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 3d8ff7ff1..5319f5a6a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,10 +1,21 @@ { "rules": { "no-with": 2, + "template-curly-spacing": ["error", "always"], "max-len": [ 2, 250 ], + "no-undef": "off", + "no-extra-semi": ["error"], + "no-empty":["error"], + "multiline-comment-style": ["error", "starred-block"], + "linebreak-style": ["error", "unix"], + "no-unused-vars": ["error"], + "no-trailing-spaces": ["error"], + "no-console": ["warn",{ + "allow": ["warn","error"] + }], "indent": [ 2, 4, @@ -12,5 +23,8 @@ "SwitchCase": 1 } ] - } + }, + "env": { + "es6": true +} } diff --git a/lib/BotFramework.js b/lib/BotFramework.js index 2d5798d92..0c03a73dd 100644 --- a/lib/BotFramework.js +++ b/lib/BotFramework.js @@ -6,8 +6,10 @@ function BotFrameworkBot(configuration) { // Create a core botkit bot var bf_botkit = Botkit(configuration || {}); - // customize the bot definition, which will be used when new connections - // spawn! + /* + * customize the bot definition, which will be used when new connections + * spawn! + */ bf_botkit.defineBot(function(botkit, config) { var bot = { @@ -17,7 +19,7 @@ function BotFrameworkBot(configuration) { }; bot.send = function(message, cb) { - function done(err, res) { + function done(err) { if (cb) { cb(err); } @@ -112,10 +114,12 @@ function BotFrameworkBot(configuration) { bf_botkit.middleware.normalize.use(function(bot, message, next) { - // Break out user & channel fields from event - // - These fields are used as keys for tracking conversations and storage. - // - Prefixing with channelId to ensure that users & channels for different - // platforms are unique. + /* + * Break out user & channel fields from event + * - These fields are used as keys for tracking conversations and storage. + * - Prefixing with channelId to ensure that users & channels for different + * platforms are unique. + */ var prefix = message.address.channelId + ':'; message.user = prefix + message.address.user.id; @@ -174,6 +178,6 @@ function BotFrameworkBot(configuration) { }; return bf_botkit; -}; +} module.exports = BotFrameworkBot; diff --git a/lib/ConsoleBot.js b/lib/ConsoleBot.js index 44b8442e0..616728fe2 100644 --- a/lib/ConsoleBot.js +++ b/lib/ConsoleBot.js @@ -41,6 +41,7 @@ function TextBot(configuration) { }; bot.send = function(message, cb) { + // eslint-disable-next-line no-console console.log('BOT:', message.text); if (cb) { cb(); @@ -101,6 +102,6 @@ function TextBot(configuration) { }; return text_botkit; -}; +} module.exports = TextBot; diff --git a/lib/CoreBot.js b/lib/CoreBot.js index 433d6f6e9..1e0a75742 100755 --- a/lib/CoreBot.js +++ b/lib/CoreBot.js @@ -1,14 +1,14 @@ /** * This is a module that makes a bot * It expects to receive messages via the botkit.ingest function - **/ + * + */ var mustache = require('mustache'); var simple_storage = require(__dirname + '/storage/simple_storage.js'); var ConsoleLogger = require(__dirname + '/console_logger.js'); var LogLevels = ConsoleLogger.LogLevels; var ware = require('ware'); var clone = require('clone'); -var fs = require('fs'); var studio = require('./Studio.js'); var os = require('os'); var async = require('async'); @@ -38,8 +38,10 @@ function Botkit(configuration) { botkit.utterances = utils.getUtterances(); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - // define some middleware points where custom functions - // can plug into key points of botkits process + /* + * define some middleware points where custom functions + * can plug into key points of botkits process + */ botkit.middleware = { spawn: ware(), ingest: ware(), @@ -55,8 +57,10 @@ function Botkit(configuration) { conversationEnd: ware(), }; - // list of events to exclude from conversations - // useful to exclude things like delivery confirmations, and other behind the scenes events + /* + * list of events to exclude from conversations + * useful to exclude things like delivery confirmations, and other behind the scenes events + */ botkit.excludedEvents = []; // add a single event or an array of events to be excluded from the conversations @@ -81,7 +85,7 @@ function Botkit(configuration) { }; - botkit.middleware.ingest.run(obot, opayload, source, function(err, bot, payload, source) { + botkit.middleware.ingest.run(obot, opayload, source, function(err, bot, payload) { if (err) { console.error('An error occurred in the ingest middleware: ', err); botkit.trigger('ingest_error', [err, obot, opayload]); @@ -129,9 +133,11 @@ function Botkit(configuration) { if (err) { // log the error to console, so people recognize it console.error('An error occurred in the receive middleware: ', err); - // an error occured in the receive middleware - // fire the error event instead of disposing the message - // can be obtained by using controller.on('receive_error')[...] + /* + * an error occured in the receive middleware + * fire the error event instead of disposing the message + * can be obtained by using controller.on('receive_error')[...] + */ botkit.trigger('receive_error', [err, obot, omessage]); botkit.trigger('pipeline_error', [err, obot, omessage, 'receive']); } else { @@ -178,7 +184,8 @@ function Botkit(configuration) { this.capture_options = {}; this.startTime = new Date(); this.lastActive = new Date(); - /** will be pointing to a callback which will be called after timeout, + /** + * will be pointing to a callback which will be called after timeout, * conversation will be not be ended and should be taken care by callback */ this.timeOutHandler = null; @@ -191,7 +198,7 @@ function Botkit(configuration) { var that = this; var capture_key = this.sent[this.sent.length - 1].text; - botkit.middleware.capture.run(that.task.bot, response, that, function(err, bot, response, convo) { + botkit.middleware.capture.run(that.task.bot, response, that, function(err, bot, response) { if (response.text) { response.text = response.text.trim(); } else { @@ -202,8 +209,10 @@ function Botkit(configuration) { capture_key = that.capture_options.key; } - // capture the question that was asked - // if text is an array, get 1st + /* + * capture the question that was asked + * if text is an array, get 1st + */ if (typeof(that.sent[that.sent.length - 1].text) == 'string') { response.question = that.sent[that.sent.length - 1].text; } else if (Array.isArray(that.sent[that.sent.length - 1].text)) { @@ -235,15 +244,19 @@ function Botkit(configuration) { // do other stuff like call custom callbacks if (this.handler) { this.capture(message, function(message) { - // if the handler is a normal function, just execute it! - // NOTE: anyone who passes in their own handler has to call - // convo.next() to continue after completing whatever it is they want to do. + /* + * if the handler is a normal function, just execute it! + * NOTE: anyone who passes in their own handler has to call + * convo.next() to continue after completing whatever it is they want to do. + */ if (typeof(that.handler) == 'function') { that.handler(message, that); } else { - // handle might be a mapping of keyword to callback. - // lets see if the message matches any of the keywords - var match, patterns = that.handler; + /* + * handle might be a mapping of keyword to callback. + * lets see if the message matches any of the keywords + */ + var patterns = that.handler; for (var p = 0; p < patterns.length; p++) { if (patterns[p].pattern && botkit.hears_test([patterns[p].pattern], message)) { botkit.middleware.heard.run(that.task.bot, message, function(err, bot, message) { @@ -253,8 +266,10 @@ function Botkit(configuration) { } } - // none of the messages matched! What do we do? - // if a default exists, fire it! + /* + * none of the messages matched! What do we do? + * if a default exists, fire it! + */ for (var p = 0; p < patterns.length; p++) { if (patterns[p].default) { botkit.middleware.heard.run(that.task.bot, message, function(err, bot, message) { @@ -292,7 +307,8 @@ function Botkit(configuration) { /** * active includes both ACTIVE and ENDING * in order to allow the timeout end scripts to play out - **/ + * + */ this.isActive = function() { return (this.status == 'active' || this.status == 'ending'); }; @@ -320,9 +336,11 @@ function Botkit(configuration) { this.handleAction = function(condition) { - // condition.action - // if (condition.action=='execute_script') - // condition.execute will be present + /* + * condition.action + * if (condition.action=='execute_script') + * condition.execute will be present + */ var that = this; switch (condition.action) { case 'execute_script': @@ -352,8 +370,10 @@ function Botkit(configuration) { new_convo.context.transition_from = that.context.script_name || null; new_convo.context.transition_from_id = that.context.script_id || null; - // if thread == default, this is the normal behavior and we don't need to call gotoThread - // in fact, calling gotoThread will cause it to override behaviors in the scripts `before` hook. + /* + * if thread == default, this is the normal behavior and we don't need to call gotoThread + * in fact, calling gotoThread will cause it to override behaviors in the scripts `before` hook. + */ if (thread != 'default') { new_convo.gotoThread(thread); } @@ -472,7 +492,7 @@ function Botkit(configuration) { return; } } - } else {} + } }; // proceed to the next message after waiting for an answer @@ -482,8 +502,10 @@ function Botkit(configuration) { this.repeat = function() { if (this.sent.length) { - // is this the last message in the queue? then just push it on again - // if not, sayFirst it to the front so it doesn't repeat AFTER other messages + /* + * is this the last message in the queue? then just push it on again + * if not, sayFirst it to the front so it doesn't repeat AFTER other messages + */ if (!this.messages.length) { this.messages.push(this.sent[this.sent.length - 1]); } else { @@ -562,10 +584,12 @@ function Botkit(configuration) { this.transitionTo = function(thread, message) { - // add a new transition thread - // add this new message to it - // set that message action to execute the actual transition - // then change threads to transition thread + /* + * add a new transition thread + * add this new message to it + * set that message action to execute the actual transition + * then change threads to transition thread + */ var num = 1; while (this.hasThread('transition_' + num)) { @@ -768,7 +792,7 @@ function Botkit(configuration) { } catch (err) { botkit.log('Error in message template. Mustache failed with error: ', err); rendered = text; - }; + } return rendered; }; @@ -781,11 +805,13 @@ function Botkit(configuration) { this.task.conversationEnded(this); }; - // was this conversation successful? - // return true if it was completed - // otherwise, return false - // false could indicate a variety of failed states: - // manually stopped, timed out, etc + /* + * was this conversation successful? + * return true if it was completed + * otherwise, return false + * false could indicate a variety of failed states: + * manually stopped, timed out, etc + */ this.successful = function() { // if the conversation is still going, it can't be successful yet @@ -856,8 +882,10 @@ function Botkit(configuration) { if (this.processing) { // do nothing. The bot is waiting for async process to complete. } else if (this.handler) { - // check timeout! - // how long since task started? + /* + * check timeout! + * how long since task started? + */ var duration = (now.getTime() - this.task.startTime.getTime()); // how long since last active? var lastActive = (now.getTime() - this.lastActive.getTime()); @@ -866,8 +894,10 @@ function Botkit(configuration) { (duration > this.task.timeLimit) && // timelimit is up (lastActive > this.task.timeLimit) // nobody has typed for 60 seconds at least ) { - // if timeoutHandler is set then call it, otherwise follow the normal flow - // this will not break others code, after the update + /* + * if timeoutHandler is set then call it, otherwise follow the normal flow + * this will not break others code, after the update + */ if (this.timeOutHandler) { this.timeOutHandler(this); } else if (this.hasThread('on_timeout')) { @@ -894,9 +924,11 @@ function Botkit(configuration) { return; } - // make sure the first message is delayed appropriately. - // this comes into play when the thread changes or the conversation starts. - // we need to set the delay based on NOW. + /* + * make sure the first message is delayed appropriately. + * this comes into play when the thread changes or the conversation starts. + * we need to set the delay based on NOW. + */ if (this.messages.length && this.messages[0].delay && !this.messages[0].timestamp) { this.messages[0].timestamp = now.getTime() + this.messages[0].delay; } @@ -905,17 +937,21 @@ function Botkit(configuration) { this.messages[0].timestamp <= now.getTime()) { var message = this.messages.shift(); - // make sure next message is delayed appropriately - // this will offset the NEXT message from the SEND time. + /* + * make sure next message is delayed appropriately + * this will offset the NEXT message from the SEND time. + */ if (this.messages.length && this.messages[0].delay) { this.messages[0].timestamp = now.getTime() + parseInt(this.messages[0].delay); } if (message.conditional) { this.evaluateCondition(message.conditional); - // we want to stop processing this message - // because evaluate conditional can process a bunch of stuff - // and then move on to the next step internally + /* + * we want to stop processing this message + * because evaluate conditional can process a bunch of stuff + * and then move on to the next step internally + */ return; } else { @@ -932,9 +968,11 @@ function Botkit(configuration) { this.lastActive = new Date(); - // is there any text? - // or an attachment? (facebook) - // or multiple attachments (slack) + /* + * is there any text? + * or an attachment? (facebook) + * or multiple attachments (slack) + */ if (message.text || message.attachments || message.attachment) { var outbound = this.cloneMessage(message); @@ -949,9 +987,11 @@ function Botkit(configuration) { if (err) { botkit.log('An error occurred while sending a message: ', err); - // even though an error occurred, set sent to true - // this will allow the conversation to keep going even if one message fails - // TODO: make a message that fails to send _resend_ at least once + /* + * even though an error occurred, set sent to true + * this will allow the conversation to keep going even if one message fails + * TODO: make a message that fails to send _resend_ at least once + */ that.sent[that.sent.length - 1].sent = true; that.sent[that.sent.length - 1].api_response = err; @@ -960,8 +1000,10 @@ function Botkit(configuration) { that.sent[that.sent.length - 1].sent = true; that.sent[that.sent.length - 1].api_response = sent_message; - // if sending via slack's web api, there is no further confirmation - // so we can mark the message delivered + /* + * if sending via slack's web api, there is no further confirmation + * so we can mark the message delivered + */ if (that.task.bot.type == 'slack' && sent_message && sent_message.ts) { that.sent[that.sent.length - 1].delivered = true; } @@ -979,8 +1021,10 @@ function Botkit(configuration) { // do nothing } - // end immediately instead of waiting til next tick. - // if it hasn't already been ended by a message action! + /* + * end immediately instead of waiting til next tick. + * if it hasn't already been ended by a message action! + */ if (this.isActive() && !this.messages.length && !this.handler && !this.processing) { this.stop('completed'); } @@ -994,7 +1038,7 @@ function Botkit(configuration) { botkit.debug('CREATED A CONVO FOR', this.source_message.user, this.source_message.channel); this.gotoThread('default'); - }; + } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ @@ -1103,8 +1147,10 @@ function Botkit(configuration) { var users = {}; - // go through all conversations - // extract normalized answers + /* + * go through all conversations + * extract normalized answers + */ for (var c = 0; c < this.convos.length; c++) { var user = this.convos[c].source_message.user; @@ -1120,8 +1166,10 @@ function Botkit(configuration) { this.getResponsesBySubject = function() { var answers = {}; - // go through all conversations - // extract normalized answers + /* + * go through all conversations + * extract normalized answers + */ for (var c = 0; c < this.convos.length; c++) { var convo = this.convos[c]; @@ -1144,7 +1192,7 @@ function Botkit(configuration) { } } }; - }; + } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ @@ -1225,8 +1273,10 @@ function Botkit(configuration) { for (var t = 0; t < tests.length; t++) { if (message.text) { - // the pattern might be a string to match (including regular expression syntax) - // or it might be a prebuilt regular expression + /* + * the pattern might be a string to match (including regular expression syntax) + * or it might be a prebuilt regular expression + */ var test = null; if (typeof(tests[t]) == 'string') { try { @@ -1264,8 +1314,10 @@ function Botkit(configuration) { botkit.hears = function(keywords, events, middleware_or_cb, cb) { - // the third parameter is EITHER a callback handler - // or a middleware function that redefines how the hear works + /* + * the third parameter is EITHER a callback handler + * or a middleware function that redefines how the hear works + */ var test_function = botkit.hears_test; if (cb) { test_function = middleware_or_cb; @@ -1336,8 +1388,10 @@ function Botkit(configuration) { }); - // first, look for hearing type events - // these are always handled before normal event handlers + /* + * first, look for hearing type events + * these are always handled before normal event handlers + */ for (var e = 0; e < hearing.length; e++) { var res = hearing[e].callback.apply(this, data); if (res === false) { @@ -1345,12 +1399,14 @@ function Botkit(configuration) { } } - // now, if we haven't already heard something, - // fire the remaining event handlers + /* + * now, if we haven't already heard something, + * fire the remaining event handlers + */ if (handlers.length) { botkit.middleware.triggered.run(data[0], data[1], function(err, bot, message) { for (var e = 0; e < handlers.length; e++) { - var res = handlers[e].callback.apply(this, data); + var res = handlers[e].callback.apply(this, [bot, message]); if (res === false) { return; } @@ -1440,8 +1496,10 @@ function Botkit(configuration) { }; - // change the speed of sending messages in a conversation - // defaults to 1500 + /* + * change the speed of sending messages in a conversation + * defaults to 1500 + */ botkit.setTickDelay = function(delay) { botkit.tickDelay = delay; }; @@ -1526,7 +1584,7 @@ function Botkit(configuration) { })); botkit.webserver.use(express.static(static_dir)); - var server = botkit.webserver.listen( + botkit.webserver.listen( botkit.config.port, botkit.config.hostname, function() { @@ -1536,7 +1594,8 @@ function Botkit(configuration) { cb(null, botkit.webserver); } botkit.trigger('webserver_up', [botkit.webserver]); - }); + } + ); return botkit; }; @@ -1546,7 +1605,7 @@ function Botkit(configuration) { /** * Define a default worker bot. This function should be customized outside * of Botkit and passed in as a parameter by the developer - **/ + */ botkit.worker = function(botkit, config) { this.botkit = botkit; this.config = config; @@ -1609,13 +1668,14 @@ function Botkit(configuration) { botkit.config = configuration; - /** Default the application to listen to the 0.0.0.0, the default + /** + * Default the application to listen to the 0.0.0.0, the default * for node's http module. Developers can specify a hostname or IP * address to override this. - **/ + */ if (!botkit.config.hostname) { botkit.config.hostname = '0.0.0.0'; - }; + } if (!configuration.logLevel) { @@ -1647,6 +1707,7 @@ function Botkit(configuration) { botkit.debug = botkit.log.debug; if (!botkit.config.disable_startup_messages) { + // eslint-disable-next-line no-console console.log('Initializing Botkit v' + botkit.version()); } diff --git a/lib/Facebook.js b/lib/Facebook.js index 668e8882a..4f07d4b12 100644 --- a/lib/Facebook.js +++ b/lib/Facebook.js @@ -15,9 +15,11 @@ function Facebookbot(configuration) { var facebook_botkit = Botkit(configuration || {}); - // For backwards-compatibility, support the receive_via_postback config option - // this causes facebook_postback events to be replicated as message_received events - // allowing them to be heard without subscribing to additional events + /* + * For backwards-compatibility, support the receive_via_postback config option + * this causes facebook_postback events to be replicated as message_received events + * allowing them to be heard without subscribing to additional events + */ if (facebook_botkit.config.receive_via_postback) { facebook_botkit.on('facebook_postback', function(bot, message) { facebook_botkit.trigger('message_received', [bot, message]); @@ -76,8 +78,10 @@ function Facebookbot(configuration) { }); - // customize the bot definition, which will be used when new connections - // spawn! + /* + * customize the bot definition, which will be used when new connections + * spawn! + */ facebook_botkit.defineBot(function(botkit, config) { var bot = { @@ -196,8 +200,10 @@ function Facebookbot(configuration) { cb(); }; - // return info about the specific instance of this bot - // including identity information, and any other info that is relevant + /* + * return info about the specific instance of this bot + * including identity information, and any other info that is relevant + */ bot.getInstanceInfo = function(cb) { return facebook_botkit.getInstanceInfo(cb); }; @@ -241,10 +247,12 @@ function Facebookbot(configuration) { return bot; }); - // return info about the specific instance of this bot - // including identity information, and any other info that is relevant - // unlike other platforms, this has to live on the controller - // so that we can use it before a bot is spawned! + /* + * return info about the specific instance of this bot + * including identity information, and any other info that is relevant + * unlike other platforms, this has to live on the controller + * so that we can use it before a bot is spawned! + */ facebook_botkit.getInstanceInfo = function(cb) { return new Promise(function(resolve, reject) { var uri = 'https://' + api_host + '/' + api_version + '/me?access_token=' + configuration.access_token; @@ -321,8 +329,10 @@ function Facebookbot(configuration) { var payload = req.body; - // facebook may send more than 1 message payload at a time - // we split these up into multiple message objects for ingestion + /* + * facebook may send more than 1 message payload at a time + * we split these up into multiple message objects for ingestion + */ if (payload.entry) { for (var e = 0; e < payload.entry.length; e++) { var payload_entry = ''; @@ -352,15 +362,19 @@ function Facebookbot(configuration) { facebook_botkit.middleware.spawn.use(function(worker, next) { - // copy the identity that we get when the app initially boots up - // into the specific bot instance + /* + * copy the identity that we get when the app initially boots up + * into the specific bot instance + */ worker.identity = facebook_botkit.identity; next(); }); - // universal normalizing steps - // handle normal messages from users (text, stickers, files, etc count!) + /* + * universal normalizing steps + * handle normal messages from users (text, stickers, files, etc count!) + */ facebook_botkit.middleware.normalize.use(function normalizeMessage(bot, message, next) { // handle normalization for sessions events @@ -485,10 +499,12 @@ function Facebookbot(configuration) { facebook_botkit.middleware.receive.use(function handleDelivery(bot, message, next) { if (message.type === 'message_delivered' && facebook_botkit.config.require_delivery) { - // loop through all active conversations this bot is having - // and mark messages in conversations as delivered = true - // note: we don't pass the real event in here because message_delivered events are excluded from conversations and won't ever match! - // also note: we only use message.delivery.watermark since message.delivery.mids can sometimes not be in the payload (#1311) + /* + * loop through all active conversations this bot is having + * and mark messages in conversations as delivered = true + * note: we don't pass the real event in here because message_delivered events are excluded from conversations and won't ever match! + * also note: we only use message.delivery.watermark since message.delivery.mids can sometimes not be in the payload (#1311) + */ bot.findConversation({user: message.user}, function(convo) { if (convo) { for (var s = 0; s < convo.sent.length; s++) { @@ -1702,9 +1718,11 @@ function Facebookbot(configuration) { }; - // Verifies the SHA1 signature of the raw request payload before bodyParser parses it - // Will abort parsing if signature is invalid, and pass a generic error to response - function verifyRequest(req, res, buf, encoding) { + /* + * Verifies the SHA1 signature of the raw request payload before bodyParser parses it + * Will abort parsing if signature is invalid, and pass a generic error to response + */ + function verifyRequest(req, res, buf) { var expected = req.headers['x-hub-signature']; var calculated = getSignature(buf); if (expected !== calculated) { @@ -1755,6 +1773,6 @@ function Facebookbot(configuration) { return facebook_botkit; -}; +} module.exports = Facebookbot; diff --git a/lib/GoogleHangoutsBot.js b/lib/GoogleHangoutsBot.js index 3a91fedbb..d970f9a81 100644 --- a/lib/GoogleHangoutsBot.js +++ b/lib/GoogleHangoutsBot.js @@ -1,5 +1,5 @@ var Botkit = require(__dirname + '/CoreBot.js'); -var {google} = require('googleapis'); +var { google } = require('googleapis'); function GoogleHangoutsBot(configuration) { @@ -95,7 +95,7 @@ function GoogleHangoutsBot(configuration) { for (var t = 0; t < botkit.tasks.length; t++) { for (var c = 0; c < botkit.tasks[t].convos.length; c++) { if ( - botkit.tasks[t].convos[c].isActive() && + botkit.tasks[t].convos[c].isActive() && botkit.tasks[t].convos[c].source_message.user == message.user && botkit.tasks[t].convos[c].source_message.channel == message.channel && botkit.excludedEvents.indexOf(message.type) == -1 // this type of message should not be included @@ -218,6 +218,6 @@ function GoogleHangoutsBot(configuration) { google_hangouts_botkit.startTicking(); return google_hangouts_botkit; -}; +} module.exports = GoogleHangoutsBot; diff --git a/lib/JabberBot.js b/lib/JabberBot.js index 06bdfe57c..0ccb0bb29 100644 --- a/lib/JabberBot.js +++ b/lib/JabberBot.js @@ -15,7 +15,7 @@ function JabberBot(configuration) { var min = date.getUTCMinutes() < 10 ? '0' + date.getUTCMinutes() : date.getUTCMinutes(); var ss = date.getUTCSeconds() < 10 ? '0' + date.getUTCSeconds() : date.getUTCSeconds(); return ''.concat(yyyy).concat('-').concat(mm).concat('-').concat(dd).concat('T').concat(hh).concat(':').concat(min).concat(':').concat(ss); - }; + } controller.middleware.format.use(function(bot, message, platform_message, next) { // clone the incoming message @@ -25,8 +25,10 @@ function JabberBot(configuration) { next(); }); - // customize the bot definition, which will be used when new connections - // spawn! + /* + * customize the bot definition, which will be used when new connections + * spawn! + */ controller.defineBot(function(botkit, config) { var xmpp = require('simple-xmpp'); @@ -51,8 +53,10 @@ function JabberBot(configuration) { console.log('Yes, I\'m connected!'); request_roster(); - // send whitespace to keep the connection alive - // and prevent timeouts + /* + * send whitespace to keep the connection alive + * and prevent timeouts + */ setInterval(function() { xmpp.conn.send(' '); }, 1800000); @@ -140,7 +144,6 @@ function JabberBot(configuration) { if (body) { var message = body.getText(); var from = stanza.attrs.from; - var id = from.split('/')[0]; var xmpp_message = {}; xmpp_message.user = from; diff --git a/lib/JabberGroupManager.js b/lib/JabberGroupManager.js index 220c00ad0..d64e20f45 100644 --- a/lib/JabberGroupManager.js +++ b/lib/JabberGroupManager.js @@ -138,33 +138,7 @@ Caps.prototype.toQueryNode = function() { return el; }; -/** - * Creates a {Caps} from an XML node - * - * @param {Object} query - * - * @returns {Caps} - */ -function fromQueryNode(query) { - var node = query.attrs.node.split('#')[0]; - var caps = new Caps(node); - var identities = query.getChildren('identity'); - var features = query.getChildren('feature'); - - identities.forEach(function(id) { - caps.addIdentity(id.attrs.category, id.attrs.type, id.attrs.name, id.attrs.lang); - }); - features.forEach(function(feature) { - caps.addFeature(feature.attrs.var); - }); - - return caps; -} - function JabberGroupManager(config, xmpp, bot, controller) { - var group_manager = { - config: config || {}, - }; var joinedRoomsPasswordMap = new Map(); var joinedPersistRoomsId = new Set(); @@ -173,7 +147,7 @@ function JabberGroupManager(config, xmpp, bot, controller) { const bot_caps_node_addr = 'http://protocols.cisco.com/jabber-bot'; var bot_caps = createCapsNode(bot_caps_node_addr); - xmpp.on('online', function(data) { + xmpp.on('online', function() { publishCapabilities(); joinPresetRooms(); }); @@ -197,13 +171,13 @@ function JabberGroupManager(config, xmpp, bot, controller) { bot_caps.addFeature('http://jabber.org/protocol/disco#items'); bot_caps.addFeature('http://jabber.org/protocol/muc'); return bot_caps; - }; + } function publishCapabilities() { let presence_stanza = new Stanza('presence'); presence_stanza.cnode(bot_caps.toCapsNode()); xmpp.conn.send(presence_stanza); - }; + } function joinPresetRooms() { if (config.group && config.group.rooms) { @@ -230,7 +204,7 @@ function JabberGroupManager(config, xmpp, bot, controller) { } } }); - }; + } function handleCapabilityIq(stanza) { if (stanza.type === 'get') { @@ -242,7 +216,6 @@ function JabberGroupManager(config, xmpp, bot, controller) { if (bot_caps_node_addr == caps_node_addr) { let from = stanza.attrs.from; let to = stanza.attrs.to; - let result = bot_caps.toQueryNode(); let disco_id = stanza.id ? stanza.id : 'disco1'; let iq_stanza = new Stanza('iq', { 'id': disco_id, 'type': 'result', 'to': from, 'from': to }); iq_stanza.cnode(bot_caps.toQueryNode()); @@ -251,7 +224,7 @@ function JabberGroupManager(config, xmpp, bot, controller) { } } } - }; + } function handleRoomDiscoQueryIq(stanza) { if (stanza.attrs.type !== 'result') @@ -284,7 +257,7 @@ function JabberGroupManager(config, xmpp, bot, controller) { return; } } - }; + } function handleInviteMessage(stanza) { let muc_message = stanza.getChild('x', 'http://jabber.org/protocol/muc#user'); @@ -305,7 +278,7 @@ function JabberGroupManager(config, xmpp, bot, controller) { joinedRoomsPasswordMap.set(getBareRoomId(room_id), password); xmpp.join(room_id, password); } - }; + } function handleMembershipPresence(stanza) { let group_type = stanza.getChild('x', 'http://jabber.org/protocol/muc#user'); @@ -339,7 +312,7 @@ function JabberGroupManager(config, xmpp, bot, controller) { sendRoomDiscoQueryIq(room_id, jid); } - }; + } function sendRoomDiscoQueryIq(room_id, jid) { let from = jid; @@ -349,7 +322,7 @@ function JabberGroupManager(config, xmpp, bot, controller) { let iq_stanza = new Stanza('iq', { 'id': disco_id, 'type': 'get', 'to': to, 'from': from }); iq_stanza.c('query', { xmlns: 'http://jabber.org/protocol/disco#info', 'node': node}); xmpp.conn.send(iq_stanza); - }; + } function saveJoinPersistRooms(room_id, room_password) { let id = MD5(room_id); @@ -362,14 +335,20 @@ function JabberGroupManager(config, xmpp, bot, controller) { room.room_id = room_id; room.password = room_password; room.type = 'joined_persist_rooms'; - controller.storage.teams.save(room, function(err, room) { + controller.storage.teams.save(room, function(err) { + if (err) { + console.error('Error saving room info:', err); + } }); }); } function saveLeavePersistRooms(room_id) { let id = MD5(room_id); - controller.storage.teams.delete(id, function(err, room) { + controller.storage.teams.delete(id, function(err) { + if (err) { + console.error('Error saving room info:', err); + } }); } diff --git a/lib/SlackBot.js b/lib/SlackBot.js index 374ef0dfb..dc3dcb2bf 100755 --- a/lib/SlackBot.js +++ b/lib/SlackBot.js @@ -11,34 +11,42 @@ function Slackbot(configuration) { // Set some default configurations unless they've already been set. - // Should the RTM connections ingest received messages - // Developers using the new Events API will set this to false - // This allows an RTM connection to be kept alive (so bot appears online) - // but receive messages only via events api + /* + * Should the RTM connections ingest received messages + * Developers using the new Events API will set this to false + * This allows an RTM connection to be kept alive (so bot appears online) + * but receive messages only via events api + */ if (slack_botkit.config.rtm_receive_messages === undefined) { slack_botkit.config.rtm_receive_messages = true; } var spawned_bots = []; - // customize the bot definition, which will be used when new connections - // spawn! + /* + * customize the bot definition, which will be used when new connections + * spawn! + */ slack_botkit.defineBot(require(__dirname + '/Slackbot_worker.js')); // Middleware to track spawned bots and connect existing RTM bots to incoming webhooks slack_botkit.middleware.spawn.use(function(worker, next) { - // lets first check and make sure we don't already have a bot - // for this team! If we already have an RTM connection, copy it - // into the new bot so it can be used for replies. + /* + * lets first check and make sure we don't already have a bot + * for this team! If we already have an RTM connection, copy it + * into the new bot so it can be used for replies. + */ var existing_bot = null; if (worker.config.id) { for (var b = 0; b < spawned_bots.length; b++) { if (spawned_bots[b].config.id) { if (spawned_bots[b].config.id == worker.config.id) { - // WAIT! We already have a bot spawned here. - // so instead of using the new one, use the exist one. + /* + * WAIT! We already have a bot spawned here. + * so instead of using the new one, use the exist one. + */ existing_bot = spawned_bots[b]; } } @@ -56,10 +64,12 @@ function Slackbot(configuration) { }); - // set up configuration for oauth - // slack_app_config should contain - // { clientId, clientSecret, scopes} - // https://api.slack.com/docs/oauth-scopes + /* + * set up configuration for oauth + * slack_app_config should contain + * { clientId, clientSecret, scopes} + * https://api.slack.com/docs/oauth-scopes + */ slack_botkit.configureSlackApp = function(slack_app_config, cb) { slack_botkit.log('** Configuring app as a Slack App!'); @@ -90,8 +100,10 @@ function Slackbot(configuration) { slack_botkit.log('** Serving app landing page at : http://' + slack_botkit.config.hostname + ':' + slack_botkit.config.port + '/'); - // FIX THIS!!! - // this is obvs not right. + /* + * FIX THIS!!! + * this is obvs not right. + */ webserver.get('/', function(req, res) { res.send('Howdy!'); @@ -166,7 +178,7 @@ function Slackbot(configuration) { } }); } else { - cb(new Error(`could not find team ${team_id}`)); + cb(new Error(`could not find team ${ team_id }`)); } } }); @@ -205,8 +217,8 @@ function Slackbot(configuration) { let basestring = signature.join(':'); const hash = 'v0=' + crypto.createHmac('sha256', slack_botkit.config.clientSigningSecret) - .update(basestring) - .digest('hex'); + .update(basestring) + .digest('hex'); let retrievedSignature = req.header('X-Slack-Signature'); if (hash !== retrievedSignature) { @@ -228,8 +240,10 @@ function Slackbot(configuration) { slack_botkit.log.error('Could not load team while processing webhook: ', err); return res.status(500).send(); } else if (!team) { - // if this is NOT a slack app, it is ok to spawn a generic bot - // this is only likely to happen with custom slash commands + /* + * if this is NOT a slack app, it is ok to spawn a generic bot + * this is only likely to happen with custom slash commands + */ if (!slack_botkit.config.clientId) { bot = slack_botkit.spawn({}); } else { @@ -242,9 +256,11 @@ function Slackbot(configuration) { // Identify the bot from either team storage or identifyBot() bot.team_info = team; - // The bot identity is only used in handleEventsAPI during this flow - // Recent changes in Slack will break other integrations as they no longer - // require a bot and therefore Slack won't send the bot information. + /* + * The bot identity is only used in handleEventsAPI during this flow + * Recent changes in Slack will break other integrations as they no longer + * require a bot and therefore Slack won't send the bot information. + */ if (payload.type === 'event_callback') { if (!team.bot) { @@ -262,8 +278,10 @@ function Slackbot(configuration) { } - // include the response channel so that they can be used in - // responding to slash commands and outgoing webhooks + /* + * include the response channel so that they can be used in + * responding to slash commands and outgoing webhooks + */ bot.res = res; // pass the payload into Botkit's message handling pipeline! @@ -278,13 +296,17 @@ function Slackbot(configuration) { slack_botkit.middleware.ingest.use(function sendResponse(bot, message, res, next) { if (res && res.statusCode) { - // this is an http response - // always send a 200 + /* + * this is an http response + * always send a 200 + */ res.status(200); - // conditionally send a response back to Slack to acknowledge the message. - // we do NOT want to respond to incoming webhooks or slash commands - // as the response can be used by developers to actually deliver a reply + /* + * conditionally send a response back to Slack to acknowledge the message. + * we do NOT want to respond to incoming webhooks or slash commands + * as the response can be used by developers to actually deliver a reply + */ if (!message.command && !message.trigger_word && !message.submission) { res.send(''); } @@ -298,8 +320,10 @@ function Slackbot(configuration) { if (message.ok != undefined) { // this is a confirmation of something we sent. if (slack_botkit.config.require_delivery) { - // loop through all active conversations this bot is having - // and mark messages in conversations as delivered = true + /* + * loop through all active conversations this bot is having + * and mark messages in conversations as delivered = true + */ for (var t = 0; t < slack_botkit.tasks.length; t++) { var task = slack_botkit.tasks[t]; if (task.isActive()) { @@ -367,7 +391,7 @@ function Slackbot(configuration) { // remove direct mention so the handler doesn't have to deal with it message.text = message.text.replace(direct_mention, '') - .replace(/^\s+/, '').replace(/^\:\s+/, '').replace(/^\s+/, ''); + .replace(/^\s+/, '').replace(/^\:\s+/, '').replace(/^\s+/, ''); } else { @@ -379,7 +403,7 @@ function Slackbot(configuration) { if (message.text.match(direct_mention)) { // this is a direct mention message.text = message.text.replace(direct_mention, '') - .replace(/^\s+/, '').replace(/^\:\s+/, '').replace(/^\s+/, ''); + .replace(/^\s+/, '').replace(/^\:\s+/, '').replace(/^\s+/, ''); message.type = 'direct_mention'; } else if (message.text.match(mention)) { @@ -402,7 +426,8 @@ function Slackbot(configuration) { }); - /* Handler functions for the various ways Slack might send a message to + /* + * Handler functions for the various ways Slack might send a message to * Botkit via webhooks. These include interactive messages (button clicks), * events api (messages sent over web hook), slash commands, and outgoing webhooks * (patterns matched in slack that result in a webhook) @@ -415,14 +440,18 @@ function Slackbot(configuration) { message.user = message.user.id; message.channel = message.channel.id; - // put the action value in the text field - // this allows button clicks to respond to asks + /* + * put the action value in the text field + * this allows button clicks to respond to asks + */ if (message.type == 'interactive_message') { message.text = message.actions[0].value; - // handle menus too! - // take the first selected item - // TODO: When Slack supports multi-select menus, this will need an update! + /* + * handle menus too! + * take the first selected item + * TODO: When Slack supports multi-select menus, this will need an update! + */ if (message.actions[0].selected_options) { message.text = message.actions[0].selected_options[0].value; } @@ -530,15 +559,19 @@ function Slackbot(configuration) { - /* End of webhook handler functions - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + /* + * End of webhook handler functions + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ slack_botkit.saveTeam = function(team, cb) { slack_botkit.storage.teams.save(team, cb); }; - // look up a team's memory and configuration and return it, or - // return an error! + /* + * look up a team's memory and configuration and return it, or + * return an error! + */ slack_botkit.findTeamById = function(id, cb) { slack_botkit.storage.teams.get(id, cb); }; @@ -569,10 +602,12 @@ function Slackbot(configuration) { }; - // set up a web route for redirecting users - // and collecting authentication details - // https://api.slack.com/docs/oauth - // https://api.slack.com/docs/oauth-scopes + /* + * set up a web route for redirecting users + * and collecting authentication details + * https://api.slack.com/docs/oauth + * https://api.slack.com/docs/oauth-scopes + */ slack_botkit.createOauthEndpoints = function(webserver, callback) { slack_botkit.log('** Serving login URL: http://' + @@ -663,22 +698,26 @@ function Slackbot(configuration) { slack_botkit.trigger('oauth_error', [err]); } else { - // auth contains at least: - // { access_token, scope, team_name} - // May also contain: - // { team_id } (not in incoming_webhook scope) - // info about incoming webhooks: - // { incoming_webhook: { url, channel, configuration_url} } - // might also include slash commands: - // { commands: ??} + /* + * auth contains at least: + * { access_token, scope, team_name} + * May also contain: + * { team_id } (not in incoming_webhook scope) + * info about incoming webhooks: + * { incoming_webhook: { url, channel, configuration_url} } + * might also include slash commands: + * { commands: ??} + */ // what scopes did we get approved for? var scopes = auth.scope.split(/\,/); - // temporarily use the token we got from the oauth - // we need to call auth.test to make sure the token is valid - // but also so that we reliably have the team_id field! - //slack_botkit.config.token = auth.access_token; + /* + * temporarily use the token we got from the oauth + * we need to call auth.test to make sure the token is valid + * but also so that we reliably have the team_id field! + *slack_botkit.config.token = auth.access_token; + */ auth_test({token: auth.access_token}, function(err, identity) { if (err) { @@ -693,9 +732,11 @@ function Slackbot(configuration) { } else { req.identity = identity; - // we need to deal with any team-level provisioning info - // like incoming webhooks and bot users - // and also with the personal access token from the user + /* + * we need to deal with any team-level provisioning info + * like incoming webhooks and bot users + * and also with the personal access token from the user + */ slack_botkit.findTeamById(identity.team_id, function(err, team) { @@ -734,7 +775,7 @@ function Slackbot(configuration) { slack_botkit.trigger('create_bot', [bot, team.bot]); } - slack_botkit.saveTeam(team, function(err, id) { + slack_botkit.saveTeam(team, function(err) { if (err) { slack_botkit.log.error('An error occurred while saving a team: ', err); if (callback) { @@ -751,13 +792,15 @@ function Slackbot(configuration) { } if (team.bot) { - // call auth test on the bot token - // to capture its name + /* + * call auth test on the bot token + * to capture its name + */ auth_test({ token: team.bot.token }, function(err, auth_data) { team.bot.name = auth_data.user; - slack_botkit.saveTeam(team, function(err, id) { + slack_botkit.saveTeam(team, function(err) { if (err) { slack_botkit.log.error('An error occurred while saving a team: ', err); } @@ -777,12 +820,14 @@ function Slackbot(configuration) { }; } - // Always update these because the token could become invalid - // and scopes could change. + /* + * Always update these because the token could become invalid + * and scopes could change. + */ user.access_token = auth.access_token; user.scopes = scopes; - slack_botkit.storage.users.save(user, function(err, id) { + slack_botkit.storage.users.save(user, function(err) { if (err) { slack_botkit.log.error( @@ -828,6 +873,6 @@ function Slackbot(configuration) { return slack_botkit; -}; +} module.exports = Slackbot; diff --git a/lib/Slack_web_api.js b/lib/Slack_web_api.js index e360150f5..a00704e0e 100755 --- a/lib/Slack_web_api.js +++ b/lib/Slack_web_api.js @@ -179,10 +179,12 @@ module.exports = function(bot, config) { // generate all API methods slackApiMethods.forEach(function(slackMethod) { - // most slack api methods are only two parts, of the form group.method, e.g. auth.test - // some have three parts: group.subgroup.method, e.g, users.profile.get - // this method loops through all groups in a method, ensures they exist, - // then adds the method to the terminal group + /* + * most slack api methods are only two parts, of the form group.method, e.g. auth.test + * some have three parts: group.subgroup.method, e.g, users.profile.get + * this method loops through all groups in a method, ensures they exist, + * then adds the method to the terminal group + */ var groups = slackMethod.split('.'); var method = groups.pop(); diff --git a/lib/Slackbot_worker.js b/lib/Slackbot_worker.js index 51bf32e6f..f4ed3d138 100755 --- a/lib/Slackbot_worker.js +++ b/lib/Slackbot_worker.js @@ -17,8 +17,10 @@ module.exports = function(botkit, config) { } }; - // Set when destroy() is called - prevents a reconnect from completing - // if it was fired off prior to destroy being called + /* + * Set when destroy() is called - prevents a reconnect from completing + * if it was fired off prior to destroy being called + */ var destroyed = false; var pingTimeoutId = null; var retryBackoff = null; @@ -117,8 +119,10 @@ module.exports = function(botkit, config) { * Shutdown and cleanup the spawned worker */ bot.destroy = function() { - // this prevents a startRTM from completing if it was fired off - // prior to destroy being called + /* + * this prevents a startRTM from completing if it was fired off + * prior to destroy being called + */ destroyed = true; if (retryBackoff) { retryBackoff.close(); @@ -168,7 +172,7 @@ module.exports = function(botkit, config) { }); bot.msgcount = 1; - bot.rtm.on('pong', function(obj) { + bot.rtm.on('pong', function() { lastPong = Date.now(); }); @@ -267,7 +271,7 @@ module.exports = function(botkit, config) { */ cb && cb('Identity Unknown: Not using RTM api'); return null; - }; + } }; bot.identifyTeam = function(cb) { @@ -414,12 +418,12 @@ module.exports = function(botkit, config) { }; /** - * Allows responding to slash commands and interactive messages with a plain - * 200 OK (without any text or attachments). - * - * @param {function} cb - An optional callback function called at the end of execution. - * The callback is passed an optional Error object. - */ + * Allows responding to slash commands and interactive messages with a plain + * 200 OK (without any text or attachments). + * + * @param {function} cb - An optional callback function called at the end of execution. + * The callback is passed an optional Error object. + */ bot.replyAcknowledge = function(cb) { if (!bot.res) { cb && cb(new Error('No web response object found')); @@ -488,7 +492,7 @@ module.exports = function(botkit, config) { method: 'POST', json: msg }; - request(requestOptions, function(err, resp, body) { + request(requestOptions, function(err) { /** * Do something? */ @@ -559,7 +563,7 @@ module.exports = function(botkit, config) { method: 'POST', json: msg }; - request(requestOptions, function(err, resp, body) { + request(requestOptions, function(err) { /** * Do something? */ @@ -600,7 +604,7 @@ module.exports = function(botkit, config) { method: 'POST', json: msg }; - request(requestOptions, function(err, resp, body) { + request(requestOptions, function(err) { /** * Do something? */ @@ -911,8 +915,10 @@ module.exports = function(botkit, config) { }; - // return info about the specific instance of this bot - // including identity information, and any other info that is relevant + /* + * return info about the specific instance of this bot + * including identity information, and any other info that is relevant + */ bot.getInstanceInfo = function(cb) { return new Promise(function(resolve, reject) { diff --git a/lib/Studio.js b/lib/Studio.js index c699d4018..6a5d86c19 100644 --- a/lib/Studio.js +++ b/lib/Studio.js @@ -12,11 +12,13 @@ module.exports = function(controller) { // define a place for the studio specific features to live. controller.studio = {}; - /* ---------------------------------------------------------------- + /* + * ---------------------------------------------------------------- * Botkit Studio Script Services * The features in this section grant access to Botkit Studio's * script and trigger services - * ---------------------------------------------------------------- */ + * ---------------------------------------------------------------- + */ function genConfig(bot) { @@ -61,8 +63,10 @@ module.exports = function(controller) { return sdk.getScripts(tag); }; - // create a simple script - // with a single trigger and single reply + /* + * create a simple script + * with a single trigger and single reply + */ controller.studio.createScript = function(bot, trigger, text) { var sdk = new SDK(genConfig(bot || {})); return sdk.createScript(trigger, text); @@ -70,16 +74,12 @@ module.exports = function(controller) { // load a script from the pro service controller.studio.getScriptById = function(bot, id, user) { - - var userHash = md5(user); var sdk = new SDK(genConfig(bot)); return sdk.getScriptById(id, user); }; // load a script from the pro service controller.studio.getScript = function(bot, text, user) { - - var userHash = md5(user); var sdk = new SDK(genConfig(bot)); return sdk.getScript(text, user); }; @@ -160,8 +160,10 @@ module.exports = function(controller) { } - /* Fetch a script from Botkit Studio by name, then execute it. - * returns a promise that resolves when the conversation is loaded and active */ + /* + * Fetch a script from Botkit Studio by name, then execute it. + * returns a promise that resolves when the conversation is loaded and active + */ controller.studio.run = function(bot, input_text, user, channel, original_message) { return new Promise(function(resolve, reject) { @@ -176,9 +178,11 @@ module.exports = function(controller) { }; - /* Fetch a script from Botkit Studio by name, but do not execute it. + /* + * Fetch a script from Botkit Studio by name, but do not execute it. * returns a promise that resolves when the conversation is loaded - * but developer still needs to call convo.activate() to put it in motion */ + * but developer still needs to call convo.activate() to put it in motion + */ controller.studio.get = function(bot, input_text, user, channel, original_message) { var context = { text: input_text, @@ -229,9 +233,11 @@ module.exports = function(controller) { }); }; - /* Fetch a script from Botkit Studio by id, but do not execute it. + /* + * Fetch a script from Botkit Studio by id, but do not execute it. * returns a promise that resolves when the conversation is loaded - * but developer still needs to call convo.activate() to put it in motion */ + * but developer still needs to call convo.activate() to put it in motion + */ controller.studio.getById = function(bot, id, user, channel, original_message) { var context = { id: id, @@ -328,8 +334,10 @@ module.exports = function(controller) { reject(err); }); } else { - // return with no conversation - // allow developer to run a default script + /* + * return with no conversation + * allow developer to run a default script + */ resolve(null); } }).catch(function(err) { @@ -340,12 +348,7 @@ module.exports = function(controller) { }; - controller.studio.testTrigger = function(bot, input_text, user, channel) { - var context = { - text: input_text, - user: user, - channel: channel, - }; + controller.studio.testTrigger = function(bot, input_text, user) { return new Promise(function(resolve, reject) { controller.studio.evaluateTrigger(bot, input_text, user).then(function(command) { if (command !== {} && command.id) { @@ -410,13 +413,17 @@ module.exports = function(controller) { for (var v = 0; v < command.variables.length; v++) { if (command.variables[v].value) { - // set the key/value as a mustache variable - // accessible as {{vars.name}} in the templates + /* + * set the key/value as a mustache variable + * accessible as {{vars.name}} in the templates + */ convo.setVar(command.variables[v].name, command.variables[v].value); - // also add this as an "answer" to a question - // thus making it available at {{responses.name}} and - // convo.extractResponse(name); + /* + * also add this as an "answer" to a question + * thus making it available at {{responses.name}} and + * convo.extractResponse(name); + */ convo.responses[command.variables[v].name] = { question: command.variables[v].name, text: command.variables[v].value, @@ -628,7 +635,7 @@ module.exports = function(controller) { runHooks( answer_hooks[command.command] ? answer_hooks[command.command].slice() : [], convo, - function(convo) { + function() { c.next(); } ); @@ -661,11 +668,13 @@ module.exports = function(controller) { }); }; - /* ---------------------------------------------------------------- + /* + * ---------------------------------------------------------------- * Botkit Studio Stats * The features below this line pertain to communicating with Botkit Studio's * stats feature. - * ---------------------------------------------------------------- */ + * ---------------------------------------------------------------- + */ @@ -738,7 +747,9 @@ module.exports = function(controller) { try { json = JSON.parse(body); - } catch (e) {} + } catch (e) { + // Swallow this error. + } if (!json || json == null) { return reject('Response from Botkit Studio API was empty or invalid JSON'); @@ -792,12 +803,14 @@ module.exports = function(controller) { break; } return x; - }; + } - /* Every time a bot spawns, Botkit calls home to identify this unique bot + /* + * Every time a bot spawns, Botkit calls home to identify this unique bot * so that the maintainers of Botkit can measure the size of the installed - * userbase of Botkit-powered bots. */ + * userbase of Botkit-powered bots. + */ if (!controller.config.stats_optout) { controller.on('spawned', function(bot) { diff --git a/lib/Teams.js b/lib/Teams.js index a1afe9710..e962c0338 100644 --- a/lib/Teams.js +++ b/lib/Teams.js @@ -1,8 +1,4 @@ var Botkit = require(__dirname + '/CoreBot.js'); -var express = require('express'); -var bodyParser = require('body-parser'); -var querystring = require('querystring'); -var request = require('requestretry'); var clone = require('clone'); var async = require('async'); var TeamsAPI = require(__dirname + '/TeamsAPI.js'); @@ -20,7 +16,7 @@ function TeamsBot(configuration) { let tokenExpiresIn = (configuration.token_expires_in || 3600) * 1000; let expiryCheckDelta = 1000 * 60 * 10; setTimeout(controller.api.getToken, (tokenExpiresIn - expiryCheckDelta), tokenHandler); - }; + } controller.api.getToken(tokenHandler); controller.defineBot(function(botkit, config) { @@ -126,8 +122,10 @@ function TeamsBot(configuration) { bot.replyToComposeExtension = function(src, attachments, cb) { - // attachments will be an array of attachments - // need to wrap it in necessary stuff + /* + * attachments will be an array of attachments + * need to wrap it in necessary stuff + */ var resp = { composeExtension: { type: 'result', @@ -180,7 +178,7 @@ function TeamsBot(configuration) { for (var t = 0; t < botkit.tasks.length; t++) { for (var c = 0; c < botkit.tasks[t].convos.length; c++) { if ( - botkit.tasks[t].convos[c].isActive() && + botkit.tasks[t].convos[c].isActive() && botkit.tasks[t].convos[c].source_message.user == message.user && botkit.excludedEvents.indexOf(message.type) == -1 // this type of message should not be included @@ -195,10 +193,12 @@ function TeamsBot(configuration) { cb(); }; - // return info about the specific instance of this bot - // including identity information, and any other info that is relevant + /* + * return info about the specific instance of this bot + * including identity information, and any other info that is relevant + */ bot.getInstanceInfo = function(cb) { - return new Promise(function(resolve, reject) { + return new Promise(function(resolve) { var instance = { identity: {}, team: {}, @@ -418,8 +418,10 @@ function TeamsBot(configuration) { // replies to these end up in the right place for (var m = 0; m < message.raw_message.membersAdded.length; m++) { - // clone the message - // and copy this member into the from list + /* + * clone the message + * and copy this member into the from list + */ delete(message.http_res); // <-- that can't be cloned safely var copy = clone(message); copy.from = message.raw_message.membersAdded[m]; @@ -441,8 +443,10 @@ function TeamsBot(configuration) { // replies to these end up in the right place for (var m = 0; m < message.raw_message.membersRemoved.length; m++) { - // clone the message - // and copy this member into the from list + /* + * clone the message + * and copy this member into the from list + */ delete(message.http_res); // <-- that can't be cloned safely var copy = clone(message); copy.from = message.raw_message.membersRemoved[m]; @@ -460,10 +464,12 @@ function TeamsBot(configuration) { next(); } else if (message.raw_message.channelData && message.raw_message.channelData.eventType) { - // channelCreated - // channelDeleted - // channelRenamed - // teamRenamed + /* + * channelCreated + * channelDeleted + * channelRenamed + * teamRenamed + */ message.type = message.raw_message.channelData.eventType; // replies to these end up in general @@ -509,10 +515,12 @@ function TeamsBot(configuration) { }); - // This middleware looks for Slack-style user mentions in a message - // <@USERID> and translates them into Microsoft Teams style mentions - // which look like @User Name and have a matching row in the - // message.entities field. + /* + * This middleware looks for Slack-style user mentions in a message + * <@USERID> and translates them into Microsoft Teams style mentions + * which look like @User Name and have a matching row in the + * message.entities field. + */ controller.middleware.send.use(function(bot, message, next) { var matches; diff --git a/lib/TeamsAPI.js b/lib/TeamsAPI.js index ea21c4f45..434e810e8 100644 --- a/lib/TeamsAPI.js +++ b/lib/TeamsAPI.js @@ -20,9 +20,11 @@ module.exports = function(configuration) { } if (res.statusCode == 202) { - // this message has been queued for delivery on the Teams-side - // Awkward that it does not return the normal message object - // this prevents use of message updating for messages that get queued + /* + * this message has been queued for delivery on the Teams-side + * Awkward that it does not return the normal message object + * this prevents use of message updating for messages that get queued + */ if (cb) { return cb(null, {}); } else return; } diff --git a/lib/TwilioIPMBot.js b/lib/TwilioIPMBot.js index d63890a57..2311bc3bf 100644 --- a/lib/TwilioIPMBot.js +++ b/lib/TwilioIPMBot.js @@ -1,5 +1,4 @@ var Botkit = require(__dirname + '/CoreBot.js'); -var request = require('request'); var Twilio = require('twilio'); var async = require('async'); @@ -9,8 +8,10 @@ function Twiliobot(configuration) { // Create a core botkit bot var twilio_botkit = Botkit(configuration || {}); - // customize the bot definition, which will be used when new connections - // spawn! + /* + * customize the bot definition, which will be used when new connections + * spawn! + */ twilio_botkit.defineBot(function(botkit, config) { var bot = { type: 'twilioipm', @@ -52,7 +53,7 @@ function Twiliobot(configuration) { bot.channels.forEach(function(chan) { bot.api.channels(chan.sid).members.create({ identity: bot.identity - }).then(function(response) { + }).then(function() { botkit.debug('added ' + bot.identity + ' as a member of the ' + chan.friendlyName); }).catch(function(error) { @@ -82,8 +83,10 @@ function Twiliobot(configuration) { } }).catch(function(error) { botkit.log('Error loading channel list: ' + error); - // fails if no channels exist - // set the channels to empty + /* + * fails if no channels exist + * set the channels to empty + */ bot.channels = { channels: [] }; }); @@ -91,31 +94,34 @@ function Twiliobot(configuration) { bot.configureBotIdentity = function() { if (bot.identity !== null || bot.identity !== '') { - var userRespIter = 0; - var existingIdentity = null; // try the get by identity thing - bot.api.users(bot.identity).fetch().then(function(response) { + bot.api.users(bot.identity).fetch().then(function() { bot.autoJoinChannels(); }).catch(function(error) { - // if not make the new user and see if they need to be added to all the channels - bot.api.users.create({ - identity: bot.identity - }).then(function(response) { - bot.autoJoinChannels(); - }).catch(function(error) { - botkit.log('Could not get Bot Identity:'); - botkit.log(error); + if (error) { + console.error(error); process.exit(1); - }); + } else { + // if not make the new user and see if they need to be added to all the channels + bot.api.users.create({ + identity: bot.identity + }).then(function() { + bot.autoJoinChannels(); + }).catch(function(error) { + botkit.log('Could not get Bot Identity:'); + botkit.log(error); + process.exit(1); + }); + } }); } }; /** - * This handles the particulars of finding an existing conversation or - * topic to fit the message into... - */ + * This handles the particulars of finding an existing conversation or + * topic to fit the message into... + */ bot.findConversation = function(message, cb) { botkit.debug('CUSTOM FIND CONVO', message.user, message.channel); for (var t = 0; t < botkit.tasks.length; t++) { @@ -306,7 +312,7 @@ function Twiliobot(configuration) { // join the channel bot.api.channels(message.channel).members.create({ identity: bot.identity - }).then(function(response) { + }).then(function() { return bot.api.channels(message.channel).fetch().then(function(response) { bot.channels.push(response); twilio_botkit.debug('Subscribing to new channel.'); diff --git a/lib/TwilioSMSBot.js b/lib/TwilioSMSBot.js index 5bf7f8d64..e9fbe9add 100644 --- a/lib/TwilioSMSBot.js +++ b/lib/TwilioSMSBot.js @@ -1,8 +1,5 @@ -var path = require('path'); var os = require('os'); var Botkit = require('./CoreBot'); -var express = require('express'); -var bodyParser = require('body-parser'); var Twilio = require('twilio'); function TwilioSMS(configuration) { diff --git a/lib/Web.js b/lib/Web.js index bac5f4e54..1d4e5d337 100644 --- a/lib/Web.js +++ b/lib/Web.js @@ -51,7 +51,7 @@ function WebBot(configuration) { ws.on('error', (err) => console.error('Websocket Error: ', err)); - ws.on('close', function(err) { + ws.on('close', function() { bot.connected = false; }); @@ -73,16 +73,20 @@ function WebBot(configuration) { controller.middleware.ingest.use(function(bot, message, reply_channel, next) { - // this could be a message from the WebSocket - // or it might be coming from a webhook. - // configure the bot appropriately so the reply goes to the right place! + /* + * this could be a message from the WebSocket + * or it might be coming from a webhook. + * configure the bot appropriately so the reply goes to the right place! + */ if (!bot.ws) { bot.http_response = reply_channel; } - // look for an existing conversation for this user/channel combo - // why not just pass in message? because we only care if there is a conversation ongoing - // and we might be dealing with "silent" message that would not otherwise match a conversation + /* + * look for an existing conversation for this user/channel combo + * why not just pass in message? because we only care if there is a conversation ongoing + * and we might be dealing with "silent" message that would not otherwise match a conversation + */ bot.findConversation({ user: message.user, channel: message.channel @@ -97,8 +101,10 @@ function WebBot(configuration) { } } else { - // replace the reply channel in the active conversation - // this is the one that gets used to send the actual reply + /* + * replace the reply channel in the active conversation + * this is the one that gets used to send the actual reply + */ convo.task.bot.http_response = bot.http_response; } } @@ -205,7 +211,7 @@ function WebBot(configuration) { bot.typingDelay = function(message) { - return new Promise(function(resolve, reject) { + return new Promise(function(resolve) { var typingLength = 0; if (message.typingDelay) { typingLength = message.typingDelay; @@ -289,11 +295,13 @@ function WebBot(configuration) { }; - // return info about the specific instance of this bot - // including identity information, and any other info that is relevant + /* + * return info about the specific instance of this bot + * including identity information, and any other info that is relevant + */ bot.getInstanceInfo = function(cb) { - return new Promise(function(resolve, reject) { + return new Promise(function(resolve) { var instance = { identity: {}, team: {}, @@ -319,7 +327,7 @@ function WebBot(configuration) { }; bot.getMessageUser = function(message, cb) { - return new Promise(function(resolve, reject) { + return new Promise(function(resolve) { // normalize this into what botkit wants to see controller.storage.users.get(message.user, function(err, user) { diff --git a/lib/WebexBot.js b/lib/WebexBot.js index 84120657c..534733fc5 100644 --- a/lib/WebexBot.js +++ b/lib/WebexBot.js @@ -10,7 +10,7 @@ function WebexBot(configuration) { // [COMPAT] Webex rebrand, see https://github.com/howdyai/botkit/issues/1346 if (controller.config.ciscospark_access_token) { - console.log('DEPRECATED: please switch your configuration property from "ciscospark_access_token" to "access_token"'); + console.warn('DEPRECATED: please switch your configuration property from "ciscospark_access_token" to "access_token"'); controller.config.access_token = controller.config.ciscospark_access_token; } @@ -51,7 +51,7 @@ function WebexBot(configuration) { } if (!controller.config.secret) { - console.log('WARNING: No secret specified. Source of incoming webhooks will not be validated. https://developer.webex.com/webhooks-explained.html#auth'); + console.warn('WARNING: No secret specified. Source of incoming webhooks will not be validated. https://developer.webex.com/webhooks-explained.html#auth'); // throw new Error('secret parameter required to secure webhooks'); } @@ -59,7 +59,7 @@ function WebexBot(configuration) { controller.resetWebhookSubscriptions = function() { controller.api.webhooks.list().then(function(list) { for (var i = 0; i < list.items.length; i++) { - controller.api.webhooks.remove(list.items[i]).then(function(res) { + controller.api.webhooks.remove(list.items[i]).then(function() { // console.log('Removed subscription: ' + list.items[i].name); }).catch(function(err) { console.error('Error removing subscription:', err); @@ -83,7 +83,7 @@ function WebexBot(configuration) { 'COMPATIBILITY: because we detected the "ciscospark_access_token" configuration property, ', 'the "' + compat_path + '" path is used instead of "' + webhook_path + '"' ]; - console.log(lines.join(' ')); + console.warn(lines.join(' ')); webhook_path = compat_path; } @@ -97,7 +97,7 @@ function WebexBot(configuration) { }); - var list = controller.api.webhooks.list().then(function(list) { + controller.api.webhooks.list().then(function(list) { var hook_id = null; for (var i = 0; i < list.items.length; i++) { @@ -118,7 +118,7 @@ function WebexBot(configuration) { event: 'all', secret: controller.config.secret, name: webhook_name, - }).then(function(res) { + }).then(function() { console.log('Webex: SUCCESSFULLY UPDATED WEBEX WEBHOOKS'); if (cb) cb(); }).catch(function(err) { @@ -133,8 +133,7 @@ function WebexBot(configuration) { event: 'all', secret: controller.config.secret, name: webhook_name, - }).then(function(res) { - + }).then(function() { console.log('Webex: SUCCESSFULLY REGISTERED WEBEX WEBHOOKS'); if (cb) cb(); }).catch(function(err) { @@ -150,8 +149,10 @@ function WebexBot(configuration) { controller.middleware.spawn.use(function(worker, next) { - // copy the identity that we get when the app initially boots up - // into the specific bot instance + /* + * copy the identity that we get when the app initially boots up + * into the specific bot instance + */ worker.identity = controller.identity; next(); @@ -163,7 +164,7 @@ function WebexBot(configuration) { if (controller.config.limit_to_org) { if (!message.raw_message.orgId || message.raw_message.orgId != controller.config.limit_to_org) { // this message is from a user outside of the proscribed org - console.log('WARNING: this message is from a user outside of the proscribed org', controller.config.limit_to_org); + console.warn('WARNING: this message is from a user outside of the proscribed org', controller.config.limit_to_org); return false; } } @@ -187,7 +188,7 @@ function WebexBot(configuration) { } if (!allowed) { - console.log('WARNING: this message came from a domain that is outside of the allowed list', controller.config.limit_to_domain); + console.warn('WARNING: this message came from a domain that is outside of the allowed list', controller.config.limit_to_domain); // this message came from a domain that is outside of the allowed list. return false; } @@ -345,8 +346,10 @@ function WebexBot(configuration) { }; - // customize the bot definition, which will be used when new connections - // spawn! + /* + * customize the bot definition, which will be used when new connections + * spawn! + */ controller.defineBot(function(botkit, config) { var bot = { @@ -367,8 +370,10 @@ function WebexBot(configuration) { botkit.startTask(bot, message_options, function(task, convo) { convo.on('sent', function(sent_message) { - // update this convo so that future messages will match - // since the source message did not have this info in it. + /* + * update this convo so that future messages will match + * since the source message did not have this info in it. + */ convo.source_message.user = message_options.toPersonEmail; convo.source_message.channel = sent_message.roomId; @@ -461,7 +466,7 @@ function WebexBot(configuration) { headers: { 'Authorization': 'Bearer ' + controller.config.access_token }, - }, function(err, response, body) { + }, function(err, response) { if (!err) { var obj = response.headers; @@ -493,8 +498,10 @@ function WebexBot(configuration) { }; - // return info about the specific instance of this bot - // including identity information, and any other info that is relevant + /* + * return info about the specific instance of this bot + * including identity information, and any other info that is relevant + */ bot.getInstanceInfo = function(cb) { return new Promise(function(resolve, reject) { var instance = { diff --git a/lib/storage/simple_storage.js b/lib/storage/simple_storage.js index 8768a2d1b..335883bf3 100755 --- a/lib/storage/simple_storage.js +++ b/lib/storage/simple_storage.js @@ -1,26 +1,26 @@ /* -Storage module for bots. - -Supports storage of data on a team-by-team, user-by-user, and channel-by-channel basis. - -save can be used to store arbitrary object. -These objects must include an id by which they can be looked up. -It is recommended to use the team/user/channel id for this purpose. -Example usage of save: -controller.storage.teams.save({id: message.team, foo:"bar"}, function(err){ - if (err) - console.log(err) -}); - -get looks up an object by id. -Example usage of get: -controller.storage.teams.get(message.team, function(err, team_data){ - if (err) - console.log(err) - else - console.log(team_data) -}); -*/ + * Storage module for bots. + * + * Supports storage of data on a team-by-team, user-by-user, and channel-by-channel basis. + * + * save can be used to store arbitrary object. + * These objects must include an id by which they can be looked up. + * It is recommended to use the team/user/channel id for this purpose. + * Example usage of save: + * controller.storage.teams.save({id: message.team, foo:"bar"}, function(err){ + * if (err) + * console.log(err) + * }); + * + * get looks up an object by id. + * Example usage of get: + * controller.storage.teams.get(message.team, function(err, team_data){ + * if (err) + * console.log(err) + * else + * console.log(team_data) + * }); + */ var Store = require('jfs'); diff --git a/tests/lib/Slack_web_api.test.js b/tests/lib/Slack_web_api.test.js index 1067b0e21..85aa8d225 100644 --- a/tests/lib/Slack_web_api.test.js +++ b/tests/lib/Slack_web_api.test.js @@ -117,8 +117,10 @@ describe('callApiWithoutToken', () => { }; const cb = jest.fn(); - // this seems to be an API inconsistency: - // callAPIWithoutToken uses bot.config, but callAPI uses that passed config + /* + * this seems to be an API inconsistency: + * callAPIWithoutToken uses bot.config, but callAPI uses that passed config + */ mockBot.config = config; instance = slackWebApi(mockBot, {}); @@ -144,7 +146,7 @@ describe('postForm', () => { cb = jest.fn(); }); - test(`${methodName}: handles success`, () => { + test(`${ methodName }: handles success`, () => { method('some.action', 'data', cb); expect(mockRequest.post).toHaveBeenCalledTimes(1); const firstArg = mockRequest.post.mock.calls[0][0]; @@ -157,12 +159,12 @@ describe('postForm', () => { expect(cb).toHaveBeenCalledWith(null, { ok: true }); }); - test(`${methodName}: defaults callback`, () => { + test(`${ methodName }: defaults callback`, () => { method('some.action', 'data'); expect(mockRequest.post).toHaveBeenCalledTimes(1); }); - test(`${methodName}: handles request lib error`, () => { + test(`${ methodName }: handles request lib error`, () => { const error = new Error('WHOOPS!'); mockRequest.post.mockImplementation((params, callback) => { callback(error, null, null); @@ -174,7 +176,7 @@ describe('postForm', () => { expect(cb).toHaveBeenCalledWith(error); }); - test(`${methodName}: handles 429 response code`, () => { + test(`${ methodName }: handles 429 response code`, () => { mockRequest.post.mockImplementation((params, callback) => { callback(null, { statusCode: 429 }, null); }); @@ -187,7 +189,7 @@ describe('postForm', () => { expect(firstArg.message).toBe('Rate limit exceeded'); }); - test(`${methodName}: handles other response codes`, () => { + test(`${ methodName }: handles other response codes`, () => { mockRequest.post.mockImplementation((params, callback) => { callback(null, { statusCode: 400 }, null); }); @@ -200,7 +202,7 @@ describe('postForm', () => { expect(firstArg.message).toBe('Invalid response'); }); - test(`${methodName}: handles error parsing body`, () => { + test(`${ methodName }: handles error parsing body`, () => { mockRequest.post.mockImplementation((params, callback) => { callback(null, { statusCode: 200 }, '{'); }); @@ -213,7 +215,7 @@ describe('postForm', () => { expect(firstArg).toBeInstanceOf(Error); }); - test(`${methodName}: handles ok.false response`, () => { + test(`${ methodName }: handles ok.false response`, () => { mockRequest.post.mockImplementation((params, callback) => { callback(null, { statusCode: 200 }, '{ "ok": false, "error": "not ok"}'); }); diff --git a/tests/lib/Teams.test.js b/tests/lib/Teams.test.js index 2aa2aae14..0e4ad34d0 100644 --- a/tests/lib/Teams.test.js +++ b/tests/lib/Teams.test.js @@ -1,5 +1,4 @@ 'use strict'; -let teamsBot; let teamsApi; let config = { clientId: 'client', diff --git a/tests/unit/storage.test.js b/tests/unit/storage.test.js index e3b0ecbf6..d4dc6e329 100644 --- a/tests/unit/storage.test.js +++ b/tests/unit/storage.test.js @@ -1,12 +1,12 @@ 'use strict'; /* -Tests for storage modules. -This file currently test simple_storage.js. - -If you build a new storage module, -you must add it to this test file before your PR will be considered. -*/ + * Tests for storage modules. + * This file currently test simple_storage.js. + * + * If you build a new storage module, + * you must add it to this test file before your PR will be considered. + */ const mkdirp = require('mkdirp'); @@ -17,13 +17,13 @@ expect.extend({ if (pass) { return { message: () => - `Ok`, + `Ok`, pass: true, }; } else { return { message: () => - `expected ${received} to be either null or undefined`, + `expected ${ received } to be either null or undefined`, pass: false, }; } @@ -46,7 +46,7 @@ describe('Simple Storage', () => { describe('Has correct methods', () => { - test(`Interfaces for ${key}`, () => { + test(`Interfaces for ${ key }`, () => { expect(store).toBeDefined(); expect(store.save).toBeInstanceOf(Function); expect(store.get).toBeInstanceOf(Function); @@ -55,7 +55,7 @@ describe('Simple Storage', () => { }); }); - describe(`Operations for ${key}`, () => { + describe(`Operations for ${ key }`, () => { const store = storage[key]; test('Save', (done) => { @@ -77,7 +77,7 @@ describe('Simple Storage', () => { }); ['TESTX', undefined, null].forEach((id) => { - test(`Get - data not present (${typeof id})`, (done) => { + test(`Get - data not present (${ typeof id })`, (done) => { store.get(id, (err, data) => { expect(err).toBeTruthy(); expect(data).toBeNullOrUndefined(); @@ -106,7 +106,7 @@ describe('Simple Storage', () => { }); ['TESTX', undefined, null].forEach((id) => { - test(`Delete - data not present' (${typeof id})`, (done) => { + test(`Delete - data not present' (${ typeof id })`, (done) => { store.delete(id, (err, data) => { expect(err).toBeTruthy(); expect(data).toBeNullOrUndefined();