I am learning flask Restful API, where I came upon RequestParser
wherein my example includes
data_put = reqparse.RequestParser(bundle_errors=True)
data_put.add_argument("username",type=str,help="Username not provided",location="json",required=True)
data_put.add_argument("new_password",type=str,help="New password not provided", location="json", required=True )
this above code snippet works great with username and new_password parameter and returns error message if any, as
{
"message": {
"username": "Username not provided",
}
}
this is great.
But is it possible to insert a user defined value into the response message,
for example, can I get a response as
{
"message": {
"username": "Username not provided",
"error_code": 1000
}
}
where value of error code will be a variable.
Yeah, you can remove the required from the .add_argument line, and the in the class, where you get the post/get after you do
args = data_put.parseargs()
You can check if there is the username in the args
if args["username"]:
return {"message": "Wrong username"}
And return a HTTP status or error code
Related
Right now, I'm making a PATCH request to https://discord.com/api/v9/users/#me.
f'https://discord.com/api/v9/users/#me',
json = {"username": name},
headers = self.headers(self.getCookies(), token, self.config['x-super-properties']),
proxy=self.proxy
This normally works (I have a bunch of other functions using the same layout) but I'm not exactly sure what to use as the JSON.
I'm thinking I need a password slot in the field but I don't have the password and I'm just using the token. This is the response I get when I log it in console:
{"code": 50035, "errors": {"password": {"_errors": [{"code": "PASSWORD_DOES_NOT_MATCH", "message": "Password does not match."}]}}, "message": "Invalid Form Body"}
How do I get multiple 'text answers' in whatsApp? When I add more than one 'text response' in intents they work normally in the dialogFlow console.
But when I repeat the same question on whatsapp I get only one answer box instead of 3, for example, that I had created.
I am using twilio to communicate with the whatsapp API. I also use Horoku cloud services to host the application.
Everything works normal. But I received only one message box instead of multiple in whatsapp.
I think the problem is my python code 'app.py'.
app.py
#app.route("/") #just to test Heroku cloud services
def hello():
return "Hello, World!"
#app.route("/sms", methods=['POST'])
def sms_reply():
"""Respond to incoming calls with a simple text message."""
# Fetch the message
msg = request.form.get('Body')
phone_no = request.form.get('From')
reply = fetch_reply(msg, phone_no)
# Create reply
resp = MessagingResponse()
resp.message(reply)
enter code here
return str(resp)
utils.py
import dialogflow_v2 as dialogflow
dialogflow_session_client = dialogflow.SessionsClient()
PROJECT_ID = "weather-husgcf"
def detect_intent_from_text(text, session_id, language_code='pt-BR'):
session = dialogflow_session_client.session_path(PROJECT_ID, session_id)
text_input = dialogflow.types.TextInput(text=text, language_code=language_code)
query_input = dialogflow.types.QueryInput(text=text_input)
response = dialogflow_session_client.detect_intent(session=session, query_input=query_input)
return response.query_result
def fetch_reply(query, session_id):
response = detect_intent_from_text(query, session_id)
return response.fulfillment_text
https://i.imgur.com/a/b2QSYUB "ScreenShots"
Twilio developer evangelist here.
In your fetch_reply method you call on the query_result's fulfillment_text property. According the QueryResult documentation fulfillmentText is deprecated/legacy:
The text to be pronounced to the user or shown on the screen. Note: This is a legacy field, fulfillmentMessages should be preferred.
The fullfillmentMessages property is defined as a list of Message objects. So to return all 3 of your messages your code should probably loop through the messages adding them to the response, something like this:
def fetch_reply(query, session_id):
response = detect_intent_from_text(query, session_id)
return response.fulfillment_messages
Then your route should look something like this:
#app.route("/sms", methods=['POST'])
def sms_reply():
"""Respond to incoming calls with a simple text message."""
# Fetch the message
msg = request.form.get('Body')
phone_no = request.form.get('From')
replies = fetch_reply(msg, phone_no)
# Create reply
resp = MessagingResponse()
for reply in replies:
resp.message(reply.text)
return str(resp)
I haven't tested this, just worked from the DialogFlow documentation. Let me know if it helps.
Old-ish question but here's the answer (Dialogflow v2).
Assuming you have some sort of sendMessage(mobile_num, text) function, you iterate over the fulfillment_messages like this:
for message in response.query_result.fulfillment_messages:
sendMessage(mobile_num, message.text.text[0])
From the webhook you get a json like this:
{
"queryText": string,
"languageCode": string,
"speechRecognitionConfidence": number,
"action": string,
"parameters": {
object
},
"allRequiredParamsPresent": boolean,
"cancelsSlotFilling": boolean,
"fulfillmentText": string,
"fulfillmentMessages": [
{
"text": {
"text": [
"Some text"
]
}
},
{
"text": {
"text": [
"Some more text"
]
}
},
],
"webhookSource": string,
"webhookPayload": {
object
},
"outputContexts": [
{
object (Context)
}
],
"intent": {
object (Intent)
},
"intentDetectionConfidence": number,
"diagnosticInfo": {
object
},
"sentimentAnalysisResult": {
object (SentimentAnalysisResult)
}
}
where fulfillmentMessages is an array you have to iterate over.
Hope this helps.
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.
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.
I have a permissions request that looks like this:
timestamp, signature = genPermissionsAuthHeader.getAuthHeader(str(self.username), str(self.password), str(access_token), str(token_secret), "POST", "https://api-3t.sandbox.paypal.com/nvp") # https://svcs.sandbox.paypal.com/Permissions/GetBasicPersonalData
log.info(timestamp)
log.info(signature)
authorization_header = "timestamp=" + timestamp + ",token=" + access_token + ",signature=" + signature
log.info(authorization_header)
headers = {
"X-PAYPAL-AUTHORIZATION": authorization_header,
}
url = "https://api-3t.sandbox.paypal.com/nvp"
nvp_params = {
"METHOD": "TransactionSearch",
"STARTDATE": "2012-01-01T05:38:48Z",
}
r = requests.post(url, data=nvp_params, headers=headers)
log.info(r.text)
self.response.content_disposition = "text/html"
self.response.write(r.text)
I have an access token and token secret from the permissions API using my PayPal credentials on developer.paypal.com under "Sandbox Accounts"
When I run this method I get the error message:
TIMESTAMP=2014%2d04%2d21T22%3a50%3a18Z&CORRELATIONID=c8f9212035b60
&ACK=Failure&VERSION=0%2e000000&BUILD=10277387&L_ERRORCODE0=10002
&L_SHORTMESSAGE0=Authentication%2f
Authorization%20Faile
d&L_LONGMESSAGE0=You%20do%20not%20have%20permissions%20to%20make%20this%20API%20call
&L_SEVERITYCODE0=ErrorNone
I can make a call to GetBasicPersonalDetails and it seems to work. Any help would be great, thanks!
I found the answer, I was missing the "SUBJECT" parameter on the parameter string being sent for the payment. So just in case anyone else runs across this in the future the full code after getting the permissions tokens to run a test payment for the sandbox is:
def test_sales(self, access_token=None, token_secret=None):
timestamp, signature = genPermissionsAuthHeader.getAuthHeader(str(self.username), str(self.password), str(access_token), str(token_secret), "POST", "https://api-3t.sandbox.paypal.com/nvp") # https://svcs.sandbox.paypal.com/Permissions/GetBasicPersonalData
log.info(timestamp)
log.info(signature)
authorization_header = "timestamp=" + timestamp + ",token=" + access_token + ",signature=" + signature
log.info(authorization_header)
headers = {
"X-PAYPAL-AUTHORIZATION": authorization_header,
}
url = "https://api-3t.sandbox.paypal.com/nvp"
nvp_params = {
"METHOD": "DoDirectPayment",
"PAYMENTACTION": "Sale",
"AMT": "22.00",
"ACCT": "4111111111111111",
"CVV2": "111",
"FIRSTNAME": "Jane",
"LASTNAME": "Smith",
"EXPDATE": "012018",
"IPADDRESS": "127.0.0.1",
"STREET": "123 Street Way",
"CITY": "Englewood",
"STATE": "CO",
"ZIP": "80112",
"VERSION": "86",
"SIGNATURE": self.signature,
"USER": self.username,
"PWD": self.password,
"SUBJECT": "person_who_you_acting_on_behalf_of#domain.com"
}
r = requests.post(url, data=nvp_params, headers=headers)
log.info("Search transaction\n\n" + r.text + "\n\n")
self.response.content_disposition = "text/html"
self.response.write(urllib.unquote(r.text).decode('utf8'))
And for generating the header I used: https://github.com/paypal/python-signature-generator-for-authentication-header
Hope this helps someone, thanks!
Here is some information on the error message you are getting. One reason is invalid API Credentials. Another possibility is you are trying to pass an expired token. Once a transaction is created on PayPal the token is no longer valid. Instead you have a transaction id created.
Below is some more information on PayPal API Error Messages.
PayPal API Error Messages
If you are attempting a transaction search for your most recent transactions in PayPal, then you can use the PaymentDetailsRequest API
Here is an integration guide from the PayPal Developer Site:
Get Payment Details PayPal API Codes
TransactionSearch is not part of the AdaptivePayments API,
so no "X-PAYPAL-AUTHORIZATION" is required with this method.
Assuming that you got the permission for TransactionSearch method on the target account (see https://developer.paypal.com/docs/classic/permissions-service/gs_PermissionsService/)
the following code will works:
import requests
api_username="username"
api_password="password"
api_signature="signature"
target_account_email="xxx.yyy-buyer#zzz.com" #customers email
data_req = {
'METHOD':'TransactionSearch',
'SUBJECT':, target_account_email,
'VERSION':'86.0',
'STARTDATE':'2009-10-11T00:00:00Z',
'USER':api_username,
'PWD':api_password,
'SIGNATURE':api_signature
}
response=requests.post(url_en_point,data=data_req,timeout=3).text
print response