diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..bff65d4 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: gunicorn app:app --log-file=- \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..b33eebf --- /dev/null +++ b/app.py @@ -0,0 +1,94 @@ +import os +import sys +import json +from datetime import datetime + +import requests +from flask import Flask, request + +app = Flask(__name__) + + +@app.route('/', methods=['GET']) +def verify(): + # when the endpoint is registered as a webhook, it must echo back + # the 'hub.challenge' value it receives in the query arguments + if request.args.get("hub.mode") == "subscribe" and request.args.get("hub.challenge"): + if not request.args.get("hub.verify_token") == os.environ["VERIFY_TOKEN"]: + return "Verification token mismatch", 403 + return request.args["hub.challenge"], 200 + + return "Hello world", 200 + + +@app.route('/', methods=['POST']) +def webhook(): + + # endpoint for processing incoming messaging events + + data = request.get_json() + log(data) # you may not want to log every incoming message in production, but it's good for testing + + if data["object"] == "page": + + for entry in data["entry"]: + for messaging_event in entry["messaging"]: + + if messaging_event.get("message"): # someone sent us a message + + sender_id = messaging_event["sender"]["id"] # the facebook ID of the person sending you the message + recipient_id = messaging_event["recipient"]["id"] # the recipient's ID, which should be your page's facebook ID + message_text = messaging_event["message"]["text"] # the message's text + + send_message(sender_id, "roger that!") + + if messaging_event.get("delivery"): # delivery confirmation + pass + + if messaging_event.get("optin"): # optin confirmation + pass + + if messaging_event.get("postback"): # user clicked/tapped "postback" button in earlier message + pass + + return "ok", 200 + + +def send_message(recipient_id, message_text): + + log("sending message to {recipient}: {text}".format(recipient=recipient_id, text=message_text)) + + params = { + "access_token": os.environ["PAGE_ACCESS_TOKEN"] + } + headers = { + "Content-Type": "application/json" + } + data = json.dumps({ + "recipient": { + "id": recipient_id + }, + "message": { + "text": message_text + } + }) + r = requests.post("https://graph.facebook.com/v2.6/me/messages", params=params, headers=headers, data=data) + if r.status_code != 200: + log(r.status_code) + log(r.text) + + +def log(msg, *args, **kwargs): # simple wrapper for logging to stdout on heroku + try: + if type(msg) is dict: + msg = json.dumps(msg) + else: + msg = unicode(msg).format(*args, **kwargs) + print u"{}: {}".format(datetime.now(), msg) + except UnicodeEncodeError: + pass # squash logging errors in case of non-ascii text + sys.stdout.flush() + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..2085576 --- /dev/null +++ b/readme.md @@ -0,0 +1,16 @@ +# Facebook Messenger Bot +This is a simple python template that uses Flask to build a webhook for Facebook's Messenger Bot API. + +Read more in my [tutorial that uses this repository](https://blog.hartleybrody.com/fb-messenger-bot/). + +*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. + +## "Callback verification failed" + +![Facebook Error](https://cloud.githubusercontent.com/assets/18402893/21538944/f96fcd1e-cdc7-11e6-83ee-a866190d9080.png) + +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. + +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. + +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. \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fe15f17 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,9 @@ +Flask==0.11.1 +Jinja2==2.8 +MarkupSafe==0.23 +Werkzeug==0.11.10 +click==6.6 +gunicorn==19.6.0 +itsdangerous==0.24 +requests==2.10.0 +wsgiref==0.1.2 diff --git a/runtime.txt b/runtime.txt new file mode 100644 index 0000000..2ce112e --- /dev/null +++ b/runtime.txt @@ -0,0 +1 @@ +python-2.7.14 \ No newline at end of file