Firebase FCM: Different Sound Settings for Topic Push Notifications - node.js

I am writing an iOS app that allows people to set sound settings (either default sound or no sound) for a particular push notification that subscribe to a particular topic.
Different people will have different sound settings, is there a way to send push notification settings to a topic, but with differing sound settings depending on the user.
I have the following implementation:
exports.pushNotifications = functions.database.ref('/companies/{companyID}/posts').onWrite((snap, context) => {
const companyID = context.params.companyID
const message = {
"condition": `'allCompanies' in topics || '${companyID}' in topics`,
"apns": {
"headers": {
"apns-priority": "5"
},
"payload": {
"aps": {
"alert": {
"body": "New gossips"
},
"sound": "default", //Any ways to vary this?
"badge": 1
}
}
}
};
return admin.messaging().send(message)
.then((response) => {
return console.log('PNForAllCompanies Successful: ', response);
})
.catch((error) => {
return console.log('PNForAllCompanies Error: ', error);
});
})
I tried to find resources in this area but seems limited. Does anyone have any idea to do so?
EDIT (For clearer description of use case):
In the settings page of the app, users can set the sound settings (either default, or none) of a push notification when a new post is added with the tag "My Company" like so:
How I implement this is to do a database trigger to that company node. When there is a new post added to that company node, it will send a push notification to everyone who has subscribed to that companyID as a topic.
However, for everyone who have subscribed to that companyID as a topic may like to have sound when this notification is pushed while others may not want silent. With that, is there a way vary the sound parameter depending on the user's preference?

The value for the sound parameter should be the name of the sound file included in the app. For more details about the payload parameter, see the official documentation:
The sound to play when the device receives the notification.
Sound files can be in the main bundle of the client app or in the Library/Sounds folder of the app's data container. See the iOS Developer Library for more information.
"Different people will have different sound settings, is there a way to send push notification settings to a topic, but with differing sound settings depending on the user."
I'm not sure if I understand your use-case properly, but if you want the sound to vary depending on the topic the message it's coming from, you'll have to handle that from the client app side -- determining which topic the message it actually came from.

Related

BotFramework conversation not found

I've been trying to test a function app sending an activity to a bot that has an existing conversation, but to simplify for this post, I'll speak in terms of sending it via postman. I've have been butting up against an issue wherein the conversationId is not being found, despite confirming it does exist beforehand and I'm not entirely sure what I've done wrong.
I log onto portal azure, and go to my bot to Test in Web Chat. I authenticate the bot, and the conversation starts.
Here, I've checked the conversationId is exactly what I expect to be by examining the conversation calls response in Chromes debug tools, in this case it is 1GJ0N9UYKGyELu3LqpDF6b-a
Here is the exact conversation response...
conversationId: "1GJ0N9UYKGyELu3LqpDF6b-a"
expires_in: 3600
referenceGrammarId: "fcab5fbf-67c7-bf55-934a-274e525c78a9"
streamUrl: "wss://webchat.botframework.com/v3/directline/conversations/1GJ0N9UYKGyELu3LqpDF6b-a/stream?watermark=-&t=ew0KICAi...."
token: "ew0KICA..."
So from here, in my mind I should be able to do the following in postman
POST https://webchat.botframework.com/v3/directline/conversations/1GJ0N9UYKGyELu3LqpDF6b-a/activities
Content-Type: application/json
Authorization: Bearer {My webchats channels secret code}
Body:
{
"type": "message",
"from": {
"name": "foo"
},
"text": "bar"
}
I'd expect a 200OK and the message 'bar' to appear in my Test In Web Chat from 'foo', but it does not. Instead I get an error in postman stating:
{
"error": {
"code": "BadArgument",
"message": "Conversation not found"
}
}
How exactly can this be? If I've just created that conversation and can demonstrate that conversationId is in use, why is the post message saying it can't be found? Am I incorrectly using channels? Or doing something blindingly obvious here?
So to answer my own question, to make a long story short. It looks like the example activity supplied in the Microsoft documentation doesn't quite cut it. There is something else that is required, although I didn't have time to narrow it down.
The solution I took, as I was running low on time was to write a method to save an activity to cosmosDb as part of the authentication flow. This way I have an ironclad activity that I know has worked in at least the invoke stages of the dialog, and I know a conversation reference is correct and present. From there I pulled the activity and changed 4 fields in it.
activity.Type = "message",
activity.From = new From { Id = "{BotId}", Name = "Gilbert Bottfried", Role = "bot },
activity.Text = "{My message}",
activity.Subject = "{my message subject}"
From there, it was essentially a case of just creating a connector client and firing off this repurposed activity.
AppCredentials.TrustServiceUrl(serviceUrl, DateTime.MaxValue);
ConnectorClient client = new ConnectorClient(
new Uri(serviceUrl),
MicrosoftAppId,
MicrosoftAppPassword);
await client.Conversations.SendToConversationAsync(activity.Conversation.Id, activity);
It seems that this was enough to get it working, and it makes for a nice referenceable conversation Id for future messages. Although I found other issues with working with WebChat, because I suspect it's not entirely stable sending messages to and throw via websockets. The testing experience was much more stable on msteams itself, it seemed to handle my barrage of test messages like a champ.
This is essentially a bruteforce method, as I'm storing and sending a lot of unnecessary data, but it works. I may append this answer to trim down what I find to be necessary in the future, but that will require testing.

Normal Push Notifications appear silently or not at all when the flutter app is terminated

I'm using firebase-admin on nodejs to send push notifications to users:
https://firebase.google.com/docs/admin/setup
I'm using firebase_messaging on flutter:
https://pub.dev/packages/firebase_messaging
I'm trying to send a push notification with the highest priority on both android and ios.
firebase.messaging(firebaseApp).send({
token,
notification,
android: { priority: 'high' },
apns: { headers: { 'apns-priority': '10' }, payload: { aps: { sound: 'default' } } },
data
}
On my development devices it works like a charm both when the app is in the background and when it's terminated.
I'm receiving push notifications that visibly pop and make a sound 100% of the time, on both android and ios.
The issue is on other devices -
If the app is in the background, I can sometimes see an actual push notification visibly pop, and make a sound as it should. Sometimes not.
If the app is terminated, a push notification is received - but it doesn't visibly pop nor make a sound, I can only see it if I scroll down the menu from the top of the screen, it's listed as a received push notification.
Sometimes the notification is not receieved at all.
I tried to change the priority of notifications from my app to high on the actual device as well, but it didn't change anything.
My users keep complaining that they're not receiving push notifications - I'm guessing they either actually don't receieve them or simply don't see them since they're recieved silently as I described above.
I literally have no idea what's going on and why it doesn't work as it should on devices other than my own development devices.
Any ideas?
There are two tags that need to be intact when we are sending push from firebase api
priority
android_channel_id
If android 7.0 or 8.0 above device do not receive the android_channel_id than it will not show notification and so always set default notification channel in the android manifest.
we can check available tags in json request we are setting via node.
from here
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/default_notification_channel_id"/>
like this and make sure you create the notification channel at mobile end.
String CHANNEL_ID = "your_channel id";
String CHANNEL_DESCRIPTION = "Your description to show in settings";
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_DESCRIPTION, NotificationManager.IMPORTANCE_HIGH);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
If you see the flutter app logs it will show you some error like default channel not set in manifest or no channel found in notification.
make sure you put logs in your question to resolve this or contact me to resolve the issue.
Also make sure you read
Optionally handle background messages section from here fcm flutter lib
there they mentioned adding fcm in android folder.

Setting a priority in inbox style stacked notifications with firebase-admin and nodejs

I'm developing an app that can receive push notifications. In my nodejs serve sourcecode, I create a notification thanks to the 'firebase-admin' library. I use ionic/cordova-phonegap-plugin-push for the reception of said notifications.
I also managed to make the notifications stack themselves like Gmail notifications, or Discord notifications, etc... (ONE notification containing MULTIPLE notifications) using the 'style':'inbox' and 'summaryText' properties. Here is the message object I create in the backend nodejs server :
const admin = require('firebase-admin');
let message = {
token: user.deviceId,
data: {
title: notification.title,
body: status,
style: 'inbox',
summaryText: 'You have %n% new notifications',
contentAvailable: 'true',
type, // custom data I need
targetId // custom data I need
},
android: { // android configuration
priority
},
apns: { // ios configuration
headers: {
apnsPriority
}
}
}
console.log("message", message);
admin.messaging().send(message)...
My first issue was that if the app is either killed or in the background, when you open it, with or without taping the stacked notifications, I only get the last notification received in the push.on('notification') phonegap event...
If there's a way to get ALL stacked notifications, I'm all ears, cause it don't seem like it's possible...
That's why I have another issue : as I can't get all notifications data, I would like to set a priority so that when I tap on the stacked notifications, I get the datas from the notification with the HIGHEST priority...
As you can see I've set priority variables for both Android and iOS but it doesn't seem to work... I'm only testing on Android right now.
I've asked my dear friend Google for the past 4hours without finding the answer...
Is there a solution to this kind of issue ?
Thanks in advance for your help :)

Permission for all users to post to a specific feed

I have been attempting to implement stream via react native and seem to be struggling with what looks like a permissions issue in relation to all users being unable to post to another 'entities' feed. My use case is essentially several 'topic' pages, where all users of my app can post to and comment etc. The topic page will also have an owner who can manage the page if needs be, so they too are essentially a 'user.
I've read elsewhere that global write permissions are not enabled by default so may need a member of the stream team to look at this for me if possible.
Here is the code I'm trying to use on the client side:
let user = client.feed('user', "bob");
let activity = {
actor: "bob",
verb: 'post',
object: "Hello world",
foreign_id: 'post:1',
to: ['user:topic-page-1'],
};
user
.addActivity(activity)
.then(data => {
console.log('success');
})
.catch(reason => {
alert(reason);
});
Another small issue I can't seem to get to the bottom of, is even when posting to the same user's timeline, the post username is always displaying as "Unknown" no matter what data I attach. What am I getting wrong here please?
For the actor field to be treated as a user entity, you should use a reference, something like client.currentUser or client.user('bob'). This should fix your post username issue.

How to find (and delete) message-less Twilio media?

If a Twilio message has been deleted, is there a way to locate any media associated with it (i.e. orphaned media)? Twilio docs explicitly state that deleting a message doesn't delete the media associated with it; if the message is gone but the media wasn't deleted first, is the media just publicly available forever?
If it's relevant, I'm using the nodejs package provided by Twilio (http://twilio.github.io/twilio-node/). Overall, I'm writing an app that deletes all messages and media by looping through all messages, and then all media, using the API. If there's a better way to do that (which thus makes my question moot), please let me know.
I can't find the reference now, but I believe I read somewhere that if a message is deleted, there is no longer a reference to the media instance and you're out of luck. I'm not sure if that's true.
At any rate, if I understand your question, I've had some success in the past using the Media portion of the API to list the media resources for a given message, and loop-delete the media instances first. Twilio's example of getting that list:
var accountSid = 'ACda6f132a3c49700934481addd5ce1659';
var authToken = "{{ auth_token }}";
var client = require('twilio')(accountSid, authToken);
client.messages('MM800f449d0399ed014aae2bcc0cc2f2ec').media.list(function(err, data) {
data.medias.forEach(function(media) {
console.log(media.ContentType);
});
});
You could then go back and loop-delete messages and not risk orphaning media instances.

Resources