diff --git a/README.md b/README.md index 81a8b02..7b7c0a7 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ This code is enough to operate bots for all supported platforms. Claudia Bot Bui * Line * Kik * GroupMe +* Google Assistant +* Cortana ## Creating bots diff --git a/lib/alexa/parse.js b/lib/alexa/parse.js index 4386f20..322da03 100644 --- a/lib/alexa/parse.js +++ b/lib/alexa/parse.js @@ -12,7 +12,8 @@ module.exports = function alexaParse(messageObject) { sender: messageObject.session.user.userId, text: getSlotValues(messageObject.request.intent.slots) || '', originalRequest: messageObject, - type: 'alexa-skill' + type: 'alexa-skill', + accessToken: messageObject.session.user.accessToken }; } @@ -21,7 +22,8 @@ module.exports = function alexaParse(messageObject) { sender: messageObject.session.user.userId, text: '', originalRequest: messageObject, - type: 'alexa-skill' + type: 'alexa-skill', + accessToken: messageObject.session.user.accessToken }; } -}; +}; \ No newline at end of file diff --git a/lib/bot-builder.js b/lib/bot-builder.js index 089e8dd..878a4a1 100644 --- a/lib/bot-builder.js +++ b/lib/bot-builder.js @@ -11,6 +11,8 @@ const groupmeSetup = require('./groupme/setup'); const lineSetup = require('./line/setup'); const viberSetup = require('./viber/setup'); const alexaSetup = require('./alexa/setup'); +const googleSetup = require('./google/setup'); +const cortanaSetup = require('./cortana/setup'); const fbTemplate = require('./facebook/format-message'); const slackTemplate = require('./slack/format-message'); const slackDialog = require('./slack/format-dialog'); @@ -68,6 +70,12 @@ module.exports = function botBuilder(messageHandler, options, optionalLogError) if (isEnabled('alexa')) { alexaSetup(api, messageHandlerPromise, logError); } + if (isEnabled('google')) { + googleSetup(api, messageHandlerPromise, logError); + } + if (isEnabled('cortana')) { + cortanaSetup(api, messageHandlerPromise, logError); + } return api; }; diff --git a/lib/cortana/parse.js b/lib/cortana/parse.js new file mode 100644 index 0000000..ae34d83 --- /dev/null +++ b/lib/cortana/parse.js @@ -0,0 +1,17 @@ +'use strict'; + +module.exports = function cortanaParse(session, request) { + if (session) { + const entities = session.message.entities || []; + const authToken = entities.find((entity) => { + return entity.type === 'AuthorizationToken'; + }) || {}; + return { + sender: session.message.user.id, + text: session.message.text || '', + originalRequest: request, + type: 'cortana-skill', + accessToken: authToken.token + }; + } +}; diff --git a/lib/cortana/reply.js b/lib/cortana/reply.js new file mode 100644 index 0000000..f5d39d2 --- /dev/null +++ b/lib/cortana/reply.js @@ -0,0 +1,13 @@ +'use strict'; + +module.exports = function cortanaReply(botResponse, session) { + if (typeof botResponse === 'string') { + session.endConversation(botResponse); + } else if (Array.isArray(botResponse)) { + for(let message of botResponse) { + session.send(message); + } + } else { + session.send(botResponse); + } +}; diff --git a/lib/cortana/setup.js b/lib/cortana/setup.js new file mode 100644 index 0000000..a69de39 --- /dev/null +++ b/lib/cortana/setup.js @@ -0,0 +1,104 @@ +'use strict'; + +const prompt = require('souffleur'); +const cortanaParse = require('./parse'); +const cortanaReply = require('./reply'); +const color = require('../console-colors'); +const builder = require('botbuilder'); +const envUtils = require('../utils/env-utils'); + +let connector = null; +let universalBot = null; + +let self = this; +self.chatConnectorRequestListener = null; +self.promiseResolver = null; + +module.exports = function cortanaSetup(api, bot, logError, optionalParser, optionalResponder) { + let parser = optionalParser || cortanaParse; + let responder = optionalResponder || cortanaReply; + + api.post('/cortana', (request) => { + if (connector == null) { + connector = new builder.ChatConnector({ + appId: envUtils.decode(request.env.cortanaAppId), + appPassword: envUtils.decode(request.env.cortanaAppPassword) + }); + + universalBot = new builder.UniversalBot(connector, (session) => { + let message = parser(session, request); + bot(message, request) + .then(botReply => { + responder(botReply, session); + }) + .catch(logError); + }); + + let oldSend = universalBot.send; + universalBot.send = function(messages, done) { + let newDone = function () { + done(); + self.promiseResolver(); + }; + oldSend.call(universalBot, messages, newDone); + }; + + universalBot.use({ + receive: function(event, next) { + if(event.type === 'conversationUpdate') { + self.promiseResolver(); + } + next(); + }, + send: function(event, next) { + next(); + } + }); + + self.chatConnectorRequestListener = connector.listen(); + } + + let promise = new Promise((resolve) => { + self.promiseResolver = resolve; + let reqWrapper = { + body: request.body, + headers: request.headers + }; + let resWrapper = { + status: () => { + }, + end: () => { + } + }; + self.chatConnectorRequestListener(reqWrapper, resWrapper); + }); + return promise; + }); + + api.addPostDeployStep('cortana', (options, lambdaDetails, utils) => { + return Promise.resolve().then(() => { + if (options['configure-cortana-skill']) { + console.log(`\n\n${color.green}Cortana skill command setup${color.reset}\n`); + console.log(`\nConfigure your Cortana Skill endpoint to HTTPS and set this URL:.\n`); + console.log(`\n${color.cyan}${lambdaDetails.apiUrl}/cortana${color.reset}\n`); + console.log(`\nIn the SSL Certificate step, select "${color.dim}My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority${color.reset}".\n`); + + return prompt(['appId', 'appPassword']) + .then(results => { + const deployment = { + restApiId: lambdaDetails.apiId, + stageName: lambdaDetails.alias, + variables: { + cortanaAppId: envUtils.encode(results['appId']), + cortanaAppPassword: envUtils.encode(results['appPassword']) + } + }; + console.log(`\n`); + + return utils.apiGatewayPromise.createDeploymentPromise(deployment); + }).catch(logError); + } + }).then(() => `${lambdaDetails.apiUrl}/cortana`) + .catch(logError); + }); +}; diff --git a/lib/google/assistant.js b/lib/google/assistant.js new file mode 100644 index 0000000..88c3f22 --- /dev/null +++ b/lib/google/assistant.js @@ -0,0 +1,22 @@ +const { ActionsSdkApp } = require('actions-on-google'); +const expressMockery = require('node-mocks-http'); + +function getAssistant(request) { + + // Prep the request and response. + var mockRequest = expressMockery.createRequest({ + body: request.body + }); + + var mockResponse = expressMockery.createResponse(); + + // We need this monkey patch because node-mocks-http doesn't have the append. + mockResponse['append'] = (header, value) => { + console.log('Google SDK added a header: "' + header + '": "' + value + '"'); + }; + + // Feed the request/response to the assistant SDK + return new ActionsSdkApp({ request: mockRequest, response: mockResponse }); +} + +module.exports = getAssistant; \ No newline at end of file diff --git a/lib/google/parse.js b/lib/google/parse.js new file mode 100644 index 0000000..cad417d --- /dev/null +++ b/lib/google/parse.js @@ -0,0 +1,13 @@ +'use strict'; + +module.exports = function googleParse(assistant, request) { + if (assistant) { + return { + sender: assistant.getUser().userId, + text: assistant.getRawInput(), + originalRequest: request, + type: 'google-action', + accessToken: assistant.getUser().accessToken + }; + } +}; diff --git a/lib/google/reply.js b/lib/google/reply.js new file mode 100644 index 0000000..30cd329 --- /dev/null +++ b/lib/google/reply.js @@ -0,0 +1,9 @@ +'use strict'; + +module.exports = function googleReply(botResponse, botName, assistant) { + if (typeof botResponse === 'string') { + assistant.tell(botResponse); + return assistant.response_._getData(); + } + return botResponse; +}; diff --git a/lib/google/setup.js b/lib/google/setup.js new file mode 100644 index 0000000..3b1cff5 --- /dev/null +++ b/lib/google/setup.js @@ -0,0 +1,50 @@ +'use strict'; + +const prompt = require('souffleur'); +const googleParse = require('./parse'); +const googleReply = require('./reply'); +const color = require('../console-colors'); +const envUtils = require('../utils/env-utils'); +const getAssistant = require('./assistant'); + +module.exports = function googleSetup(api, bot, logError, optionalParser, optionalResponder) { + let parser = optionalParser || googleParse; + let responder = optionalResponder || googleReply; + + api.post('/google', (request) => { + const assistant = getAssistant(request); + return bot(parser(assistant, request), request) + .then(botReply => { + return responder(botReply, envUtils.decode(request.env.googleAppName), assistant); + }) + .catch(logError); + }); + + api.addPostDeployStep('google', (options, lambdaDetails, utils) => { + return Promise.resolve().then(() => { + if (options['configure-google-action']) { + console.log(`\n\n${color.green}Google Action command setup${color.reset}\n`); + console.log(`\nConfigure your Google Action endpoint to HTTPS and set this URL:.\n`); + console.log(`\n${color.cyan}${lambdaDetails.apiUrl}/google${color.reset}\n`); + console.log(`\nIn the SSL Certificate step, select "${color.dim}My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority${color.reset}".\n`); + + return prompt(['Google App Name']) + .then(results => { + const deployment = { + restApiId: lambdaDetails.apiId, + stageName: lambdaDetails.alias, + variables: { + googleAppName: envUtils.encode(results['Google App Name']) + } + }; + + console.log(`\n`); + + return utils.apiGatewayPromise.createDeploymentPromise(deployment); + }) + .catch(logError); + } + }) + .then(() => `${lambdaDetails.apiUrl}/google`).catch(logError); + }); +}; diff --git a/lib/utils/env-utils.js b/lib/utils/env-utils.js index 77e6351..d081e05 100644 --- a/lib/utils/env-utils.js +++ b/lib/utils/env-utils.js @@ -2,9 +2,11 @@ module.exports = { encode(str) { + if(!str) return ''; return new Buffer(str).toString('base64').replace(/\+/g, '-'); }, decode(str) { + if(!str) return ''; return new Buffer(str.replace(/\-/g, '+'), 'base64').toString('utf8'); } }; diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 2679973..19d3cf4 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -4,6 +4,23 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@sinonjs/formatio": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "requires": { + "samsam": "1.3.0" + } + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, "acorn": { "version": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", "integrity": "sha1-dEbTlFnFT7SagObuZHgUm5QOyCI=", @@ -24,6 +41,17 @@ } } }, + "actions-on-google": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/actions-on-google/-/actions-on-google-1.10.0.tgz", + "integrity": "sha512-LpjUAddk3vmDeE5hoUjUYbPzpKjiITlBiiXNq1MHnp35GFg/YnG6XJGS8NlYE3vtIN/1mX9AE3vCxS1xYCPxeA==", + "requires": { + "debug": "2.6.9", + "google-auth-library": "1.4.0", + "lodash.camelcase": "4.3.0", + "lodash.snakecase": "4.1.1" + } + }, "agent-base": { "version": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz", "integrity": "sha1-mDi1wzkrliutAx5qTF4QJKvsRc4=", @@ -119,6 +147,21 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, "ast-types": { "version": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", "integrity": "sha1-wgdX/nLucSeOoP89h+XCyjDZ7fg=", @@ -132,6 +175,11 @@ "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "aws-sdk": { "version": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.222.1.tgz", "integrity": "sha1-2Ew0ADu4gtH+wXxBx0y4F72oSRQ=", @@ -156,6 +204,25 @@ } } }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + }, + "axios": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "requires": { + "follow-redirects": "1.4.1", + "is-buffer": "1.1.6" + } + }, "balanced-match": { "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", @@ -166,6 +233,20 @@ "integrity": "sha1-+xNmgjPZYUz1+0vOlam6QJbN+AE=", "dev": true }, + "base64url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", + "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, "bl": { "version": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w=", @@ -204,6 +285,44 @@ } } }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.1" + }, + "dependencies": { + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + } + } + }, + "botbuilder": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/botbuilder/-/botbuilder-3.14.1.tgz", + "integrity": "sha512-LczOC6tPziwqUEvbm5svXn6pZ3818UMYdG/QkxGYXTfjUD7DJFgXfBNGRGJq2wVkh6UbReTv6aWasX2OYjUbNg==", + "requires": { + "async": "1.5.2", + "base64url": "2.0.0", + "chrono-node": "1.3.5", + "jsonwebtoken": "7.4.3", + "promise": "7.3.1", + "request": "2.85.0", + "rsa-pem-from-mod-exp": "0.8.4", + "sprintf-js": "1.0.3", + "url-join": "1.1.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, "brace-expansion": { "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", @@ -236,6 +355,11 @@ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", "dev": true }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-from": { "version": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", "integrity": "sha1-TLiDLSNhJYmwQG6eKVbBfwb99TE=", @@ -259,6 +383,11 @@ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, "chalk": { "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", @@ -276,6 +405,14 @@ "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", "dev": true }, + "chrono-node": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/chrono-node/-/chrono-node-1.3.5.tgz", + "integrity": "sha1-oklSmKMtqCvMAa2b59d++l4kQSI=", + "requires": { + "moment": "2.22.1" + } + }, "circular-json": { "version": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", @@ -332,6 +469,14 @@ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, "compress-commons": { "version": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", @@ -377,6 +522,29 @@ "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" } }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.1" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + } + } + }, "d": { "version": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", @@ -385,6 +553,14 @@ "es5-ext": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz" } }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, "data-uri-to-buffer": { "version": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", "integrity": "sha1-dxY+qcINhkG0cH6PGKvfmnjzSDU=", @@ -393,7 +569,6 @@ "debug": { "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, "requires": { "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" } @@ -427,6 +602,11 @@ "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, "depd": { "version": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", @@ -452,6 +632,24 @@ "stream-shift": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz" } }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", + "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", + "requires": { + "base64url": "2.0.0", + "safe-buffer": "5.1.1" + } + }, "end-of-stream": { "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", @@ -684,6 +882,16 @@ "integrity": "sha1-tUrRnxW4hDxXa/uH+6nRPIK/5Ws=", "dev": true }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, "fast-levenshtein": { "version": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", @@ -723,6 +931,44 @@ "write": "https://registry.npmjs.org/write/-/write-0.2.1.tgz" } }, + "follow-redirects": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", + "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", + "requires": { + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, "fs.realpath": { "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", @@ -760,6 +1006,16 @@ } } }, + "gcp-metadata": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.6.3.tgz", + "integrity": "sha512-MSmczZctbz91AxCvqp9GHBoZOSbJKAICV7Ow/AIWSJZRrRchUd5NL1b2P4OfP+4m490BEUPhhARfpHdqCxuCvg==", + "requires": { + "axios": "0.18.0", + "extend": "3.0.1", + "retry-axios": "0.3.2" + } + }, "generate-function": { "version": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", @@ -786,6 +1042,14 @@ "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" } }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, "glob": { "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", @@ -817,11 +1081,71 @@ "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" } }, + "google-auth-library": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-1.4.0.tgz", + "integrity": "sha512-vWRx6pJulK7Y5V/Xyr7MPMlx2mWfmrUVbcffZ7hpq8ElFg5S8WY6PvjMovdcr6JfuAwwpAX4R0I1XOcyWuBcUw==", + "requires": { + "axios": "0.18.0", + "gcp-metadata": "0.6.3", + "gtoken": "2.3.0", + "jws": "3.1.4", + "lodash.isstring": "4.0.1", + "lru-cache": "4.1.2", + "retry-axios": "0.3.2" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", + "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + } + } + }, + "google-p12-pem": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-1.0.2.tgz", + "integrity": "sha512-+EuKr4CLlGsnXx4XIJIVkcKYrsa2xkAmCvxRhX2HsazJzUBAJ35wARGeApHUn4nNfPD03Vl057FskNr20VaCyg==", + "requires": { + "node-forge": "0.7.5", + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, "graceful-fs": { "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, + "gtoken": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-2.3.0.tgz", + "integrity": "sha512-Jc9/8mV630cZE9FC5tIlJCZNdUjwunvlwOtCz6IDlaiB4Sz68ki29a1+q97sWTnTYroiuF9B135rod9zrQdHLw==", + "requires": { + "axios": "0.18.0", + "google-p12-pem": "1.0.2", + "jws": "3.1.4", + "mime": "2.3.1", + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, "gunzip-maybe": { "version": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.1.tgz", "integrity": "sha1-Occu2J0bSbpwjhh3ZQBIiQKlICc=", @@ -835,6 +1159,33 @@ "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + } + } + }, "has-ansi": { "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", @@ -843,6 +1194,34 @@ "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" } }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + }, + "dependencies": { + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + } + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, "http-errors": { "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", @@ -875,6 +1254,16 @@ } } }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, "https-proxy-agent": { "version": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", @@ -955,6 +1344,11 @@ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "is-deflate": { "version": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", "integrity": "sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ=", @@ -1015,11 +1409,26 @@ "integrity": "sha1-rMoc022+RLl0uSQyFVWnC6A7HPQ=", "dev": true }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, "isarray": { "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "isemail": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", + "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, "jasmine": { "version": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", @@ -1048,6 +1457,17 @@ "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", "dev": true }, + "joi": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", + "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", + "requires": { + "hoek": "2.16.3", + "isemail": "1.2.0", + "moment": "2.22.1", + "topo": "1.1.0" + } + }, "js-yaml": { "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", @@ -1064,6 +1484,22 @@ } } }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, "json-stable-stringify": { "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", @@ -1072,6 +1508,11 @@ "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" } }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, "jsonify": { "version": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", @@ -1082,6 +1523,55 @@ "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", "dev": true }, + "jsonwebtoken": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz", + "integrity": "sha1-d/UCHeBYtgWheD+hKD6ZgS5kVjg=", + "requires": { + "joi": "6.10.1", + "jws": "3.1.4", + "lodash.once": "4.1.1", + "ms": "2.0.0", + "xtend": "4.0.1" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "just-extend": { + "version": "1.1.27", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", + "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==" + }, + "jwa": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", + "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", + "requires": { + "base64url": "2.0.0", + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.9", + "safe-buffer": "5.1.1" + } + }, + "jws": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", + "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", + "requires": { + "base64url": "2.0.0", + "jwa": "1.1.5", + "safe-buffer": "5.1.1" + } + }, "lazystream": { "version": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", @@ -1104,11 +1594,74 @@ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", "dev": true }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=" + }, + "lolex": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", + "integrity": "sha512-A5pN2tkFj7H0dGIAM6MFvHKMJcPnjZsOMvR7ujCjfgW5TbV6H9vb1PgxLtHvjqNZTHsUolz+6/WEO0N1xNx2ng==" + }, "lru-cache": { "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", "dev": true }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, "minimal-request-promise": { "version": "https://registry.npmjs.org/minimal-request-promise/-/minimal-request-promise-1.5.0.tgz", "integrity": "sha1-YPXX9VtAJtGXB04uFVYm1MxcLrw=" @@ -1141,6 +1694,11 @@ } } }, + "moment": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", + "integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==" + }, "ms": { "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", @@ -1151,11 +1709,62 @@ "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", "dev": true }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "net": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/net/-/net-1.0.2.tgz", + "integrity": "sha1-0XV+yaf7I3HYPPR1XOPifhCCk4g=" + }, "netmask": { "version": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", "dev": true }, + "nise": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.3.3.tgz", + "integrity": "sha512-v1J/FLUB9PfGqZLGDBhQqODkbLotP0WtLo9R4EJY2PPu5f5Xg4o0rA8FDlmrjFSv9vBBKcfnOSpfYYuu5RTHqg==", + "requires": { + "@sinonjs/formatio": "2.0.0", + "just-extend": "1.1.27", + "lolex": "2.3.2", + "path-to-regexp": "1.7.0", + "text-encoding": "0.6.4" + } + }, + "node-forge": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==" + }, + "node-mocks-http": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.6.7.tgz", + "integrity": "sha512-0a+2ynRfWyU1tN9DQ9Pq29SC9L5QafyXfQ4ae5dA39TYP8K8j74ohKvGKzlQ2vvfbnj17MbXLi35WnmUTl9xmw==", + "requires": { + "accepts": "1.3.5", + "depd": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "mime": "1.6.0", + "net": "1.0.2", + "parseurl": "1.3.2", + "range-parser": "1.2.0", + "type-is": "1.6.16" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + } + } + }, "normalize-path": { "version": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", @@ -1169,6 +1778,11 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, "object-assign": { "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", @@ -1252,6 +1866,11 @@ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, "path-is-absolute": { "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", @@ -1262,6 +1881,21 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, "peek-stream": { "version": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", "integrity": "sha1-OzXYS3zLvSYv/zHcENpWhW6tbWc=", @@ -1272,6 +1906,11 @@ "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" } }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, "pify": { "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", @@ -1310,6 +1949,14 @@ "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "2.0.6" + } + }, "proxy-agent": { "version": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.2.0.tgz", "integrity": "sha1-6FPNhAABNWLSPI3J4d6vmwsKFTo=", @@ -1324,6 +1971,11 @@ "socks-proxy-agent": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz" } }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, "pump": { "version": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", @@ -1348,11 +2000,21 @@ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, "querystring": { "version": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, "raw-body": { "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", @@ -1393,6 +2055,42 @@ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, + "request": { + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + }, + "dependencies": { + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + } + } + }, "require-uncached": { "version": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", @@ -1416,6 +2114,11 @@ "onetime": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz" } }, + "retry-axios": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-0.3.2.tgz", + "integrity": "sha512-jp4YlI0qyDFfXiXGhkCOliBN1G7fRH03Nqy8YdShzGqbY5/9S2x/IR6C88ls2DFkbWuL3ASkP7QD3pVrNpPgwQ==" + }, "rimraf": { "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", @@ -1424,6 +2127,11 @@ "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" } }, + "rsa-pem-from-mod-exp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/rsa-pem-from-mod-exp/-/rsa-pem-from-mod-exp-0.8.4.tgz", + "integrity": "sha1-NipCxtMEBW1JOz8SvOq7LGV2ptQ=" + }, "run-async": { "version": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", @@ -1467,6 +2175,30 @@ "integrity": "sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=", "dev": true }, + "sinon": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", + "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", + "requires": { + "@sinonjs/formatio": "2.0.0", + "diff": "3.5.0", + "lodash.get": "4.4.2", + "lolex": "2.3.2", + "nise": "1.3.3", + "supports-color": "5.4.0", + "type-detect": "4.0.8" + }, + "dependencies": { + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, "slice-ansi": { "version": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", @@ -1477,6 +2209,21 @@ "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", "dev": true }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.1" + }, + "dependencies": { + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + } + } + }, "socks": { "version": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", @@ -1538,6 +2285,11 @@ "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" } }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, "strip-ansi": { "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", @@ -1631,6 +2383,11 @@ "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=" + }, "text-table": { "version": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", @@ -1655,10 +2412,47 @@ "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", "dev": true }, + "topo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", + "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", + "requires": { + "hoek": "2.16.3" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, "tsscmp": { "version": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, "type-check": { "version": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", @@ -1667,6 +2461,20 @@ "prelude-ls": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } + }, "typedarray": { "version": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", @@ -1686,6 +2494,11 @@ "querystring": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" } }, + "url-join": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", + "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=" + }, "user-home": { "version": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", @@ -1704,6 +2517,16 @@ "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", "dev": true }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, "wordwrap": { "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", diff --git a/package.json b/package.json index ae5d5d3..809c96d 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,9 @@ "slack", "twilio", "kik", - "groupme" + "groupme", + "cortana", + "google" ], "author": "Slobodan Stojanovic (http://slobodan.me/), ", "contributors": [ @@ -38,10 +40,14 @@ ], "license": "MIT", "dependencies": { + "actions-on-google": "^1.7.0", "alexa-message-builder": "^1.1.0", "claudia-api-builder": "^4.1.1", + "botbuilder": "^3.14.1", "minimal-request-promise": "^1.3.0", + "node-mocks-http": "^1.6.6", "oh-no-i-insist": "^1.0.0", + "sinon": "^4.5.0", "souffleur": "^1.0.0", "tsscmp": "^1.0.5" }, diff --git a/spec/alexa/alexa-parse-spec.js b/spec/alexa/alexa-parse-spec.js index 46fb9a3..d9522d4 100644 --- a/spec/alexa/alexa-parse-spec.js +++ b/spec/alexa/alexa-parse-spec.js @@ -17,16 +17,16 @@ describe('Alexa parse', () => { }); it('should return original request with an empty text if the intent is missing', () => { let msg = {request: {}, session: { user: { userId: 'claudia alexa user'} } }; - expect(parse(msg)).toEqual({ sender: 'claudia alexa user', text: '', originalRequest: msg, type: 'alexa-skill'}); + expect(parse(msg)).toEqual({ sender: 'claudia alexa user', text: '', originalRequest: msg, type: 'alexa-skill', accessToken: undefined }); }); it('should return original request with an empty text if the intent name is missing', () => { let msg = {request: { intent: {}}, session: { user: { userId: 'claudia alexa user'} } }; - expect(parse(msg)).toEqual({ sender: 'claudia alexa user', text: '', originalRequest: msg, type: 'alexa-skill'}); + expect(parse(msg)).toEqual({ sender: 'claudia alexa user', text: '', originalRequest: msg, type: 'alexa-skill', accessToken: undefined }); }); it('should return a parsed object with proper sender and text when the intent name and session user are present', () => { let msg = { request: { intent: { name: 'intent 1'}}, session: { user: { userId: 'claudia alexa user'}} }; - expect(parse(msg)).toEqual({ sender: 'claudia alexa user', text: '', originalRequest: msg, type: 'alexa-skill'}); + expect(parse(msg)).toEqual({ sender: 'claudia alexa user', text: '', originalRequest: msg, type: 'alexa-skill', accessToken: undefined }); }); }); diff --git a/spec/cortana/cortana-parse-spec.js b/spec/cortana/cortana-parse-spec.js new file mode 100644 index 0000000..d0dc91a --- /dev/null +++ b/spec/cortana/cortana-parse-spec.js @@ -0,0 +1,21 @@ + +/*global describe, it, expect, require, beforeEach */ +'use strict'; +var parse = require('../../lib/cortana/parse'); + +describe('Cortana Reply', () => { + beforeEach(() => { + }); + + it('Sets the AccessToken if AuthorizationToken is present in session', () => { + var session = { message: { user: { id: '1' }, entities: [{ type: 'AuthorizationToken', token: '1234' }, {}] } }; + var parsed = parse(session); + expect(parsed.accessToken).toEqual('1234'); + }); + + it('Sets AccessToken to undefined if AuthorizationToken is not present in session', () => { + var session = { message: { user: { id: '1' }, entities: [{}] } }; + var parsed = parse(session); + expect(parsed.accessToken).toEqual(undefined); + }); +}); diff --git a/spec/cortana/cortana-reply-spec.js b/spec/cortana/cortana-reply-spec.js new file mode 100644 index 0000000..7e21e68 --- /dev/null +++ b/spec/cortana/cortana-reply-spec.js @@ -0,0 +1,25 @@ +/*global describe, it, expect, require, jasmine, beforeEach */ +'use strict'; +var reply = require('../../lib/cortana/reply'); + +describe('Cortana Reply', () => { + var session; + beforeEach(() => { + session = jasmine.createSpyObj('session', ['send', 'endConversation']); + }); + + it('just calls send when its an object', () => { + reply({}, session); + expect(session.send).toHaveBeenCalled(); + }); + + it('just calls endConversation when its an string', () => { + reply('a text', session); + expect(session.endConversation).toHaveBeenCalled(); + }); + + it('calls send for each object if is an array', () => { + reply(['a text', { text: 'object text'}], session); + expect(session.send.calls.count()).toBe(2); + }); +}); diff --git a/spec/cortana/cortana-setup-spec.js b/spec/cortana/cortana-setup-spec.js new file mode 100644 index 0000000..d3d147b --- /dev/null +++ b/spec/cortana/cortana-setup-spec.js @@ -0,0 +1,77 @@ +/*global require, describe, it, expect, beforeEach, beforeAll, afterAll jasmine*/ +'use strict'; +var underTest = require('../../lib/cortana/setup'); +var botBuilder = require('botbuilder'); +const sinon = require('sinon'); +describe('Cortana setup', () => { + var api, bot, logError, parser, responder, universal, botPromise, builder; + + beforeAll(() => { + builder = sinon.stub(botBuilder, 'ChatConnector').returns({ 'listen': Function }); + universal = sinon.stub(botBuilder, 'UniversalBot').returns({ + 'use': function () { + return { + 'receive': (event, next) => { next(); }, + 'send': (event, next) => { next(); } + }; + } + }); + }); + + afterAll(() => { + builder.restore(); + universal.restore(); + }); + + beforeEach(() => { + api = jasmine.createSpyObj('api', ['get', 'post', 'addPostDeployStep']); + bot = jasmine.createSpy().and.returnValue(botPromise); + parser = jasmine.createSpy(); + logError = jasmine.createSpy(); + responder = jasmine.createSpy(); + + underTest(api, bot, logError, parser, responder); + }); + describe('message processor', () => { + const envConfig = { cortanaAppId: 'YXBwX3Rlc3Q=', cortanaAppPassword: 'YmVzdA==' }; + const singleMessageTemplate = { + type: 'message', + id: '9GaUpYmT6YU', + timestamp: '2018-04-26T17:31:37.6846046Z', + serviceUrl: 'https://CortanaBFChannelEastUs.azurewebsites.net/', + channelId: 'cortana', + from: + { id: 'E4144E913F76C' }, + conversation: { id: 'd35535' }, + recipient: { id: 'bot_cortana' }, + locale: 'en-US', + text: 'hello cortana', + entities: + [{ type: 'Intent', name: 'None', entities: [] }, + { + type: 'AuthorizationToken', + token: 'eyJhbGc', + status: 0 + }, + { type: 'DeviceInfo', supportsDisplay: 'true' }] + }; + it('wires the POST request for cortana to the message processor', () => { + expect(api.post.calls.count()).toEqual(1); + expect(api.post).toHaveBeenCalledWith('/cortana', jasmine.any(Function)); + }); + describe('processing a single message', () => { + var handler; + beforeEach(() => { + handler = api.post.calls.argsFor(0)[1]; + }); + it('connector to be called', () => { + handler({ body: singleMessageTemplate, env: envConfig }); + expect(builder.called).toBeTruthy(); + }); + it('Universal bot to be called', () => { + handler({ body: singleMessageTemplate, env: envConfig }); + expect(universal.called).toBeTruthy(); + }); + }); + }); +}); diff --git a/spec/google/google-parse-spec.js b/spec/google/google-parse-spec.js new file mode 100644 index 0000000..54c257c --- /dev/null +++ b/spec/google/google-parse-spec.js @@ -0,0 +1,34 @@ + +/*global describe, it, expect, require, beforeEach */ +'use strict'; +const getAssistant = require('../../lib/google/assistant'); +var parse = require('../../lib/google/parse'); + +describe('Google Reply', () => { + beforeEach(() => { + }); + + it('Sets the AccessToken if AuthorizationToken is present in session', () => { + const assistant = getAssistant(request); + var parsed = parse(assistant, request); + expect(parsed.accessToken).toEqual('USER_ACCESSTOKEN'); + }); + + it('Sets the user_id if it is present', () => { + const assistant = getAssistant(request); + var parsed = parse(assistant, request); + expect(parsed.sender).toEqual('USER_ID'); + }); +}); + + +const request = { + body: { + 'user': { + 'userId': 'USER_ID', + 'accessToken': 'USER_ACCESSTOKEN', + 'locale': 'en-US', + 'lastSeen': '2018-04-25T14:27:02Z' + }, + 'isInSandbox': true + }}; \ No newline at end of file diff --git a/spec/google/google-reply-spec.js b/spec/google/google-reply-spec.js new file mode 100644 index 0000000..8eb26d9 --- /dev/null +++ b/spec/google/google-reply-spec.js @@ -0,0 +1,24 @@ +/*global describe, it, expect, require, jasmine, beforeEach */ +'use strict'; +var reply = require('../../lib/google/reply'); + + +describe('Google Reply', () => { + var assistant; + beforeEach(() => { + assistant = jasmine.createSpyObj('assistant', ['tell']); + assistant.response_ = jasmine.createSpyObj('assistant.response_', ['_getData']); + }); + + it('Basic tests to test reply', ()=> { + expect(reply()).toEqual(undefined); + expect(reply(undefined, 'Claudia Google Bot')).toEqual(undefined); + expect(reply({ hello: 'Google'}, 'Claudia Google Bot')).toEqual({ hello: 'Google'}); + }); + + it('just calls tell when its an object', () => { + reply('Hello', '', assistant); + expect(assistant.tell).toHaveBeenCalled(); + }); + +}); \ No newline at end of file diff --git a/spec/google/google-setup-spec.js b/spec/google/google-setup-spec.js new file mode 100644 index 0000000..b18b876 --- /dev/null +++ b/spec/google/google-setup-spec.js @@ -0,0 +1,48 @@ +/*global require, describe, it, expect, beforeEach, jasmine*/ +'use strict'; +var underTest = require('../../lib/google/setup'); +describe('Google setup', () => { + var api, bot, logError, parser, responder, botPromise, botResolve; + + beforeEach(() => { + api = jasmine.createSpyObj('api', ['get', 'post', 'addPostDeployStep']); + botPromise = new Promise((resolve) => { + botResolve = resolve; + }); + bot = jasmine.createSpy().and.returnValue(botPromise); + parser = jasmine.createSpy(); + logError = jasmine.createSpy(); + responder = jasmine.createSpy(); + + underTest(api, bot, logError, parser, responder); + }); + describe('message processor', () => { + + const singleMessageTemplate = { + 'user': { + 'userId': 'USER_ID', + 'accessToken': 'USER_ACCESSTOKEN', + 'locale': 'en-US', + 'lastSeen': '2018-04-25T14:27:02Z' + }, + 'isInSandbox': true + }; + it('wires the POST request for google to the message processor', () => { + expect(api.post.calls.count()).toEqual(1); + expect(api.post).toHaveBeenCalledWith('/google', jasmine.any(Function)); + }); + describe('processing a single message', () => { + var handler; + beforeEach(() => { + handler = api.post.calls.argsFor(0)[1]; + }); + it('connector to be called', () => { + handler(singleMessageTemplate); + expect(parser).toHaveBeenCalled(); + }); + it('test promise', () => { + botResolve(); + }); + }); + }); +});