How to build Slack clone using socket.io - node.js

We are building a slack clone, where could be many organizations, which each organization have multiple rooms or channels like slack.
I have 2-3 mongo models to save messages:
model conversations{
id: Int
participants:[userIds]
date:Date
lastMessage:Message
}
model message {
id:Int
body:String
conversationId: Conversation
date:Date
}
model User {
id:Int
name:Sting
organisationId:Organisation
}
model Organisation {
id:Int
name:String
}
Each organization can have many rooms/ channel and the user can be in that room/channel.
I'm thinking to use new socket.io namespace for each organization. Each namespace im using socket.io rooms as channels, where users can subscribe to rooms and communicate
I'm not sure how the client will create namespace for each organization, how in each namespace can create rooms as there is no room concept in socket.io client side.
I just want someone who can help me understand how can i implement namespaces and rooms in socket from client and also on server side.
I know how to listen to events and and send to events in general, but not sure how to go about this.

I remember I made an online game with socket.io.
The flow was simple, some user was able to create their own room and some of them was able to join their rooms.
I think you should use this method. By creating a channel by an Organization or a user, you should start listening to the room.
the namespace should be the name of the room.

Related

Handle chat system with socket.io, nodejs and mongodb

I have to create a chat system for our client online shop, we use nodejs/mongodb/socket.io.
I just tested if the realtime conversation between my nodejs and a simple html page is working :
const server = app.listen(app.get('port'), () => {
console.log("working");
});
var io = require('socket.io').listen(server);
io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg);
});
socket.emit('I just emit here for test', 'hello');
});
This code just working, now the fun part is to be able to make a shop manager discuss to a client, but clients shouldn't able to discuss between them (I have already a "clients" and "shop manager" collection ) like
below picture :
So, could someone tells me what is the best workflow to achieve this?, it means how to identify a client? and begin conversation to him? i am a bit lost with socket.io ...
Thanks for your help.
Create a message schema which will store conversations between client and manager.
Create a schema which will hold rooms or communication IDs.
Whenever a client logs into your system, show him the list of rooms, and when a client picks any room, show him the conversation.
Now, how to create a room?
Whenever a client wants to communicate with a manager (let's use ClientA and ManagerA), check if the conversation already exists or not. If a communication already exists, create a unique room like "clientA-room-managerA" and add both the parties to that room, store all the conversations in existing messages schema.
If the communication does not exist, create a room like "clientA-room-managerA" and then create a chat record in the schema which will hold communication Ids, and then start the room same as before "clientA-room-managerA"
By this way you should be able to create multiple chat records for a client and manager.
A client will not be able to communicate with other clients
A Manager can have communication with various clients
Consider a manager with user id: 123456789 and client with 0987654321, then you can create a room like:
var room = manager.user_id + "-room-" + client.user_id;
// room = 123456789-room-0987654321
//then join the client and manager to the room
manager_socket.join(room);
client_socket.join(room);
//you can send a message in a room:
io.sockets.in(room).emit('new_message',{"msg":"hi there"});
PS:
This is a kind of group chat where the group contains 2 members i.e. Client and a manager. For reference you can see this links:
http://psitsmike.com/2011/10/node-js-and-socket-io-multiroom-chat-tutorial/
https://github.com/jgonera/socket.io-multichat
In socket.io each socket has an individual ID which you can use to communicate between particular sockets. You can assign a particular value to the ID if you want, for example the user's MongoDB _id, for example:
this.userEmit(userID).emit('got user settings', settings);
// where userEmit is a custom function that will handle an error case when the id can't be found
You can also broadcast to specific "rooms", whereby only sockets that are members of that room will receive the message, e.g.:
io.sockets.in(groupID).emit('update group status', {
groupID: groupID,
onlineMembers: x.length
});
See their documentation for some examples: https://socket.io/docs/rooms-and-namespaces/

better approach for one to one and group chat nodejs Socket.io

I am implementing one to one and group chat in my application in NodeJs using socket.io and angular 4 on client side. I am new to socket.io and angular 4.I want to ask what is better approach for this e.g if user want to send a message to specific user or it want to send a message to group of users.
According to my Rnd should I keep the obj of all connected users and that obj contain the socket id of that user with his user name (email or what ever ) so that if some user want to send message to some one we should need his user name and we can access his id through his user name .
Or is there any solution except this ?
And where should i keep that obj of user and socket id global variable or database ?
One-to-one and group chat is very similar. If we use rooms in socket.io https://socket.io/docs/rooms-and-namespaces/#.
In one-to-one only 2 users are in the same room. where as in a group chat more than 2 people can be in the same room.
So when a person sends a mesage, they send it to the room they belong to and want to chat with instead of sending it to individual users. Then, everyone in that room, whether its one other person or multiple people will receive it.
- Node.js
Join a client to a room
io.on('connection', function(client){
client.join(conversation._id)
});
Emitting a message to a room
client.broadcast.to(conversation_id).emit('message:send:response', {
msg: res.msg,
conversation_id: res.data._id
});
- Angular
Listen to emitted messages
getMessages(conversation_id) {
let observable = new Observable(observer => {
this.socket.on('message:send:response', (chat) => {
if (chat.conversation_id === conversation_id) {
observer.next(chat.msg);
}
})
});
return observable;
}

How to give the user an ability to create a new chat room in socket.io?

How to give the user an ability to create a new chat room in socket.io?
I couldn't find any documentation about how to do this.
Demo logic :
User emit a createRoom event
Server check role if have permission , create a new room , emit createdRoom event to user
User receive this event and save this room info

Design choice using node.js and express and socket.io

I want to make a web app where every user can create a chat room that other users can join. I would like to have a main node server managing the rooms, and every time a user creates a new room, a new chat server should be started by the main server and it should manage the room.
My question is, how can I make the new server start in node.js and how can I manage it?
Socket.io allows you too use the room feature and have the behavior you want (separate chat rooms) without running a separate chat server. Running a separate chat server is not really convenient in node.js because it means running another process, and it makes communication between the main server and the chat servers extra complicated.
What i would advise is using that feature and adopt the following kind of design:
io.on('connection', function(socket) {
//initialize the object representing the client
//Your client has not joined a room yet
socket.on('create_room', function(msg) {
//initalize the object representing the room
//Make the client effectively join that room, using socket.join(room_id)
}
socket.on('join_room', function(msg) {
//If the client is currently in a room, leave it using socket.leave(room_id); I am assuming for the sake of simplicity that a user can only be in a single room at all time
//Then join the new room using socket.join(room_id)
}
socket.on('chat_msg', function(msg) {
//Check if the user is in a room
//If so, send his msg to the room only using socket.broadcast.to(room_id); That way, every socket that have joined the room using socket.join(room_id) will get the message
}
}
With this design, you're simply adding listeners to event, and once set up, the whole server is running fine without having to deal with concurrency or sub processes.
It's still very minimalist and you'll probably want to handle a few more concepts, such as unique nicknames, or password authentication etc.
But that can easily be done using this design.
Have fun experimenting with socket.io and node.js!

Socket.IO define namespace in runtime

In socket.IO there are 2 ways to send message to users separately: rooms and namespaces. In my project I need both of them - namespaces to divide users of different applications and rooms for each namespace for private messages and other specific stuff.
It's quite easy to create rooms directly in runtime. But is it possible to do the same trick with namespaces? I'd like to do something like this:
io.of(*someFunctionToCreateNameSpaceInRuntime*)
.on('connection', function (socket) {
socket.emit(***);
});
There is very similar question, but id doesn't work now. Is it possible to send namespace name with params and store it somewhere before connection event fires?
Thanks for any advise.

Resources