Here are three different ways i try to send data message fcm.
1. With pyfcm
def send_fcm(fcm_tokens, title=None, body=None, data_message=None):
push_service = FCMNotification(api_key=app.config['FCM_KEY'])
try:
if type(fcm_tokens) is list:
print(fcm_tokens, data_message)
result = push_service.notify_multiple_devices(registration_ids=fcm_tokens, data_message=data_message)
print(result, '++++++++++++++', flush=True)
else:
print(fcm_tokens, 'single device', data_message)
result = push_service.notify_single_device(registration_id=fcm_tokens, data_message=data_message)
print(result, flush=True)
except errors.InvalidDataError as e:
print(e, flush=True)
2. With firebase_admin sdk
def send_fcm_with_sdk(tokens, data_message=None):
if type(tokens) is list:
message = messaging.MulticastMessage(
data=data_message,
tokens=tokens, )
response = messaging.send_multicast(message)
print('{0} messages were sent successfully'.format(response.success_count), flush=True)
else:
message = messaging.Message(
data=data_message,
token=tokens,
)
print(message)
response = messaging.send(message)
print('Successfully sent message:', response)
3. With rest api
def send_fcm_with_rest(tokens, title=None, body=None, image=None, data_message=None):
headers = {
'Content-Type': 'application/json',
'Authorization': 'key=xxxxxxxKEY',
'Content-Type': 'application/json'
}
url = 'https://fcm.googleapis.com/fcm/send'
if type(tokens) is list:
payload = {
"registration_ids": tokens,
"collapse_key": "type_a",
"data": data_message
}
else:
payload = {
"to": tokens,
"collapse_key": "type_a",
"data": data_message
}
print(json.dumps(payload))
resp = requests.post(url, headers=headers, data=json.dumps(payload))
print(resp.text.encode('utf8'), flush=True)
return resp
The strange thing is all three of them run correctly and show a success message, with success_id, but none of fcm is received on the android side.
I tried sending from POSTMAN, and from postman, fcm are received on Andriod side.
Can anyone please tell me what is the issue in my code?
Your code is OK, however you should use flask==1.1.2 version as it is the stable release.
All the three methods for sending fcm is correct, later we figure out it was the issue from the frontend guy. So anyone can use these three methods if they want to.
Related
I have been attempting to solve this far too longer than id like to admit, I think the problem is how the data is being parsed with json and being interoperated via the API, as I do not have the same issue with the first function, but run into it with the second. Any help will be great.
import urllib, requests, json
def generateUserKey(username, password):
global devKey
return urllib.request.urlopen("https://pastebin.com/api/api_login.php",
urllib.parse.urlencode({"api_dev_key": devKey, "api_user_name": username, "api_user_password": password}).encode()).read()
def paste(userKey, text):
global devKey
datA = json.dumps({"api_dev_key": devKey, "api_paste_code": text, "api_user_key": userKey, "api_paste_name": "lol", "api_paste_format": "none", "api_paste_private": int(1), "api_paste_expire_date": "10M" })
resp = requests.post(url="https://pastebin.com/api/api_post.php", json=datA, data=datA)
print(resp.text)
key = generateUserKey(devKey, userName, passWord)
print(key)
paste(key, testString)
when ran I generate the following:
c0ce26a1c46d5fff3a254e519003ebb0
Bad API request, invalid api_dev_key
None
the dev key isnt invalid as its being used in the previous function to login and obtain a session key, so this is where I am stuck. Any help?
this could help:
import requests # see https://2.python-requests.org/en/master/
import json
def generateUserKey(data):
login = requests.post("https://pastebin.com/api/api_login.php", data=data)
print("Login status: ", login.status_code if login.status_code != 200 else "OK/200")
print("User token: ", login.text)
return login.text
def paste(data):
r = requests.post("https://pastebin.com/api/api_post.php", data)
print("Paste send: ", r.status_code if r.status_code != 200 else "OK/200")
print("Paste URL: ", r.text)
key = 'your key'
text = "hi"
t_title = "title of paste"
login_data = {
'api_dev_key': key,
'api_user_name': 'username',
'api_user_password': 'password'
}
data = {
'api_option': 'paste',
'api_dev_key': key,
'api_paste_code': text,
'api_paste_name': t_title,
'api_user_key': None,
# 'api_paste_expire_date': 'see_https://pastebin.com/api', # optional
# 'api_paste_private': 1, # 0 = public, 1 = unlisted, 2 = private
'api_user_key': generateUserKey(login_data)
# see_https://pastebin.com/api fro all the other arguments you can add
}
# if your data is already in json format, you can use json.dumps(data)
# data = json.dumps(data) # and now its a dict, and it can be feed to the requests.post
paste(data)
if you have any questions don't hesitate to ask
I am calling a API of OmniDocs, I am able to Add Document using Postman, passing it as form-data.
When I am trying to do the same in python it is returning Bad request.
NGOAddDocumentBDO Value
<NGOAddDocumentBDO>
<cabinetName>samplecabinet</cabinetName>
<folderIndex>3185</folderIndex>
<documentName>Restweb postman</documentName>
<userDBId></userDBId>
<volumeId>1</volumeId>
<accessType>S</accessType>
<createdByAppName>txt</createdByAppName>
<enableLog>Y</enableLog>
<versionFlag>N</versionFlag>
<textAlsoFlag></textAlsoFlag>
<ownerType>U</ownerType>
<ownerIndex>2</ownerIndex>
<nameLength></nameLength>
<thumbNailFlag>N</thumbNailFlag>
<imageData></imageData>
<encrFlag>N</encrFlag>
<passAlgoType>MD5</passAlgoType>
<userName>test123</userName>
<userPassword>Test#1234</userPassword>
<comment></comment>
<locale>en_US</locale>
<NGOAddDocDataDefCriterionBDO>
<dataDefIndex>22</dataDefIndex>
<dataDefName>DIGI2</dataDefName>
<NGOAddDocDataDefCriteriaDataBDO>
<indexId>43</indexId>
<indexType>I</indexType>
<indexValue>123</indexValue>
</NGOAddDocDataDefCriteriaDataBDO>
</NGOAddDocDataDefCriterionBDO>
<NGOAddDocKeywordsCriterionBDO>
<keyword></keyword>
</NGOAddDocKeywordsCriterionBDO>
</NGOAddDocumentBDO>
Postman output
Using fastapi in python, I am passing 'content-type': 'multipart/form-data', but not able to determine where the request is going wrong, if it is working fine with postman, not able to figure out the problem in fast-api.
lstr_add_document_response = "Empty"
lxml_add_document = """
<NGOAddDocumentBDO>
<cabinetName>samplecabinet</cabinetName>
<folderIndex>3185</folderIndex>
<documentName>Restweb postman</documentName>
<userDBId></userDBId>
<volumeId>1</volumeId>
<accessType>S</accessType>
<createdByAppName>txt</createdByAppName>
<enableLog>Y</enableLog>
<versionFlag>N</versionFlag>
<textAlsoFlag></textAlsoFlag>
<ownerType>U</ownerType>
<ownerIndex>2</ownerIndex>
<nameLength></nameLength>
<thumbNailFlag>N</thumbNailFlag>
<imageData></imageData>
<encrFlag>N</encrFlag>
<passAlgoType>MD5</passAlgoType>
<userName>test123</userName>
<userPassword>Test#1234</userPassword>
<comment></comment>
<locale>en_US</locale>
<NGOAddDocDataDefCriterionBDO>
<dataDefIndex>22</dataDefIndex>
<dataDefName>DIGI2</dataDefName>
<NGOAddDocDataDefCriteriaDataBDO>
<indexId>43</indexId>
<indexType>I</indexType>
<indexValue>123</indexValue>
</NGOAddDocDataDefCriteriaDataBDO>
</NGOAddDocDataDefCriterionBDO>
<NGOAddDocKeywordsCriterionBDO>
<keyword></keyword>
</NGOAddDocKeywordsCriterionBDO>
</NGOAddDocumentBDO>
"""
lstr_headers = {'content-type': 'multipart/form-data'}
lstr_data = {'NGOAddDocumentBDO': lxml_add_document, 'file': open('/home/donny/Desktop/omnidocs/output-document/8VQUI_something.pdf', "wb+")}
try:
lstr_add_document_response = requests.post(gstr_omnidocs_add_document_service,
data=lstr_data,
headers=lstr_headers)
print(gstr_omnidocs_add_document_service)
print(lstr_data)
print(lstr_headers)
except Exception as e:
logger.error(str(e), exc_info=True)
print("Response text=", lstr_add_document_response.text.encode('utf8'))
print(lstr_add_document_response.content)
# replace < with <
new_lstr_add_document_response = (lstr_add_document_response.text).replace("<", "<")
# get the response from the add document response
lstr_soup_response = BeautifulSoup(new_lstr_add_document_response, features="xml")
return lstr_soup_response
except Exception as e:
logger.error(str(e), exc_info=True)
Postman on right side should have icon </> to open function Code snippet which can generate code for different languages - even for Python (requests and http.client)
It gives me code which sends file in files=...
import requests
url = "http://10.10.2.41:8003/OmniBook"
payload={'NGOAddDocumentBDO': '<XML>'}
files=[
('file',('file',open('/path/to/file','rb'),'application/octet-stream'))
]
headers = {}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text)
But I couldn't test it.
i am building a kivy app that does APIs requests.
get_token() function runs first when app is launched to get all the necessary info, dicts, vars etc. After 30 min token gets expired, app has a buttons that on_press it will send request calls to the server, if the token is expired it wont work. I am trying to build a decorator #use_token that will check if simple request gets executed and receives response 200 Success code, if success: return(decorated function) else: calling get_token that will refresh token, and returning decorated function. A whole concept works, prints work at every possible block of code in every function, but when after 30 min token is expired, refresh_token() calls for get_token() inside the if statement, prints are still working but returned decorated function doesnt send requests, it prints test strings but doesnt do the main thing. That tells me that function get_token() executes inside if statement but doesn't update token information...
FIRST FUNCTION, RUNS ONES AT START:
def get_token():
url_token = "http://server.com"
payload = "{" \
"\n \"grantType\": \"password\"," \
"\n \"password\": \"string\"," \
"\n \"refreshToken\": \"string\"," \
"\n \"token\": \"string\"," \
"\n \"username\": \"admin\"" \
"\n}"
headers = {
'Content-Type': 'application/json',
'api_key': ''
}
global readyToken
readyToken = requests.request("POST", url_token, headers=headers, data=payload).json()['token']
print("Getting a NEW TOKEN!")
get_token()
DECORATOR FUNCTION:
def use_token(func):
#functools.wraps(func)
def refresh_token(*args):
url_check = "simplerequest.com"
response = requests.request("PUT", url_check, headers=HEADERS)
print("This print from url_check block "+str(response))
str_response = str(response)
if '401' in str_response:
print("401 found, Token is Expired, refreshing with get_token")
get_token()
else:
print("200 Code, success, passing, leaving else statement")
pass
print("emptying str_response and calling for decorated function:")
str_response = ""
return func(*args)
return refresh_token
DECORATED FUNCTION:
global URL_QC, HEADERS
URL_QC = "www.server.com"
HEADERS = {
'Content-Type': 'application/json',
'api_key': readyToken
}
#use_token
def change_channel(self, display_mac, ch_number):
print("Hello from DECORATED function!!!")
payload = "{\"deviceIds\": [" + str(display_mac) + "],\"menu\": \"save_sch_channel\", \"productType\": \"string\", \"value\":" + str(ch_number) + "}"
response = requests.request("PUT", URL_QC, headers=HEADERS, data=payload)
You are not updating the HEADERS variable when the readyToken changes.
HEADERS = {
'Content-Type': 'application/json',
'api_key': readyToken
}
In python, strings are passed by value. So here, you are only setting HEADERS['api_key'] to the current value of readyToken once. If you change readyToken later, the HEADERS is not updated because it only retains the original value of readyToken.
This can be solved by simply updating readyToken in the HEADERS every time it changes:
def get_token():
url_token = "http://server.com"
payload = {
"grantType": "password",
"password": "string",
"refreshToken": "string",
"token": "string",
"username": "admin"
}
headers = {
"Content-Type": 'application/json',
"api_key": ""
}
response = requests.post(url_token, headers=headers, data=payload)
print(f'Got Response: {response.json()}')
global readyToken
readyToken = response.json()['token']
# We also need to update headers!
global HEADERS
HEADERS['api_key'] = readyToken
Even better, if you are only using readyToken in the HEADERS, remove the readyToken variable entirely and simply update the global HEADERS variable:
def get_token():
...
response = requests.post(url_token, headers=headers, data=payload)
print(f'Got Response: {response.json()}')
global HEADERS
HEADERS['api_key'] = response.json()['token']
Alfa Q thank you so much, all your guesses and fixes was right! I do use token only in header, therefore i got read of readyToken and put token expression right into 'api_key' value. I also restructured the code and made a class implementing all your fixes:
token.py:
class Token:
def __init__(self):
self.url_check = "www.check.com"
self.url_token = "www.server.com"
self.payload = "{" \
"\n \"grantType\": \"password\"," \
"\n \"password\": \"password\"," \
"\n \"refreshToken\": \"string\"," \
"\n \"token\": \"string\"," \
"\n \"username\": \"admin\"" \
"\n}"
self.headers_token = {
'Content-Type': 'application/json',
'api_key': self.get_token()
}
def get_token(self):
return requests.post(self.url_token, headers=self.headers, data=self.payload).json()['token']
def use_token(self, func):
#functools.wraps(func)
def refresh_token(*args):
response = requests.put(self.url_check, headers=self.headers_token)
print("This print from url_check block: " + str(response))
if response.status_code == 200:
print('Status 200 | Token OK - No refresh necessary')
return func(*args)
elif response.status_code == 401:
print('Status 401 | Token is Expired - Refreshing')
self.get_token()
return func(*args)
else:
print(f'Status {response.status_code} | Error Occurred')
print("Print from REFRESH_TOKEN")
return refresh_token
main.py:
#token.use_token
def change_channel(self, display_mac, ch_number):
print("Hello from DECORATED function!!!")
payload = "{\"deviceIds\": [" + str(display_mac) + "],\"menu\": \"save_sch_channel\", \"productType\": \"string\", \"value\":" + str(ch_number) + "}"
response = requests.request("PUT", URL_QC, headers=token.headers_token, data=payload)
print(response)
1) I require a function which should publish a post with the given message and photo.
One can use the page ID and access tokens provided in self.page_id and self.page_access_token
def __init__(self):
self.page_id = Facebook.get_access_token('FACEBOOK_PAGE_ID')
self.page_access_token = Facebook.get_access_token('FACEBOOK_PAGE_ACCESS_TOKEN')
2) To find which API to hit, check out developer section of the Facebook API: https://developers.facebook.com/docs/graph-api/reference/page/photos/#example-2
3) The function should not return anything.
def publish_photo_msg(self, message, image_url):
#your code here
return
Please help.
python
params = (
('access_token', self.page_access_token),
)
Next, let us fix the data dictionary:
python
data = {
'url': image_url,
'caption': 'this is the caption'
}
Now, let’s proceed to the URL. There are many ways to set this. Here is one way:
python
url = 'https://graph.facebook.com/v5.0/' + self.page_id + '/photos?access_token=' + self.page_access_token
Since we have stored the access_token in the params tuple, let’s make use of it in the requests.post() call.
python
url = 'https://graph.facebook.com/v5.0/' + self.page_id + '/photos'
response = requests.post(url=url, params=params, data=data)
Lastly, you can also verify if your requests.post() call was successful by checking the value of the response variable:
python
print response.status_code, response.json()
For easy reference, here is the full implementation of the publish_photo_msg function with all the suggestions incorporated:
python
params = (
('access_token', self.page_access_token),
)
data = {
'url': image_url,
'caption': message
}
url = 'https://graph.facebook.com/v5.0/' + self.page_id + '/photos'
response = requests.post(url=url, params=params, data=data)
print(response.status_code, response.json())
I am developing a Facebook messenger bot using Flask and want to utilize the Twitter API for a feature of the bot. I am therefore using Tweepy to simplify the process. However, I am unable to get OAuth working in my program. I believe the source of the issue is that the request token is not saving or being received properly, because when I do auth.get_access_token I get an error - either "OAuth has no object request_token" or "string indices must be integers" depending on how I'm saving the OAuth handler instance. Sometimes, it also fails to get the request_token and doesn't send the link back to the user. I tried to check this by printing out the request token in my oauth_verification() function and it was blank. I've been stuck on this for a few hours, and any help would be greatly appreciated. My code is as follows:
PAT = '[pat here]'
auth = tweepy.OAuthHandler('[key here]', '[secret here]')
auth_req_token = ''
#app.route('/', methods=['GET'])
def handle_verification():
print("Handling Verification.")
if request.args.get('hub.verify_token', '') == '[verification token]':
print("Verification successful!")
return request.args.get('hub.challenge', '')
else:
print("Verification failed!")
return 'Error, wrong validation token'
#app.route('/', methods=['POST'])
def handle_messages():
print("Handling Messages")
payload = request.get_data()
print(payload)
for sender, message in messaging_events(payload):
print("Incoming from %s: %s" % (sender, message))
parse_message(PAT, sender, message)
return "ok"
def parse_message(PAT, sender, message):
original_message = message
message = str(message.decode('unicode_escape'))
message = message.replace("?", "")
if message.isdigit():
oauth_verification(PAT, sender, original_message.decode("utf-8"))
else:
split_msg = message.split(" ")
print(split_msg)
try:
platform = split_msg[split_msg.index("followers") - 1]
does_location = split_msg.index("does") + 1
have_location = split_msg.index("have")
name = split_msg[does_location:have_location]
name = " ".join(name)
print("Name: " +name + " Platform: " + platform)
init_oauth(name, PAT, sender)
except ValueError:
reply_error(PAT, sender)
def init_oauth(name, token, recipient):
try:
redirect_url = auth.get_authorization_url()
auth_req_token = auth.request_token
r = requests.post("https://graph.facebook.com/v2.6/me/messages",
params={"access_token": token},
data=json.dumps({
"recipient": {"id": recipient},
"message": {"text": "Please login to Twitter, and reply with your verification code " + redirect_url}
}),
headers={'Content-type': 'application/json'})
except tweepy.TweepError:
print('Error! Failed to get request token.')
def oauth_verification(token, recipient, verifier):
auth.request_token = auth_req_token
try:
auth.get_access_token(verifier) # issue is here - I am able to get authentication link, but not able to get access token
api = tweepy.API(auth)
r = requests.post("https://graph.facebook.com/v2.6/me/messages",
params={"access_token": token},
data=json.dumps({
"recipient": {"id": recipient},
"message": {"text": "Successfully authenticated Twitter!"}
}),
headers={'Content-type': 'application/json'})
except tweepy.TweepError:
print('Error! Failed to get access token.')
As auth_req_token is a global variable, you need to use the global keyword to change its value in init_oauth:
def init_oauth(name, token, recipient):
global auth_req_token
try:
redirect_url = auth.get_authorization_url()
auth_req_token = auth.request_token
# ...