We require only 3 easy steps to create a simple Facebook Messenger using Flask & PyAIML ?
- Create a webservice to accept & reply message
- Deploy the webservice online so it could be accessed by Facebook
- Create a Faceboook Messenger app and register the webservice as a webhook
Create a webservice
Verify identity by comparing hub.verify_token
to internal variable:
@app.route('/' + secret, methods=['GET', 'POST']) def chat(): if request.method == 'GET': if verify_token == request.args.get('hub.verify_token'): return request.args.get('hub.challenge') else: return 'invalid token', 400
We will be required to define
hub.verify_token
when registering our app to facebook
Accepting facebook message (using webhook):
@app.route('/' + secret, methods=['GET', 'POST']) ... elif request.method == 'POST': data = request.get_json() for entry in data['entry']: for message in entry['messaging']: if 'message' in message: pprint(message) ... return data, 200
Use AIML engine to find response to message using k.respond()
and POST the reply to Facebook (in this case, I use requests)
k = aiml.Kernel() k.learn('std-startup.xml') k.respond('load aiml b') ... elif request.method == 'POST': data = request.get_json() for entry in data['entry']: for message in entry['messaging']: if 'message' in message: pprint(message) data = json.dumps({ 'recipient': {'id': message['sender']['id']}, 'message': {'text': k.respond(message['message']['text'])} }) return data, 200
Here is the complete code of the webservice.
The PyAIML is not available in
pip
anymore so you will need to include its directory in your distribution/deployment
Deploy the webservice online
There are several ways to do this. The easiest way is to run Flask server in the background. In Linux, it will be something like: nohup python server.py > server.out 2>&1&
(later it can be stopped using kill
command). Another way, which is considered more production-ready, is to use webserver (eg. Nginx) & application server (eg. WSGI). Here, I use nginx and uwsgi to deploy Flask webservice on Debian 7 Wheezy 32-bit (why? because I assume it’s the lightest OS for VPS).
Installing uwsgi:
pip install requests[security] pip install uwsgi
then, test your installation by calling:
uwsgi --help
if you hit an error during installation, most likely it’s a dependency issue (eg. OS shared library)
Create uwsgi config file for the webservice. For example aimlbot.ini
:
# UWSGI configuration [uwsgi] # application's base folder base = /var/www/aimlbot chdir = %(base) # python module to import app = server module = %(app) # socket file's location socket = %(base)/%n.sock #permissions for the socket file chmod-socket = 664 #the variable that holds a flask application callable = app #location of log files logto = /var/log/uwsgi/%n.log
Create the log directory and set the ownership to match your user (eg. www-data
):
sudo mkdir /var/log/uwsgi sudo chown -R www-data:www-data /var/log/uwsgi
Test your configuration by running and checking the log. Once everything ok just kill the process.
sudo -u www-data uwsgi -ini aimlbot.ini sudo tail -100f /var/log/uwsgi/aimlbot.log
Next, setup uswgi Emperor to manage the webservice process by creating separate directories and links to the config file:
sudo mkdir -p /etc/uwsgi/apps-available sudo mkdir -p /etc/uwsgi/apps-enabled sudo ln -s /var/www/aimlbot/aimlbot.ini /etc/uwsgi/apps-available/ sudo ln -s /etc/uwsgi/apps-available/aimlbot.ini /etc/uwsgi/apps-enabled/
Download init script inside /etc/init.d
cd /etc/init.d wget https://gist.githubusercontent.com/yohanesgultom/fbacf601ce49bd38363b/raw/14b53c4a3554a80ee26d0c0e6af1fa32f6e5dfee/uwsgi chmod +x uwsgi update-rc.d uwsgi defaults
Make sure the
OWNER
andGROUP
in/etc/init.d/uwsgi
can access your distribution’s files
Test the service works by checking the output in the log
sudo service uwsgi start sudo tail -100f /var/log/uwsgi/emperor.log sudo tail -100f /var/log/uwsgi/aimlbot.log sudo service uwsgi restart sudo service uwsgi stop
Finally create a subdomain (or domain) config for nginx eg. /etc/nginx/sites-available/aimlbot
:
# Nginx subdomain configuration server { listen 80; server_name aimlbot.gultom.me; charset utf-8; client_max_body_size 75M; location / { try_files $uri @yourapplication; } location @yourapplication { include uwsgi_params; uwsgi_pass unix:/var/www/aimlbot/aimlbot.sock; } }
Enabled the site and restart nginx:
sudo ln -s /etc/nginx/sites-available/aimlbot /etc/nginx/sites-enabled sudo service nginx restart
Make sure your app is running and accessible in the configured domain eg https://aimlbot.gultom.me. If the webservice is not accessible, check for possible error in the logs eg: /var/log/nginx/error.log
, /var/log/uwsgi/aimlbot.log
or /var/log/uwsgi/emperor.log
Create a Faceboook Messenger app
Finally you just need to simply follow the guide in https://developers.facebook.com/docs/messenger-platform/guides/setup to create a Facebook Messenger app for your bot ?. Once you get the Page Token and register the webhook, you can add another facebook user as tester so you can try to chat with your bot.
In case you want your bot to be publicly available, you will need to submit your app for review by also providing Privacy and Policy URL (example). I got one for free from iubenda.com.
References
- Complete project code https://github.com/yohanesgultom/fb-aiml-bot
- Setting up UWSGI + Flask http://flask.pocoo.org/docs/0.12/deploying/uwsgi/
- Setting up UWSGI Emperor (UWSGI as service) + Nginx https://kradalby.no/uwsgi-and-nginx-on-debian-wheezy.html