directline v3 gives error 400 - python

In the Step Sending an Activity to the bot As per the documentation Here,
https://docs.botframework.com/en-us/restapi/directline3/#navtitle
I should pass this as the body content of the post request
{
"type": "message",
"from": {
"id": "user1"
},
"text": "hello"
}
I am using the following parameters to make POST request in python, but its not working.
msg = {"type": "message","channelId": "directline","conversation":{"id": str(convId)},"from":{"id": "test_user1"},"text": "hello"}
header = {"Authorization":"Bearer q1-Tr4sRrAI.cwA.BmE.n7xMxGl-QLoT7qvJ-tNIcwAd69V-KOn5see6ki5tmOM", "Content-Type":"application/json", "Content-Length": "512"}
send2 = "https://directline.botframework.com/v3/directline/conversations/"+str(convId)+"/activities"
rsa1 = requests.post(send2,data=msg, headers=header)
This gives me this error:
{
"error": {
"code": "MissingProperty",
"message": "Invalid or missing activities in HTTP body"
}
}
Before this step everything is working fine.
Edit 1: Even i added content-length as updated in the code, it gives the same error
Edit 2: If i changed the msg to json.dumps(msg)
rsa1 = requests.post(send2,data=json.dumps(msg), headers=header)
I get response:
{u'error': {u'message': u'Failed to send activity: bot returned an error', u'code': u'ServiceError'}}
{
"error": {
"code": "ServiceError",
"message": "Failed to send activity: bot returned an error"
}
}
The directline API is only not working, on skype client everything is working fine.

According to the code that you've posted, your request body looks like this:
{
"type": "message",
"channelId": "directline",
"conversation": {
"id": str(convId)
},
"from": {
"id": "test_user1"
},
"text": "hello"
}
I'd suspect that your error is caused by the fact that the conversation ID value that you're including in the request body is not surrounded with double quotes in the JSON that's sent over the wire.
For simplicity (and to eliminate the error you're receiving), I'd suggest that you try omitting the channelId property and the conversation property from the request body, as I don't believe that either of these properties are necessary (i.e., you are issuing the request to the Direct Line URI, so the Bot Framework knows that Direct Line is the channel, and the conversation ID is already being specified in the request URI). In other words, try this as your request body:
{
"type": "message",
"from": {
"id": "test_user1"
},
"text": "hello"
}

When passing a dictionary to data it gets urlencoded automatically, so the api returns an error as it expects json data.
You can either use the json lib, or preferably pass your dictionary to the json parameter.
Using json.dumps :
rsa1 = requests.post(send2, data=json.dumps(msg), headers=header)
Using requests only :
rsa1 = requests.post(send2, json=msg, headers=header)
Also you don't have to add "Content-Length" in header and if you use the second example you don't have to add "Content-Type" either.

Related

SNS always sends default message instead of the specific protocol message that is given

Here is the code
message = {
"default":"Sample fallback message",
"http":{
"data":[
{
"type":"articles",
"id":"1",
"attributes":{
"title":"JSON:API paints my bikeshed!",
"body":"The shortest article. Ever.",
"created":"2015-05-22T14:56:29.000Z",
"updated":"2015-05-22T14:56:28.000Z"
}
}
]
}
}
message_as_json = json.dumps(message)
response = sns_client.publish(TopicArn = "arn:aws:sns:us-east-1:MY-ARN",
Message = message_as_json, MessageStructure = "json")
print(response)
To test, I used ngrok to connect the localhost (which runs my flask app) to the web and created a http subscription.
When I publish the message I can only see default message in that.
Any idea why this happens?
You need to specify the value of the http key as a simple JSON string value according to the AWS boto3 docs:
Keys in the JSON object that correspond to supported transport
protocols must have simple JSON string values.
Non-string values will cause the key to be ignored.
import json
import boto3
sns_client = boto3.client("sns")
message = {
"default": "Sample fallback message",
"http": json.dumps(
{
"data": [
{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON:API paints my bikeshed!",
"body": "The shortest article. Ever.",
"created": "2015-05-22T14:56:29.000Z",
"updated": "2015-05-22T14:56:28.000Z",
},
}
]
}
),
}
response = sns_client.publish(
TopicArn="arn:aws:sns:us-east-1:MY-ARN", Message=json.dumps(message), MessageStructure="json"
)

Sentiment Analysis using Google Cloud API in Python giving error

I'm trying to perform sentiment analysis using google NLP cloud API.
Below is my code
import requests
url = "https://language.googleapis.com/v1/documents:analyzeSentiment"
myobj = {
"key": "XYZ",
"document":{
"type":"PLAIN_TEXT",
"language": "EN",
"content":"'Lawrence of Arabia' is a highly rated film biography about British Lieutenant T. E. Lawrence. Peter O'Toole plays Lawrence in the film."
},
"encodingType":"UTF8",
"Content-Type": "application/json"
}
x = requests.post(url, data = myobj)
print(x.text)
But it is giving me error
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"Content-Type\": Cannot bind query parameter. Field 'Content-Type' could not be found in request message.\nInvalid JSON payload received. Unknown name \"document\": Cannot bind query parameter. 'document' is a message type. Parameters can only be bound to primitive types.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"Content-Type\": Cannot bind query parameter. Field 'Content-Type' could not be found in request message."
},
{
"description": "Invalid JSON payload received. Unknown name \"document\": Cannot bind query parameter. 'document' is a message type. Parameters can only be bound to primitive types."
}
]
}
]
}
}
Does anybody know why it is happening? Will appreciate any help. Thanks.
Use the json parameter instead of data:
x = requests.post(url, json=myobj)

How to change error format of all errors using Connexion + Tornado

I'm using Connexion (https://github.com/zalando/connexion) to make sure my openapi-specification is well-followed and to have easy integration points to connect my routes to the underlying functions.
In any case, the default error responses from Connexion are json responses following the Problem Details for HTTP APIs RFC. That is the following format, e.g.:
{
"detail": "None is not of type 'object'",
"status": 404,
"title": "BadRequest",
"type": "about:blank"
}
However, I would like to change the format of all errors sent to something like:
{
error: {
code: 400,
message: 'BadRequest',
detail: 'ID unknown'
innererror: {...}
}
}
I can not find any way to intercept every error to change the format of what is returned. I know I can extend the connection.exception.ProblemException class and add a dict to the extparameter in its constructor, but for any 400 error for example, I can't intercept it.
So, I know that it is possible to add error handlers for specific error codes, e.g.:
app.add_error_handler(404, error.normalize)
app.add_error_handler(400, error.normalize)
However, for the 404 handler I manage to successfully intercept the error. But for the 400 (e.g. a json validation error) - the interception does not work.
How can I intercept each and every error that is sent from Connexion and change the json format, even if it is just to extend it like:
{
"detail": "Could not find page",
"error": {
"code": 404,
"message": "Could not find requested document."
},
"status": 404,
"title": "NotFound",
"type": "about:blank"
}
I use Connexion, with a 'tornado' server.
Thanks in advance.
Tom
With the latest version (connexion==2.5.1) this works for me:
from connexion import ProblemException
[...]
connexion_app.add_error_handler(400, render_http_exception)
connexion_app.add_error_handler(404, render_http_exception)
connexion_app.add_error_handler(ProblemException, render_problem_exception)
My exception handling functions:
from flask import jsonify
def render_http_exception(error):
resp = {
'error': {
'status': error.name,
'code': error.code,
'message': error.description,
}
}
return jsonify(resp), error.code
def render_problem_exception(error):
resp = {
'error': {
'status': error.title,
'code': error.status,
'message': error.detail,
}
}
return jsonify(resp), error.status
You can easily change it to your format.

Outlook API email attachment issue

I am trying to use Outlook's REST API in my python code to send an email in behalf of a user who already gives me his consent.
I was able to successfully send text emails using their /me/sendmail node with the following payload:
email_payload = {
"Message": {
"Subject": email_subject,
"Body": {
"ContentType": "Text",
"Content": email_body
},
"ToRecipients": [
{
"EmailAddress": {
"Address": to
}
}
]
}
}
However, when trying to add attachments (based on their documentation), I encounter some issues:
email_payload["Message"]["Attachments"] = [
{
"ContentType": "application/pdf",
"Name": "{0}".format("something.pdf"),
"ContentBytes": base64.b64encode(attachment.read())
}
]
Issues consist in 415 response status code with the following content:
{u'error': {u'message': u'A missing or empty content type header was found when trying to read a message. The content type header is required.', u'code': u'RequestBodyRead'}}
Couldn't find anything regarding this in their documentation. Hope somebody can enlighten me :)
For anyone else having such issues, here's the context and fix:
Initially, since I was sending only plain-text emails, my request header looked like this:
request_headers = {
'Authorization': "Bearer {0}".format(token),
}
And the actual request:
api_response = requests.post(
request_url,
json.dumps(body),
headers=request_headers
)
As you might have noticed I wasn't sending any content-type in my headers (not sure why), but everything went well so far up until when I decided to add attachments too.
Seems like if my request_headers would contain Content-Type too, everything would go well:
request_headers = {
'Authorization': 'Bearer {0}'.format(refreshed_token),
'Content-Type': 'application/json'
}

PayPal Adaptive Payments - Preapproval request results in "Invalid request" error

I can't figure out what's happening with my Preapproval HTTP POST request. I'm just trying to do a basic call to PayPal's Adaptive Payments API, the Preapproval call specifically. And the PayPal error 580001 "Invalid request" is not that helpful in itself.
Request Headers (based on my Sandbox's account credentials, which I changed to xxx):
{
'X-PAYPAL-REQUEST-DATA-FORMAT': 'JSON',
'X-PAYPAL-SECURITY-PASSWORD': 'xxx',
'X-PAYPAL-RESPONSE-DATA-FORMAT': 'JSON',
'X-PAYPAL-SECURITY-SIGNATURE': 'xxx',
'X-PAYPAL-SECURITY-USERID': 'xx',
'X-PAYPAL-APPLICATION-ID': 'APP-80W284485P519543T'
}
My request payload (HTTP POST, body encoded in JSON):
{
"requireInstantFundingSource": "TRUE",
"returnUrl": "http://www.google.com/?paypal=ok",
"maxTotalAmountOfAllPayments": 1002,
"maxNumberOfPaymentsPerPeriod": 1,
"endingDate": "2014-03-14T16:49:36+0000",
"requestEnvelope.errorLanguage": "en_US",
"clientDetails.applicationId": "XXX",
"cancelUrl": "http://www.google.com/paypal=cancel",
"startingDate": "2013-09-15T16:49:36+0000",
"feesPayer": "PRIMARYRECEIVER",
"currencyCode": "SEK"
}
The above POST body is posted to:
https://svcs.sandbox.paypal.com/AdaptivePayments/Preapproval
Response from Paypal ("prettified" for understanding):
{
"responseEnvelope": {
"ack": "Failure",
"timestamp": "2013-09-10T09:56:43.031-07:00",
"build": "6941298",
"correlationId": "26d55e6bfcaa0"
},
"error": [
{
"category": "Application",
"domain": "PLATFORM",
"severity": "Error",
"message": "Invalid request: {0}",
"subdomain": "Application",
"errorId": "580001"
}
]
}
Any feedback is appreciated.
OK fixed. How?
Fix #1
The arguments requestEnvelope.errorLanguage and clientDetails.applicationId need to be "JSONified" into objects on their own, such as:
"requestEnvelope": {
"errorLanguage": "en_US"
},
and
"clientDetails": {
"applicationId": "APP-XXXXXXXXXXXXX"
},
respectively.
Fix #2
Date formats; date format should be of the form 2014-03-15T20:14:38.007+00:00 and not 2014-03-14T20:14:38+0000 as I was passing. Note the milliseconds, and the timezone with the colon in the utc offset.
Next time an Invalid request comes up the parameters I'm passing will be the first thing to look at.

Categories

Resources