Motivation
When facebook announced their messenger bot API, and I had a look at the documentation, I thought that natural language processing is something that really requires effort and time, and that could take some time to have something useful on top of it.
To do it properly, it does not only requires to understand each sentence, but also to maintain the context of the conversation.
I gave a try to wit.ai, but I did not find it so easy to use.
But when I read on of the Facebook developer blog a post about massenger platform policies and read that they opened the Subscription Messaging, I thought that could be a very nice substitute for native apps push notifications.
I mean, if you do not have the time / money yet to invest into a native app, and you have a web app that would benefit from having notifications, why not implement them with an already existing app with a huge user base?
The facebook messenger platform has the nice feature of showing dialogs, with buttons, that can trigger posts to your endpoint with a payload that you set for each button.
This way we could use a very dumb interface, based on those dialogs to guide the user to complete a subscription for our notifications.
First steps
So, I decided to give it a try. Googled about it, and decided give a click to a couple of results:
How to build a Facebook Messenger bot using Django and Ngrok
I mostly followed the steps on the basic tutorial, with the only difference of not using ngrok.
Instead of that I used my running web server to forward a port with ssh, to my development virtual machine in my laptop, where I would run an stunnel process (a proxy to add TLS), with the certificate from my web server, that finally would connect to the running http django development server.
So, I had to enable port forwarding in the web server, by adding to /etc/ssh/sshd_config
GatewayPorts yes
And then I run the command:
ssh -nNT -R 8443:my_dev_virtual_machine_ip:8334 remote_server
And obviously, the webhook parameter in the Facebook developer control panel must include the port:
https://remote_server:8443/my_fb_endpoint
You can find more about port forwardin in: Trackets Blog
However, one of the main problems when using this approach is that the ssh connection drops very often (and with it the port forwarding, of course).
I must admit that ngrok would have been an easier path.
Already existing python libraries
After playing with the very basics of setting the endpoint, and redirecting it to my development server, with raw python code, I though it was worth to invest some time in finding existing libraries to manage the messaging part.
I’ve found some pet project on github, a Flask targeted repo, and a couple of python libraries that could do the work.
-
David Chua’s pymessenger (100 stars at the time of writing this in github: contributions graph )
-
Nam Ngo’s messengerbot (60 stars at the time of writing this in github: contributions graph )
Although the first one has far more stars, looking at the contribution graph I found the second one had more recent contributions. But given that there is not a ‘widely used’ one, the best check is to look at the source.
pymessenger
At first look it has less classes.
It has a single Bot class, that is used for sending different type of messages. Most of the function calls have inside hardcoded dictionaries to be converted to json. The problems is that there are not following the DRY, and instead of composing the different parts of the message, each call has repeated dictionary structures (look at this snippet from the code):
def send_generic_message(self, recipient_id, elements):
payload = {
'recipient': {
'id': recipient_id
},
'message': {
"attachment": {
"type": "template",
"payload": {
"template_type": "generic",
"elements": elements
}
}
}
}
return self._send_payload(payload)
def send_button_message(self, recipient_id, text, buttons):
payload = {
'recipient': {
'id': recipient_id
},
'message': {
"attachment": {
"type": "template",
"payload": {
"template_type": "button",
"text": text,
"buttons": buttons
}
}
}
}
return self._send_payload(payload)
Two different functions with a lot of repeated dictionary parts.
It also has a FacebookGraphApi object, that is not needed for the messenger bots.
Also an empty Receipt class (I did not found where it is used). Also the UserProfileApi that uses the FacebookGraphApi to fetch the user profile. And a utils.py file for some hub signature validation and the app secret proof.
(BTW: looking at its code I discovered the request_toolbelt package that is a nice feature that I will take into account for the future)
messengerbot
This project uses a more structured way of providing the facebook messenger functionality.
It has its code spread among several files for different clases: Attachments, Elements, Templates, and so one. Each class has its well defined properties that nicely maps to the official facebook bots documentation
Also objects have more validation for its properties, like checking for the maximum length of the message or the button title, raising the appropiate exceptions. Generally speaking, the code looks much more pythonic to me. And the fact it does not have empty classes, or code that is not needed for the library functionality makes me feel more confident on the quality and the future of the library.
So, finally decided to go with messengerbot and give the repo a star (and also a little contribution :).