1
0
mirror of https://github.com/pavlobu/deskreen.git synced 2025-05-16 15:30:20 -07:00
deskreen/app/server/socket.ts
Pavlo Buidenkov a3996c7a76 added darkwire.io server and app/client
add client test works
2020-08-30 16:49:23 +03:00

200 lines
4.3 KiB
TypeScript

/* eslint-disable no-async-promise-executor */
import _ from 'lodash';
import Io from 'socket.io';
// eslint-disable-next-line import/no-cycle
import { getIO } from './signalingServer';
import getStore from './store';
interface User {
socketId: string;
publicKey: string;
isOwner: boolean;
}
interface Room {
id: string;
users: User[];
isLocked: boolean;
createdAt: number;
}
interface SocketOPTS {
roomId: string;
socket: Io.Socket;
room: Room;
roomIdOriginal: string;
}
export default class Socket implements SocketOPTS {
roomId: string;
socket: Io.Socket;
room: Room;
roomIdOriginal: string;
constructor(opts: SocketOPTS) {
const { roomId, socket, room, roomIdOriginal } = opts;
this.roomId = roomId;
this.socket = socket;
this.roomIdOriginal = roomIdOriginal;
this.room = room;
if (room.isLocked) {
this.sendRoomLocked();
return;
}
this.init(opts);
}
async init(opts: SocketOPTS) {
const { roomId, socket } = opts;
await this.joinRoom(roomId, socket);
this.handleSocket(socket);
}
sendRoomLocked() {
this.socket.emit('ROOM_LOCKED');
}
async saveRoom(room: Room) {
const json = {
...room,
updatedAt: Date.now(),
};
return getStore().set('rooms', this.roomId, JSON.stringify(json));
}
async destroyRoom() {
return getStore().del('rooms', this.roomId);
}
fetchRoom() {
return new Promise(async (resolve) => {
const res = await getStore().get('rooms', this.roomId);
resolve(JSON.parse(res || '{}'));
});
}
// eslint-disable-next-line class-methods-use-this
joinRoom(roomId: string, socket: Io.Socket) {
return new Promise((resolve, reject) => {
if (getStore().hasSocketAdapter) {
// TODO: what is this?
// getIO()
// .of('/')
// .adapter.remoteJoin(socket.id, roomId, (err: Error) => {
// if (err) {
// reject();
// }
// resolve();
// });
} else {
socket.join(roomId, (err) => {
if (err) {
reject();
}
resolve();
});
}
});
}
async handleSocket(socket: Io.Socket) {
socket.on('ENCRYPTED_MESSAGE', (payload) => {
socket.to(this.roomId).emit('ENCRYPTED_MESSAGE', payload);
});
socket.on('USER_ENTER', async (payload) => {
let room: Room = (await this.fetchRoom()) as Room;
if (_.isEmpty(room)) {
room = {
id: this.roomId,
users: [],
isLocked: false,
createdAt: Date.now(),
};
}
const newRoom: Room = {
...room,
users: [
...(room.users || []),
{
socketId: socket.id,
publicKey: payload.publicKey,
isOwner: (room.users || []).length === 0,
},
],
};
await this.saveRoom(newRoom);
getIO()
.to(this.roomId)
.emit('USER_ENTER', {
...newRoom,
id: this.roomIdOriginal,
});
});
socket.on('TOGGLE_LOCK_ROOM', async (__, callback) => {
const room: Room = (await this.fetchRoom()) as Room;
const user = (room.users || []).find(
(u) => u.socketId === socket.id && u.isOwner
);
if (!user) {
callback({
isLocked: room.isLocked,
});
return;
}
await this.saveRoom({
...room,
isLocked: !room.isLocked,
});
socket.to(this.roomId).emit('TOGGLE_LOCK_ROOM', {
locked: !room.isLocked,
publicKey: user && user.publicKey,
});
callback({
isLocked: !room.isLocked,
});
});
socket.on('disconnect', () => this.handleDisconnect(socket));
socket.on('USER_DISCONNECT', () => this.handleDisconnect(socket));
}
async handleDisconnect(socket: Io.Socket) {
const room: Room = (await this.fetchRoom()) as Room;
const newRoom = {
...room,
users: (room.users || [])
.filter((u) => u.socketId !== socket.id)
.map((u, index) => ({
...u,
isOwner: index === 0,
})),
};
await this.saveRoom(newRoom);
getIO().to(this.roomId).emit('USER_EXIT', newRoom.users);
if (newRoom.users && newRoom.users.length === 0) {
await this.destroyRoom();
}
socket.disconnect(true);
}
}