UNPKG

uyem

Version:
393 lines 17.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createServer = exports.prisma = void 0; /****************************************************************************************** * Repository: https://github.com/kolserdav/werift-sfu-react.git * File name: main.ts * Author: Sergey Kolmiller * Email: <uyem.ru@gmail.com> * License: MIT * License text: See in LICENSE file * Copyright: kolserdav, All rights reserved (c) * Create Date: Wed Aug 24 2022 14:14:09 GMT+0700 (Krasnoyarsk Standard Time) ******************************************************************************************/ /* eslint-disable import/first */ /* eslint-disable no-case-declarations */ const uuid_1 = require("uuid"); const dotenv_1 = __importDefault(require("dotenv")); dotenv_1.default.config(); const client_1 = require("@prisma/client"); const ws_1 = __importDefault(require("./core/ws")); const rtc_1 = __importDefault(require("./core/rtc")); const interfaces_1 = require("./types/interfaces"); const lib_1 = require("./utils/lib"); const constants_1 = require("./utils/constants"); const db_1 = __importDefault(require("./core/db")); const chat_1 = __importDefault(require("./addons/chat")); const recordVideo_1 = __importDefault(require("./addons/recordVideo")); const settings_1 = __importDefault(require("./addons/settings")); exports.prisma = new client_1.PrismaClient(); const database = new db_1.default({ prisma: exports.prisma }); const chat = new chat_1.default({ prisma: exports.prisma }); process.on('uncaughtException', (err) => { (0, lib_1.log)('error', 'uncaughtException', err); }); process.on('unhandledRejection', (err) => { (0, lib_1.log)('error', 'unhandledRejection', err); }); /** * Create WebRTC SFU server */ function createServer({ port = constants_1.PORT, cors = constants_1.CORS, db = constants_1.DATABASE_URL, onRoomOpen, onRoomClose, onRoomConnect, onRoomDisconnect, checkTokenCb, cloudPath: _cloudPath, logLevel, }, cb) { if (require.main !== module) { if (!db && !constants_1.DATABASE_URL) { (0, lib_1.log)('error', 'DATABASE_URL: not provided', { db, DATABASE_URL: constants_1.DATABASE_URL }, true); return; } (0, lib_1.log)('info', 'Using DATABASE_URL:', (0, lib_1.cleanDbUrl)(db), true); } process.env.DATABASE_URL = db || constants_1.DATABASE_URL; if (!_cloudPath) { /* log('warn', 'Cloud dir path "--cloud" is not set, video recording is not available', { _cloudPath, }); */ } (0, lib_1.setLogLevel)(logLevel); const cloudPath = _cloudPath || constants_1.CLOUD_DIR_PATH; const wss = new ws_1.default({ port, cloudPath, prisma: exports.prisma }); const rtc = new rtc_1.default({ ws: wss, prisma: exports.prisma }); const settings = new settings_1.default({ cloudPath, prisma: exports.prisma }); const recordVideo = new recordVideo_1.default({ settings, rtc, ws: wss, cloudPath, prisma: exports.prisma, }); settings.checkTokenCb = checkTokenCb || settings.checkTokenCb; chat.checkTokenCb = checkTokenCb || chat.checkTokenCb; recordVideo.checkTokenCb = checkTokenCb || recordVideo.checkTokenCb; wss.checkTokenCb = checkTokenCb || wss.checkTokenCb; const getConnectionId = () => { const connId = (0, uuid_1.v4)(); if (wss.sockets[connId]) { return getConnectionId(); } return connId; }; wss.connection.on('connection', (ws, req) => { const { origin } = req.headers; const protocol = req.headers['sec-websocket-protocol']; const notAllowed = cors.split(',').indexOf(origin || '') === -1; const connId = getConnectionId(); if (cors && notAllowed) { const message = 'Block CORS attempt'; (0, lib_1.log)('warn', message, { headers: req.headers }); ws.send(JSON.stringify({ type: interfaces_1.MessageType.SET_ERROR, connId, data: { message, type: 'warn', }, })); ws.close(); return; } ws.on('message', async (message) => { let _data = ''; if (typeof message !== 'string') { _data = message.toString('utf8'); } const rawMessage = wss.parseMessage(_data); if (!rawMessage) { return; } const { type, id } = rawMessage; switch (type) { case interfaces_1.MessageType.GET_USER_ID: const { isRoom, userName, locale } = wss.getMessage(interfaces_1.MessageType.GET_USER_ID, rawMessage).data; await wss.setSocket({ id, ws, connId, isRoom: isRoom || false, userName, locale }); wss.sendMessage({ type: interfaces_1.MessageType.SET_USER_ID, id, data: { name: userName, }, connId, }); break; case interfaces_1.MessageType.GET_ROOM: rtc.handleGetRoomMessage({ message: wss.getMessage(interfaces_1.MessageType.GET_ROOM, rawMessage), port, cors, onRoomConnect, onRoomOpen, }); break; case interfaces_1.MessageType.GET_CHAT_UNIT: chat.setUnit({ roomId: wss.getMessage(interfaces_1.MessageType.GET_CHAT_UNIT, rawMessage).id, userId: wss.getMessage(interfaces_1.MessageType.GET_CHAT_UNIT, rawMessage).data.userId, ws, locale: wss.getMessage(interfaces_1.MessageType.GET_CHAT_UNIT, rawMessage).data.locale, connId, }); break; case interfaces_1.MessageType.GET_SETTINGS_UNIT: settings.setUnit({ roomId: wss.getMessage(interfaces_1.MessageType.GET_SETTINGS_UNIT, rawMessage).id, userId: wss.getMessage(interfaces_1.MessageType.GET_SETTINGS_UNIT, rawMessage).data.userId, ws, locale: wss.getMessage(interfaces_1.MessageType.GET_SETTINGS_UNIT, rawMessage).data.locale, connId, }); break; case interfaces_1.MessageType.GET_CHAT_MESSAGES: chat.getChatMessages(rawMessage); break; case interfaces_1.MessageType.GET_ROOM_GUESTS: const _roomId = wss.getMessage(interfaces_1.MessageType.GET_ROOM_GUESTS, rawMessage).data.roomId; wss.sendMessage({ type: interfaces_1.MessageType.SET_ROOM_GUESTS, id, data: { roomUsers: rtc.rooms[_roomId], muteds: rtc.muteds[_roomId], adminMuteds: rtc.adminMuteds[_roomId], asked: rtc.askeds[_roomId], banneds: rtc.banneds[_roomId], }, connId, }); break; case interfaces_1.MessageType.GET_CLOSE_PEER_CONNECTION: rtc.closePeerConnectionHandler(rawMessage); break; case interfaces_1.MessageType.GET_ROOM_MESSAGE: chat.handleRoomMessage(rawMessage); break; case interfaces_1.MessageType.GET_LOCALE: ws.send(JSON.stringify({ type: interfaces_1.MessageType.SET_LOCALE, data: { locale: (0, lib_1.getLocale)(wss.getMessage(interfaces_1.MessageType.GET_LOCALE, rawMessage).data.locale) .client, }, })); break; case interfaces_1.MessageType.GET_EDIT_MESSAGE: chat.handleEditMessage(rawMessage); break; case interfaces_1.MessageType.GET_CREATE_MESSAGE: chat.handleCreateMessage(rawMessage); break; case interfaces_1.MessageType.GET_CREATE_QUOTE: chat.handleCreateQuote(rawMessage); break; case interfaces_1.MessageType.GET_DELETE_MESSAGE: chat.handleDeleteMessage(rawMessage); break; case interfaces_1.MessageType.GET_BLOCK_CHAT: chat.getBlockChatHandler(rawMessage); break; case interfaces_1.MessageType.GET_TO_MUTE: rtc.getToMuteHandler(rawMessage); break; case interfaces_1.MessageType.GET_TO_BAN: rtc.handleGetToBan(rawMessage); break; case interfaces_1.MessageType.GET_TO_UNMUTE: rtc.handleGetToUnMute(rawMessage); break; case interfaces_1.MessageType.GET_RECORD: recordVideo.handleVideoRecord(rawMessage); break; case interfaces_1.MessageType.GET_VIDEO_DELETE: settings.videoDeleteHandler(rawMessage); break; case interfaces_1.MessageType.GET_TO_UNBAN: rtc.handleGetToUnBan(rawMessage); break; case interfaces_1.MessageType.GET_MUTE_FOR_ALL: rtc.getMuteForAllHandler(rawMessage); break; case interfaces_1.MessageType.GET_MUTE: rtc.getMuteHandler(rawMessage); break; case interfaces_1.MessageType.GET_VIDEO_FIND_MANY: settings.videoFindManyHandler(rawMessage); break; case interfaces_1.MessageType.GET_ASK_FLOOR: rtc.setAskedFloorHandler(rawMessage); break; case interfaces_1.MessageType.GET_VIDEO_TRACK: rtc.getVideoTrackHandler(rawMessage); break; case interfaces_1.MessageType.GET_VIDEO_SETTINGS: recordVideo.getVideoSettingsHandler(rawMessage); break; case interfaces_1.MessageType.GET_TO_ADMIN: rtc.getToAdminHandler(rawMessage); break; case interfaces_1.MessageType.GET_VIDEO_FIND_FIRST: settings.videoFindFirstHandler(rawMessage); break; case interfaces_1.MessageType.GET_VIDEO_UPDATE: settings.videoUpdateHandler(rawMessage); break; default: wss.sendMessage(rawMessage); } }); const getUserId = (_connId) => { let userId = ''; const keys = Object.keys(wss.sockets); keys.every((item) => { const sock = item.split(rtc.delimiter); if (sock[1] === _connId) { // eslint-disable-next-line prefer-destructuring userId = sock[0]; return false; } return true; }); return userId; }; // eslint-disable-next-line no-param-reassign ws.on('close', async () => { let skip = false; if (protocol === 'chat') { Object.keys(chat.users).every((item) => { if (skip) { return false; } Object.keys(chat.users[item]).every((_item) => { if (chat.users[item][_item].connId === connId) { chat.cleanUnit({ roomId: item, userId: _item }); skip = true; return false; } return true; }); return true; }); } else if (protocol === 'settings') { Object.keys(settings.users).every((item) => { if (skip) { return false; } Object.keys(settings.users[item]).every((_item) => { if (settings.users[item][_item].connId === connId) { settings.cleanUnit({ roomId: item, userId: _item }); skip = true; return false; } return true; }); return true; }); } if (protocol !== 'room') { return; } const userId = getUserId(connId); if (userId) { const socketId = wss.getSocketId(userId, connId); if (wss.sockets[socketId]) { (0, lib_1.log)('log', 'Delete socket', { userId, connId }); delete wss.sockets[socketId]; } else { (0, lib_1.log)('warn', 'No socket delete', { s: Object.keys(wss.sockets) }); } database.changeUserOnline({ userId, online: false }); (0, lib_1.log)('info', 'User disconnected', userId); const roomKeys = Object.keys(rtc.rooms); roomKeys.every((item) => { let index = -1; rtc.rooms[item].every((_item, i) => { if (_item.id.toString() === userId) { index = i; return false; } return true; }); if (index !== -1) { rtc.rooms[item].splice(index, 1); if (onRoomDisconnect) { onRoomDisconnect({ roomId: item, userId, roomUsers: rtc.rooms[item] }); } if (rtc.onRoomDisconnect) { rtc.onRoomDisconnect({ roomId: item, userId, roomUsers: rtc.rooms[item] }); } // delete mute const mute = rtc.muteds[item].indexOf(userId); if (mute !== -1) { rtc.muteds[item].splice(mute, 1); } // delete offVideo const offVideo = rtc.offVideo[item].indexOf(userId); if (offVideo !== -1) { rtc.offVideo[item].splice(offVideo, 1); } // delete askeds const askeds = rtc.askeds[item].indexOf(userId); if (askeds !== -1) { rtc.askeds[item].splice(askeds, 1); } rtc.sendCloseMessages({ roomId: item, userId }); rtc.cleanConnections(item, userId.toString()); if (rtc.rooms[item].length === 0) { delete rtc.rooms[item]; delete rtc.streams[item]; delete rtc.banneds[item]; delete rtc.askeds[item]; delete rtc.muteForAll[item]; delete rtc.offVideo[item]; delete rtc.peerConnectionsServer[item]; database.changeRoomArchive({ roomId: item.toString(), archive: true }); delete rtc.muteds[item]; delete rtc.adminMuteds[item]; delete chat.users[item]; delete chat.blocked[item]; if (onRoomClose) { onRoomClose({ roomId: item, roomLength: rtc.getRoomLenght(), port }); } } database.deleteGuest({ userId, roomId: item }); delete wss.users[userId]; return false; } return true; }); } }); }); wss.connection.on('listening', () => { (0, lib_1.log)('info', 'Uyem server listen at port:', port, true); if (cb) { cb(wss.connection); } }); } exports.createServer = createServer; if (require.main === module) { createServer({ port: constants_1.PORT, cors: constants_1.CORS, cloudPath: constants_1.CLOUD_DIR_PATH, checkTokenCb: async () => ({ errorCode: 0, unitId: '1', }), }); } //# sourceMappingURL=main.js.map