Meteor - sending a message to all clients - javascript

I am building an application using Meteor.js with flashMessage to display informative messages for the user. Currently the message is tied to click events of individual users, but I want to display that message for all users.
Is there a way of using Meteor and flashMessages to accomplish this? Or another package should be used?
Cheers.

There are probably multiple ways, but here is one, using a collection of messages:
Common:
Messages = new Meteor.Collection('messages');
Client:
if (Meteor.isClient()) {
Meteor.subscribe('messages');
var msgs = Messages.find();
msgs.observeChanges({
added: function(id, obj) {
FlashMessages.sendInfo(obj.text);
}
});
}
Server:
if (Meteor.isServer()) {
Meteor.publish('messages', function() {
return Messages.find();
});
}
And then just insert messages like {text: "my text"} into the Messages collection and they should be displayed on all clients.
PS: You may want to remove the inserted messages again after a while, or else any newly arriving client will be shown all past messages. Alternatively you could just subscribe to recent messages.

Related

How to allow JavaScript to receive a message sent to a specific user (or self) using Signal R?

I previously asked this question but it was closed for duplication owing to this thread (SignalR - Sending a message to a specific user using (IUserIdProvider) *NEW 2.0.0*) - but this doesn't show the JavaScript as made clear in my title.
I have a WebForm application in ASP.Net that uses SignalR to push live data to the user logged in. The setup works perfectly, but realised I am broadcasting messages to all clients, which whilst it doesn't cause the wrong data to displayed to the logged in user, does cause the JavaScript function to get called for all users when just one has a data push.
I have amended the Hub code to broadcast to a specific user (User) and provided the User ID, and I have also tried Client with a Connection ID. Both fire off fine in the codebehind, but the javascript will not update the front end.
I believe it's because the JavaScript has not been modified to listen for a message sent to the user, but I'm not sure how I need to adapt the code to allow the message to be received.
The 2 tried lines in Hub here:
context.Clients.User(Me.Context.User.Identity.GetUserId()).ReceiveNotification(notifCount)
context.Clients.Client(Me.Context.ConnectionId).ReceiveNotification(notifCount)
JavaScript/jQuery function for the SignalR message here:
$(function () {
var nf = $.connection.notificationHub;
nf.client.receiveNotification = function (notifCount) {
// Update data
}
$.connection.hub.start().done(function () {
nf.server.sendNotifications();
}).fail(function (e) {
alert(e);
});
//$.connection.hub.start();
});
For calling back to the client (or self) you should use:
Clients.Caller.addContosoChatMessageToPage(name, message);
And for calling users you should use:
Clients.Client(Context.ConnectionId).addContosoChatMessageToPage(name, message);
Reference - docs

How to send a message with a random #mention on Slack using BotKit?

I'm new to developing bots and trying to use BotKit within Slack to mention a random user in the #test channel every week. Here is the code I have so far:
controller.hears('interactive', 'direct_message', function(bot, message) {
// send webhooks
bot.configureIncomingWebhook({url: 'https://hooks.slack.com/services/my/hook/uri'});
bot.sendWebhook({
text: 'Hey!',
channel: '#test',
},function(err,res) {
// handle error
});
});
Right now this sends a message "Hey!" to the #test channel when I direct message the bot "interactive", which is fine. How can I get all the usernames of users, and randomize them so that the text outputs like so: text: '"Hey " + "#" + random.username + " !"',. I would want this message to send every week as well.
Any ideas?
Slack provides a users.list function as described here: Slack API users.list
The members array contains user objects. You can user user[0].name to access the first username you want to #mention. in the demo they provide this would be #bobby.
Potential problems could arise because it returns the list in "no particular order"... you could potentially store it in a separate database and look to add elements if they are new and randomize based on your database entries.

Cant loop through users to send them individual message FB.ui()

I am looking for a way to send messages to multiple people without creating group chats and I have been working on this for two days now. I am trying to use a little hack where it loops through and ID list and basically takes values in an array and loops through them so one by one it sends a message. Basically, one ID sends message, then it loops back second ID sends message and so on until all parties have received a message. Here is my code so far
tl1.addEventListener("click", function() { //Send Message
try
{
var users = ['100008601850848', '100002242788752'];
for (var i = 0; i < users.length; i++)
{
FB.ui({
app_id: '1226220854077249',
method: 'SEND',
link: 'https://developers.facebook.com/apps/1226220854077249/roles/test-users/',
to: users[i]
});
}
}
catch(error)
{
console.log(error);
}
}, false);
Am I approaching this right? It does not send a message to all of them it only puts the first user in the field. All I am trying to do is make a loop that sends messages to one user then the next and so on. Basically sending it to multiple ID's but without creating groups as the FB.UI() does
There is only one way to use the send dialog, and if it creates a group chat then that´s what you have to live with. Right now you are trying to open several popups at once, which is a pretty ugly workaround - if it even works.

What is the correct way to listen to nested changes using Firebase?

Background:
I'm trying to send SMS messages via the browser using Firebase, Twilio, and Node.js. My current data structure in Firebase looks like this:
{ messages :
{ +15553485 :
{ FB-GENERATED-KEY-1 :
{ body: "hello world"
timestamp: 1461758765472 }
},
{ FB-GENERATED-KEY-3 :
{ body: "I love dogs"
timestamp: 1461758765475 }
}
}
},
{ +15550000 :
{ FB-GENERATED-KEY-2 :
{ body: "goodbye world"
timestamp: 1461758765473 }
},
{ FB-GENERATED-KEY-4 :
{ body: "I love cats"
timestamp: 1461758765476 }
}
}
}
}
When a message is added to Firebase via the frontend the backend needs to get notified in order to send an SMS via Twilio. When the backend gets a reply from the phone (via Twilio), it adds it to Firebase.
Problems:
When I listen for changes to a thread I receive all messages sent/recieved for that phone number. Obviously the backend doesn't want to send all the messages again, so I'm only interested in the most recent message added to the thread.
Also I can't seem to easily get the phone number (the key) that has messages underneath it.
What I've tried:
ref.child('messages').on('child_added', ...) — this works for new phone numbers that are added at /messages, however Firebase doesn't send through the new phone number (key), only everything from FB-GENERATED-KEY-2 down.
ref.child('messages').on('child_changed', ...) — this returns all of the messages in a thread, not only the new ones. I can sort on the server and find the most recent message, but that seems like it'll get heavy quite quickly – what if you've sent thousands of messages?
Storing messages at the root level (aka. flattening the tree) and storing the number as an attribute instead could work, but I'm going to need to use the phone number as a sort of index to connect with other data later (like a foreign key).
Questions:
How can I only get the most recent message when listening to activity on the parent /messages and not a particular phone number?
How can I get the key (phone number) when using a child_ event?
Does this data structure make sense?
You can get the Firebase key by calling key() on the snapshot returned by your child_added listener.
Then you can add another nested listener like this:
ref.child('messages').on('child_added', function (snapshot) {
var phone = snapshot.key();
ref.child('messages').child(phone).on('child_added', function (message) {
//send SMS
}, function (error) {
});
}, function (error) {
});
The Firebase API allows you to listen for changes in value or for operations on children. It does not have a way to listen for changes in grandchildren.
In NoSQL databases you often need to model the data for the way your application uses it. If I look at your specific use-case:
When a message is added to Firebase via the frontend the backend needs to get notified in order to send an SMS via Twilio.
I see a queue here:
smsQueue: {
pushId1: {
number: "+15553485",
body: "hello world",
timestamp: 1461758765472
},
pushId2: {
number: "+15550000",
body: "goodbye world",
timestamp: 1461758765473
},
pushId3: {
number: "+15553485",
body: "I love dogs",
timestamp: 1461758765475
},
pushId4: {
number: "+15550000",
body: "I love cats",
timestamp: 1461758765476
}
}
With this structure your back-end (which hopefully uses firebase-queue) can take each task from the queue, call twilio and delete the item from the queue.

Can you list users in Meteor without a login system?

For example, if I did a chatroom where all you ahve to do is enter a username (so you don't log in), can I still somehow list out all the people in that chatroom? How can I do this?
Instead of using the normal Meteor.users collection, it would probably be easiest to create your own collection for such simple authentication.
If you wanted to make it really simple (most likely, as long as you didn't care if 2 people have the same name), just store the name as a property of a chat room message document.
Edit - answer to comment:
To detect when a user disconnects, you can add an event handler in your publish function like this:
Meteor.publish('some_collection', function(){
var connectionId = this.connection ? this.connection.id : 'server';
this._session.socket.on("close", Meteor.bindEnvironment(function(){
// deal with connectionId closing
}));
});
You can do that.
Simply publish all users and every coming client should subscribe.
server:
Meteor.publish('allUsers', function(){
return Meteor.users.find({},{fields:{profile:1}});
})
client :
Meteor.startup(function(){
Meteor.subscribe('allUsers');
})
Template.listOfUsers.users = function(){
return Meteor.users.find();
}
This is very basic example, which should be adjusted to your needs.

Categories