I'm trying to send an image with a facebook bot. I can send text fine, but whenever I try to send a message I get an error: TypeError: open file 'plot.jpg', mode 'rb' at 0x7f34a2fe8b70 is not JSON serializable. I'm using flask and heroku for the bot if that makes a difference.
This is my code:
def send_message(recipient_id, message_text):
log("sending message to {recipient}: {text}".format(recipient=recipient_id, text=message_text))
params = {
"access_token": os.environ["PAGE_ACCESS_TOKEN"]
}
headers = {
"Content-Type": "application/json"
}
log(os.getcwd())
data = json.dumps({
'recipient': {
'id': recipient_id
},
'message': {
'attachment': {
'type': 'image',
'payload': {}
}
},
'filedata': (os.path.basename('plot.jpg'), open('plot.jpg', 'rb'))
})
r = requests.post("https://graph.facebook.com/v2.6/me/messages", params=params, headers=headers, data=data)
if r.status_code != 200:
log(r.status_code)
log(r.text)
I got the same issue and i solved it by using multipart/form-data, instead of encoding the entire payload using json.dumps() you can use the MultipartEncoder from requests-toolbelt-0.8.0 to multipart encode the payload.
Note - Facebook's Graph API is accepting only png images for some unknown reasons, in the below example i've used a png file.
*Edited the code(redundant end parenthesis)
import json
import requests
from requests_toolbelt import MultipartEncoder
def send_message(recipient_id, message_text):
log("sending message to {recipient}: {text}".format(recipient=recipient_id, text=message_text))
params = {
"access_token": os.environ["PAGE_ACCESS_TOKEN"]
}
log(os.getcwd())
data = {
# encode nested json to avoid errors during multipart encoding process
'recipient': json.dumps({
'id': recipient_id
}),
# encode nested json to avoid errors during multipart encoding process
'message': json.dumps({
'attachment': {
'type': 'image',
'payload': {}
}
}),
'filedata': (os.path.basename('plot.png'), open('plot.png', 'rb'), 'image/png')
}
# multipart encode the entire payload
multipart_data = MultipartEncoder(data)
# multipart header from multipart_data
multipart_header = {
'Content-Type': multipart_data.content_type
}
r = requests.post("https://graph.facebook.com/v2.6/me/messages", params=params, headers=multipart_header, data=multipart_data)
if r.status_code != 200:
log(r.status_code)
log(r.text)
Related
The code snippet is simply about performing a post request to a machine learning model endpoint and logging out the response if successful.
import urllib.request
import json
import os
import ssl
def allowSelfSignedHttps(allowed):
# bypass the server certificate verification on client side
if allowed and not os.environ.get('PYTHONHTTPSVERIFY', '') and getattr(ssl, '_create_unverified_context', None):
ssl._create_default_https_context = ssl._create_unverified_context
allowSelfSignedHttps(True) # this line is needed if you use self-signed certificate in your scoring service.
# Request data goes here
# The example below assumes JSON formatting which may be updated
# depending on the format your endpoint expects.
# More information can be found here:
# https://learn.microsoft.com/azure/machine-learning/how-to-deploy-advanced-entry-script
data = {
"Inputs": {
"data": [
{
"test_date": "2000-01-01T00:00:00.000Z",
"cough": false,
"fever": 0,
"sore_throat": false,
"shortness_of_breath": 0,
"head_ache": 0,
"age_60_and_above": "example_value",
"gender": "example_value"
}
]
},
"GlobalParameters": {
"method": "predict"
}
}
body = str.encode(json.dumps(data))
url = 'http://8daf0a82-3a30-4581-96c3-5d4374473502.southafricanorth.azurecontainer.io/score'
api_key = '' # Replace this with the API key for the web service
# The azureml-model-deployment header will force the request to go to a specific deployment.
# Remove this header to have the request observe the endpoint traffic rules
headers = {'Content-Type':'application/json', 'Authorization':('Bearer '+ api_key)}
req = urllib.request.Request(url, body, headers)
try:
response = urllib.request.urlopen(req)
result = response.read()
print(result)
except urllib.error.HTTPError as error:
print("The request failed with status code: " + str(error.code))
# Print the headers - they include the requert ID and the timestamp, which are useful for debugging the failure
print(error.info())
print(error.read().decode("utf8", 'ignore'))
I have tried this, but I keep getting
"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://8daf0a82-3a30-4581-96c3-5d4374473502.southafricanorth.azurecontainer.io/score. (Reason: CORS request did not succeed). Status code: (null)."
function predict() {
axios
.post(
"http://8daf0a82-3a30-4581-96c3-5d4374473502.southafricanorth.azurecontainer.io/score",
{
Inputs: {
data: [
{
cough: S1Val.value,
fever: S2Val.value,
sore_throat: S3Val.value,
shortness_of_breath: S4Val.value,
head_ache: S5Val.value,
age_60_and_above: a1.value,
gender: a2.value,
},
],
},
GlobalParameters: {
method: "predict",
},
},
{
headers: {
"Access-Control-Allow-Orgin": "*",
"Content-Type": "application/json",
},
}
)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
}
Also note that this endpoint doesn't require any authentication that's why I didn't append an API key to the Bearer when performing the request.
I have a problem with code. I try to get list of products and stocks from Baselinker. I receive 200 response but unfortunately also have response:
{'status': 'ERROR', 'error_code': 'ERROR_UNKNOWN_METHOD',
'error_message': 'An empty or unknown method has been used'}
I think I made mistake with methods definition but I try everything I can and problem still exist.
import requests
import json
import webbrowser
from pprint import pprint
params = {
"inventory_id": "1762"
}
parameters = json.dumps(params)
headers = {
"X-BLToken" : token,
'method': "getInventoryProductsStock",
'parameters': parameters
}
response = requests.get('https://api.baselinker.com/connector.php', headers=headers)
print(response)
show = response.json()
print(show)
Parameters should not be placed in a header. You should send a POST request (not a GET) with data, containing 'method' key and optionally 'parameters'.
Try this:
import json
import requests
data = {
"method": "getInventoryProductsStock"
"parameters": json.dumps({"inventory_id": 1762})
}
headers = {
"X-BLToken" : token,
}
response = requests.post('https://api.baselinker.com/connector.php', headers=headers, data=data)
print(response)
show = response.json()
print(show)
I am working on a api call with python. Here I have the parameters in json format that was generated in the website I am trying to access. But when I try to run the program I get an 415: unsupported Media Type error. Not sure what I am doing wrong, as I am using the parameters generated by the website.
this is my code so far
def jprint(obj):
text = json.dumps(obj, sort_keys=True, indent=4)
print(text)
url = 'https://einv-apisandbox.nic.in/gstvital/api/auth'
parameters = {
"header": {
"ClientID": "TheClientIDGoesHere",
"ClientSecret": "TheClientSecretGoesHere"
},
"data": {
"UserName": "Username",
"Password": "Password",
"AppKey": "AppKey",
"ForceRefreshAccessToken": "false"
}
}
response = requests.post(url, params=parameters)
jprint(response.json())
In the above code, I have removed the actual parameters and replaced them with dummy text. But when I try them with the actual parameters I get the following error
{
"status": 415,
"title": "Unsupported Media Type",
"traceId": "|df46105a-49e1b43f80675626.",
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.13"
}
One thing I changed was this code "ForceRefreshAccessToken": "false". In the generated json code, the false was not inside quotes
Not sure what I am doing wrong. Please help me.
import requests
import json
def jprint(obj):
text = json.dumps(obj, sort_keys=True, indent=4)
print(text)
url = 'https://einv-apisandbox.nic.in/gstvital/api/auth'
parameters = {
"header": {
"ClientID": "TheClientIDGoesHere",
"ClientSecret": "TheClientSecretGoesHere"
},
"data": {
"UserName": "Username",
"Password": "Password",
"AppKey": "AppKey",
"ForceRefreshAccessToken": False
}
}
hdr = {"Content-Type": "application/json"}
response = requests.post(url, data=parameters, headers=hdr)
print(response.status_code)
print(response.json())
Error 415 indicates that the media type is not supported by the site. This can be fixed by explicitly stating in the header that the content-type will be JSON.
hdr = {"Content-Type": "application/json"} The response code from the site is "200:OK", therefore your request works.
I guess my question is relatively simple and naive, but I'm new to use REST APIs so I would be grateful for any help or hint.
I'm trying to send a request with urllib (or another Python's library that I no need to install).
Based on their guide, The format is:
POST https://vision.googleapis.com/v1/images:annotate?key=YOUR_API_KEY
and the JSON request format is:
{
"requests":[
{
"image":{
"content":"/9j/7QBEUGhvdG9...image contents...eYxxxzj/Coa6Bax//Z"
},
"features":[
{
"type":"LABEL_DETECTION",
"maxResults":1
}
]
}
]
}
When I try to send the following text (just for test) in the URL line in my browser:
https://vision.googleapis.com/v1/images:{
"requests":[
{
"image":{
"content":"/9j/7QBEUGhvdG9eYxxxzj/Coa6Bax//Z"
},
"features":[
{
"type":"LABEL_DETECTION",
"maxResults":1
}
]
}
]
}?key=my_api_key
I get unfortunately a 404 error.
What should I do? Should I use any library in order to generate the request? Or should I to place the JSON request in another place in the URL?
If you need to send Request Body with the URL you can use CURL. To test REST API's there is a famous software called POSTMAN. By using this you can send requests and receive the response.
CURL,
curl -v -H "Content-Type: application/json" -X POST \
-d '{"image":{"content":"/9j/7QBEUGhvdG9...image contents...eYxxxzj/Coa6Bax//Z"}, "features":[{"type":"LABEL_DETECTION","maxResults":1}]}' https://vision.googleapis.com/v1/images:annotate?key=YOUR_API_KEY
Using POSTMAN you can give these values to it and get results.
Give URL,
https://vision.googleapis.com/v1/images:annotate?key=YOUR_API_KEY
Choose HTTP METHOD as,
POST
And add the REQUEST BODY under the raw field and choose JSON(application/json),
{
"requests":[
{
"image":{
"content":"/9j/7QBEUGhvdG9...image contents...eYxxxzj/Coa6Bax//Z"
},
"features":[
{
"type":"LABEL_DETECTION",
"maxResults":1
}
]
}
]
}
This works for me:
import base64
import requests
import json
URL = "https://vision.googleapis.com/v1/images:annotate?key=YOUR_TOKEN"
#image to base64, which is a long long text
def encode_image(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read())
#make api call
def image_request(image_path):
data = {
"requests":[
{
"image":{
"content":encode_image(image_path)
},
"features":[
{
"type":"LABEL_DETECTION", #other options: LABEL_DETECTION FACE_DETECTION LOGO_DETECTION CROP_HINTS WEB_DETECTION
"maxResults": 10
}
]
}
]
}
r = requests.post(URL, json = data)
return r.text
#arg = path of image
def main(argv):
api_answer = json.loads(image_request(argv[1]))
try:
rows = api_answer['responses'][0]['labelAnnotations']
except:
print(file_to_proccess)
print(api_answer)
data = []
for item in rows:
data.append([item['mid'], item['description'], item['score'], item['topicality']])
# save somewhere the data list...
if __name__ == "__main__":
main(sys.argv)
this was tested and work perfect
import base64
import requests
import json
url = "https://vision.googleapis.com/v1/images:annotate"
querystring = {"key":".........."}
headers = {
'Content-Type': "application/json",
}
def encode_image(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read())
def image_request(image_path):
payload = '{ \"requests\":[ { \"image\":{ \"content\":\"'+encode_image(image_path).decode('utf-8')+'" }, \"features\":[ { \"type\":\"TEXT_DETECTION\" } ] } ]}'
response = requests.request("POST", url, data=payload, headers=headers, params=querystring)
return response.text
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.