socketio / socket.io-adapter

The Socket.IO in-memory adapter

Home Page:https://socket.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow excluding all sockets in a room

sebamarynissen opened this issue · comments

I have a use case where I need to send a message to all sockets except a certain user. In my application I let my sockets join a room equal to their user id, which looks like this:

io.on('connection', () => {
  let user = authenticate(socket);
  socket.join(user.id);
});

I noticed that it was possible to implement this behavior by extending the socket.io adapter as:

const BaseAdapter = require('socket.io-adapter');

class Adapter extends BaseAdapter {
  broadcast(packet, opts) {
    let {
      rooms,
      except = new Set(),
      ...rest
    } = opts;
    if (rooms.size === 0 && except.size > 0) {
      for (let id of [...except]) {
        if (!this.rooms.has(id)) continue;
        for (let sid of this.rooms.get(id)) {
          if (sid !== id) {
            except.add(sid);
          }
        }
      }
    }
    return super.broadcast(packet, {
      rooms,
      except,
      ...rest,
    });
  }
}

which works nicely. (Note that I have implemented some custom logic that allows me to use io.except('user').emit() by calling the namespace's adapter directly.

However, I'm in a position now where I need this functionality to work with socket.io-redis as well. This is a problem because I can't have socket.io-redis extend from my custom adapter. I filed a PR for this but it looks like this is not possible due to TypeScript limitations. Hence I thought it would be a nice functionality to have in the adapter itself. I will file a PR for this.