I have some problems with my project, i hope you will help me!
Description:
I use library from https://github.com/ToothlessGear/node-gcm to build server push notification for some devices.
I have configured API key from Google Cloud Message to SenderId.
My code:
var message2 = new gcm.Message();
**// ... or some given values
var message2 = new gcm.Message({
collapseKey: 'demo',
delayWhileIdle: true,
timeToLive: 3,
data: {
key1: 'message1',
key2: 'message2'
}
});
// Change the message data
// ... as key-value
message2.addData('key1','message1');
message2.addData('key2','message2');
// ... or as a data object (overwrites previous data object)
message2.addData({
key1: 'message1',
key2: 'message2'
});
// Change the message variables
message2.collapseKey = 'demo';
message2.delayWhileIdle = true;
message2.timeToLive = 3;
message2.dryRun = true;
// Set up the sender with you API key
var sender = new gcm.Sender('AIzaSyBzb1PsEBEiAjagslkEANqyxxxxxxxxx');
// Add the registration IDs of the devices you want to send to
var registrationIds = [];
registrationIds.push('APA91bHAbFJYpHsSN-uz1Hkh8XjBw4xU87VIz5hZYOtobVv6I2pUZM67pWUGbb5zcP2HxXrooYiIOhzhIV7TuRDbVOlRDak-.xxxxxxxxxx');
sender.send(message2, registrationIds, 4, function(err, result) {
console.log(result);
});**
Then, I ran and recevied message as picture!
According to the documentation, MismatchSenderId means that the sender (API key) does not have access to send notifications to the registration ID:
A registration ID is tied to a certain group of senders. When a client app registers for GCM, it must specify which senders are allowed to send messages. You should use one of those sender IDs when sending messages to the client app. If you switch to a different sender, the existing registration IDs won't work.
You should make sure that your registration ID allows notification from the sender.
Related
We are creating a bot that can join the team meeting and it can start the recording as it joins the team meeting. But we are getting this error(Expected not null
Parameter name: client). I am attaching the code below:
when debugger goes to CreateLocalMediaSession() session method then at that method it gives the error.(Expected not null
Parameter name: client)
public async Task<ICall> JoinCallAsync()
{
// A tracking id for logging purposes. Helps identify this call in logs.
var scenarioId = Guid.NewGuid();
var (chatInfo, meetingInfo) = JoinInfo.ParseJoinURL("https://teams.microsoft.com/l/meetup-join/19:meeting_YTI5NDQ2ODQtMmNlNy00YTBhLTg2NTMtYmZmOGIyMzdhMTgw#thread.v2/0?context=%7B%22Tid%22:%22204d6395-ea6c-4e64-abea-e04cd30845e2%22,%22Oid%22:%225a95f69b-70e2-40d3-8b9a-5810ffcc6ec9%22%7D");
var tenantId = (meetingInfo as OrganizerMeetingInfo).Organizer.GetPrimaryIdentity().GetTenantId();
var mediaSession = this.CreateLocalMediaSession(scenarioId);
var joinParams = new JoinMeetingParameters(chatInfo, meetingInfo, mediaSession)
{
TenantId = tenantId,
};
if (!string.IsNullOrWhiteSpace("bot"))
{
// Teams client does not allow changing of one's display name.
// If the display name is specified, we join as an anonymous (guest) user
// with the specified display name. This will put the bot in lobby
// unless lobby bypass is disabled.
joinParams.GuestIdentity = new Identity
{
Id = Guid.NewGuid().ToString(),
DisplayName = "bot",
};
}
var statefulCall = await this.Client.Calls().AddAsync(joinParams, scenarioId).ConfigureAwait(false);
statefulCall.GraphLogger.Info($"Call creation complete: {statefulCall.Id}");
return statefulCall;
}
Code for creating local media session:
private ILocalMediaSession CreateLocalMediaSession(Guid mediaSessionId = default)
{
try
{
// create media session object, this is needed to establish call connections
return this.Client.CreateMediaSession(
new AudioSocketSettings
{
StreamDirections = StreamDirection.Recvonly,
// Note! Currently, the only audio format supported when receiving unmixed audio is Pcm16K
SupportedAudioFormat = AudioFormat.Pcm16K,
ReceiveUnmixedMeetingAudio = true //get the extra buffers for the speakers
},
new VideoSocketSettings
{
StreamDirections = StreamDirection.Inactive
},
mediaSessionId: mediaSessionId);
}
catch (Exception e)
{
_logger.Log(System.Diagnostics.TraceLevel.Error, e.Message);
throw;
}
}
We are creating a bot that can join the team meeting and it can start the recording as it joins the team meeting. But we are getting this error(Expected not null
Parameter name: client). I am attaching the code below:
error facing:
enter image description here
I have some code where I'm reading messages off of an Azure Event Hub that I want to either send an email or send an SMS.
The email is working through send grid, but I'm not sure how to configure the SMS part though.
I think I'd want to use Twilio and here's a sample of what my code's like. The "messageCollector" works for sending Email since there's some configuration for SendGrid in the local json. How do I configure Twilio?
[FunctionName("SendAlert")]
public static async Task Run(
[EventHubTrigger("v1-email-hub", Connection = "EventHubConnection")] EventData[] events,
[SendGrid] IAsyncCollector<SendGridMessage> messageCollector,
[TwilioSms] IAsyncCollector<CreateMessageOptions> smsCollector,
[Inject] NotificationEventLogic eventLogic,
ILogger log)
{
foreach (EventData eventData in events)
{
string messageBody = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);
var notificationEvents = JsonConvert.DeserializeObject<List<NotificationEvent>>(messageBody);
foreach (var ev in notificationEvents)
{
if (ev.NotificationEventType == NotificationEventType.Email)
{
var message = new SendGridMessage();
// ... ... make message and add it
await messageCollector.AddAsync(message);
}
else if (ev.NotificationEventType == NotificationEventType.SMS)
{
// Not sure how to get this to work
var mobileMessage = new CreateMessageOptions(new PhoneNumber(ev.Data))
{
Body = $"Notification {ev.NotificationId}"
};
await smsCollector.AddAsync(mobileMessage);
}
// await smsCollector.AddAsync()
await eventLogic.CreateEventAsync(ev);
}
}
}
You will need to configure it in attribute
[TwilioSms(AccountSidSetting = "TwilioAccountSid", AuthTokenSetting = "TwilioAuthToken", From = "+1425XXXXXXX")]
as it mentioned in documentation
TwilioAccountSid This value must be set
to the name of an app setting that holds your Twilio Account Sid e.g.
TwilioAccountSid. If not set, the default app setting name is
"AzureWebJobsTwilioAccountSid".
TwilioAuthToken This value must be set to
the name of an app setting that holds your Twilio authentication token
e.g. TwilioAccountAuthToken. If not set, the default app setting name
is "AzureWebJobsTwilioAuthToken".
I am a beginner with node.js and API's, I followed the getstream.io tutorials and came up with the below code
Would the below code send a notification from user1 to user2?
And how do I confirm that this successfully happens?
var stream = require('getstream');
// Instantiate a new client (server side)
client = stream.connect('key', 'secret', '25553');
// creates token so user1 can read and write
var token = client.feed('user', '1').token;
var user1 = client.feed('user', '1', token);
// Create a bit more complex activity
activity = {
'name': 'Jack',
'location': {'type': 'point', 'coordinates': [37.769722,-122.476944]},
'to' : ['notification:user2']
};
user1.addActivity(activity)
.then(function(data) { /* on success */ })
.catch(function(reason) { /* on failure */ });
// update the buyer status value for the activity
activity.name = 'James';
// send the update to the APIs
client.updateActivities([activity]);
//client side
//creates new client for reading
var client2 = stream.connect('key', null, '25553');
//creates read only token from sever client
var readonlyToken = client.feed('user', '1').getReadOnlyToken();
//user 2 gets read only token from user 1
var user2 = client2.feed('user', '1', readonlyToken);
//notification seen
user2.get({limit:5, mark_seen:true})
.then(function(data) { /* on success */ })
.catch(function(reason) { /* on failure */ });
If this code is all on the back end then you don't need to generate the tokens. You only need the tokens to pass to the front-end client.
For your client-side code you don't want this line:
var readonlyToken = client.feed('user', '1').getReadOnlyToken();
As mentioned in other posts, you generate that read-only token on the back end, pass it to the front end, and it's only good for websocket connections to Stream, of which you have a very limited supply (only 500 connections on our free plan) so generally we recommend that your back end pulls the feeds and sends the activity data to the front end.
Finally, the mark_seen and mark_read flags are used on notification feeds only, and your code is trying to use it on your user feed which is a flat feed.
I have something like this in a Node app:
var sender = new gcm.Sender("XPTO");
var registrationIds = ["whatever"];
...
var message = new gcm.Message({
data: {
avatar: body_data.avatar,
message: body_data.message
}
});
sender.send(message, registrationIds, 4, function (err, result) { console.log("success"); });
It works fine, the notification arrives and goes to the tray if the app if not opened.
But if I send a new notification to the same registrationId, the old notification is "updated" (or removed) and only the new one is shows.
If I add a random integer as parameter to notId
message.addData("notId", parseInt(Math.random() * 25));
the notifications are kept in the tray, but then the tray start to show multiple notifications.
Is there a way to group the notifications?
Android devices group same kind of notifications. If you set set different collapseKey for each kind of notification, they won't get grouped with others. You can have at most 4 different collapseKey at the same time visible to user in tray.
I'm using the node-xmpp module to connect to a XMPP server and join a group chat. Connecting to the server, setting the presence, joining the room and reading out messages works so far. But I want to receive the userlist of the room too.
The XMPP protocol requires to send a presence stanza when the client enters the room (http://xmpp.org/extensions/xep-0045.html#enter-pres). But how can I now parse it in node?
My code currently looks like this:
var xmpp = require('node-xmpp');
// Create the XMPP Client
var cl = new xmpp.Client({
jid: jid,
password: password,
reconnect: true
});
// Do things when online
cl.on('online', function() {
util.log("We're online!");
// Set client's presence
cl.send(new xmpp.Element('presence', { type: 'available' }).c('show').t('chat'));
cl.send(new xmpp.Element('presence', { to: room_jid+'/'+room_nick }).c('x', { xmlns: 'http://jabber.org/protocol/muc' }).c('history', {seconds: 1}));
// Send keepalive
setInterval(function() {
cl.send(' ');
}, 30000);
cl.on('stanza', function(stanza) {
// always log error stanzas
if (stanza.attrs.type == 'error') {
util.log('[error] ' + stanza);
return;
}
// ignore everything that isn't a room message
if (!stanza.is('message') || !stanza.attrs.type == 'chat') {
return;
}
var body = stanza.getChild('body');
// message without body is probably a topic change
if (!body) {
return;
}
// Extract username
var from, room, _ref;
_ref = stanza.attrs.from.split('/'), room = _ref[0], from = _ref[1];
var message = body.getText();
// Log topics and messages to the console
if(!from) {
util.log('Topic: ' + message);
} else {
util.log('[' + from + ']: ' + message);
}
});
});
I already tried triggering presence by using
if(stanza.is('presence')) {}
within the cl.on('stanza') part but it doesn't work.
UPDATE: I'm describing a new method now which doesn't require the client to send requests.
Background: When the client joins a group chat, the server returns presence stanzas which contain information about the connected users to the group chat.
cl.on('stanza', function(stanza) {
// always log error stanzas
if (stanza.attrs.type == 'error') {
util.log('[error] ' + stanza);
return;
}
if(stanza.is('presence')){
// We are only interested in stanzas with <x> in the payload or it will throw some errors
if(stanza.getChild('x') !== undefined) {
// Deciding what to do based on the xmlns attribute
var _presXmlns = stanza.getChild('x').attrs.xmlns;
switch(_presXmlns) {
// If someone is joining or leaving
case 'http://jabber.org/protocol/muc#user':
// Get the role of joiner/leaver
_presRole = stanza.getChild('x').getChild('item').attrs.role;
// Get the JID of joiner/leaver
_presJID = stanza.getChild('x').getChild('item').attrs.jid;
// Get the nick of joiner/leaver
_presNick = stanza.attrs.from.split('/')[1];
// If it's not none, this user must be joining or changing his nick
if(_presRole !== 'none') {
// We are now handling the data of joinging / nick changing users. I recommend to use an in-memory store like 'dirty' [https://github.com/felixge/node-dirty] to store information of the users currentliy in the group chat.
} else {
// We are now handling the data of leaving users
}
break;
}
return;
}
return;
}
OLD METHOD
I previously described a method how to query the server for current users in the group chat. By maintaining a store where all user traffic (joining, leaving, nick changing) is stored, this is no longer required. However you could still use it to make sure the data is consistent by issues like a presence stanza was not delivered to the client correctly. That's the reason it's still described below:
To request a list with users connected to the room, you need to perform the following actions:
First send a request to the server and ask for the user list:
cl.send(new xmpp.Element('iq', {from: jid, to: room_jid, type: 'get' }).c('query', { xmlns: 'http://jabber.org/protocol/disco#items' }));
then listen for iq-stanzas, parse them and populate an array with the data:
// Catching the requested user list
if(stanza.is('iq')){
// Fetching usernames from return data (data structure: http://xmpp.org/extensions/xep-0045.html#example-12)
var _items = stanza.getChild('query').getChildren('item');
var users = new Array();
for(var i = 0; i<_items.length; i++) {
// We are building an object here to add more data later
users[i] = new Object();
users[i]['name'] = _items[i].attrs.name;
}
console.log(util.inspect(users, {depth: null, colors: true}));
return;
}
This will provide you with a user list. To request unique JIDs you have to probe every user. To keep the list up to date, you should remove users when they leave and add + probe when they join.