Facebook send API sending audio issue - python

Can't send audio through facebook send api. It always returns with an HTTP 400 Bad Request. I use python and urllib for the http request.
Json:
'recipient':{
'id' : userId
},
'message' : {
'attachment' : {
'type' : 'audio',
'payload' : {
'url' : url
}
}
}
}
Request:
def send_msg(userId,data,accessKey):
HEADERS = {
'Content-Type':'application/json'
}
url = 'https://graph.facebook.com/v2.6/me/messages?access_token='+accessKey
msg_json = {
'message' : {
'attachment' : {
'type' : 'audio',
'payload' : {
'url' : url
}
}
}
data = json.dumps(msg_json).encode('utf-8')
req = urllib.request.Request(url,data,HEADERS)
resp = urllib.request.urlopen(req)
The code works on image and file attachment but it doesn't work on audio.

The problem in the json blueprint is the missing 'Content-type' that should have a value of 'audio/mpeg' that specifies the file format for the mp3 audio uploads

Related

Python-Authlib: setting an Oauth2 Async client with (service principal) and (user, password)

I come here for help after being stuck a few hours creating an OAuth2 Async httpx client.
It's one of those situations that feels so close, and still doesn't come through in the end.
I'm using this oauth2 session/client documentation:
What I need:
Creating an oauth2_async_client with authentication implemented at the creation -hopefully-.
The flow isn't that much different than what is described in the documentation.
Understanding the usage of fetch_token in the client.
About the flow:
I have two sets of credentials: a service principal (id, secret), and (user, password) that are called inside data.
The Postman Authentication request looks like this:
// Postman call
auth_enc = btoa(sp_key+":"+sp_secret)
var a_request = {
url : auth_login,
method : 'POST',
header : { "Authorization": "Basic "+auth_enc,
"Content-Type":"application/x-www-form-urlencoded"},
body: {
mode: "urlencoded",
urlencoded : [
{ key: 'username' , value: user },
{ key: 'password' , value: pass },
{ key: 'grant_type', value:'password'},
] } }
pm.sendRequest(a_request, (error, response) => {
if (error === null) {
pm.environment.set("ERP_TOKEN", response.json()["access_token"])
};
} );
What I tried:
class ERPClientX(OauthAsyncClient):
def __init__(self, config, **kwargs):
self.config = config
clienters = {
'client_id' : config['client_id'],
'client_secret': config['client_secret'],
'token_endpoint_auth_method': 'client_secret_basic'}
authers = {
'url' : self.config['auth-url'],
'data' : self.config['auth-data']), # Keys: {grant_type, username, password}
'headers': {'Content-Type': "application/x-www-form-urlencoded"}}
super().__init__(**clienters, **kwargs)
self.create_authorization_url(**authers)
self.base_url = self.config['base-url']
self.headers.update(self.std_headers)
std_headers = { # For the general request, not auth.
'Accept-Encoding' : 'gzip, deflate',
'Content-Type' : 'application/json',
'Accept' : 'application/json',
'Format' : 'json'}
async def inside_call(self, call_params):
sub_url = f"/call-me-maybe/{params['number']}/"
the_resp = await self.get(sub_url) # prepended by base_url defined above.
# Do something with result.
results_ls = the_resp.json()['d']['results']
for each_result in results_ls:
each_result.pop('__metadata')
results_df = (pd.DataFrame(results_ls)
.assign(ts_call=dt.now().strftime("%Y-%m-%d %H:%M:%S")))
return results_df
The error I get:
TypeError: 'str' object cannot be interpreted as an integer
...
307
308 super().__init__(**clienters, **kwargs)
--> 309 uri, _ = self.create_authorization_url(**authers)
310
When I didn't include the data and headers parameters in create_authorization_url -authers dict, I got another error:
<MissingTokenError \"missing_token\".
The documentation has several examples of using fetch_token but haven't been able to get my head around it.
Thank you for your help.

Microsoft Graph API how to send an attachment in a chat

I want to use the Microsoft Graph API to send messages with attachments to chats or channels.
https://learn.microsoft.com/en-us/graph/api/chatmessage-post?view=graph-rest-1.0&tabs=http#example-4-send-a-message-with-file-attachment-in-it
I can send normal messages already just fine like this:
def post_message(chat_id: str, subject: str = "", content_type: str = "text", content: str = "") -> None:
url = f"https://graph.microsoft.com/v1.0/chats/{chat_id}/messages"
json = {
"subject": subject,
"body": {
"contentType": content_type,
"content": content
}
}
res = requests.post(url, headers=header, json=json)
I try to copy the body from the example in the link above, substitute for my values and swap json variable for this one:
attachment_id = '7QW90B10D7-B5AK-420A-AC78-1156324A54F2' # not real, only to show how it looks like
json = {
"body": {
"contentType": 'html',
"content": f'i dunno what i\'m doing. <attachment id="{attachment_id}"></attachment>'
},
'attachments': [
{
'id': attachment_id,
'contentType': 'reference',
'contentUrl': 'https://foo.sharepoint.com/sites/bar/User%20documentation/Databricks/Databricks%20guide.pptx',
'name': 'Databricks guide.pptx'
}
]
}
I get requests.exceptions.HTTPError: 400 Client Error: Bad Request for url
What's wrong with the code? How to get attachment id from a file correctly because I am not sure I got the right value?
I was able to get it working with your code, (using both formats <attachment id=\"\"> and <attachment id="">), so it seems the error is probably with your attachment_id.
I retrieved the driveItem ID by following this answer, where the driveItem ID is the GUID value in the eTag property in the response.
You could get the file by the path:
https://graph.microsoft.com/v1.0/sites/{site-id}/drive/root:/{item-path}
For example:
https://graph.microsoft.com/v1.0/sites/{site-id}/drive/root:/test.docx
If the file is in a folder, it would be like this:
https://graph.microsoft.com/v1.0/sites/{site-id}/drive/root:/folder1/test.docx
Sample request after obtaining the ID
access_token = ""
attachment_name = "file.txt"
attachment_path = "https://domain.sharepoint.com/Shared%20Documents"
attachment_id = "12345678-1234-1234-1234-123456789123"
attachment_url = f"{attachment_path}/{attachment_name}"
chat_id = ""
req_url = f"https://graph.microsoft.com/v1.0/chats/{chat_id}/messages"
req_headers = {
"Authorization": "Bearer " + access_token,
"Content-Type": "application/json"
}
json = {
"body": {
"contentType": "html",
"content": f"Test message <attachment id=\"{attachment_id}\"></attachment>"
},
"attachments": [
{
"id": attachment_id,
"contentType": "reference",
"contentUrl": attachment_url,
"name": attachment_name
}
]
}
result = requests.post(url = req_url, headers = req_headers, json = json)

SendBird Error 400403 Invalid value: JSON body

I am trying to create user using send bird API
I am using python to make the API call, but getting error code 400403,
If I try from postman it works, not sure where I'm going wrong in the code
Following is my code -
import json
import requests
url = ‘https://api-someappidhere.sendbird.com/v3/users’
headers = {
'Content-Type' : 'application/json; charset=utf8',
'Api-Token' : 'secondaryApiToken'
}
data = {
'user_id' : 'someuserId',
'nickname' : 'somenickname',
'profile_url' : ''
}
try:
apiResponse = requests.post(url, headers=headers, data=data)
apiResponse = apiResponse.json()
return response
except Exception as error:
print(error)
I am getting the following response -
{
"hasError": false,
"result": {
"message": "Invalid value: \"JSON body.\".",
"code": 400403,
"error": true
}
}
References -
https://docs.sendbird.com/platform/quick_start
https://docs.sendbird.com/platform/error_codes
You should use json.dumps().
import json
import requests
url = ‘https://api-someappidhere.sendbird.com/v3/users’
headers = {
'Content-Type' : 'application/json; charset=utf8',
'Api-Token' : 'secondaryApiToken'
}
data = {
'user_id' : 'someuserId',
'nickname' : 'somenickname',
'profile_url' : ''
}
jsonData = json.dumps(data)
try:
apiResponse = requests.post(url, headers=headers, data=jsonData)
apiResponse = apiResponse.json()
return response
except Exception as error:
print(error)

openstack cannot retrieve authentication token from API

I am trying to retrieve the authentication token from the API using requests library from python. Here is the attempt I have made so far:
def get_token():
data = {
"auth" : {
"identity" : {
"methods" : [ "password" ],
"password": {
"user" : {
"name" : OS_USERNAME,
"domain": { "name": "Default" },
"password": OS_PASSWORD
}
}
}
}
}
r = requests.post(
OS_AUTH_URL+'/auth/tokens',
headers = HEADERS,
json = data, # https://stackoverflow.com/questions/9733638
verify = False
)
print(r.content)
j = json.loads(r.content)
return j['token']['user']['id']
I get token in the response :
{
"token": {
"issued_at": "2018-07-03T11:03:59.000000Z",
"audit_ids": [
"Fg1ywtZBQ1CkigCw70If9g"
],
"methods": [
"password"
],
"expires_at": "2018-07-03T12:03:59.000000Z",
"user": {
"password_expires_at": null,
"domain": {
"id": "default",
"name": "Default"
},
"id": "e0dc5beb383a46b98dad824c5d76e719",
"name": "admin"
}
}
}
However, when I am reusing this token to get, for instance, the list of projects :
def get_tenantID():
r = requests.get(
OS_AUTH_URL+'/auth/projects',
headers = HEADERS,
verify = False
)
return r
r = get_token()
HEADERS['X-Auth-Project-Id'] = 'admin'
HEADERS['X-Auth-Token'] = r
r = get_tenantID()
I get this error as if I would not be authenticated:
<Response [401]>
{"error": {"message": "The request you have made requires authentication.", "code": 401, "title": "Unauthorized"}}
Googling around and using openstack token issue command showed me that usually, token are more like:
gAAAAABaCo1F1CIMVlsTBeuqYH8tm2qR29tbkmUL4vZuhCNPXJI39TQ2YzL6Twoj8fNcAyLe3WhCYW2O1YpbBF0G8mo4bt7Kf0IRsoDOoJ6uWa3RYyJ5SQNoB_5n8EnVXbKPxFYOZ_iFBnaVtL1_XDrGbwsrlDeyy8lZTDdLsqY52pUhFR-7Uow
which is not what I get with get_token.
What am I doing wrong?
Many thanks!
When you use the auth API directly, the token issued comes in the X-Subject-Token header.
Thus, to retrieve in your python example, you could access the response.headers dict like this:
token = r.headers['X-Subject-Token']
More info about authentication in the Keystone v3 docs
1. fetch authentication token as mentioned below:
r = requests.post(
OS_AUTH_URL+'/auth/tokens',
headers = HEADERS,
json = data,
verify = False
)
token = r.headers[X-Subject-Token]
2. Pass this token in header for further request:
{
'X-Auth-Token': token
}

YouTube API video upload error: parseError /w python

The example code for Google's YouTube Data API is a piece of junk. It's so complicated and tied to the oauth redirect flow that I can't use it. Trying to go raw with requests pip and not getting too far.
I've followed the instructions exactly (as far as I can tell), with the following code:
import json
import os
import sys
import urllib
import requests
payload_file = None
payload = None
print 'Loading Config'
# Get the directory path of this file. When using any relative file paths make
# sure they are relative to current_dir so that the script can be run from any CWD.
current_dir = os.path.dirname(os.path.abspath(__file__))
# Reads in the config.json file then parses it
config = json.loads(open(os.path.join(current_dir, '..', 'config.json')).read())
print 'Parsing Payload'
for i in range(len(sys.argv)):
if sys.argv[i] == "--json" and (i + 1) < len(sys.argv):
payload = json.loads(sys.argv[i + 1])
elif sys.argv[i] == "-payload" and (i + 1) < len(sys.argv):
payload_file = sys.argv[i + 1]
with open(payload_file,'r') as f:
payload = json.loads(f.read())
break
print 'Configuring youtube with token {0}'.format(payload['token'])
print 'Downloading video...'
# See how big it is
f = urllib.urlopen(payload['url'])
content_length = int(f.headers["Content-Length"])
# Download it
# urllib.urlretrieve(payload['url'], "video.mp4")
metadata = {
'snippet' : {
'title': payload['title'],
"categoryId": 22
},
'status' : {
"privacyStatus": "public",
"embeddable": True,
"license": "youtube"
}
}
if 'tags' in payload:
metadata['snippet']['tags'] = payload['tags']
if 'description' in payload:
metadata['snippet']['description'] = payload['description']
headers = {
'Authorization' : 'Bearer {0}'.format(payload['token']),
'Content-Type' : 'application/json; charset=UTF-8',
'Content-Length' : json.dumps(metadata).__len__(),
'X-Upload-Content-Length' : content_length,
'X-Upload-Content-Type' : 'video/*',
}
print 'Attempting to upload video'
print headers
# upload video file
r = requests.post('https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status', data=metadata, headers=headers);
print "RESPONSE!"
print r.text
# files = {
# 'file': video_file,
# }
# r = requests.post('https://www.googleapis.com/upload/youtube/v3/videos', data={ "video" : video }, headers=headers);
Obviously its not finished, but its dying on the metadata upload request with the following output:
Loading Config
Parsing Payload
Configuring youtube with token <access-token>
Downloading video...
Attempting to upload video
{'X-Upload-Content-Length': 51998563, 'Content-Length': 578, 'Content-Type': 'application/json; charset=UTF-8', 'X-Upload-Content-Type': 'video/*', 'Authorization': 'Bearer <access-token>'}
RESPONSE!
{
"error": {
"errors": [
{
"domain": "global",
"reason": "parseError",
"message": "Parse Error"
}
],
"code": 400,
"message": "Parse Error"
}
}
This error is not even listed in their "Errors" docs.
What is wrong with my code?
Here is an example in python that works. It assumes you've already done the oauth part though.
import requests
from os import fstat
import json
fi = open('myvideo.mp4')
base_headers = {
'Authorization': '%s %s' % (auth_data['token_type'],
auth_data['access_token']),
'content-type': 'application/json'
}
initial_headers = base_headers.copy()
initial_headers.update({
'x-upload-content-length': fstat(fi.fileno()).st_size,
'x-upload-content-type': 'video/mp4'
})
initial_resp = requests.post(
'https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails',
headers=initial_headers,
data=json.dumps({
'snippet': {
'title': 'my title',
},
'status': {
'privacyStatus': 'unlisted',
'embeddable': True
}
})
)
upload_url = initial_resp.headers['location']
resp = requests.put(
upload_url,
headers=base_headers,
data=fi
)
fi.close()
the above is graet, just adding: you can also get the youtube id from the response (for future use):
cont = json.loads(resp.content)
youtube_id = cont['id']

Categories