How to Create a Facebook Messenger Bot with Python Flask
Tags: flask, python, bot, messenger
Published: 2018-08-20 11:38:28

---
title: How to Create a Facebook Messenger Bot with Python Flask
published: true
description: Comprehensive How to Create a Facebook Messenger Bot with Python Flask
tags: flask, python, bot, messenger
---

The bot-revolution has taken over, and everyone is building a bot. In this post we take you through creating your first bot using Python/Flask. The codebase can be found here on [Github](https://github.com/codecraf8/facebook-messenger-bot-python-flask).

![Alt text of image](https://blog.apcelent.com/images/facebook-messenger-bot-python-flask.png)

A lightweight web application needs to be created to compliment our bot.

The different technologies that we are going to use are as follows :

* Server backend: [Flask](http://flask.pocoo.org/)
* Secure tunneling to localhost: [Ngrok](https://ngrok.com/)
* Natural Language Processing platform: [API AI](https://dialogflow.com/)
* Deployment on Facebook Messenger
* [Python wrapper](https://github.com/csparpa/pyowm) of [OpenWeatherMap web API](https://openweathermap.org/) for weather reports

We are going to demonstrate a very simple feature :

Enquired about the current weather of a location, chatbot should return the weather information.

Example:

Question: What is the current weather of New Delhi?

Reply: Current weather report of New Delhi : max temp: 42.0 min temp: 40.0 current temp: 40.95 wind speed :2.6 humidity 20%

![Alt text of image](https://blog.apcelent.com/images/chatbot_may_17_weather_chatbot.png)

## 1. Setup API AI

API AI is a conversational experiences platform. Register and create an account at [API AI](https://console.dialogflow.com/api-client/#/login). Create an agent to access test console. Navigate to Settings of the agent and get the Client Access Token.

![Alt text of image](https://blog.apcelent.com/images/chatbot_may_17_create_agent.png)

### Creating an intent

An intent is mapping between user expression and the desired response.

We add an intent with user expression "What's the weather in Singapore?"

![Alt text of image](https://blog.apcelent.com/images/chatbot_may_17_intent_contexts.png)

where Singapore is tagged as an entity of type @sys.geo-city. This parameter can take any value in the conversation and used to determine the response in our application.

We add following response for the user expression: "Current weather report of $geo-city :"

![Alt text of image](https://blog.apcelent.com/images/chatbot_may_17_intent_user_response.png)

### API AI Python client

We can use [API AI python SDK](https://pypi.org/project/apiai/1.2.3/) for natural language processing.

## 2. Setup Open Weather Map

Open Weather Map provides [API](https://openweathermap.org/api) for accessing current weather data of any location on earth. There is nice [python wrapper](https://github.com/csparpa/pyowm) for using these APIs. Register to open weather map and fetch the API key for getting weather data.

```python
owm = pyowm.OWM('your_open_weather_map_api_key')  # You MUST provide a valid API key

forecast = owm.daily_forecast(input_city)

observation = owm.weather_at_place(input_city)
w = observation.get_weather()
print(w)                      
print(w.get_wind())                 
print(w.get_humidity())      
max_temp = str(w.get_temperature('celsius')['temp_max'])  
min_temp = str(w.get_temperature('celsius')['temp_min'])
current_temp = str(w.get_temperature('celsius')['temp'])
wind_speed = str(w.get_wind()['speed'])
humidity = str(w.get_humidity())
```

If you have a pro subscription for open weather map, then use following:

```python
owm = pyowm.OWM(API_key='your-API-key', subscription_type='pro')
```

## 3. Setting up the Flask Server

```python
import apiai
```

Add client access tokens, page access tokens and verify token

```python
CLIENT_ACCESS_TOKEN = 'your_client_access_token_from_api_ai'
PAGE_ACCESS_TOKEN = 'your_facebook_page_access_token'
VERIFY_TOKEN = 'verification_token_for_facebook_chatbot_using_python'

ai = apiai.ApiAI(CLIENT_ACCESS_TOKEN)
```

Facebook webhook send the request to the application and if the verification is complete if the token returned by application matches the token entered in facebook application

```python
@app.route('/', methods=['GET'])
def handle_verification():
    if (request.args.get('hub.verify_token', '') == VERIFY_TOKEN):
        print("Verified")
        return request.args.get('hub.challenge', '')
    else:
        print("Wrong token")
        return "Error, wrong validation token"
```

Application will parse all messages sent by the facebook messenger

```python
@app.route('/', methods=['POST'])
def handle_message():
    '''
    Handle messages sent by facebook messenger to the applicaiton
    '''
    data = request.get_json()

    if data["object"] == "page":
        for entry in data["entry"]:
            for messaging_event in entry["messaging"]:
                if messaging_event.get("message"):

                    sender_id = messaging_event["sender"]["id"]
                    recipient_id = messaging_event["recipient"]["id"]  
                    message_text = messaging_event["message"]["text"]  
                    send_message_response(sender_id, parse_natural_text(message_text)


     return "ok"
```

Call facebook Graph API using python requests library to send message to the facebook user

```python
def send_message(sender_id, message_text):
    '''
    Sending response back to the user using facebook graph API
    '''
    r = requests.post("https://graph.facebook.com/v2.6/me/messages",

        params={"access_token": PAGE_ACCESS_TOKEN},

        headers={"Content-Type": "application/json"},

        data=json.dumps({
        "recipient": {"id": sender_id},
        "message": {"text": message_text}
    }))
```

Use API AI to parse the message sent by the user and recieve the bot response from API AI. Fetch weather data from open weather map client and append the report with bot reponse.

```python
def parse_user_text(user_text):

    '''
    Send the message to API AI which invokes an intent
    and sends the response accordingly
    The bot response is appened with weaher data fetched from
    open weather map client
    '''

    request = ai.text_request()
    request.query = user_text

    response = json.loads(request.getresponse().read().decode('utf-8'))
    responseStatus = response['status']['code']
    if (responseStatus == 200):
        print("Bot response", response['result']['fulfillment']['speech'])

        weather_report = ''

        input_city = response['result']['parameters']['geo-city']

        #Fetching weather data
        owm = pyowm.OWM('edd197717da7951b85f8f6936fc27b13')  # You MUST provide a valid API key

        forecast = owm.daily_forecast(input_city)

        observation = owm.weather_at_place(input_city)
        w = observation.get_weather()
        print(w)                      
        print(w.get_wind())                 
        print(w.get_humidity())      
        max_temp = str(w.get_temperature('celsius')['temp_max'])  
        min_temp = str(w.get_temperature('celsius')['temp_min'])
        current_temp = str(w.get_temperature('celsius')['temp'])
        wind_speed = str(w.get_wind()['speed'])
        humidity = str(w.get_humidity())
        weather_report = ' max temp: ' + max_temp + ' min temp: ' + min_temp + ' current temp: ' + current_temp + ' wind speed :' + wind_speed + ' humidity ' + humidity + '%'
        print("Weather report ", weather_report)
        return (response['result']['fulfillment']['speech'] + weather_report)
    else:
        return ("Please try again")


def send_message_response(sender_id, message_text):
    sentenceDelimiter = ". "
    messages = message_text.split(sentenceDelimiter)

    for message in messages:
        send_message(sender_id, message)

if __name__ == '__main__':
    app.run()
```
Activate a [virtual environment](https://virtualenv.pypa.io/en/stable/), install all packages

```python
pip install -r requirements.txt
```

and run the script

```python
python fb-chatbot.py
```

### Set up tunnelling to localhost

We have used ngrok to expose local webserver to the internet so that it can be used for callback verification needs to be done for using a webhook with facebook app.

```python
sudo apt-get update
sudo apt-get install ngrok-client
```

and run the ngrok client

```python
./ngrok http -bind-tls=true 5000
```

Please note that a secure callback URL (https) is needed for verification.

### Set up facebook messenger

Create a [facebook page](https://www.facebook.com/pages/creation/?ref_type=logout_gear) and [facebook app](https://developers.facebook.com/). Add Webhook to the app.

![Alt text of image](https://blog.apcelent.com/images/chatbot_may_17_facebook_app.png)

Fetch the app ID and update it in the script.

Add Messenger to the app and generate token for the page which has to used for chat.

![Alt text of image](https://blog.apcelent.com/images/chatbot_may_17_page_access_token.png)

![Alt text of image](https://blog.apcelent.com/images/chatbot_may_17_subscription_webhook.png)

and select events for page subscription

![Alt text of image](https://blog.apcelent.com/images/chatbot_may_17_page_subscription.png)

Restart the server and now the chatbot is ready. Facebook further provides UI elements, you can play around with them [here](https://developers.facebook.com/docs/messenger-platform/reference/send-api).

This post will help you building a chatbot of your own, using API.AI. Feel free to get in touch with us, for any queries/requests.

The article originally appeared on [Apcelent Tech Blog](https://blog.apcelent.com/How-to-Create-a-Facebook-Messenger-Bot-with-Python-Flask.html).