Facebook Messenger Bot webhook verification - python

I am using Flask and fbmq, documentation here:https://github.com/conbus/fbmq,
for building a messenger bot.I have the correct access and verification codes but I am still getting a 404 NOT FOUND error. Here is my server.pt code:
from flask import Flask, request
from fbmq import Page
app = Flask(__name__)
page = Page()
#app.route('/webhook', methods=['GET'])
def validate():
if request.args.get('hub.mode', '') == 'subscribe' and \
request.args.get('hub.verify_token', '') == '':
print("Validating webhook")
return request.args.get('hub.challenge', '')
else:
return 'Failed validation. Make sure the validation tokens match.'
#app.route('/webhook', methods=['POST'])
def webhook():
payload = request.get_data(as_text=True)
print(payload)
page.handle_webhook(payload)
return "ok"
if __name__ == '__main__':
app.run( port=5000, debug=True, threaded=True)

I abandoned this project, but this was probably because I didn't add /webhook/ after my ngrok url.(I know because this solved the the problem in another project)

Related

Unable to connect 2 Apps in FLASK

I have created 2 apps in FLASK, one app will issue a GET request and pull the data, 2nd app will take that data from app 1 and issue a POST request to push data into other system.
APP1.py
from flask import Flask, jsonify, request, render_template
app = Flask(__name__)
#app.route('/pushdata', methods=['GET', 'POST'])
def testfn():
# POST request
if request.method == 'POST':
print(request.get_json()) # parse as JSON
req = request.get_json()
print(type(req))
print(req)
return 'Success!! Reached Flask', 200
# main driver function
if __name__ == '__main__':
app.run(debug=True)
APP2.py
from flask import Flask,jsonify,request,make_response,url_for,redirect
import requests, json
app = Flask(__name__)
url = 'http://xx.xx.xx.xxx:<PORT>/lemte/7/rest/tenten/'
json_data = **<JSON DATA received from APP1....................>**
headers = {'content-type': 'application/json'}
res = requests.post(url, headers=headers, auth=('XXXXX', 'YYYYY'), data=json.dumps(json_data))
print ('response from server:',res.text)
dictFromServer = res.json()
if __name__ == '__main__':
app.run(host='localhost',debug=False, use_reloader=True)
How can I achieve this? searched a lot, but unable to find any hints/suggestions.
Perhaps you could try through a POST request from APP1 to APP2 or through sockets where APP1 would be the server and APP2 the client.
Edit:
This might help:
communication-between-two-python-scripts and
communication-between-two-python-scripts
They both have the same title but different answers
this solves your problem in order to let 2 flask app talk to each other :
In APP1.py:
from flask import Flask, jsonify, request, render_template
app = Flask(__name__)
#app.route('/lemte/7/rest/tenten', methods=['GET', 'POST'])
def testfn():
if request.method == 'POST':
print(request.get_json()) # parse as JSON
req = request.get_json()
print(type(req))
print(req)
return jsonify({"message":"success!! readched flask"}),200
# return 'Success!! Reached Flask', 200
if __name__ == '__main__':
app.run(debug=True,port=5201)
In APP2.py:
from flask import Flask,jsonify,request,make_response,url_for,redirect
import requests, json
app = Flask(__name__)
url = 'http://localhost:5201/lemte/7/rest/tenten'
json_data = {"test":"hello"}
headers = {'content-type': 'application/json'}
res = requests.post(url, headers=headers, auth=('XXXXX', 'YYYYY'),
data=json.dumps(json_data))
print ('response from server:',res.text)
dictFromServer = res.json()
if __name__ == '__main__':
app.run(host='localhost',debug=False, use_reloader=True,port=5200)
You did not not specified any error here
I assume the error is that you tried to run both in same port which is not possible
You can run each in different ports by specifying port in app.run
example:
app1
from flask import Flask
app = Flask(__name__)
if __name__ == "__main__":
app.run(host="localhost", port=5000)
app2
from flask import Flask
app = Flask(__name__)
if __name__ == "__main__":
app.run(host="localhost", port=5001)
You can use python app1.py and python app2.py in two different terminals to run the servers

How to get access token from redirect url

I want to get a access token from Spotify. I get from Spotify some this:
https://example.com/callback#access_token=NwAExz...BV3O2Tk&token_type=Bearer&expires_in=3600&state=123
I see it into address bar. Where https://example.com/callback is my site and access_token needed value. How to get it?
I tried like this, but get None
print(flask.request.args.get('access_token'))
Full code
import flask
app = flask.Flask(__name__)
#app.route("/")
def render_index():
return flask.render_template('index.html')
#app.route("/redirect_spotify_token", methods = ['POST'])
def redirect_spotify_token():
return flask.redirect('https://accounts.spotify.com/authorize?...')
#app.route("/callback/spotify_token", methods = ['POST', 'GET'])
def callback_token():
#
# how to get access token?
#
return 'ok'
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080)
I do my project via a service repl.it. Maybe that's why I can't read request's args like this
flask.request.args.get('access_token')
Solution
Redirect from Spotify to /callback_token. In this case, function an arg token is None. The my page callback_token.html is parse url and redirect to callback_token() with token.
main.py
#app.route("/callback_token")
#app.route("/callback_token/<token>")
def callback_token(token=None):
if token is None:
return render_template('callback_token.html')
else:
#logic with token
return redirect(url_for('index'))
callback_token.html with javascript
var parsedHash = new URLSearchParams(
window.location.hash.substr(1)
);
location.href = `your_url.com/callback_token/${parsedHash.get('access_token')}`

flask_dance + Google Search Console API searchAnalytics

I'm currently testing Google Search Console API and Flask Dance to do the oauth stuff.
It works great for getting the /sites, but i get an
ValueError: View function did not return a response
if i try to query searchAnalytics with /search
According to https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query#try-it it must be POST + additonal data. e.g.:
json={'startDate':'2017-11-01','endDate':'2017-12-01'}
In https://developers.google.com/oauthplayground/ it works like this but with flask dance sadly not. any ideas?
import os
from werkzeug.contrib.fixers import ProxyFix
from flask import Flask, redirect, url_for
from flask_dance.contrib.google import make_google_blueprint, google
from raven.contrib.flask import Sentry
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app)
sentry = Sentry(app)
app.secret_key = os.environ.get("FLASK_SECRET_KEY", "supersekrit")
app.config["GOOGLE_OAUTH_CLIENT_ID"] = os.environ.get("GOOGLE_OAUTH_CLIENT_ID")
app.config["GOOGLE_OAUTH_CLIENT_SECRET"] = os.environ.get("GOOGLE_OAUTH_CLIENT_SECRET")
google_bp = make_google_blueprint(scope=["profile", "email", "https://www.googleapis.com/auth/webmasters"])
app.register_blueprint(google_bp, url_prefix="/login")
#app.route("/")
def index():
return "BlA BLA"
#app.route("/sites")
def sites():
if not google.authorized:
return redirect(url_for("google.login"))
resp = google.get("/webmasters/v3/sites")
siteEntry = resp.json()["siteEntry"]
result = ""
for site in siteEntry:
result = result + site["siteUrl"] + "</br>"
return result
#app.route("/search")
def search():
if not google.authorized:
return redirect(url_for("google.login"))
resp = google.post("/webmasters/v3/sites/https%3A%2F%2Fzrce.eu/searchAnalytics/query", json={'startDate':'2017-11-01','endDate':'2017-12-01'})
print(resp)
if __name__ == "__main__":
app.run()
All API routes should always return something even if its an empty response.
Simply return a response, it can be "" or resp.

Python Flask, BlueMix, js - Anonymous Function

Using Flask and BlueMix to deploy a web app. Having some js issues that I cannot seem to figure out. I keep getting the same error in the browser console. I don't know any js so any help would be very appreciated!
jquery-1.11.1.min.js:4 POST http://newfla.mybluemix.net/ 405 (Method Not Allowed)
send # jquery-1.11.1.min.js:4
m.extend.ajax # jquery-1.11.1.min.js:4
(anonymous function) # demo.js:66
m.event.dispatch # jquery-1.11.1.min.js:3
r.handle # jquery-1.11.1.min.js:3
Here is the supposed (anonymous function)
$.ajax({
type: 'POST',
data: {
text: $content.val()
},
url: '/',
dataType: 'json',
success: function(response) {
$loading.hide();
if (response.error) {
showError(response.error);
} else {
$results.show();
showTraits(response);
showTextSummary(response);
showVizualization(response);
}
}
UPDATE:
I've tried a few different things matching your suggestions. Here is where I am now, any ideas?
consumer_token = 'aaaaaaaaaaaaaaaaaaaaaaaaa' #substitute values from twitter website
consumer_secret = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
access_token = '3473558363-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
access_secret = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
auth = tweepy.OAuthHandler(consumer_token,consumer_secret)
auth.set_access_token(access_token,access_secret)
api = tweepy.API(auth)
class PersonalityInsightsService:
"""Wrapper on the Personality Insights service"""
def __init__(self, vcapServices):
"""
Construct an instance. Fetches service parameters from VCAP_SERVICES
runtime variable for Bluemix, or it defaults to local URLs.
"""
self.url = "https://gateway.watsonplatform.net/personality-insights/api"
self.username = "aaaaaa-vvvv-1111-2222-mmmmmmmm"
self.password = "password"
if vcapServices is not None:
print("Parsing VCAP_SERVICES")
services = json.loads(vcapServices)
svcName = "personality_insights"
if svcName in services:
print("Personality Insights service found!")
svc = services[svcName][0]["credentials"]
self.url = svc["url"]
self.username = svc["username"]
self.password = svc["password"]
else:
print("ERROR: The Personality Insights service was not found")
def getProfile(self, text):
"""Returns the profile by doing a POST to /v2/profile with text"""
if self.url is None:
raise Exception("No Personality Insights service is bound to this app")
response = requests.post(self.url + "/v2/profile",
auth=(self.username, self.password),
headers = {"content-type": "text/plain"},
data=text
)
try:
return json.loads(response.text)
except:
raise Exception("Error processing the request, HTTP: %d" % response.status_code)
class DemoService(object):
"""
REST service/app. Since we just have 1 GET and 1 POST URLs,
there is not even need to look at paths in the request.
This class implements the handler API for cherrypy library.
"""
screen_name = "realDonaldTrump"
maxnumtweets= 500
saveFile = open("static/public/text/en.txt",'a')
saveFile.seek(0)
saveFile.truncate()
for status in tweepy.Cursor(api.user_timeline,id=screen_name).items(maxnumtweets):
print status.text[0:2] + '\n'
saveFile = open("static/public/text/en.txt",'a')
textyt = status.text
texty = ''.join(i for i in textyt if ord(i)<128)
saveFile.write(texty.encode('utf-8')+'\n'+'\n')
saveFile.close()
def __init__(self, service):
self.service = service
self.defaultContent = None
try:
contentFile = open("static/public/text/en.txt", "r")
self.defaultContent = contentFile.read()
except Exception as e:
print "ERROR: couldn't read text file: %s" % e
finally:
contentFile.close()
def GET(self):
return render_template('newin.html', content= self.defaultContent)
def POST(self, text=None):
"""
Send 'text' to the Personality Insights API
and return the response.
"""
try:
profileJson = self.service.getProfile(text)
return json.dumps(profileJson)
except Exception as e:
print "ERROR: %s" % e
return str(e)
#app.route('/')
def main():
return render_template('index.html')
#app.route('/getpost', methods=['GET', 'POST'])
def new():
personalityInsights = PersonalityInsightsService(os.getenv("VCAP_SERVICES"))
c = DemoService(personalityInsights)
if request.method == 'GET':
return c.GET()
elif request.method == 'POST':
return c.POST()
This isn't a Javascript issue. The view function that is serving the root URL is not configured to accept POST requests. Response code 405 is METHOD NOT ALLOWED (the method here being POST as opposed to GET, PUT, DELETE, OPTIONS, HEAD, etc...
I'm able to recreate it with a very simple hello world Flask app
app.py:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World'
if __name__ == '__main__':
app.run(debug=True)
Running the app from the command line (will be made available at http://localhost:5000/):
python app.py
and then trying to post against it from another terminal (using the requests library):
import requests
response = requests.post('http://localhost:5000/', data='')
print response will yield:
<Response [405]>
Note the 405 - the same response code you received, method not allowed. You need to explicitly define any methods other than GET that you want your Flask views to use by updating the app.route decorator:
#app.route('/', methods=['GET', 'POST'])
def hello_world():
return 'Hello World'
Generally however, you'll want to implement different functionality if a client does a POST instead of a GET. You can do this by looking at the request.method (you'll also need to import request):
from flask import Flask, request
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def hello_world():
if request.method == 'GET':
return 'You GOT hello world'
elif request.method == 'POST':
return 'You POSTed hello world'
if __name__ == '__main__':
app.run(debug=True)
If you'd like to read more about the different HTTP methods, they are defined here.

Python requsts.post returning 405 error: The method is not allowed for the requested URL

Howdie do,
I'm just running a simple flask API call.
The flask API will take a XML request in and then parse the XML and print it to the terminal screen.
However, everytime I do this, I'm receiving
The method is not allowed for the requested URL
The Flask script is:
__author__ = 'Jeremy'
from flask import Flask
from flask import request
import xmltodict
app = Flask(__name__)
#app.route('/', methods=['POST'])
def parsexml():
xmlrequest = xmltodict.parse(request.data)
print xmlrequest
if __name__ == '__main__':
app.run()
The script that sends the XML is:
__author__ = 'Jeremy'
import requests
xml = """
<dtc:GetShipmentUpdates>
<dtc:GetShipmentUpdatesRequest>
<dtc:SearchStartTime>2015-07-12T12:00:00</dtc:SearchStartTime>
<dtc:SearchEndTime>2015-07-12T12:30:00</dtc:SearchEndTime>
</dtc:GetShipmentUpdatesRequest>
</dtc:GetShipmentUpdates> """
headers = {'Content-Type': 'application/xml'}
r = requests.post('http://127.0.0.1:5000/', data=xml, headers=headers)
print r.content
Does anyone know why this is happening and if so, how can I send a POST request to my flask application running on 127.0.0.1:5000
You aren't returning anything from parsexml. Try returning some content:
#app.route('/', methods=['POST'])
def parsexml():
xmlrequest = xmltodict.parse(request.data)
print xmlrequest
return "Thanks for the data!"
Howdie do,
You can't send POST requests to /
So I changed it to go to the following:
__author__ = 'Jeremy'
from flask import Flask
from flask import request
import xmltodict
app = Flask(__name__)
#app.route('/')
def say_hello():
return "Say goodbye Jeremy"
#app.route('/api', methods=['POST'])
def parsexml():
xmlrequest = xmltodict.parse(request.data)
return xmlrequest
if __name__ == '__main__':
app.run(host='0.0.0.0', port=int("80"))
Work now

Categories