Categories: Software Development

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

0 0 votes
Article Rating
yohanes.gultom@gmail.com

Share
Published by
yohanes.gultom@gmail.com

Recent Posts

Get Unverified SSL Certificate Expiry Date with Python

Getting verified SSL information with Python (3.x) is very easy. Code examples for it are…

3 years ago

Spring Data Couchbase 4 Multibuckets in Spring Boot 2

By default, Spring Data Couchbase implements single-bucket configuration. In this default implementation, all POJO (Plain…

3 years ago

Firebase Auth Emulator with Python

Last year, Google released Firebase Auth Emulator as a new component in Firebase Emulator. In…

3 years ago

Google OIDC token generation/validation

One of the authentication protocol that is supported by most of Google Cloud services is…

4 years ago

Fast geolocation query with PostGIS

If you need to to add a spatial information querying in your application, PostGIS is…

4 years ago

Auto speech-to-text (Indonesian) with AWS Transcribe and Python

Amazon Web Service Transcribe provides API to automatically convert an audio speech file (mp3/wav) into…

4 years ago