socio
Version:
A WebSocket Real-Time Communication (RTC) API framework.
87 lines (86 loc) • 3.15 kB
JavaScript
import { E } from "./logging.js";
export class ServerChatRoom {
static #room_ids = new Set();
static #id_counter = 0;
#room_id;
#users = new Set();
#messages = new Set();
history_length;
server_interface;
constructor(ServerSendToClients, message_history_length = 10) {
const room_id = ++ServerChatRoom.#id_counter;
ServerChatRoom.#room_ids.add(room_id);
this.#room_id = room_id;
this.history_length = message_history_length;
this.server_interface = ServerSendToClients;
}
CloseRoom() { ServerChatRoom.#room_ids.delete(this.#room_id); }
get room_id() { return this.#room_id; }
static get room_ids() { return ServerChatRoom.#room_ids; }
Join(client_id) {
this.#users.add({ client_id });
this.server_interface([client_id], { rel: 'SocioChatRoom', type: 'msg_history', msgs: this.#messages });
}
Leave(client_id) { this.#users.delete({ client_id }); }
Post(client_id, text) {
const new_message = { user: { client_id }, ts: (new Date()).getTime(), text };
this.#messages.add(new_message);
if (this.#messages.size > this.history_length)
this.#messages.delete(this.#messages.values().next().value);
const clients = [...this.#users.values()].map(c => c.client_id);
this.server_interface(clients, { rel: 'SocioChatRoom', type: 'new_msg', msgs: new Set([new_message]) });
}
}
export class ChatRoomClient {
#current_room_id = 0;
serv;
msg_hook;
constructor(ClientSendToServer, msg_hook) {
this.serv = ClientSendToServer;
this.msg_hook = msg_hook;
}
Join(room_id) {
this.serv({ rel: 'SocioChatRoom', type: 'join', room_id });
this.#current_room_id = room_id;
}
Leave() { this.serv({ rel: 'SocioChatRoom', type: 'leave', room_id: this.#current_room_id }); }
Post(text) { this.serv({ rel: 'SocioChatRoom', type: 'new_msg', text, room_id: this.#current_room_id }); }
Receive(msgs) { this.msg_hook(msgs); }
}
export function HandleChatRoomServ(client, data, chat_rooms) {
if (data?.data?.rel == 'SocioChatRoom') {
const chat = chat_rooms.find(c => c.room_id === data.data?.room_id);
if (!chat)
return;
switch (data.data?.type) {
case 'join': {
chat.Join(client.id);
break;
}
case 'leave': {
chat.Leave(client.id);
break;
}
case 'new_msg': {
chat.Post(client.id, data.data?.text);
break;
}
default: throw new E('Unknown SocioChatRoom SERV msg type!');
}
}
}
export function HandleChatRoomCMD(data, chat) {
if (data?.rel == 'SocioChatRoom') {
switch (data?.type) {
case 'msg_history': {
chat.Receive(data?.msgs);
break;
}
case 'new_msg': {
chat.Receive(data?.msgs);
break;
}
default: throw new E('Unknown SocioChatRoom CMD msg type!');
}
}
}