bootbot icon indicating copy to clipboard operation
bootbot copied to clipboard

Proposal to support multi page bots

Open ntgx opened this issue 6 years ago • 10 comments

Had the same issue as #125 and this is my attempt for a fix. I've been testing it for the past few days and everything's working so far. All tests pass and it doesn't create any breaking changes for people using it for one page. Let me know what you think about the approach :)

Anyone who wants to support multiple pages just needs to pass an object instead of a string to the access token option in the following format and they're good to go

accessToken: {
    'PAGE_ONE_ID': 'PAGE_ONE_ACCESS_TOKEN',
    'PAGE_TWO_ID': 'PAGE_TWO_ACCESS_TOKEN',
 }

This lets you handle messages from both pages exactly like you used to and if you want to send different messages to different pages you can just check the value on chat.pageId first

bot.on('message', (payload, chat) => {
  const text = payload.message.text;
  chat.say(`Echo: ${text}`);
});

Even though all the methods on the chat object stay the same you have to pass pageId for some methods on bot if you plan to support multiple pages:

bot.setGreetingText(greeting, pageId);
bot.setGetStartedButton(action, pageId);
bot.setPersistentMenu(menu, null, pageId);

The functions that require accessToken in BootBot.js just call _getAccessToken(pageId) which looks like

_getAccessToken(pageId) {
    return typeof this.accessToken === 'string' ? this.accessToken : this.accessToken[pageId];
}
  • handleFacebookData(data) gets the pageId from each entry and passes it to all the event handlers
  • So most methods on bot now take an optional pageId
  • The Chat constructor also takes an optional pageId and sets it to this
  • The Conversation constructor also takes an optional pageId which it passes to super()

ntgx avatar Jun 21 '18 10:06 ntgx

Thanks @ntgx. It looks nice and like you put some time into it. I hope @Charca or I get some time to look at it fully in the next days. This is much requested feature and first class support would be nice (instead of my handleFacebookData solution).

mraaroncruz avatar Jun 25 '18 08:06 mraaroncruz

Thanks @ntgx! PR looks good to me at a first glance, I'm not a huge fan of passing around yet another param to basically every method on the API, but I understand the need for doing so.

I'll have to do some more testing before merging this, but this is looking great. Thanks a lot!

Charca avatar Jul 09 '18 23:07 Charca

+1, My suggestion is: we can implement a useAccessToken method or something like that just before we send a response, so when we find a message is for a pageid, we call to that method like bot.useAccessToken()? in implemention we should have a map like [{pageId: accessToken}] .

You know we dont need accessToken when we set webhook and any other express things when starting the bot server.. so we can omit accessToken at startup, this feature will be very much helpful in a multipage app where a new page can be added or removed on the fly.. I am running this situation right now. any kind of help is appreciated.. Thanks @ntgx thanks for this, and can you do something like this quickly?

mahmed0715 avatar Aug 17 '18 19:08 mahmed0715

Please check my request @Charca

mahmed0715 avatar Aug 17 '18 19:08 mahmed0715

actually we dont need to do any change as we just use the accessToken that is set to the bot instance, like ${this.accessToken} so when we need to send a response from different page, we just set bot.accessToken = "whateverAccessTokenWeHaveforOtherPage"; and send the response.. thats it.. how is it @ntgx @Charca ? please let me know..

mahmed0715 avatar Aug 17 '18 19:08 mahmed0715

@mahmed0715 I don't think overwriting the accessToken value on the fly is a good idea. You can end up with a weird state when you try to use the accessToken of page A to reply to a message coming from page B. I think using a map of page IDs and access tokens like in this PR is the way to go. What don't you like about @ntgx's solution?

Charca avatar Aug 20 '18 13:08 Charca

yeah you are right @Charca , but i think overwriting in right place could be good if possible. need to check if I can get things done, otherwise that solution is okay. I will overwrite exactly before call to fb api..will see..

mahmed0715 avatar Aug 20 '18 16:08 mahmed0715

Ran into an error while running this code. When pressing 'Get Started' bots would send back a number of messages equal to the number of times the for loop ran. Is it possible to set the get started button for multiple pages?

for(let i =0; i < Object.keys(accessTokens).length;i++){ bot.setGetStartedButton((payload, chat) => { chat.getUserProfile().then((user)=>{ //Code was here }); }); },ActivePages[i]); }

ghost avatar Aug 24 '18 03:08 ghost

Hey @DevinODowd are you still having this problem? I do something very similar and it's working fine for me

ntgx avatar Oct 03 '18 11:10 ntgx

Dears @ntgx & @Charca, did this pull request approved and merged into master? And if not is there any estimated time to be approved ?

AkramLazkanee avatar Dec 11 '19 11:12 AkramLazkanee