0

I have searched long and far. I am typically familiar with the LAMP stack so apologies - I am learning Node as I'm trying to build a chat feature - similar to how Intercom/drift would work.

I have been led to believe that Socket.io is a good way to go about this, and I am having a little bit of trouble. The basic overview is something like this:

  • Users can use my service to have a live chat feature enabled on their websites (they each have a unique API key)
  • They can add the chat to any number of web pages/domains (via a script tag)
  • The chat should be private between any single end user of the website, and the admin of the script tag (owner of the API key used to include the script on the page)

I'm having trouble with this.

Should I create dynamic namespaces for each URL, or is it a room?

Lets say I create a dynamic room on the client side that is unique such as is used in https://stackoverflow.com/a/19150254/1173155

// client side code
var dynamicRoomName = API_KEY + "_" + fullURL  + "_" + expressSessionId;
var socket = io.connect();
socket.emit('create room', dynamicRoomName);

// server side code
io.sockets.on('connection', function(socket) {
  socket.on('create room', function(room) {
    socket.join(room);
  });
});

The only person who should be able to see this chat other than the end user is the admin of that API Key, which I'm not sure how to implement.

I realise I will likely need a DB of some sort to keep track of the chats/rooms ect. Is there any good resource on how to learn how to implement this kind of thing?

Help is much appreciated!


Just going to expand a small bit on this, perhaps for my own good while working on the problem.

  • There can be many admins (unique APIs)
  • Admins are responsible for only their own chats - they cannot see any chats that do not belong to their API key
  • Many users can chat with one admin (in private)
    • All chat is 1 to 1
  • The end user and the admin user will thus use different clients
    • Admin can be in numerous chats to individual users
    • Users would typically be in one chat to one admin
  • Admins can't create chats (only receive incoming) - but of course can reply
shanehoban
  • 870
  • 1
  • 9
  • 30

1 Answers1

1

I don't think you want to use a namespace because then your server would have to be pre-listening on the server to every possible namespace in order to hear a connection to it. That seems impractical and inefficient. There are a number of different possible schemes. Here's one I think is fairly simple to implement.

  1. You create one namespace for this admin chat.
  2. Your server listens to that namespace and accepts incoming connections to it.
  3. The client connects to that namespace when they want the chat with the admin.
  4. The client then sends an initiateChat message with the API_KEY as data.
  5. The server is coded to not accept any other messages until initiateChat has been received with a valid API_KEY
  6. When the server receives the initiateChat message, it looks up the API_KEY in your database and if it finds it in the database and that user is currently online, it starts a chat session with them. If they are not currently available, it sends a message back to the client indicating they are not currently online.
  7. Now the socket is open for chat related messages.
  8. You can use a dynamically created room name to keep track of the two end points if you want and join both sockets to that room.
  9. If the admin user can be involved in multiple chats with the same socket, then you will have to make sure the chat messages it sends are labeled with which chat they belong to so you know which room name to send the message to on your server.
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • How SocketIO Server can listen to dynamic namespace, sir? – Quynh Nguyen Apr 15 '18 at 16:19
  • @QuỳnhNguyễn - Not sure what you mean. It takes an `io.of("someNamespace").on("connection", ....)` on the server for it to listen to a namespace. So, you can't listen for a namespace that you don't know the name of and you have to listen separately for every single namespace. A namespace is probably the wrong tool for something there are lots of. I described in my answer a better way to accept connections to lots of different potential chats. Did you read and understand what I proposed in my answer? – jfriend00 Apr 15 '18 at 16:20
  • I mean here is dynamic namespace, sir. How SocketIO Server can adding one more namespace for new Admin when it running? – Quynh Nguyen Apr 15 '18 at 16:22
  • @QuỳnhNguyễn - Last time I'm going to say this. Using a socket.io namespace for your particular problem is the WRONG tool for the job. – jfriend00 Apr 15 '18 at 16:24
  • Yes I read your workflow but I'm learning how we can handle SocketIO Server when we have one more `admin` -> we need to create one more name space. – Quynh Nguyen Apr 15 '18 at 16:24
  • 2
    @QuỳnhNguyễn - I don't think you understood my proposal. It works perfectly fine with multiple admins. When you get the `initiateChat` message on the server, you just use your server logic to determine which admin it is supposed to connect to based on the API_KEY passed. This is a lot simpler than trying to create lots of namespace listeners. – jfriend00 Apr 15 '18 at 16:25
  • @jfriend00 thanks a bunch for this, I'll work through it and see can I implement it. On points 8 & 9: Do you think I could use user session IDs for unique room names - seeing as these are pretty much arbitrary? I'm having trouble passing express-session session ID to socket IO at the moment – shanehoban Apr 15 '18 at 16:35
  • 1
    @shanehoban - You don't need to use the session ID. You can just coin a new unique ID for the room name. It could just be a random number plus the current date time turned into a string. You then communicate that back to the admin and they include it with their messsages to you know which chat they are sending to. For the end-user, if they can only be in one chat at a time, then you can just set the chatID on their socket object so anytime they send a message, you know which room to send it to. – jfriend00 Apr 15 '18 at 16:44
  • @jfriend00 Amazing, that sounds about right, thanks a million! – shanehoban Apr 15 '18 at 16:55
  • 1
    @shanehoban - FYI, this is a simple little library for generating unique IDs: https://www.npmjs.com/package/really-unique-id. It combines, random number, date time and a counter so ids are always unique . – jfriend00 Apr 15 '18 at 17:02