Display channel name in featherjs chat client - javascript

I am following this repo to build a chat application.
I am trying to show the channel name (the default room which users are logged into) in the chat client.
Is there a way to access channel info from
const client = feathers();
in the file

No, I do not believe so. Channels are a construct on the server side built on top of sockets. Each client are a socket receiving and sending data to the server. On the server sockets/clients can be grouped together into channels, so that you can easily broadcast to many clients, for example:
app.channel('authenticated').send({
warning: "Perimeter has been breached"
});
From what I understand you are trying to create a chat with multiple rooms a.k.a channels. In order to do that you need first to implement the ability to join a specific channel first, this can be done by creating multiple channels on the server, take a look here: https://docs.feathersjs.com/api/channels.html#example
in your src/channels.js:
const { user } = connection;
if (user.room == 'yoyo') {
app.channel('yoyo').join(connection);
}
Then I would recommend to store the room in the user object.
On the client side, when user sign up you could for example do something like this (app.js, line 19):
await client.service('users').create(Object.assign({ room: 'yoyo' }, credentials));
You could get which room to join from the signup form or perhaps from the path.

Related

How can a socket.io room name be passed from the front end to the back end?

I am currently making an application that is using React.js on the front end and Node.js on the back end. During development, I discovered that I needed to use sockets in order to reflect real time changes to all of the users in a particular room. To do this, I am using this code on my Node.js backend:
io.emit("name", {
action: "action",
data: data
});
and then to receive the requests on my front end I am doing this:
import openSocket from "socket.io-client";
const socket = openSocket(url);
socket.on("name", (data) => {
... logic
});
While this code works, I am currently emitting information to all players that are connected to my socket. However, I only want to emit information to the players in a certain room. The part I dont understand is how to tell socket.io which users are in a certain room. I read the documentation and the concept of rooms seems to be only a server side thing, and to add a player to a room this code can be used:
io.on('connection', socket => {
socket.join('some room');
});
But the room name I want this particular connection to join is stored on my front end. Is there a way I can pass this data from the front end to the back end so that it can be used when 'connection' is made? If not, how do I get the roomID I need? Thanks!

Send FCM Notification to multiple users using their UID through cloud functions

i have users Uid in an 'users' array as ['uid1','uid2'] now i will be sending notifications to these users in cloud function?
exports.sendNotificationFromCr = functions.database.ref('/cr/{crUid}/notifications/{notificationid}/').onWrite(event => {
const uid = ['uid1','uid2']; // some how i get this.
// some work to send notifications
// to all tokens of uid1 and uid2.
}
here is the database structure:
users/
uid1/
name:{name}
FCM-key/
token1:true
token2:true
uid2/
...
FCM-key/
token3:true
using ['uid1','uid2'] i want to send notification to all 3 tokens in my database. how to do that?
If you're using something like firebase. Then you would want to have a notifications database model, that has the userId, the notification title, body and perhaps image, also a seen flag (true or false).
You would then post notifications either from your clients or from your cloud server code into the database. One per client/notification. If you have thousands of users you would use some sort of server-side cronjob, to offload this so that it runs outside of say your client to server API.
On the clients, you would be listening for new rows in that model filtering on the userId and when they appear, display them to the client in your UI. Once the client has seen the notification you would mark it as seen on the client.
Without knowing what platforms, code base, DB you are using it's impossible to explain in code terms how this would be done.
There are various API's for IOS and Android and Firebase that resolve this.

Pusher with multi-database companies

I'm trying to figure out what's the best approach to use Pusher in my application.
My app consists in a normal website where users log in
Each user is connected to a company
Each company has its own database
So, I need my app to allow the send of regular messages and notifications (like popups) to people that only belong to the company signed for.
Doubts/problems:
If I create a channel called notifications and send events to it, all users (no matter what company) will receive it
If I set up some sort of token associated to the company won't work because some notifications/messages should only be sent to a restrict users
In my previous project I associated a token to the company because there was no activity between users only a "show-off" of what PHP was doing (within a loop) in each company, something like:
PHP:
$this->pusher->trigger($company_pusher_token, 'feedback', $data);
JS:
var token = $('#company_pusher_token').val();
var channel = pusher.subscribe(token);
channel.bind('feedback', function(data)
{
alert('working..');
});
So, how should I proceed to accomplish what I'm looking for?
It looks like you are going in the right direction.
The channel name would always start with the company unique prefix. If only a subset of users of that company should be notified then combine the prefix with the group ID.
Channels:
"notifications": send to all companies, all clients
"<company-token>-notifications": send to all clients from a given company
"<company-token>-<group-id>-notifications": send to all clients from a group within a given company
By the way if you want to make sure your customers can't bind to another company's channel make sure either the company token is not guessable, or use the "private-" prefix to let you control the authorization on the subscription of channels.

Sending data to specific client and not to the whole channel

I am currently playing with Faye.js. Upon subscription to a channel I want that specific client to receive an object that would be irrelevant to anybody already in the channel.
How can this be achieved?
More detail:
The object is an array of the last 20 chat comments in the room. Anybody already in the room would have received this object already or been a part of the chats and so it is not required for these to receive it.
Thank you in advance.
The only way I've come across is to generate a client-side GUID. When the client connects, it announces itself to the others through a 'public' channel, you can then use the GUID to send messages directly to this client.
For example, take the piece of code from the answer of this previous question to generate something that looks like a UUID.
You can then do something on the client-side like this:
var guid = guidGenerator();
client.subscribe('/privChannel_' + guid, onPrivateMessage);
client.subscribe('/pubChannel', onPublicMessage);
client.publish('/announce', { 'myId': guid });
function onPrivateMessage() {
// do something
};
function onPublicMessage() {
// do something
};
Your server should always subscribe to the '/announce' channel, and when any message is posted in that channel it should store that id so that it can identify that particular client. Then, the server can use this id to publish to a channel only this client should be subscribed to.
Note however that this is not a good idea for sensitive data. Other clients could also subscribe to '/announce' and farm the guids for malicious purposes.

Sending data only to chosen users using Socket.io-node

Is it possible to send data using socket.io-node just to chosen group of users? For example, how could I implement chat with different rooms? I dont want .broadcast() to send data to all logged in users.
Normally you should have for each room a list of connected user and those user all have a client object that you should have stored somewhere. So when you want to send a message to a specific room, you just have to iterate over the connected user of that room and access their client object and send the data.
In short, it is possible you just have to send your data to each of the users in the group one-by-one.
socket.io has a grouping functionality built in
On the socket object for a single connection, like you get passed when a new user connects, you can call .join('roomName') where roomName is any string you want to use to identify the "room", you could use a room name like "profile/14" to create a channel for updates to user #14's profile.
Then on the main io object do something like:
io.sockets.in('profile/14').emit('newComment', {message:'hello'});
The message will go out to all connections that have .join()'d the given room.
Typically I'll have my client emit a "hello" event onConnect that identifies what content the client is interested in subscribing to, and then on the server side my handler for the "hello" event handles .join()'ing the client into whatever rooms are needed

Categories