Python Firebase Admin SDK appears successful but I never receive the notification - python

I'm attempting to use the Python Firebase Admin SDK to send push notifications for my mobile app. I've tested it with the notification composer in the Firebase Console, so I know my device can receive push notifications, but when I try to use the SDK I never receive anything. Nor do I see the notification listed on the Firebase console notification page.
Here's the exact code(minus my personal info) that I'm using to send the notification:
import firebase_admin
from firebase_admin import credentials, messaging
token = "registration token"
creds = credentials.Certificate('path/to/cert.json')
app = firebase_admin.initialize_app(creds)
msg = messaging.Message(data={'title': 'Test'}, token=token)
print(messaging.send(msg, app=app))
This returns a URL that follows the format /project/<project name>/messages/<message ID> but that URL doesn't work for me. It will just redirect me to the Firebase console base domain and a blank screen. Also, the notifications should be listed under /notifications shouldn't they?

I had had this problem for a week. But it was resolved. Follow these:
Make sure your APNs Certificates or APNs Authentication Key were uploaded in Cloud Messaging settings in Firebase Console
Sure that you use the correct FCM token when sending a firebase.messaging.Message which included apns (messaging.APNSConfig).
Check your AppDelegate.m file was setup following Firebase Docs. In my case, I forgot add [FIRMessaging messaging].APNSToken = deviceToken; in function application:didRegisterForRemoteNotificationsWithDeviceToken:. Keep in mind that the response when you send a message in your server did not say anything about the push notification to your iOS devices even you received a message (it did not contain a notification). And I also don't know how to check whether notification delivered or not.
My python server code:
def push_notification():
title = "Your title"
message = "Your message"
ntf_data = {"key": "value"}
fcm_token = "your_fcm_token"
topic = "your_topic"
# apns
alert = ApsAlert(title = title, body = message)
aps = messaging.Aps(alert = alert, sound = "default")
payload = messaging.APNSPayload(aps)
# message
msg = messaging.Message(
notification = messaging.Notification(
title = title,
body = message
),
data = ntf_data,
token = fcm_token,
topic = topic,
apns = messaging.APNSConfig(payload = payload)
)
# send
res = messaging.send(msg)
And frontend react-native notification listener code:
onNotificationListener = firebase.notifications().onNotification((notification) => {
console.log("received notification:", notification)
}
Feel free to ask if there is any problem in my answer or if you need more information. Happy coding.

The return value is a message ID string, and currently it doesn't point to anything (i.e. not a valid URL). It's just the unique ID that FCM has assigned to your notification, and it indicates the notification has been successfully handed off to FCM for delivery. Also, I believe that notifications sent from the SDK do not appear in the Firebase console. You need an actual client (Android, IOS or web) to test this flow end-to-end.

Related

Is there a way to skip python-O365 Account authentication or make it possible to complete it on a UI?

I want to read outlook emails and save the attachments, and I'm using python-O365 module for that. The problem is this module requires account authentication in order to access outlook.
The workflow is in this way:
User accesses the function/api, which then uses predefined/hardcoded credentials to connect to the outlook account.
client = "XXXXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXX"
secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
credentials = (client, secret)
account = Account(credentials)
At this point the function provides a url in the console for the user to go visit and provide consent and asks the user to paste the authenticated url back in the console. Image below for reference.
The problem here is that I want this authentication to be done on UI, not in the console. Im pushing this API to a server, where it will be not possible for the user to access the console to get this url and paste back the authenticated url.
Is there a way to either skip this authentication on whole? Or atleast a way to redirect the user directly to this mentioned url in console and provide the authenticated url to console directly from UI?
I got my answer myself. Basically I imported the functions that are being used in O365 library into my code, and reworked them a bit to get what I wanted done.
Here it goes,
So by default on a GET request, this django API shows the link that user needs to visit, sign-in and provide consent.(client and secret are hardcoded).
consent_url, _ = con.get_authorization_url(**kwargs) This line of code is being used in oauth_authentication_flow function in O365 module to print out the consent_url in console. I used it to just return the consent_url to UI.
Once user sign-in and consent is provided and they copy the token-url to paste it back to console, result = con.request_token(token_url, **kwargs) this line of code is used in the same oauth_authentication_flow function in O365 module to check if access token and refresh token are successfully generated and stored.
So using a POST request, now a user can submit the token_url back to my django API to get access to O365 api without relying on console.
#api_view(['GET','POST'])
def setupMail(request,**kwargs):
client = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
credentials = (client, secret)
scopes=['basic', 'message_all']
global account
account = Account(credentials)
protocol = MSGraphProtocol()
con = O365.Connection(credentials, scopes=protocol.get_scopes_for(scopes),**kwargs)
if request.method == "GET":
consent_url, _ = con.get_authorization_url(**kwargs)
return Response('Visit the following url to give consent: ' + consent_url)
if request.method == "POST":
token_url = request.data.get('token')
if token_url:
result = con.request_token(token_url, **kwargs) # no need to pass state as the session is the same
if result:
return Response('Authentication Flow Completed. Oauth Access Token Stored. '
'You can now use the API.')
else:
return Response('Something go wrong. Please try again. ' + str(bool(result)))
else:
return Response('Authentication Flow aborted.')
else:
return Response('Bad Request',status=status.HTTP_400_BAD_REQUEST)
Please let me know if there are any security concerns that I need to be worried about.

Firebase Admin Send Multicast not getting called or working

I'm working on django project in which i need to send notifications to the users using firebase admin sdk. but when ever i tried to send notification i see no logs for messaging.send_multicast(message). can anyone help me on this?
message = messaging.MulticastMessage(
data={
'data': str(self.data)
},
tokens=registration_tokens,
)
print('message', message)
response = messaging.send_multicast(message)
print('response', response.success_count, response.failure_count)
The code above to send a multicast data message is correct and should work. Do you get any errors?
Also have you made sure to initialise the Firebase admin SDK with correct credentials:
import firebase_admin
from firebase_admin import credentials, messaging
cred = credentials.Certificate(<credentials_path>)
default_app = firebase_admin.initialize_app(cred)
If you want to send a notification that's visible on the user's phone, should use the notification attribute, like so:
message = messaging.MulticastMessage(
notification=messaging.Notification(
title="Notification Title",
body="Notification Text",
),
tokens=registration_tokens
)
response = messaging.send_multicast(message)
print('response', response.success_count, response.failure_count)

Can't register webhook for Twitter Account Activity API [python3]

I'm trying to set up a Twitter app using the Account Activity API, to replace my old set up which used the user streaming endpoint. I want to be able to get DM messages to one user sent to a particular URL in real time.
Following these migration instructions, I've set up a webhook endpoint on my site, as described here. I've checked that process is working, by making sure that when I open https://example.com/webhook_endpoint?crc_token=foo in my browser, I get a token in response.
Now I'm trying and failing to register my webhook. I'm using the following code, and getting a 403 response.
from requests_oauthlib import OAuth1Session
import urllib
CONSUMER_KEY = 'my consumer key'
CONSUMER_SECRET = 'my consumer secret'
ACCESS_TOKEN = 'my access token'
ACCESS_SECRET = 'my access secret'
twitter = OAuth1Session(CONSUMER_KEY,
client_secret=CONSUMER_SECRET,
resource_owner_key=ACCESS_TOKEN,
resource_owner_secret=ACCESS_SECRET)
webhook_endpoint = urllib.parse.quote_plus('https://example.com/webhook/')
url = 'https://api.twitter.com/1.1/account_activity/all/env-beta/'
'webhooks.json?url={}'.format(webhook_endpoint)
r = twitter.post(url)
403 response content: {"errors":[{"code":200,"message":"Forbidden."}]}
I can successfully post a status using the same session object and
r = twitter.post('https://api.twitter.com/1.1/statuses/update.json?status=Test')
What am I doing wrong here?
This turned out to be due to a combination of:
Not having created an environment here: https://developer.twitter.com/en/account/environments as described here: https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/guides/getting-started-with-webhooks
using the wrong consumer secret in the function that created the token returned at the /webhook endpoint

How to transcribe audio in Twilio and using Python?

Hi everyone Im in a tangle as how to recorded, transcribe and retrieve the text from the transcription in Twilio. How do I do it? Example:
# Download the Python helper library from twilio.com/docs/python/install
from twilio.rest import TwilioRestClient
# Your Account Sid and Auth Token from twilio.com/user/account
account_sid = "AC30bd8bdca7572344721eb96c15a5c0c7"
auth_token = "your_auth_token"
client = TwilioRestClient(account_sid, auth_token)
transcription = client.transcriptions.get("TR8c61027b709ffb038236612dc5af8723")
print(transcription.transcription_text)
in client.transcriptions.get, How do I get the latest transcription? I need the Uri (I believe) but have no idea how to access it/variable name.
On a side note, what alternatives to the Twilio transcription are there and how do I access the appropriate recordings in my script to transcribe?
Twilio developer evangelist here.
You can access all your transcriptions by listing them as follows:
# Your Account Sid and Auth Token from twilio.com/user/account
account_sid = "AC30bd8bdca7572344721eb96c15a5c0c7"
auth_token = "your_auth_token"
client = TwilioRestClient(account_sid, auth_token)
for transcription in client.transcriptions.list():
print transcription.transcriptiontext
You can also set the TranscriptionUrl attribute so you get notified with a transcription ID when a transcription is complete. That way you can use the code snipped you posted above.

Automating Box Authentication - Python

I'm writing an app that interacts directly with my Box account. I need to perform all the operations listed in the Python SDK API. Sure enough, I'm trying to get over the authentication part. Given my client_id and client_secret, I have the following script:
#!/usr/bin/env python
import boxsdk
import requests
def store_tokens_callback(access_token, refresh_token):
# I don't know why this is never being called.
print access_token, refresh_token
oauth = boxsdk.OAuth2(
client_id="<my_client_id>",
client_secret="<client_secret>",
store_tokens=store_tokens_callback,
)
auth_url, csrf_token = oauth.get_authorization_url('http://127.0.0.1')
print auth_url
print csrf_token
r = requests.get(auth_url)
print r.text
client = boxsdk.Client(oauth)
I do get the auth_url:
https://app.box.com/api/oauth2/authorize?state=box_csrf_token_<csrf_tken>&response_type=code&client_id=<client_id>&redirect_uri=http%3A%2F%2F127.0.0.1
However, clicking in that URL all the time won't do it. I need a way to automate this authentication process, so I don't have to click at this button every time:
Sure enough, I could add a little Selenium task to get click on that button and get the url with the code, however I was looking for something easier ... between the lines.
A few questions:
How can I automate the auth process in the Box SDK?
Why isn't stoke_tokens_callback being called?
Check out the enterprise edition documentation, which allows you to interact via API calls only (no button clicking needed).
I had exactly the same requirement. The SDK will handle refreshing the access token when it expires, using the 60 day refresh token. The refresh token itself is also refreshed, meaning it's valid for yet another 60 days. Using the code below, having first "primed" the access and refresh tokens, will be good as long as the API is invoked at least once every 60 days. Follow the Box SDK instructions for obtaining your initial access and refresh tokens. You'll then have to install these Python modules:
pip.exe install keyring
pip.exe install boxsdk
Then use keyring.exe to prime the credential store:
keyring.exe set Box_Auth <AuthKey>
keyring.exe set Box_Ref <RefreshKey>
From here:
"""An example of Box authentication with external store"""
import keyring
from boxsdk import OAuth2
from boxsdk import Client
CLIENT_ID = 'specify your Box client_id here'
CLIENT_SECRET = 'specify your Box client_secret here'
def read_tokens():
"""Reads authorisation tokens from keyring"""
# Use keyring to read the tokens
auth_token = keyring.get_password('Box_Auth', 'mybox#box.com')
refresh_token = keyring.get_password('Box_Refresh', 'mybox#box.com')
return auth_token, refresh_token
def store_tokens(access_token, refresh_token):
"""Callback function when Box SDK refreshes tokens"""
# Use keyring to store the tokens
keyring.set_password('Box_Auth', 'mybox#box.com', access_token)
keyring.set_password('Box_Refresh', 'mybox#box.com', refresh_token)
def main():
"""Authentication against Box Example"""
# Retrieve tokens from secure store
access_token, refresh_token = read_tokens()
# Set up authorisation using the tokens we've retrieved
oauth = OAuth2(
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
access_token=access_token,
refresh_token=refresh_token,
store_tokens=store_tokens,
)
# Create the SDK client
client = Client(oauth)
# Get current user details and display
current_user = client.user(user_id='me').get()
print('Box User:', current_user.name)
if __name__ == '__main__':
main()

Categories