Simple Facebook Messenger bot using Python Flask and PyAIML

We require only 3 easy steps to create a simple Facebook Messenger using Flask & PyAIML 🐍

  1. Create a webservice to accept & reply message
  2. Deploy the webservice online so it could be accessed by Facebook
  3. 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 and GROUP 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

Leave a Reply

Your email address will not be published. Required fields are marked *