Custom HTTP Exceptions in Python - python

I want to make a python script to automate JIRA-similar ticket responses.
For this, I am using json and requests library. Since http requests can be quite unreliable sometimes, I wanted to my script to retry the HTTP request in case it fails. So far I have this:
def openNewTicket(queueID, subject, content):
post_url = "{}/ticket/".format(default_url)
#Filling body OBJ
myObj = { "ContentType": "text/plain",
"Subject" : subject,
"Content": content,
"Queue": queueID,
"CustomFields": { "33": "alarm", "26": "yes", "24": "technical incident" }
}
#Formatting obj to json
jsonBody = json.dumps(myObj)
print jsonBody
try:
response = requests.post(post_url, data=jsonBody, headers=authorization_header))
date = datetime.datetime.now()
writeLog("{} - Created ticket {}\n".format(date, response['id']))
rocketChat.sendChatMessage("modem", "Sucessfully created ticket {}".format(response['id']))
return 0
except Exception:
time.sleep(1)
return openNewTicket(queueID, subject, content)
The problem is: For some reason when I get 201 status code(created), it counts as an Exception and iterates again. Is there a way I can tell python that 201 status code is not an Exception?

Related

send post request to itunes Reporter

I am trying to send a POST request to Itunes reporter API to download a sales report: https://help.apple.com/itc/appsreporterguide/#/apd68da36164
In the queryInput, I pass in "1234" which is the vendorId.
import requests
headers = { "access_token": "123"}
json_data = {
"version": "1.0",
"mode": "Test",
"queryInput": "[p=Reporter.properties, Sales.getReport, 1234, Sales, Summary, Daily, 20230101]"
}
response = requests.post('https://reportingitc-reporter.apple.com/reportservice/sales/v1',
headers=headers, json=json_data)
#content = response.json()
print(response.content, response.status_code)
However, looks like the way I am passing parameters is incorrect because I only get this as the response:
b'' 400
I am certain that the access token is correct but not sure if i am passing it correctly.

How to reply to a existing message in Microsoft Teams channel via Rest API(incoming webhook)?

I am able to post a message to a team channel using incoming webhook(code sample below). What I am trying to achieve next is to reply to the same message whenever I have a new update. It's just a simple message in reply and need not to be conversational bot. I tried searching and found some options like teams bot and microsoft graph api. I wanted to know if there is a straightforward way to do it using incoming webhook or something else before exploring this options.
import requests
import json
from urllib.request import Request, urlopen, URLError, HTTPError
webhookurl = "https://factset.webhook.office.com/webhookb2/******************"
message = {
"#type": "MessageCard",
"#context": "http://schema.org/extensions",
"themeColor": "FF0000",
"summary": "Event Happened",
"sections": [
{
"activityTitle": "Main Title",
"activitySubtitle": "Sub title",
"markdown": True,
"facts": [
{
"name": "Start Time (UTC)",
"value": "2021-06-11 05:48:10"
},
{
"name": "Last Updated Time (UTC)",
"value": "2021-06-11 06:16:15"
}
]
},
}
req = Request(webhookurl, data=json.dumps(message).encode("utf-8"),
headers={"content-type": "application/json"})
try:
response = urlopen(req)
response.read()
except HTTPError as e:
print("Request failed : ", e.code, e.reason)
except URLError as e:
print("Server connection failed: ", e.reason, e.reason)
Currently Webhook doesn`t support to send back message. This can be done by using Graph API. You can raise UserVoice if this needs to be considered as a future request.
I was able to do it via microsoft graph using delegated workflow. Get access on behalf of a user

How to make a post request with the Python requests library?

I am using the following filters in Postman to make a POST request in a Web API but I am unable to make a simple POST request in Python with the requests library.
First, I am sending a POST request to this URL (http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets) with the following filters in Postman applied to the Body, with the raw and JSON(application/json) options selected.
Filters in Postman
{
"filter": {
"filters": [
{
"field": "RCA_Assigned_Date",
"operator": "gte",
"value": "2017-05-31 00:00:00"
},
{
"field": "RCA_Assigned_Date",
"operator": "lte",
"value": "2017-06-04 00:00:00"
},
{
"field": "T_Subcategory",
"operator": "neq",
"value": "Temporary Degradation"
},
{
"field": "Issue_Status",
"operator": "neq",
"value": "Queued"
}],
"logic": "and"
}
}
The database where the data is stored is Cassandra and according to the following links Cassandra not equal operator, Cassandra OR operator,
Cassandra Between order by operators, Cassandra does not support the NOT EQUAL TO, OR, BETWEEN operators, so there is no way I can filter the URL with these operators except with AND.
Second, I am using the following code to apply a simple filter with the requests library.
import requests
payload = {'field':'T_Subcategory','operator':'neq','value':'Temporary Degradation'}
url = requests.post("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets",data=payload)
But what I've got is the complete data of tickets instead of only those that are not temporary degradation.
Third, the system is actually working but we are experiencing a delay of 2-3 mins to see the data. The logic goes as follows: We have 8 users and we want to see all the tickets per user that are not temporary degradation, then we do:
def get_json():
if user_name == "user 001":
with urllib.request.urlopen(
"http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets?user_name=user&001",timeout=15) as url:
complete_data = json.loads(url.read().decode())
elif user_name == "user 002":
with urllib.request.urlopen(
"http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets?user_name=user&002",timeout=15) as url:
complete_data = json.loads(url.read().decode())
return complete_data
def get_tickets_not_temp_degradation(start_date,end_date,complete_):
return Counter([k['user_name'] for k in complete_data if start_date < dateutil.parser.parse(k.get('DateTime')) < end_date and k['T_subcategory'] != 'Temporary Degradation'])
Basically, we get the whole set of tickets from the current and last year, then we let Python to filter the complete set by user and so far there are only 10 users which means that this process is repeated 10 times and makes me no surprise to discover why we get the delay...
My questions is how can I fix this problem of the requests library? I am using the following link Requests library documentation as a tutorial to make it working but it just seems that my payload is not being read.
Your Postman request is a JSON body. Just reproduce that same body in Python. Your Python code is not sending JSON, nor is it sending the same data as your Postman sample.
For starters, sending a dictionary via the data arguments encodes that dictionary to application/x-www-form-urlencoded form, not JSON. Secondly, you appear to be sending a single filter.
The following code replicates your Postman post exactly:
import requests
filters = {"filter": {
"filters": [{
"field": "RCA_Assigned_Date",
"operator": "gte",
"value": "2017-05-31 00:00:00"
}, {
"field": "RCA_Assigned_Date",
"operator": "lte",
"value": "2017-06-04 00:00:00"
}, {
"field": "T_Subcategory",
"operator": "neq",
"value": "Temporary Degradation"
}, {
"field": "Issue_Status",
"operator": "neq",
"value": "Queued"
}],
"logic": "and"
}}
url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"
response = requests.post(url, json=filters)
Note that filters is a Python data structure here, and that it is passed to the json keyword argument. Using the latter does two things:
Encode the Python data structure to JSON (producing the exact same JSON value as your raw Postman body value).
Set the Content-Type header to application/json (as you did in your Postman configuration by picking the JSON option in the dropdown menu after picking raw for the body).
requests is otherwise just an HTTP API, it can't make Cassandra do any more than any other HTTP library. The urllib.request.urlopen code sends GET requests, and are trivially translated to requests with:
def get_json():
url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"
response = requests.get(url, params={'user_name': user}, timeout=15)
return response.json()
I removed the if branching and replaced that with using the params argument, which translates a dictionary of key-value pairs to a correctly encoded URL query (passing in the user name as the user_name key).
Note the json() call on the response; this takes care of decoding JSON data coming back from the server. This still takes long, you are not filtering the Cassandra data much here.
I would recommend using the json attribute instead of data. It handles the dumping for you.
import requests
data = {'user_name':'user&001'}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets/"
r = requests.post(url, headers=headers, json=data)
Update, answer for question 3. Is there a reason you are using urllib? I’d use python requests as well for this request.
import requests
def get_json():
r = requests.get("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets”, params={"user_name": user_name.replace(" ", "&")})
return r.json
# not sure what you’re doing here, more context/code example would help
def get_tickets_not_temp_degradation(start_date, end_date, complete_):
return Counter([k['user_name'] for k in complete_data if start_date < dateutil.parser.parse(k.get('DateTime')) < end_date and k['T_subcategory'] != 'Temporary Degradation'])
Also, is the username really supposed to be user+001 and not user&001 or user 001?
I think, you can use requests library as follows:
import requests
import json
payload = {'field':'T_Subcategory','operator':'neq','value':'Temporary Degradation'}
url = requests.post("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets",data=json.dumps(payload))
You are sending user in url, use it through post, but its depend upon how end points are implemented. You can try the below code :
import requests
from json import dumps
data = {'user_name':'user&001'}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets/"
r = requests.post(url, headers=headers, data=dumps(data))

directline v3 gives error 400

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.

QPX Express API from Python

I am trying to use Google's QPX Express API from python. I keep running into a pair of issues in sending the request. At first what I tried is this:
url = "https://www.googleapis.com/qpxExpress/v1/trips/search?key=MY_KEY_HERE"
values = {"request": {"passengers": {"kind": "qpxexpress#passengerCounts", "adultCount": 1}, "slice": [{"kind": "qpxexpress#sliceInput", "origin": "RDU", "destination": location, "date": dateGo}]}}
data = json.dumps(values)
req = urllib2.Request(url, data, {'Content-Type': 'application/json'})
f = urllib2.urlopen(req)
response = f.read()
f.close()
print(response)
based upon the code from: urllib2 and json
When I run the above code I get the following error message:
TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.
I searched for a solution and adapted my code based upon the following question: TypeError: POST data should be bytes or an iterable of bytes. It cannot be str
I changed my code to this:
url = "https://www.googleapis.com/qpxExpress/v1/trips/search?key=AIzaSyCMp2ZnKI3J91sog7a7m7-Hzcn402FyUZo"
values = {"request": {"passengers": {"kind": "qpxexpress#passengerCounts", "adultCount": 1}, "slice": [{"kind": "qpxexpress#sliceInput", "origin": "RDU", "destination": location, "date": dateGo}]}}
data = json.dumps(values)
data = data.encode("utf-8")
req = urllib2.Request(url, data, {'Content-Type': 'application/json'})
f = urllib2.urlopen(req)
response = f.read()
f.close()
print(response)
However, when I run this code I get the following error message:
urllib.error.HTTPError: HTTP Error 400: Bad Request
I also tried changing utf-8 to ascii but I was unsuccessful. How can I get this working properly?
Here is a solution using the excelent requests library.
import json
import requests
api_key = "YOUR API KEY HERE"
url = "https://www.googleapis.com/qpxExpress/v1/trips/search?key=" + api_key
headers = {'content-type': 'application/json'}
params = {
"request": {
"slice": [
{
"origin": "TXL",
"destination": "LIM",
"date": "2015-01-19"
}
],
"passengers": {
"adultCount": 1
},
"solutions": 2,
"refundable": False
}
}
response = requests.post(url, data=json.dumps(params), headers=headers)
data = response.json()
print data
I am not sure why you request is not working. Maybe it is really the request parameters that were wrong. The date definitely needs to be in the future!
False needs to be in lowercase in JSON, so you need to quote it in Python, like this "refundable" : "false". Otherwise, your query looks good (obviously you'll need to update the date). By the way, it isn't good practice to include your API key in a public forum.

Categories

Resources