memo/lib/rooms.js

207 lines
6.3 KiB
JavaScript
Raw Normal View History

2011-03-10 08:20:27 -05:00
// This is based on PubSubCore
// https://github.com/PeterScott/pubsubcore/blob/master/pubsubcore.js
// PubSubCore: Simple pub/sub library for Node.js and Socket.IO
2025-06-03 12:12:48 +02:00
const util = require('util')
const sets = require('simplesets')
const io = require('socket.io')
const net = require('net')
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
/// ///////////////////////////
2011-03-10 08:20:27 -05:00
// Tracking who's in what room
2025-06-03 12:12:48 +02:00
/// ///////////////////////////
2011-03-10 08:20:27 -05:00
// Dict mapping room names with people to sets of client objects.
2025-06-03 12:12:48 +02:00
const rooms = {}
2011-03-10 08:20:27 -05:00
// Dict mapping room names with people to sets of usernames.
2025-06-03 12:12:48 +02:00
const room_users = {}
2011-03-10 08:20:27 -05:00
// Dict mapping sids to sets of rooms.
2025-06-03 12:12:48 +02:00
const sid_rooms = {}
2011-03-10 08:20:27 -05:00
// Add a client to a room and return the sid:client mapping.
2025-06-03 12:12:48 +02:00
exports.add_to_room = function(client, room, callback) {
// console.log('Client ' + client.username + ' (' + client.id + ') added to room ' + room);
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
if (!(sid_rooms.hasOwnProperty(client.id))) sid_rooms[client.id] = new sets.Set()
sid_rooms[client.id].add(room)
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
if (!(rooms.hasOwnProperty(room))) rooms[room] = new sets.Set()
rooms[room].add(client)
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
if (!(room_users.hasOwnProperty(room))) room_users[room] = new sets.Set()
room_users[room].add(client.username)
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
callback(rooms[room].array())
}
2011-03-10 08:20:27 -05:00
// Remove a client from all rooms and return the username:client
// mapping for everybody in those rooms.
2025-06-03 12:12:48 +02:00
exports.remove_from_all_rooms = function(client, callback) {
const affected_clients = new sets.Set()
if (sid_rooms.hasOwnProperty(client.id)) {
const client_rooms = sid_rooms[client.id].array()
for (let i = 0; i < client_rooms.length; i++) {
const room = client_rooms[i]
2011-03-10 08:20:27 -05:00
if (rooms.hasOwnProperty(room)) {
2025-06-03 12:12:48 +02:00
rooms[room].remove(client)
if (rooms[room].size() === 0) { delete rooms[room] }
2011-03-10 08:20:27 -05:00
}
if (room_users.hasOwnProperty(room)) {
2025-06-03 12:12:48 +02:00
room_users[room].remove(client.username)
if (room_users[room].size() === 0) { delete room_users[room] }
2011-03-10 08:20:27 -05:00
}
if (rooms.hasOwnProperty(room)) {
2025-06-03 12:12:48 +02:00
const this_room = rooms[room].array()
for (let j = 0; j < this_room.length; j++) { affected_clients.add(this_room[j]) }
2011-03-10 08:20:27 -05:00
}
}
2025-06-03 12:12:48 +02:00
}
// console.log('Client ' + client.username + ' (' + client.id + ') disconnected.');
delete sid_rooms[client.id]
callback(affected_clients.array())
}
2011-03-10 08:20:27 -05:00
// Remove a client from a room and return the username:client mapping
// for everybody in that room. Returns [] if the room does not exist,
// or if the client was not in the room to begin with.
function remove_from_room(client, room, callback) {
2025-06-03 12:12:48 +02:00
if (!rooms.hasOwnProperty(room) || !rooms[room].has(client)) {
callback([])
return
}
// Delete from the room
rooms[room].remove(client)
if (rooms[room].size() === 0) { delete rooms[room] }
if (room_users.hasOwnProperty(room)) {
room_users[room].remove(client.username)
if (room_users[room].size() === 0) { delete room_users[room] }
}
callback(exports.room_clients(room))
2011-03-10 08:20:27 -05:00
}
// Return list of clients in the given room.
exports.room_clients = function(room) {
2025-06-03 12:12:48 +02:00
return rooms.hasOwnProperty(room) ? rooms[room].array() : []
}
2011-03-10 08:20:27 -05:00
// Return true if room contains the given client, false otherwise.
exports.client_in_room = function(room, client) {
2025-06-03 12:12:48 +02:00
return rooms.hasOwnProperty(room) && rooms[room].has(client)
}
2011-03-10 08:20:27 -05:00
// Return list of usernames in given room
exports.users_in_room = function(room) {
2025-06-03 12:12:48 +02:00
return room_users.hasOwnProperty(room) ? room_users[room].array() : []
}
2011-03-10 08:20:27 -05:00
// Return list of usernames in given room
exports.room_clients_other_than_me = function(room, client) {
2025-06-03 12:12:48 +02:00
if (rooms.hasOwnProperty(room)) {
const clients = rooms[room]
// console.dir(clients.array());
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
clients.remove(client)
// console.dir(clients.array());
return clients.array()
}
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
return []
}
// gets the current room of the client (assumes one room -- will select first one if in multiple)
exports.get_room = function(client) {
let client_rooms = null
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
if (sid_rooms.hasOwnProperty(client.id)) {
client_rooms = sid_rooms[client.id].array()
}
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
if (client_rooms !== null) { return client_rooms[0] }
return null
}
// Generic server code
exports.add_to_room_and_announce = function(client, room, msg) {
// Add user info to the current dramatis personae
exports.add_to_room(client, room, (clients) => {
2011-03-10 08:20:27 -05:00
// Broadcast new-user notification
2025-06-03 12:12:48 +02:00
for (let i = 0; i < clients.length; i++) {
if (clients[i].id != client.id) { clients[i].json.send(msg) }
}
})
}
2011-03-10 08:20:27 -05:00
/*
exports.on_leave_room = function (client, room) {
2014-10-12 13:40:13 -04:00
2011-03-10 08:20:27 -05:00
remove_from_room(client, room, function(clients) {
console.log(client + ' disconnected, yo');
console.log(clients);
for (var i = 0; i < clients.length; i++)
clients[i].send({
announcement: true,
name: client.username || 'anonymous',
action: 'disconnected'
});
});
2014-10-12 13:40:13 -04:00
2025-06-03 12:12:48 +02:00
} */
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
// remember that this announces to all rooms that this client was a member of
exports.remove_from_all_rooms_and_announce = function(client, msg) {
exports.remove_from_all_rooms(client, (clients) => {
for (let i = 0; i < clients.length; i++) {
if (clients[i].id != client.id) { clients[i].json.send(msg) }
}
})
}
2011-03-10 08:20:27 -05:00
2025-06-03 12:12:48 +02:00
/// ///////////////////////////
2011-03-10 08:20:27 -05:00
// Broadcasting functions
2025-06-03 12:12:48 +02:00
/// ///////////////////////////
2011-03-10 08:20:27 -05:00
// Broadcast message to all clients
exports.broadcast = function(msg) {
2025-06-03 12:12:48 +02:00
if (socket) socket.broadcast(msg)
net_server_streams.each((stream) => {
stream.write(`${JSON.stringify(msg)}\r\n`)
})
}
2011-03-10 08:20:27 -05:00
// Broadcast message to all clients in a given room.
exports.broadcast_room = function(room, msg) {
2025-06-03 12:12:48 +02:00
const clients = exports.room_clients(room)
for (let i = 0; i < clients.length; i++) { clients[i].json.send(msg) }
}
2011-03-10 08:20:27 -05:00
// Broadcast message to all the other clients that are in rooms with this client
2025-06-03 12:12:48 +02:00
exports.broadcast_to_roommates = function(client, msg) {
let roommates = new sets.Set()
if (sid_rooms.hasOwnProperty(client.id)) {
const client_rooms = sid_rooms[client.id].array()
for (let i = 0; i < client_rooms.length; i++) {
const room = client_rooms[i]
if (rooms.hasOwnProperty(room)) {
const this_room = rooms[room].array()
for (let j = 0; j < this_room.length; j++) { roommates.add(this_room[j]) }
2011-03-10 08:20:27 -05:00
}
2025-06-03 12:12:48 +02:00
}
}
2014-10-12 13:40:13 -04:00
2025-06-03 12:12:48 +02:00
// remove self from the set
roommates.remove(client)
roommates = roommates.array()
2014-10-12 13:40:13 -04:00
2025-06-03 12:12:48 +02:00
// console.log('client: ' + client.id + " is broadcasting to: ");
2014-10-12 13:40:13 -04:00
2025-06-03 12:12:48 +02:00
for (let k = 0; k < roommates.length; k++) {
// console.log(' - ' + roommates[i].id);
roommates[k].json.send(msg)
}
}