-
Notifications
You must be signed in to change notification settings - Fork 256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added support for Google Hangouts Chat #125
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
'use strict'; | ||
|
||
module.exports = function googleHangoutsParse(messageObject) { | ||
if (!messageObject || !messageObject.type) return; | ||
|
||
const message = messageObject.message; | ||
|
||
const text = message && message.text ? message.text : ''; | ||
|
||
let messageType = 'unknown'; | ||
switch (messageObject.type) { | ||
case 'MESSAGE': | ||
messageType = 'message'; | ||
break; | ||
case 'ADDED_TO_SPACE': | ||
messageType = 'add-command'; | ||
break; | ||
case 'REMOVED_FROM_SPACE': | ||
messageType = 'remove-command'; | ||
break; | ||
} | ||
|
||
const sender = messageType === 'message' ? | ||
message && message.sender && message.sender.name : | ||
(messageObject.user && messageObject.user.name || 'no sender'); | ||
|
||
return { | ||
sender: sender, | ||
text: text, | ||
originalRequest: messageObject, | ||
type: `google-hangouts-chat-${messageType}` | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
'use strict'; | ||
|
||
module.exports = function googleHangoutsReply(botResponse) { | ||
if (typeof botResponse === 'string') { | ||
return { | ||
text: botResponse | ||
}; | ||
} | ||
|
||
return botResponse; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
'use strict'; | ||
|
||
const prompt = require('souffleur'); | ||
const googleHangoutsParse = require('./parse'); | ||
const googleHangoutsReply = require('./reply'); | ||
const color = require('../console-colors'); | ||
const envUtils = require('../utils/env-utils'); | ||
|
||
module.exports = function googleHangoutsSetup(api, bot, logError, optionalParser, optionalResponder) { | ||
let parser = optionalParser || googleHangoutsParse; | ||
let responder = optionalResponder || googleHangoutsReply; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use |
||
|
||
api.post('/google-hangouts-chat', request => { | ||
return bot(parser(request.body), request) | ||
.then(botReply => responder(botReply, envUtils.decode(request.env.googleHangoutsAppName))) | ||
.catch(logError); | ||
}); | ||
|
||
api.addPostDeployStep('google-hangouts-chat', (options, lambdaDetails, utils) => { | ||
return Promise.resolve().then(() => { | ||
if (options['configure-google-hangouts-chat-bot']) { | ||
console.log(`\n\n${color.green}Google Hangouts Chat bot setup${color.reset}\n`); | ||
console.log(`\nConfigure your Google Hangouts Chat bot endpoint to HTTPS and set this URL:.\n`); | ||
console.log(`\n${color.cyan}${lambdaDetails.apiUrl}/google-hangouts-chat${color.reset}\n`); | ||
|
||
return prompt(['Google Hangouts Chat bot name']) | ||
.then(results => { | ||
const deployment = { | ||
restApiId: lambdaDetails.apiId, | ||
stageName: lambdaDetails.alias, | ||
variables: { | ||
googleHangoutsAppName: envUtils.encode(results['Google Hangouts Chat bot name']) | ||
} | ||
}; | ||
|
||
console.log(`\n`); | ||
|
||
return utils.apiGatewayPromise.createDeploymentPromise(deployment); | ||
}); | ||
} | ||
}) | ||
.then(() => `${lambdaDetails.apiUrl}/google-hangouts-chat`); | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/*global describe, it, expect, require */ | ||
'use strict'; | ||
|
||
const parse = require('../../lib/google-hangouts-chat/parse'); | ||
|
||
describe('Google Hangout Chat parse', () => { | ||
it('should return nothing if the format is invalid', () => { | ||
expect(parse('string')).toBeUndefined(); | ||
expect(parse()).toBeUndefined(); | ||
expect(parse(false)).toBeUndefined(); | ||
expect(parse(123)).toBeUndefined(); | ||
expect(parse({})).toBeUndefined(); | ||
expect(parse([1, 2, 3])).toBeUndefined(); | ||
}); | ||
it('should return undefined if the session user is missing', () => { | ||
expect(parse({message: {}})).toBeUndefined(); | ||
}); | ||
it('should return original request with an empty text if the intent is missing', () => { | ||
let msg = {message: {foo: 'bar'}, type: 'ADDED_TO_SPACE'}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
expect(parse(msg)).toEqual({ sender: 'no sender', text: '', originalRequest: msg, type: 'google-hangouts-chat-add-command'}); | ||
}); | ||
it('should return original request with an empty text if the intent name is missing', () => { | ||
let msg = {message: {foo: 'bar'}, type: 'REMOVED_FROM_SPACE'}; | ||
expect(parse(msg)).toEqual({ sender: 'no sender', text: '', originalRequest: msg, type: 'google-hangouts-chat-remove-command'}); | ||
}); | ||
it('should return a parsed object with proper sender and text when the intent name and session user are present', () => { | ||
const msg = { | ||
'type': 'MESSAGE', | ||
'eventTime': '2017-03-02T19:02:59.910959Z', | ||
'space': { | ||
'name': 'spaces/AAAAAAAAAAA', | ||
'displayName': 'Ramdom Discussion Room', | ||
'type': 'ROOM' | ||
}, | ||
'message': { | ||
'name': 'spaces/AAAAAAAAAAA/messages/CCCCCCCCCCC', | ||
'sender': { | ||
'name': 'users/12345678901234567890', | ||
'displayName': 'John Doe', | ||
'avatarUrl': 'https://lh3.googleusercontent.com/.../photo.jpg', | ||
'email': '[email protected]' | ||
}, | ||
'createTime': '2017-03-02T19:02:59.910959Z', | ||
'text': 'Hello World', | ||
'thread': { | ||
'name': 'spaces/AAAAAAAAAAA/threads/BBBBBBBBBBB' | ||
} | ||
} | ||
}; | ||
|
||
expect(parse(msg)).toEqual({ | ||
sender: 'users/12345678901234567890', | ||
text: 'Hello World', | ||
originalRequest: msg, | ||
type: 'google-hangouts-chat-message' | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/*global describe, it, expect, require */ | ||
'use strict'; | ||
const reply = require('../../lib/google-hangouts-chat/reply'); | ||
|
||
describe('Google Hangouts Chat Reply', () => { | ||
|
||
it('just returns the bot response when its not a string', () => { | ||
expect(reply()).toEqual(undefined); | ||
expect(reply(undefined, 'Google Hangouts Chat Bot')).toEqual(undefined); | ||
expect(reply({ hello: 'Google Hangouts Chat Bot'}, 'Google Hangouts Chat Bot')).toEqual({ hello: 'Google Hangouts Chat Bot'}); | ||
}); | ||
|
||
it('just returns the proper Google Hangouts Chat response when its not a string', () => { | ||
expect(reply('Google Hangouts Chat Bot', 'Google Hangouts Chat Bot')) | ||
.toEqual({ | ||
text: 'Google Hangouts Chat Bot' | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/*global require, describe, it, expect, beforeEach, jasmine*/ | ||
'use strict'; | ||
const underTest = require('../../lib/google-hangouts-chat/setup'), | ||
utils = require('../../lib/utils/env-utils'); | ||
describe('Google Hangouts Chat setup', () => { | ||
let api, bot, logError, parser, responder, botPromise, botResolve, botReject; | ||
beforeEach(() => { | ||
api = jasmine.createSpyObj('api', ['get', 'post', 'addPostDeployStep']); | ||
botPromise = new Promise((resolve, reject) => { | ||
botResolve = resolve; | ||
botReject = reject; | ||
}); | ||
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 = { | ||
'type': 'MESSAGE', | ||
'eventTime': '2017-03-02T19:02:59.910959Z', | ||
'space': { | ||
'name': 'spaces/AAAAAAAAAAA', | ||
'displayName': 'Ramdom Discussion Room', | ||
'type': 'ROOM' | ||
}, | ||
'message': { | ||
'name': 'spaces/AAAAAAAAAAA/messages/CCCCCCCCCCC', | ||
'sender': { | ||
'name': 'users/12345678901234567890', | ||
'displayName': 'John Doe', | ||
'avatarUrl': 'https://lh3.googleusercontent.com/.../photo.jpg', | ||
'email': '[email protected]' | ||
}, | ||
'createTime': '2017-03-02T19:02:59.910959Z', | ||
'text': 'Hello World', | ||
'thread': { | ||
'name': 'spaces/AAAAAAAAAAA/threads/BBBBBBBBBBB' | ||
} | ||
} | ||
}; | ||
it('wires the POST request for Google Hangouts Chat to the message processor', () => { | ||
expect(api.post.calls.count()).toEqual(1); | ||
expect(api.post).toHaveBeenCalledWith('/google-hangouts-chat', jasmine.any(Function)); | ||
}); | ||
describe('processing a single message', () => { | ||
let handler; | ||
beforeEach(() => { | ||
handler = api.post.calls.argsFor(0)[1]; | ||
}); | ||
it('breaks down the message and puts it into the parser', () => { | ||
handler({body: singleMessageTemplate, env: {googleHangoutsAppName: 'Google Hangouts Chat Bot'}}); | ||
expect(parser).toHaveBeenCalledWith(singleMessageTemplate); | ||
}); | ||
it('passes the parsed value to the bot if a message can be parsed', (done) => { | ||
parser.and.returnValue('MSG1'); | ||
handler({body: singleMessageTemplate, env: {}}); | ||
Promise.resolve().then(() => { | ||
expect(bot).toHaveBeenCalledWith('MSG1', { body: singleMessageTemplate, env: {} }); | ||
}).then(done, done.fail); | ||
}); | ||
it('responds when the bot resolves', (done) => { | ||
parser.and.returnValue({sender: 'user1', text: 'MSG1', type: 'google-hangouts-chat-message'}); | ||
botResolve('Hello Google Hangouts'); | ||
handler({body: singleMessageTemplate, env: {googleHangoutsAppName: utils.encode('Google Hangouts Bot')}}).then(() => { | ||
expect(responder).toHaveBeenCalledWith('Hello Google Hangouts', 'Google Hangouts Bot'); | ||
}).then(done, done.fail); | ||
}); | ||
it('can work with bot responses as strings', (done) => { | ||
botResolve('Hello Google Hangouts'); | ||
parser.and.returnValue({sender: 'user1', text: 'Hello'}); | ||
handler({body: singleMessageTemplate, env: {googleHangoutsAppName: utils.encode('Google Hangouts Bot')}}).then(() => { | ||
expect(responder).toHaveBeenCalledWith('Hello Google Hangouts', 'Google Hangouts Bot'); | ||
}).then(done, done.fail); | ||
|
||
}); | ||
it('logs error when the bot rejects without responding', (done) => { | ||
parser.and.returnValue('MSG1'); | ||
|
||
handler({body: singleMessageTemplate, env: {googleHangoutsAppName: 'Google Hangouts Bot'}}).then(() => { | ||
expect(responder).not.toHaveBeenCalled(); | ||
expect(logError).toHaveBeenCalledWith('No No'); | ||
}).then(done, done.fail); | ||
|
||
botReject('No No'); | ||
}); | ||
it('logs the error when the responder throws an error', (done) => { | ||
parser.and.returnValue('MSG1'); | ||
responder.and.throwError('XXX'); | ||
botResolve('Yes'); | ||
handler({body: singleMessageTemplate, env: {googleHangoutsAppName: 'Google Hangouts Bot'}}).then(() => { | ||
expect(logError).toHaveBeenCalledWith(jasmine.any(Error)); | ||
}).then(done, done.fail); | ||
}); | ||
describe('working with promises in responders', () => { | ||
let responderResolve, responderReject, responderPromise, hasResolved; | ||
beforeEach(() => { | ||
responderPromise = new Promise((resolve, reject) => { | ||
responderResolve = resolve; | ||
responderReject = reject; | ||
}); | ||
responder.and.returnValue(responderPromise); | ||
|
||
parser.and.returnValue('MSG1'); | ||
}); | ||
it('waits for the responders to resolve before completing the request', (done) => { | ||
handler({body: singleMessageTemplate, env: {googleHangoutsAppName: 'Google Hangouts Bot'}}).then(() => { | ||
hasResolved = true; | ||
}); | ||
|
||
botPromise.then(() => { | ||
expect(hasResolved).toBeFalsy(); | ||
}).then(done, done.fail); | ||
|
||
botResolve('YES'); | ||
}); | ||
it('resolves when the responder resolves', (done) => { | ||
handler({body: singleMessageTemplate, env: {googleHangoutsAppName: 'Google Hangouts Bot'}}).then((message) => { | ||
expect(message).toEqual('As Promised!'); | ||
}).then(done, done.fail); | ||
|
||
botPromise.then(() => { | ||
responderResolve('As Promised!'); | ||
}); | ||
botResolve('YES'); | ||
}); | ||
it('logs error when the responder rejects', (done) => { | ||
handler({body: singleMessageTemplate, env: {googleHangoutsAppName: 'Google Hangouts Bot'}}).then(() => { | ||
expect(logError).toHaveBeenCalledWith('Bomb!'); | ||
}).then(done, done.fail); | ||
|
||
botPromise.then(() => { | ||
responderReject('Bomb!'); | ||
}); | ||
botResolve('YES'); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should use just
hangouts
because it's shorter but still describes the platform uniquely.