diff --git a/bin/cli.js b/bin/cli.js index e42ba3bc4..7a0db9ef8 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -7,7 +7,7 @@ var fs = require('fs'); var botkit = Vorpal() -var platforms = ['web', 'teams', 'ciscospark', 'slack', 'facebook']; +var platforms = ['web', 'teams', 'ciscospark', 'slack', 'facebook', 'googlehangouts']; var platform_src = [{ platform: 'web', artifact: 'https://github.com/howdyai/botkit-starter-web.git', @@ -38,6 +38,11 @@ var platform_src = [{ platform: 'facebook', artifact: 'https://github.com/howdyai/botkit-starter-facebook.git', directory: 'botkit-starter-facebook' + }, + { + platform: 'googlehangouts', + artifact: 'git@github.com:howdyai/botkit-starter-googlehangouts.git', + directory: 'botkit-starter-googlehangouts' } ]; diff --git a/docs/readme.md b/docs/readme.md index 89db59eb8..c5c59ffd6 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -16,6 +16,7 @@ All documentation for Botkit now lives at our official documentation site, [http * [Twilio SMS](https://botkit.ai/docs/readme-twiliosms.html) * [Twilio IPM](https://botkit.ai/docs/readme-twilioipm.html) * [Microsoft Bot Framework](https://botkit.ai/docs/readme-botframework.html) + * [Google Hangouts Chat](https://botkit.ai/docs/google-hangouts-chat.html) * [Extending Botkit with Plugins and Middleware](https://botkit.ai/docs/middleware.html) * [Message Pipeline](https://botkit.ai/docs/readme-pipeline.html) * [List of current plugins](https://botkit.ai/docs/readme-middlewares.html) diff --git a/examples/google_hangouts_bot.js b/examples/google_hangouts_bot.js new file mode 100644 index 000000000..c6c3152e6 --- /dev/null +++ b/examples/google_hangouts_bot.js @@ -0,0 +1,91 @@ +var Botkit = require('../lib/Botkit.js'); + +var controller = Botkit.googlehangoutsbot({ + endpoint: 'Axjn86rTGRQwisaYFyT0XZyiOCh7rZUPGx1A', + token: "YOUR_TOKEN", + debug: true, +}); + +var bot = controller.spawn({}); + +controller.setupWebserver(3000, function (err, webserver) { + controller.createWebhookEndpoints(webserver, bot, function () { + console.log(`🚀 Congratulation, the web server is online!`); + }); +}); + +controller.on('message_received', function (bot, message) { + bot.reply(message, `You said '${message.text}'`); +}); + +controller.hears('new thread', 'message_received', function (bot, message) { + bot.replyAsNewThread(message, `Hello ! this is a new thread`); +}); + +controller.hears('thread key', 'message_received', function (bot, message) { + bot.replyWithThreadKey(message, { + threadKey : "YOUR_THREAD_KEY", + requestBody : { + text : `Hi ! this message inside the same thread` + } + }); +}); + +controller.hears('convo', 'message_received', function (bot, message) { + + bot.startConversation(message, function(err, convo) { + + convo.ask('You want to know more about Botkit ?', [ + { + pattern: bot.utterances.yes, + callback: function(response, convo) { + convo.say('Take a look here https://botkit.ai/docs/'); + convo.next(); + } + }, + { + pattern: bot.utterances.no, + default: true, + callback: function(response, convo) { + convo.say('No problem'); + convo.next(); + } + } + ]); + }); + +}); + +controller.hears('cards', 'message_received', function (bot, message) { + bot.reply(message, { + requestBody: { + cards: [ + { + "sections": [ + { + "widgets": [ + { + "image": { "imageUrl": "https://image.slidesharecdn.com/botkitsignal-160526164159/95/build-a-bot-with-botkit-1-638.jpg?cb=1464280993" } + }, + { + "buttons": [ + { + "textButton": { + "text": "Get Started", + "onClick": { + "openLink": { + "url": "https://botkit.ai/docs/" + } + } + } + } + ] + } + ] + } + ] + } + ] + } + }); +}); diff --git a/lib/Botkit.js b/lib/Botkit.js index bf06c9ee9..6ae79db67 100755 --- a/lib/Botkit.js +++ b/lib/Botkit.js @@ -8,6 +8,7 @@ var SparkBot = require(__dirname + '/CiscoSparkbot.js'); var ConsoleBot = require(__dirname + '/ConsoleBot.js'); var JabberBot = require(__dirname + '/JabberBot.js'); var WebBot = require(__dirname + '/Web.js'); +var GoogleHangoutsBot = require(__dirname + '/GoogleHangoutsBot.js'); module.exports = { core: CoreBot, @@ -22,4 +23,5 @@ module.exports = { jabberbot: JabberBot, socketbot: WebBot, anywhere: WebBot, + googlehangoutsbot: GoogleHangoutsBot }; diff --git a/lib/GoogleHangoutsBot.js b/lib/GoogleHangoutsBot.js new file mode 100644 index 000000000..eefa3c99e --- /dev/null +++ b/lib/GoogleHangoutsBot.js @@ -0,0 +1,208 @@ +var Botkit = require(__dirname + '/CoreBot.js'); +var {google} = require('googleapis'); + +function GoogleHangoutsBot(configuration) { + + var api_version = 'v1'; + + var google_hangouts_botkit = Botkit(configuration || {}); + + google_hangouts_botkit.defineBot(function (botkit, config) { + + var bot = { + type: 'googleHangouts', + botkit: botkit, + config: config || {}, + utterances: botkit.utterances, + }; + + bot.send = function (message, cb) { + + const chat = google.chat({version: api_version, auth: bot.authClient}); + + chat.spaces.messages.create(message) + .then(res => { + botkit.debug('Successfully sent message to Google Hangouts : ' + res.data.name); + if (cb) { + cb(null, res.data); + } + }) + .catch(err => { + botkit.debug('Error while sending message to Google Hangouts', err); + if (cb) { + cb(err); + } + }); + }; + + bot.reply = function (src, resp, cb) { + + var message_to_send = { + parent: src.space.name, + threadKey: undefined, + requestBody: {} + }; + + if (typeof (resp) == 'string') { + message_to_send.requestBody.text = resp; + } else if (resp.text) { + message_to_send.requestBody.text = resp.text; + } else { + message_to_send.requestBody = resp.requestBody; + } + + message_to_send.requestBody.thread = { + name: src.message.thread.name + }; + + bot.say(message_to_send, cb); + + }; + + bot.replyWithThreadKey = function (src, resp, cb) { + + var msg = {}; + + msg.parent = src.space.name; + msg.threadKey = resp.threadKey; + msg.requestBody = resp.requestBody; + + bot.say(msg, cb); + }; + + bot.replyAsNewThread = function (src, resp, cb) { + + var msg = {}; + + msg.parent = src.space.name; + + if (typeof (resp) == 'string') { + msg.requestBody = { + text: resp + }; + } else { + msg.requestBody = resp; + } + + bot.say(msg, cb); + }; + + bot.findConversation = function (message, cb) { + botkit.debug('CUSTOM FIND CONVO', message.user, message.channel); + 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].source_message.user == message.user) { + botkit.debug('FOUND EXISTING CONVO!'); + cb(botkit.tasks[t].convos[c]); + return; + } + } + } + + cb(); + }; + + return bot; + }); + + google_hangouts_botkit.createWebhookEndpoints = function (webserver, bot, cb) { + + var endpoint = '/hangouts/' + google_hangouts_botkit.config.endpoint; + + google_hangouts_botkit.log( + '** Serving webhook endpoints for Google Hangout Platform at : ' + + 'http://' + google_hangouts_botkit.config.hostname + ':' + google_hangouts_botkit.config.port + endpoint + ); + + webserver.post(endpoint, function (req, res) { + google_hangouts_botkit.handleWebhookPayload(req, res, bot); + }); + + if (cb) { + cb(); + } + + return google_hangouts_botkit; + }; + + google_hangouts_botkit.handleWebhookPayload = function (req, res, bot) { + + var payload = req.body; + + if (google_hangouts_botkit.config.token && google_hangouts_botkit.config.token !== payload.token) { + res.status(401); + google_hangouts_botkit.debug('Token verification failed, Ignoring message'); + } else { + res.status(200); + google_hangouts_botkit.ingest(bot, payload, res); + } + + res.send(); + }; + + google_hangouts_botkit.middleware.format.use(function (bot, message, platform_message, next) { + + platform_message.parent = message.parent; + platform_message.threadKey = message.threadKey; + platform_message.requestBody = message.requestBody; + + next(); + + }); + + google_hangouts_botkit.middleware.spawn.use(function (worker, next) { + + let params = { + scopes: 'https://www.googleapis.com/auth/chat.bot' + }; + + google + .auth + .getClient(params) + .then(client => { + worker.authClient = client; + }) + .catch(err => { + console.error('Could not get google auth client !'); + throw new Error(err); + }); + + next(); + + }); + + google_hangouts_botkit.middleware.normalize.use(function handlePostback(bot, message, next) { + message.user = message.user.name; + if (message.message) { + message.channel = message.message.thread.name; + message.text = message.message.argumentText.trim(); + } else { + message.channel = message.space.name; + } + next(); + }); + + google_hangouts_botkit.middleware.categorize.use(function (bot, message, next) { + + if ('MESSAGE' === message.type) { + message.type = 'message_received'; + } + + if ('ADDED_TO_SPACE' === message.type) { + message.type = 'ROOM' === message.space.type ? 'room_join' : 'direct_message'; + } + + if ('REMOVED_FROM_SPACE' === message.type) { + message.type = 'ROOM' === message.space.type ? 'room_leave' : 'remove_conversation'; + } + + next(); + + }); + + google_hangouts_botkit.startTicking(); + + return google_hangouts_botkit; +}; + +module.exports = GoogleHangoutsBot; diff --git a/package.json b/package.json index 627087b2b..13a828e10 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "debug": "^3.1.0", "email-addresses": "^3.0.1", "express": "^4.15.2", + "googleapis": "^32.0.0", "https-proxy-agent": "^2.2.1", "jfs": "^0.3.0", "localtunnel": "^1.8.2",