Dialog webhookStatus:
"webhookStatus": {
"code": 14,
"message": "Webhook call failed. Error: UNAVAILABLE."
Nginx log/access:
[11/Aug/2020:06:29:59 +0000] "POST /webhook HTTP/1.1" 500 57357 "-" "Google-Dialogflow"
My urls.py code is
path('webhook/', haniumapp.views.webhook, name='webhook'),
And here is my view.py code:
# Intent name is Welcome.
def welcome():
# JSON response.
response = {
'fulfillmentText' : 'welcome!! nice to meet you.'
}
return JsonResponse(response, safe=False)
# HERE is webhook service
#csrf_exempt
def webhook(request):
if request.method == 'POST':
req = json.loads(request.body)
#get request.action
action = req.get('queryResult').get('action')
#get request.param
params = req.get('queryResult').get('parameters')
# move action
if action == 'welcome':
return welcome()
I cannot figure out why my Dialogflow webhookStatus is UNAVAILABLE.
I use a nginx-uwsgi-django server. At least the call as such seems to work. For example: mywebsite/webhook is working just fine. It also works with https.
I use nohup to start django and get nohup.out (logging txt?)
In nohup.out, post is come!
That means
dialogflow -> nginx -> django (ok)
But there is a tabspaceerror at view.py
def webhook
So i fix And it works!!!
To fix error, try to check log
Related
I have created a route with type Json in odoo 14.
#http.route('/test', auth='public', methods=['POST'], type="json", csrf=False)
def recieve_data(self, **kw):
headers = request.httprequest.headers
args = request.httprequest.args
data = request.jsonrequest
So when I receive request using this route everything is fine, but suppose I want to return a different status code like 401, I could not do that with the route which type is json.
I have also tried the bellow method but the problem with this method is that it stops all odoo future requests.
from odoo.http import request, Response
#http.route('/test', auth='public', methods=['POST'], type="json", csrf=False)
def recieve_data(self, **kw):
headers = request.httprequest.headers
args = request.httprequest.args
data = request.jsonrequest
Response.status = "401 unauthorized"
return {'error' : 'You are not allowed to access the resource'}
So in the above example If I set the response status code to 401 all other requests even if they are to different routes will be stopped and its status code changes 401 .
I have checked this problem in both odoo14 and odoo13.
You cannot specify the code of the response, as you can see the status code is hardcoded in http.py:
def _json_response(self, result=None, error=None):
# ......
# ......
return Response(
body, status=error and error.pop('http_status', 200) or 200,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
If the result is not an error the status code is always 200. but you can change the code of the method directly or use a monkey patch witch if it's not really important to specify the code of status in the result don't do ti ^^.
A simple monkey patch put this in __init__.py of the module that you want this behavior in it.
from odoo.http import JsonRequest
class JsonRequestPatch(JsonRequest):
def _json_response(self, result=None, error=None):
response = {
'jsonrpc': '2.0',
'id': self.jsonrequest.get('id')
}
default_code = 200
if error is not None:
response['error'] = error
if result is not None:
response['result'] = result
# you don't want to remove some key of another result by mistake
if isinstance(response, dict)
defautl_code = response.pop('very_very_rare_key_here', default_code)
mime = 'application/json'
body = json.dumps(response, default=date_utils.json_default)
return Response(
body, status=error and error.pop('http_status', defautl_code ) or defautl_code,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
JsonRequest._json_response = JsonRequestPatch._json_response
and in the result of JSON api you can change the code of status like this
def some_controler(self, **kwargs):
result = ......
result['very_very_rare_key_here'] = 401
return result
The risk in monkey patching is you override the method compeletly and if some change is done in Odoo in new version you have to do you it in your method too.
The above code is from odoo 13.0 I did a lot of this when I build a restfull module to work with a website uses axios witch don't allow sending body in GET request. and odoo expect the argument to be inside the body in json request.
I've added a Webhooks listener to a Discord bot, and I'm trying to use that to post notifications to a text channel when a new video is uploaded (trying to eliminate my reliance on MEE6). When I subscribe to notifications at https://pubsubhubbub.appspot.com/subscribe, I get a 200 response, and my server's console prints
66.249.84.174 - - [27/Apr/2021 05:23:51] "GET /webhooks?hub.topic=https://www.youtube.com/xml/feeds/videos.xml%3Fchannel_id%<THE_CHANNEL_ID_I_WANT_NOTIFICATIONS_FOR>&hub.challenge=<A_BUNCH_OF_NUMBERS>&hub.mode=subscribe&hub.lease_seconds=432000 HTTP/1.1" 200 -
However, when a video gets uploaded nothing happens.
I've tried manually triggering a POST request from PostMan to the same endpoint (with the XML body found here https://developers.google.com/youtube/v3/guides/push_notifications as the raw->xml body text), and that seems to hit my console and return a 200, but I'm at a loss as to why I'm not getting any indication when an upload goes up. Code below:
from flask import Flask, Response, request
app = Flask(__name__)
#app.route('/webhooks', methods=['POST'])
def respond():
print(request.json);
return Response(status=200)
#app.route('/webhooks')
def index():
print(('request', request))
print('args:', request.args) # display text in console
print('form:', request.form)
print('data:', request.data)
print('json:', request.json)
print('files:', request.files)
return request.args.get('data', 'none') # send text to web browser
if __name__ == '__main__':
app.run(host='0.0.0.0', port=<MY_PORT>)
I'm hosting on PebbleHost, which is why the host is set to 0.0.0.0; there's a separate IP I'm connecting to for the subscriptions, mapped to a dedicated port. I'm quite new to Webhooks, and this is my first time interacting with the YouTube API, so I'm certain there's something really obvious I'm overlooking.
You have to return hub.challenge for confirmation on subscription.
A Working Example that I made earlier.
from flask import Flask, request
import xmltodict
app = Flask(__name__)
#app.route("/callback", methods=['POST', 'GET'])
def callback():
if request.method == 'POST':
data = xmltodict.parse(request.data)
print(data)
return request.data
else:
return request.args.get('hub.challenge')
app.run('0.0.0.0')
I have created a messenger chatbot with flask, pymessenger and wit.ai.
I want to add facebook provided templates (like buttons, adding images and sound media)(https://developers.facebook.com/docs/messenger-platform/reference/template/button/)
There using some curl and json thing which I do not understand. Can some one help me, where should I put these snippet in my python code.
#app.route('/', methods=['POST'])
def webhook():
data = request.get_json()
log(data)
if data['object'] == 'page':
for entry in data['entry']:
for messaging_event in entry['messaging']:
sender_id = messaging_event['sender']['id']
recipient_id = messaging_event['recipient']['id']
if messaging_event.get('message'):
if 'text' in messaging_event['message']:
messaging_text = messaging_event['message']['text']
else:
messaging_text = 'no text'
response = None
entity, value = wit_response(messaging_text)
if entity == 'newstype':
response = "OK. I will send you {} news".format(str(value))
elif entity == 'cust_greet':
response = get_message()
elif entity == 'cust_bye':
response = "Bye! Have a Good Day!".format(str(value))
elif entity == 'cust_option':
response = "Option 1: Option 2:"
bot.send_text_message(sender_id, response)
return "ok", 200
def log(message):
print(message)
sys.stdout.flush()
HTTP requests use one of these two formats:
GET: All the request information is in the url
POST: Some information is sent via a JSON format to the url
What we see in the Facebook API is a POST request: the url is defined as
https://graph.facebook.com/v2.6/me/messages?access_token=<PAGE_ACCESS_TOKEN>
...and there is POST request information in the JSON section underneath
Curl is a program used to send HTTP requests from the terminal. If you install Curl, you can fill in the JSON/url information, run the command (which sends the POST request), and see the buttons pop up for the recipient. Just as you want your chatbot to do!
However, Curl is a tool, not a Python library!
To do this in Python, you can send the request through Python's built in libraries, or install a package which makes this easier (such as requests), look into "sending http requests via python".
Below is an example (adapted from this question):
from urllib.parse import urlencode
from urllib.request import Request, urlopen
# the url we are sending the request to
url = "https://graph.facebook.com/v2.6/me/..."
# the POST request data
request_data = {
"recipient": {
"id": "<PSID>"
},
"message": {
"attachment": {
...
}
}
}
# create the request with the url and the data
post_request = Request(url, urlencode(request_data).encode())
# send it to Facebook! Response is the API response from Facebook
response = urlopen(post_request).read().decode()
I am creating a self built Python chatbot that does not use a chatbot platform such as Dialogflow. The issue is that there is no easy integration with messaging apps such as Messenger to connect it too. I am trying to create a webhook to Messenger using the Messenger Send API. I am looking at the documentation and it shows me how to request a POST api call. However when I look at examples online they all seem to deal with json values called "entry" and "messaging" which I can't find anywhere and can't seem to see why it is necessary. I was wondering how exactly the input body of a Messenger Send API looks like so I can call it appropriately and what json objects are in its body. This is what I have so far from following online examples. I am using Flask. And am using Postman to test this
#app.route("/webhook", methods=['GET','POST'])
def listen():
if request.method == 'GET':
return verify_webhook(request)
if request.method == 'POST':
payload = request.json
event = payload['entry'][0]['messaging']
for x in event:
if is_user_message(x):
text = x['message']['text']
sender_id = x['sender']['id']
respond(sender_id, text)
return "ok"
Below is what I think the body of the request looks like:
{
"object":"page",
"entry":[
{
"id":"1234",
"time":1458692752478,
"messaging":[
{
"message":{
"text":"book me a cab"
},
"sender":{
"id":"1234"
}
}
]
}
]
}
But it is unable to read this and gives me an error of:
File"/Users/raphael******/Documents/*****_Project_Raphael/FacebookWebHookEdition.py", line 42, in listen
event = payload['entry'][0]['messaging']
TypeError: 'NoneType' object is not subscriptable
Where am I going wrong that the webhook is not registering the body correctly as json objects?
Here is how we do it:
# GET: validate facebook token
if request.method == 'GET':
valid = messenger.verify_request(request)
if not valid:
abort(400, 'Invalid Facebook Verify Token')
return valid
# POST: process message
output = request.get_json()
if 'entry' not in output:
return 'OK'
for entry in output['entry']:
if 'messaging' not in entry:
continue
for item in entry['messaging']:
# delivery notification (skip)
if 'delivery' in item:
continue
# get user
user = item['sender'] if 'sender' in item else None
if not user:
continue
else:
user_id = user['id']
# handle event
messenger.handle(user_id, item)
# message processed
return 'OK'
EDIT:
If you are using postman, please make sure to also set Content-Type header to application/json, otherwise Flask can't decode it with request.json. I guess that's where None comes from in your case.
I have a flask app deployed to Heroku and would like to receive text from Chatfuel (bot building platform) and send back texts in return.
Now, what I did is to use my heroku app as a web-hook, so that Chatfuel can make a simple GET or POST query to my API. The problem is that I have no experience with Flask or APIs, so I am not sure about how my app can receive information (in json format) and send it back to chatfuel.
This is what I wrote so far:
import os
import sys
import json
import requests
from flask import Flask, jsonify, render_template, 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("/json", methods=['GET','POST'])
def json():
url = "chatfuel_api"
data = json.load(urllib2.urlopen(url))
if request.json:
mydata = request.json
return "Thanks",200
else:
return "no json received"
#app.route('/hello', methods = ['GET','POST'])
def api_echo():
if request.method == 'GET':
return "ECHO: GET\n",200
if __name__ == '__main__':
app.run(debug=True)
The verify() function works, as I see an 'Hello world' message if I run the app locally. However, both json() and api_echo() don't work, and when my server receives a get or post request from chatfuel, it returns a 404 error.
As you can see, I really have a lot of confusion, and your help would be really invaluable.
Thanks
You need to make sure you have registered the proper webhook url with Chatfuel. For the code you currently have, to hit the json endpoint the url would be https://www.your_server.com/json
The verify route looks like the hub challenge FB sends, so you would have to register the root of your site (that is, with your current code) with FB to hit the verify function. That url would look like this https://www.your_site.com/