├── .gitignore ├── runtime.txt ├── Procfile ├── requirements.txt ├── readme.md └── app.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .* -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-2.7.13 -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn app:app --log-file=- -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==0.11.1 2 | Jinja2==2.8 3 | MarkupSafe==0.23 4 | Werkzeug==0.11.10 5 | click==6.6 6 | gunicorn==19.6.0 7 | itsdangerous==0.24 8 | requests==2.10.0 9 | wsgiref==0.1.2 10 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Facebook Messenger Bot 2 | This is a simple python template that uses Flask to build a webhook for Facebook's Messenger Bot API. 3 | 4 | Read more in my [tutorial that uses this repository](https://blog.hartleybrody.com/fb-messenger-bot/). 5 | 6 | *New:* [Check out my Facebook Messenger Bot Course](https://facebook-messenger-bot.teachable.com/p/facebook-messenger-bot/). It walks you through the process of getting this bot hosted on heroku step-by-step, and also unlocks all the content that's hidden in this repo's branches. 7 | 8 | ## "Callback verification failed" 9 | 10 | ![Facebook Error](https://cloud.githubusercontent.com/assets/18402893/21538944/f96fcd1e-cdc7-11e6-83ee-a866190d9080.png) 11 | 12 | The #1 error that gets reported in issues is that facebook returns an error message (like above) when trying to add the heroku endpoint to your facebook chat application. 13 | 14 | Our flask application intentionally returns a 403 Forbidden error if the token that facebook sends doesn't match the token you set using the heroku configuration variables. 15 | 16 | If you're getting this error, it likely means that you didn't set your heroku config values properly. Run `heroku config` from the command line within your application and verify that there's a key called `VERIFY_TOKEN` that has been set, and that it's set to the same value as what you've typed into the window on facebook. -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import json 4 | 5 | import requests 6 | from flask import Flask, request 7 | 8 | app = Flask(__name__) 9 | 10 | 11 | @app.route('/', methods=['GET']) 12 | def verify(): 13 | # when the endpoint is registered as a webhook, it must echo back 14 | # the 'hub.challenge' value it receives in the query arguments 15 | if request.args.get("hub.mode") == "subscribe" and request.args.get("hub.challenge"): 16 | if not request.args.get("hub.verify_token") == os.environ["VERIFY_TOKEN"]: 17 | return "Verification token mismatch", 403 18 | return request.args["hub.challenge"], 200 19 | 20 | return "Hello world", 200 21 | 22 | 23 | @app.route('/', methods=['POST']) 24 | def webhook(): 25 | 26 | # endpoint for processing incoming messaging events 27 | 28 | data = request.get_json() 29 | log(data) # you may not want to log every incoming message in production, but it's good for testing 30 | 31 | if data["object"] == "page": 32 | 33 | for entry in data["entry"]: 34 | for messaging_event in entry["messaging"]: 35 | 36 | if messaging_event.get("message"): # someone sent us a message 37 | 38 | sender_id = messaging_event["sender"]["id"] # the facebook ID of the person sending you the message 39 | recipient_id = messaging_event["recipient"]["id"] # the recipient's ID, which should be your page's facebook ID 40 | message_text = messaging_event["message"]["text"] # the message's text 41 | 42 | send_message(sender_id, "roger that!") 43 | 44 | if messaging_event.get("delivery"): # delivery confirmation 45 | pass 46 | 47 | if messaging_event.get("optin"): # optin confirmation 48 | pass 49 | 50 | if messaging_event.get("postback"): # user clicked/tapped "postback" button in earlier message 51 | pass 52 | 53 | return "ok", 200 54 | 55 | 56 | def send_message(recipient_id, message_text): 57 | 58 | log("sending message to {recipient}: {text}".format(recipient=recipient_id, text=message_text)) 59 | 60 | params = { 61 | "access_token": os.environ["PAGE_ACCESS_TOKEN"] 62 | } 63 | headers = { 64 | "Content-Type": "application/json" 65 | } 66 | data = json.dumps({ 67 | "recipient": { 68 | "id": recipient_id 69 | }, 70 | "message": { 71 | "text": message_text 72 | } 73 | }) 74 | r = requests.post("https://graph.facebook.com/v2.6/me/messages", params=params, headers=headers, data=data) 75 | if r.status_code != 200: 76 | log(r.status_code) 77 | log(r.text) 78 | 79 | 80 | def log(message): # simple wrapper for logging to stdout on heroku 81 | print str(message) 82 | sys.stdout.flush() 83 | 84 | 85 | if __name__ == '__main__': 86 | app.run(debug=True) 87 | --------------------------------------------------------------------------------