diff --git a/docs/readme-facebook.md b/docs/readme-facebook.md index dec4adf28..81088999a 100644 --- a/docs/readme-facebook.md +++ b/docs/readme-facebook.md @@ -21,6 +21,7 @@ Table of Contents * [Silent and No Notifications](#silent-and-no-notifications) * [Messenger code API](#messenger-code-api) * [Attachment upload API](#attachment-upload-api) +* [Handover Protocol](#handover-protocol) * [Running Botkit with an Express server](#use-botkit-for-facebook-messenger-with-an-express-web-server) ## Getting Started @@ -86,9 +87,9 @@ Normal messages will be sent to your bot using the `message_received` event. In | facebook_optin | a user has clicked the [Send-to-Messenger plugin](https://developers.facebook.com/docs/messenger-platform/implementation#send_to_messenger_plugin) | facebook_referral | a user has clicked on a [m.me URL with a referral param](https://developers.facebook.com/docs/messenger-platform/referral-params) | facebook_app_roles | This callback will occur when a page admin changes the role of your application. -| facebook_standby | This callback will occur when a message has been sent to your page, but your application is not the current thread owner. -| facebook_pass_thread_control | This callback will occur when thread ownership for a user has been passed to your application. -| facebook_take_thread_control | This callback will occur when thread ownership for a user has been taken away from your application. +| standby | This callback will occur when a message has been sent to your page, but your application is not the current thread owner. +| facebook_receive_thread_control | This callback will occur when thread ownership for a user has been passed to your application. +| facebook_lose_thread_control | This callback will occur when thread ownership for a user has been taken away from your application. All incoming events will contain the fields `user` and `channel`, both of which represent the Facebook user's ID, and a `timestamp` field. @@ -597,7 +598,7 @@ Allows the Primary Receiver app to take control of a specific thread from a Seco - To thread control : ```javascript -controller.api.handover.take_thread_control('PSID', 'String to pass to the secondary receiver', function (result) { +controller.api.handover.take_thread_control('', 'String to pass to pass to the secondary receiver', function (result) { // result = {"success":true} }); ``` @@ -608,7 +609,7 @@ Allows you to pass thread control from your app to another app. - To pass thread control : ```javascript -controller.api.handover.pass_thread_control('PSID', '123456789', 'String to pass to the secondary receiver app', function (result) { +controller.api.handover.pass_thread_control('', '', 'String to pass to the secondary receiver app', function (result) { // result = {"success":true} }); ``` diff --git a/lib/Facebook.js b/lib/Facebook.js index 263eccfa9..85d81d360 100644 --- a/lib/Facebook.js +++ b/lib/Facebook.js @@ -362,20 +362,13 @@ function Facebookbot(configuration) { for (var m = 0; m < payload.entry[e].messaging.length; m++) { facebook_botkit.ingest(bot, payload.entry[e].messaging[m], res); } - } + } if (payload.entry[e].standby) { for (var s = 0; s < payload.entry[e].standby.length; s++) { - const message_event = payload.entry[e].standby[s] - - const standby_message = { - sender: message_event.sender, - recipient: message_event.recipient, - timestamp: message_event.timestamp, - standby: message_event - } + var standby_message = payload.entry[e].standby[s]; + standby_message.standby = true; facebook_botkit.ingest(bot, standby_message, res); } - } } } @@ -471,6 +464,8 @@ function Facebookbot(configuration) { next(); }); + + /* Facebook Handover Protocol categorize middleware */ facebook_botkit.middleware.categorize.use(function threadControl(bot, message, next) { if (message.app_roles) { @@ -485,10 +480,10 @@ function Facebookbot(configuration) { if (message.take_thread_control) { message.type = 'facebook_lose_thread_control' } - console.log('Thread Control Step', {message}) - next() - }) + next(); + + }); facebook_botkit.on('webserver_up', function(webserver) { @@ -795,87 +790,6 @@ function Facebookbot(configuration) { } }; - var handover = { - get_secondary_receivers_list: function(cb) { - request.get({ - url: 'https://' + api_host + '/v2.6/me/secondary_receivers', - qs: { - fields: 'id,name', - access_token: configuration.access_token - }, - json: true - }, - function(err, res, body) { - if (err) { - facebook_botkit.log('Could not get secondary receivers list'); - cb && cb(err) - } else { - if (body) { - if (body.error) { - facebook_botkit.log('ERROR in secondary receivers list: ', results.error.message); - cb && cb(body.error) - } else { - facebook_botkit.debug('Successfully call page message tags', body); - cb && cb(null, body); - } - } - } - }); - }, - take_thread_control: function(recipient, metadata, cb) { - var request_body = { - recipient: { - id: recipient - }, - metadata: metadata - }; - request.post({ - url: 'https://' + api_host + '/v2.6/me/take_thread_control', - qs: {access_token: configuration.access_token}, - body: request_body, - json: true - }, - function(err, res, body) { - if (err) { - facebook_botkit.log('Could not take thread control'); - } else { - if (body) { - if (body.error) { - facebook_botkit.log('ERROR in take thread control API call: ', body.error.message); - cb && cb(body.error) - } else { - facebook_botkit.debug('Successfully taken thread control', body); - cb && cb(null, body); - } - } - } - }); - }, - pass_thread_control: function(recipient, target, metadata, cb) { - var request_body = { - recipient: { - id: recipient - }, - target_app_id: target, - metadata: metadata - }; - request.post({ - url: 'https://' + api_host + '/v2.6/me/pass_thread_control', - qs: {access_token: configuration.access_token}, - body: request_body, - json: true, - }, - function(err, res, body) { - if (err) { - facebook_botkit.log('Could not pass thread control'); - } else { - if (body) { - if (body.error) { - facebook_botkit.log('ERROR in pass thread control API call: ', body.error.message); - cb && cb(body) - } else { - facebook_botkit.debug('Successfully pass thread control', body); - cb && cb(null, body); var user_profile = function(uid, fields, cb) { if (!fields) { fields = 'first_name,last_name,timezone,gender,locale'; @@ -929,8 +843,90 @@ function Facebookbot(configuration) { }; - - + var handover = { + get_secondary_receivers_list: function (fields, cb) { + request.get({ + url: 'https://' + api_host + '/v2.6/me/secondary_receivers', + qs: { + fields: typeof(fields) == 'string' ? fields : fields.join(','), + access_token: configuration.access_token + }, + json: true + }, function (err, res, body) { + if (err) { + facebook_botkit.log('Could not get secondary receivers list'); + cb && cb(err); + } else { + if (body.error) { + facebook_botkit.log('ERROR in secondary receivers list: ', body.error.message); + cb && cb(body.error); + } else { + facebook_botkit.debug('Successfully getting secondary receivers list', body); + cb && cb(null, body); + } + } + }); + }, + take_thread_control: function (recipient, metadata, cb) { + var request_body = { + recipient: { + id: recipient + }, + metadata: metadata + }; + request.post({ + url: 'https://' + api_host + '/v2.6/me/take_thread_control', + qs: { + access_token: configuration.access_token + }, + body: request_body, + json: true + }, function (err, res, body) { + if (err) { + facebook_botkit.log('Could not take thread control'); + cb && cb(err); + } else { + if (body.error) { + facebook_botkit.log('ERROR in take thread control API call: ', body.error.message); + cb && cb(body.error); + } else { + facebook_botkit.debug('Successfully taken thread control', body); + cb && cb(null, body); + } + } + }); + }, + pass_thread_control: function (recipient, target, metadata, cb) { + var request_body = { + recipient: { + id: recipient + }, + target_app_id: target, + metadata: metadata + }; + request.post({ + url: 'https://' + api_host + '/v2.6/me/pass_thread_control', + qs: { + access_token: configuration.access_token + }, + body: request_body, + json: true + }, function (err, res, body) { + if (err) { + facebook_botkit.log('Could not pass thread control'); + cb && cb(err); + } else { + if (body.error) { + facebook_botkit.log('ERROR in pass thread control API call: ', body.error.message); + cb && cb(body.error); + } else { + facebook_botkit.debug('Successfully past thread control', body); + cb && cb(null, body); + } + } + }); + } + }; facebook_botkit.api = { @@ -944,9 +940,6 @@ 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) {