Create a weather bot for Facebook messenger bot

how-chatbot-works

When a user sends a message to a Facebook page that has bot feature setup, it is sent to the chatbot server by using webhooks. The chatbot server receives the message and It can do operations like natural language processing, access information from the database or get information from third-party services like weather info and construct the response and sends reply back to the facebook messenger API.

We will be using yahoo weather rest API to get weather information for the given latitude and longitude.

Python requests library is used to make rest API calls.

requirements.txt

fbmessenger==4.2.0
Flask==0.12.2
requests==2.18.4

weather.py

import requests

def get_yahoo_weather_for_coordinates(latitude, longitude):
    try:
        baseurl = "https://query.yahooapis.com/v1/public/yql?"
        yql_query = 'select * from weather.forecast where woeid in (SELECT woeid FROM geo.places WHERE text="({0},{1})")'.format(latitude, longitude)
        yql_url = baseurl
        result = requests.get(yql_url, params = {"q": yql_query, "format": "json"})
        return (result.json()['query']['results']['channel']['item']['condition']['text'], result.json()['query']['results']['channel']['location']['city'])
    except Exception as e:
        return None

main.py

import os
from flask import Flask, request
from fbmessenger import BaseMessenger
from fbmessenger import quick_replies
from fbmessenger.elements import Text
from fbmessenger.thread_settings import GreetingText, GetStartedButton, MessengerProfile
from weather import get_yahoo_weather_for_coordinates

def process_message(message):
    app.logger.debug('Message received: {}'.format(message))

    if 'attachments' in message['message']:
        if message['message']['attachments'][0]['type'] == 'location':
            app.logger.debug('Location received')
            weather_status, city = get_yahoo_weather_for_coordinates(message['message']['attachments'][0]['payload']['coordinates']['lat'], message['message']['attachments'][0]['payload']['coordinates']['long'])
            response = Text(text='It is {} in {}'.format(weather_status, city))
            return response.to_dict()

class Messenger(BaseMessenger):
    def __init__(self, page_access_token):
        self.page_access_token = page_access_token
        super(Messenger, self).__init__(self.page_access_token)

    def message(self, message):
        action = process_message(message)
        res = self.send(action)
        app.logger.debug('Response: {}'.format(res))

    def delivery(self, message):
        pass

    def read(self, message):
        pass

    def account_linking(self, message):
        pass

    def postback(self, message):
        payload = message['postback']['payload']

        if 'start' in payload:
            quick_reply_1 = quick_replies.QuickReply(title='Location', content_type='location')
            quick_replies_set = quick_replies.QuickReplies(quick_replies=[
                quick_reply_1
            ])
            text = {'text': 'Share your location'}
            text['quick_replies'] = quick_replies_set.to_dict()
            self.send(text)

    def optin(self, message):
        pass

    def init_bot(self):
        greeting_text = GreetingText('Welcome to weather bot')
        messenger_profile = MessengerProfile(greetings=[greeting_text])
        messenger.set_messenger_profile(messenger_profile.to_dict())

        get_started = GetStartedButton(payload='start')

        messenger_profile = MessengerProfile(get_started=get_started)
        messenger.set_messenger_profile(messenger_profile.to_dict())


app = Flask(__name__)
app.debug = True
messenger = Messenger(os.environ.get('FB_PAGE_TOKEN'))


@app.route('/webhook', methods=['GET', 'POST'])
def webhook():
    if request.method == 'GET':
        if request.args.get('hub.verify_token') == os.environ.get('FB_VERIFY_TOKEN'):
            messenger.init_bot()
            return request.args.get('hub.challenge')
        raise ValueError('FB_VERIFY_TOKEN does not match.')
    elif request.method == 'POST':
        messenger.handle(request.get_json(force=True))
    return ''


if __name__ == '__main__':
    app.run(host='0.0.0.0')