Can't get the response from webhook - python

I created a webhook using python ( using this example) for my project in api.ai
My code is here :
#!/usr/bin/env python
import urllib
import json
import os
from flask import Flask
from flask import request
from flask import make_response
# Flask app should start in global layout
app = Flask(__name__)
#app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json(silent=True, force=True)
print("Request:")
print(json.dumps(req, indent=4))
res = makeWebhookResult(req)
res = json.dumps(res, indent=4)
print(res)
r = make_response(res)
r.headers['Content-Type'] = 'application/json'
return r
def makeWebhookResult(req):
if req.get("result").get("action") != "delivery.info":
return {}
result = req.get("result")
parameters = result.get("parameters")
parcelnr = parameters.get("parcelnumber")
parcelinfo = {'5000':'your parcel has been shipped', '5001':'your parcel has
not been shipped', '5002':'should be delivered on three days', '5003':'your
parcel has not been shipped', '5004':'your parcel has been shipped'}
speech = "Parcel with numner" + parcelnr + " is " +
str(parcelinfo[parcelnr]) "
print("Response:")
print(speech)
return {
"speech": speech,
"displayText": speech,
#"data": {},
# "contextOut": [],
"source": "apiai-debot"
}
if __name__ == '__main__':
port = int(os.getenv('PORT', 5000))
print "Starting app on port %d" % port
app.run(debug=True, port=port, host='0.0.0.0')
Api agent is :
image1
image2
I don't understand where i'm wrong.
My agent work ok, but when i ask the bot to get info from the webhook i get the text response from api.ai not from webhook.
Can you help me please ?

The following is working for me. request.data will be receiving message alerts from the TradingView webhook message.
#app.route('/webhook', methods=['POST'])
def webhook():
print("\nrequest.data={}".format(request.data))
return request.data
In TradingView Alert Message, I am using following...
exchange = {{exchange}}, ticker = {{ticker}}, price = {{close}}, volume = {{volume}}
...and I am getting following message in logs:
$ heroku logs --tail
2022-01-12T20:38:00.510006+00:00 app[web.1]: request.data=b'exchange = BINANCE, ticker = BTCUSDT, price = 43671.85, volume = 10.70612'
2022-01-12T20:38:00.510512+00:00 app[web.1]: 10.1.58.75 - - [12/Jan/2022:20:38:00 +0000] "POST /webhook HTTP/1.1" 200 73 "-" "Go-http-client/1.1"

You are using the wrong url for the webhook in the fulfillment.
Your code is mapping the request to /webhook, while your url is https://your-domain.com/debotwebhook.
Either change #app.route('/webhook', methods=['POST']) to #app.route('/debotwebhook', methods=['POST']) or change the url in api.ai to https://your-domain.com/webhook
Also, I see an extra " in your speech variable after str(parcelinfo[parcelnr]).
Here is the agent I tested with your code and on the right you can see the answer:

Related

I am seeing this error in server.py file, " The browser (or proxy) sent a request that this server could not understand."

Here I am attaching my server.py and util.py
I have trained a model, and now wish to print the data on user's demand.
server.py
from flask import Flask, request, jsonify
#from waitress import serve
import util
import json
#%run util.ipynb
app = Flask(__name__)
#app.route('/hi')
def hi():
return util.areas()
#app.route('/locations')
def locations():
response = jsonify({
'locations': util.locations()
})
response.headers.add('Access-Control-Allow-Origin', '*')
return response
#app.route('/predict_home_price', methods=['GET', 'POST'])
def predict_home_price():
total_sqft = float(request.form['total_sqft'])
location = request.form['location']
size = int(request.form['size'])
bath = int(request.form['bath'])
area_type = request.form['area_type']
balcony = int(request.form['balcony'])
response = jsonify({
'estimated_price': util.get_estimated_price(area_type, location, size, total_sqft, bath, balcony)
})
response.headers.add('Access-Control-Allow-Origin', '*')
return response
if __name__ == '__main__':
print('python flask started')
app.run()
#serve(app, host='0.0.0.0', port=50100, threads=1)
util.py
import json
import joblib
import numpy as np
__locations = None
__area = None
__model = None
def get_estimated_price(area_type, location, size, total_sqft, bath, balcony):
x = np.zeros(6)
x[0] = __area.index(area_type)
x[1] = __locations.index(location)
x[2] = size
x[3] = total_sqft
x[4] = bath
x[5] = balcony
return round(__model.predict([x])[0][0],2)
def locations():
return __locations
def areas():
return __area
def load_saved_artifacts():
print("loading saved artifacts...start")
global __data_columns
global __locations
global __area
with open('./artifacts/locations.json','r') as f:
__locations = json.load(f)['data_locations']
with open('./artifacts/area.json','r') as f:
__area = json.load(f)['data_area']
global __model
__model = joblib.load('./artifacts/Banglore_Real_State_Price')
print(" loading artifacts is done")
if __name__ == '__main__':
load_saved_artifacts()
#print(locations())
#print(areas())
print(get_estimated_price('Super built-up Area','Electronic City Phase II',2,1056,2,1))
print(get_estimated_price('Built-up Area','Uttarahalli',3,1440,2,3))
print(get_estimated_price('Super built-up Area','Lingadheeranahalli',3,1521,3,1))
print(get_estimated_price('Super built-up Area','Kothanur',2,1200,2,1))
Immediate help is really appreciated
I have trained a model, and now wish to print the data on user's demand.
I am seeing this error in server.py file, " The browser (or proxy) sent a request that this server could not understand." I checked everything works fine if I am sending data to browser but not when asking for the data, I tried Postman for sending the data.
http://127.0.0.1:5000/predict_home_price -> shows bad request.
http://127.0.0.1:5000/locations -> shows correct data
http://127.0.0.1:5000/hi -> shows correct data
As you mentioned, when you're sending data to the server it works, and that's because you're using a POST request and the request has form data in it.
But when you're "asking for data", you're probably using a GET request, which has no form data in it, and that's why the server responses with an error.
You can modify your code so you can decide what you should do for each type of request:
#app.route('/predict_home_price', methods=['GET', 'POST'])
def predict_home_price():
if request.method == "POST":
# get form data and do something with it
elif request.method == "GET":
# return some value, without looking for form data

customize length of the password in dialogflow chatbot using regex entity

length of the password must be at least 6 characters while signing up using Dialogflow chatbot.
I have used system entity "any". But it is so generalized.
Webhook is written in flask python.
Also tried to do it by using [0-9]{6}$ as a regex entity. But unable to find a proper way to perform this task.
from dialogflow_fulfillment import QuickReplies, WebhookClient, Payload
from flask import Flask, request, Response, jsonify , make_response
import json
import requests
app = Flask(__name__)
def handler(agent: WebhookClient) :
"""Handle the webhook request.."""
req = request.get_json(force=True)
intent_name = req.get('queryResult').get('intent').get('displayName')
if intent_name == 'intro':
agent.add('I am the chatbot of this page. Ready to assist you with anything you need. What would you like to do?')
agent.add(QuickReplies(quick_replies=['START NOW','LOGIN']))
if intent_name == 'get_started':
url = 'http://**********.com/create_account'
userid = req.get('queryResult').get('parameters').get('email')
print(userid)
pwd = req.get('queryResult').get('parameters').get('pwd')
print(pwd)
name = req.get('queryResult').get('parameters').get('person')['name']
print(name)
age = req.get('queryResult').get('parameters').get('age')
print(age)
myobj = {'userid': userid, 'pwd': pwd , 'name' : name, 'age' : age}
x = requests.post(url, data = myobj)
result=x.text
agent.add(result)
if intent_name == 'login_screen' :
url = 'http://**********.com/auth_account'
userid = req.get('queryResult').get('parameters').get('email')
print(userid)
pwd = req.get('queryResult').get('parameters').get('pwd')
print(pwd)
myobj = {'userid': userid, 'pwd': pwd }
x = requests.post(url, data = myobj)
result = x.text
agent.add(result)
#app.route('/webhook', methods=['GET', 'POST'])
def webhook():
"""Handle webhook requests from Dialogflow."""
req = request.get_json(force=True)
agent = WebhookClient(req)
agent.handle_request(handler)
return agent.response
if __name__ == '__main__':
app.run(debug=True)
With regex :
Defined regex :
How to do this properly?
How to use regex in it?
Or should i use another approach?

Python flask returns 405 error when using twitter api

I am using python and I apologize as this is probably a very simple concept that I am not grasping but I am not very familiar with the flask framework. Right now I'm making a server with flask but run into a 405 error every time I try to do something with the twitter api shortly after. Right now my code looks something like this
In a separate file:
from flask import Flask
from threading import Thread
app = Flask('')
#app.route('/', methods=['GET', 'POST', 'DELETE'])
def home():
return "Hello world!"
def run():
app.run(host='0.0.0.0',port=8080)
app.run(debug=True, host="0.0.0.0")
def keep_alive():
t = Thread(target=run)
t.start()
Then I call my code in the main file:
from flaskfile import flask_file
flask_file()
MEDIA_ENDPOINT_URL = 'https://upload.twitter.com/1.1/media/upload.json'
POST_TWEET_URL = 'https://api.twitter.com/1.1/statuses/update.json'
CONSUMER_KEY = consumerkey
CONSUMER_SECRET = secret
ACCESS_TOKEN = accesstoken
ACCESS_TOKEN_SECRET = tokensecret
#fileName = check_and_download()
VIDEO_FILENAME = (filename)
oauth = OAuth1(CONSUMER_KEY,
client_secret=CONSUMER_SECRET,
resource_owner_key=ACCESS_TOKEN,
resource_owner_secret=ACCESS_TOKEN_SECRET)
class VideoTweet(object):
def __init__(self, file_name):
'''
Defines video tweet properties
'''
self.video_filename = file_name
self.total_bytes = os.path.getsize(self.video_filename)
self.media_id = None
self.processing_info = None
def upload_init(self):
'''
Initializes Upload
'''
print('INIT')
request_data = {
'command': 'INIT',
'media_type': 'video/mp4',
'total_bytes': self.total_bytes,
'media_category': 'tweet_video'
}
req = requests.post(url=MEDIA_ENDPOINT_URL, data=request_data, auth=oauth)
media_id = req.json()['media_id']
self.media_id = media_id
print('Media ID: %s' % str(media_id))
def upload_append(self):
'''
Uploads media in chunks and appends to chunks uploaded
'''
segment_id = 0
bytes_sent = 0
file = open(self.video_filename, 'rb')
while bytes_sent < self.total_bytes:
chunk = file.read(4*1024*1024)
print('APPEND')
request_data = {
'command': 'APPEND',
'media_id': self.media_id,
'segment_index': segment_id
}
files = {
'media':chunk
}
req = requests.post(url=MEDIA_ENDPOINT_URL, data=request_data, files=files, auth=oauth)
if req.status_code < 200 or req.status_code > 299:
print(req.status_code)
print(req.text)
sys.exit(0)
segment_id = segment_id + 1
bytes_sent = file.tell()
print('%s of %s bytes uploaded' % (str(bytes_sent), str(self.total_bytes)))
print('Upload chunks complete.')
def upload_finalize(self):
'''
Finalizes uploads and starts video processing
'''
print('FINALIZE')
request_data = {
'command': 'FINALIZE',
'media_id': self.media_id
}
req = requests.post(url=MEDIA_ENDPOINT_URL, data=request_data, auth=oauth)
print(req.json())
self.processing_info = req.json().get('processing_info', None)
self.check_status()
def check_status(self):
'''
Checks video processing status
'''
if self.processing_info is None:
return
state = self.processing_info['state']
print('Media processing status is %s ' % state)
if state == u'succeeded':
return
if state == u'failed':
sys.exit(0)
check_after_secs = self.processing_info['check_after_secs']
print('Checking after %s seconds' % str(check_after_secs))
time.sleep(check_after_secs)
print('STATUS')
request_params = {
'command': 'STATUS',
'media_id': self.media_id
}
req = requests.get(url=MEDIA_ENDPOINT_URL, params=request_params, auth=oauth)
self.processing_info = req.json().get('processing_info', None)
self.check_status()
def tweet(self):
'''
Publishes Tweet with attached video
'''
request_data = {
#leave status blank
'status': '',
'media_ids': self.media_id
}
req = requests.post(url=POST_TWEET_URL, data=request_data, auth=oauth)
print(req.json())
if __name__ == '__main__':
videoTweet = VideoTweet(VIDEO_FILENAME)
videoTweet.upload_init()
videoTweet.upload_append()
videoTweet.upload_finalize()
videoTweet.tweet()
The error returned states the following:
"Error response
Error code: 405
Message: Method Not Allowed.
Error code explanation: 405 - Specified method is invalid for this resource."
Basically I call the flask file then use twitter api to upload a file, but for some reason using the twitter api always results in a 405 error and my flask server is no longer accessible. How can I adjust my flask file to allow me to upload using the api?
405 errors are thrown when the wrong request method is used. For example a POST request being sent when a GET request was expected, or a GET request being sent when a POST request was expected.
In your check_status function you have
req = requests.get(url=MEDIA_ENDPOINT_URL, ...
But according to Twitter's documentation you should be using a post request here
req = requests.post(url=MEDIA_ENDPOINT_URL, ...

Function that should upload and deploy web-app doesn't work correctly

I was given the task (re)deploy web-application on AS wildfly through http rest appi.
Function works, but there is problem.
So function:
def upload_and_deploy(server, app):
try:
pass
files = {'file': open(distr_path + '/app-01.001.02-028.war', 'rb')}
response = requests.post('http://' + server + ':9990/management/add-content', files=files, auth=HTTPDigestAuth('login', 'password')).text
response_converted_to_json = json.loads(response)
bytes_value_from_response = response_converted_to_json["result"]["BYTES_VALUE"]
json_start = '{"content":[{"hash": {"BYTES_VALUE" : "'
json_end = '"}}], "address": [{"deployment":"'+ app + '"}], "operation":"add", "enabled":"true"}'
full_json_for_deploy_request = json_start+bytes_value_from_response+json_end
print '>>>>>>', full_json_for_deploy_request
response = requests.post('http://' + server + ':9990/management', auth=HTTPDigestAuth('login', 'password'), data= (full_json_for_deploy_request), headers=headers)
print "Start", app, "code -", response.status_code
except requests.exceptions.ConnectionError:
print 'Server - %s not run' % server
Result looks good:
>>>>>> {"content":[{"hash": {"BYTES_VALUE" : "t3W62oVUihsqyINy9rRG/T3DuI4="}}], "address": [{"deployment":"app-name"}], "operation":"add", "enabled":"true"}
Start app-name code - 200
AS logs looks not typical, but without errors:
2017-10-09 10:07:07,688 INFO [org.jboss.as.repository] (XNIO-1 task-9) WFLYDR0001: Content added at location /opt/platform/wildfly-9.0.2.Final/standalone/data/content/b7/75bada85548a1b2ac88372f6b446fd3dc3b88e/content
2017-10-09 10:07:07,704 INFO [org.jboss.as.server.deployment] (MSC service thread 1-4) WFLYSRV0027: Starting deployment of "app-name" (runtime-name: "app-name")
2017-10-09 10:07:07,983 INFO [org.jboss.as.server] (XNIO-1 task-2) WFLYSRV0010: Deployed "app-name" (runtime-name : "app-name")
So application is running, but not working.
Can somebody give me a cue, what's wrong with it?
The deployment name needs to end in a valid archive extension so the appropriate processing happens. In your case it should end in .war.
The json_end should look something like the following.
json_end = '"}}], "address": [{"deployment":"'+ app + '.war"}],"operation":"add", "enabled":"true"}'

Facebook Messenger Chatbot Code - UnboundLocalError

Using the following code, I've setup a flask app:
https://gist.github.com/ugik/a218a599b1af0ea06b1b38e3a5132078#file-flaskfbmapi-ai-rig
import requests
import json
from flask import Flask, request
import apiai
# FB messenger credentials
ACCESS_TOKEN = "EAAKsKOJ37rUBAKVZAQ21bn...UsZCXx6UWqQ6XuQr7OHnBYL3xD3Sy5u1ZAZCwip0XnTAHq25CsIpxRsbxZALRHOOguKm2unY7I06LRAZDZD"
# api.ai credentials
CLIENT_ACCESS_TOKEN = "78c0e0...d9404a2"
ai = apiai.ApiAI(CLIENT_ACCESS_TOKEN)
app = Flask(__name__)
#app.route('/', methods=['GET'])
def verify():
# our endpoint echos back the 'hub.challenge' value specified when we setup the webhook
if request.args.get("hub.mode") == "subscribe" and request.args.get("hub.challenge"):
if not request.args.get("hub.verify_token") == 'foo':
return "Verification token mismatch", 403
return request.args["hub.challenge"], 200
return 'Hello World (from Flask!)', 200
def reply(user_id, msg):
data = {
"recipient": {"id": user_id},
"message": {"text": msg}
}
resp = requests.post("https://graph.facebook.com/v2.6/me/messages?access_token=" + ACCESS_TOKEN, json=data)
print(resp.content)
#app.route('/', methods=['POST'])
def handle_incoming_messages():
data = request.json
sender = data['entry'][0]['messaging'][0]['sender']['id']
message = data['entry'][0]['messaging'][0]['message']['text']
# prepare API.ai request
req = ai.text_request()
req.lang = 'en' # optional, default value equal 'en'
req.query = message
# get response from API.ai
api_response = req.getresponse()
responsestr = api_response.read().decode('utf-8')
response_obj = json.loads(responsestr)
if 'result' in response_obj:
response = response_obj["result"]["fulfillment"]["speech"]
reply(sender, response)
return "ok"
if __name__ == '__main__':
app.run(debug=True)
However, at line 51 there is an error in my server logs:
UnboundLocalError: local variable 'response' referenced before
assignment
Which I understand the root of the cause is "response" is defined only within the if statement, however, since it is not my code, I'm having trouble defining the variable outside. Will this work if I place this code after line 48:
response = response_obj["result"]["fulfillment"]["speech"]

Categories