|
@@ -0,0 +1,305 @@
|
|
|
|
+import { pubClient } from "../connection/redis.js";
|
|
|
|
+import { ROLES, CODEMEG, EVENT, FROMTYPE } from "../enum/index.js";
|
|
|
|
+import { io } from "../core/io.js";
|
|
|
|
+import { logger } from "../core/logger.js";
|
|
|
|
+import { updateUser, removeRoomAllUsers, getAllRoomUsers, updateRoomUser } from "../service/userService.js";
|
|
|
|
+import { watchRoomService } from "../service/watchRoomService.js";
|
|
|
|
+import { setRoomConfig, getRoomConfig } from "../service/roomConfigService.js";
|
|
|
|
+import { getSig } from "../core/getSig.js";
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 检查是否是房主
|
|
|
|
+ */
|
|
|
|
+const isHoster = (role) => {
|
|
|
|
+ return String(role).toLowerCase() === ROLES.LEADER;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 创建房间
|
|
|
|
+ * @param {*} roomId
|
|
|
|
+ * @param {*} userId
|
|
|
|
+ * @param {*} user
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+const buildRoom = async (roomId, userId, user) => {
|
|
|
|
+ const hasJoin = await pubClient.HVALS(roomId, userId);
|
|
|
|
+ if (hasJoin.length === 0) {
|
|
|
|
+ logger.info("buildRoom", { roomId });
|
|
|
|
+ await pubClient.hSet(roomId, userId, JSON.stringify(user));
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 关闭房间
|
|
|
|
+ * @param {*} roomId
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+const removeRoom = async (roomId) => {
|
|
|
|
+ logger.info("removeRoom", { roomId });
|
|
|
|
+ await pubClient.del(roomId);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 加入房间
|
|
|
|
+ * @param {*} roomId
|
|
|
|
+ * @param {*} userId
|
|
|
|
+ * @param {*} user
|
|
|
|
+ */
|
|
|
|
+const joinRoom = async (roomId, userId, user) => {
|
|
|
|
+ logger.info("joinRoom", { roomId });
|
|
|
|
+ try {
|
|
|
|
+ const hasRoom = await pubClient.exists(roomId);
|
|
|
|
+ if (hasRoom) {
|
|
|
|
+ await pubClient.hSet(roomId, userId, JSON.stringify(user));
|
|
|
|
+ } else {
|
|
|
|
+ logger.info("no room join");
|
|
|
|
+ }
|
|
|
|
+ return Promise.resolve();
|
|
|
|
+ } catch (error) {
|
|
|
|
+ logger.error(error);
|
|
|
|
+ return Promise.reject(error);
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 离开房间
|
|
|
|
+ * @param {*} roomId
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+const leaveRoom = async (roomId, userId) => {
|
|
|
|
+ logger.info("leaveRoom", roomId);
|
|
|
|
+ await pubClient.hDel(roomId, userId);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 加入房间
|
|
|
|
+ * @param {*} clientRoom
|
|
|
|
+ * @param {*} socket
|
|
|
|
+ */
|
|
|
|
+const joinRoomAction = async (roomId, userId, user, socket) => {
|
|
|
|
+ const isJoinRoom = await pubClient.hExists(roomId, userId);
|
|
|
|
+ await joinRoom(roomId, userId, user);
|
|
|
|
+ if (!isJoinRoom) {
|
|
|
|
+ logger.info("加入房间 :", { userId, roomId, user });
|
|
|
|
+ socket.join(roomId);
|
|
|
|
+ const AllRoomUsers = await getAllRoomUsers(roomId);
|
|
|
|
+ const roomConfig = await getRoomConfig(roomId);
|
|
|
|
+ socket.broadcast.emit(EVENT.roomIn, {
|
|
|
|
+ user,
|
|
|
|
+ roomsPerson: AllRoomUsers,
|
|
|
|
+ roomsConfig: roomConfig,
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ logger.info(`已加入房间 :`, { userId });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+/**
|
|
|
|
+ * 离开房间
|
|
|
|
+ * @param {*} clientRoom
|
|
|
|
+ * @param {*} userUniqueId
|
|
|
|
+ * @param {*} roomUniqueId
|
|
|
|
+ * @param {*} socket
|
|
|
|
+ */
|
|
|
|
+export const leaveRoomAction = async (roomId, userId, user, socket) => {
|
|
|
|
+ logger.info("离开房间", userId);
|
|
|
|
+ socket.leave(roomId);
|
|
|
|
+ await leaveRoom(roomId, userId);
|
|
|
|
+ const AllRoomUsers = await getAllRoomUsers(roomId);
|
|
|
|
+ const roomConfig = await getRoomConfig(roomId);
|
|
|
|
+ socket.broadcast.to(roomId).emit(EVENT.roomOut, {
|
|
|
|
+ user,
|
|
|
|
+ roomsPerson: AllRoomUsers,
|
|
|
|
+ roomsConfig: roomConfig,
|
|
|
|
+ });
|
|
|
|
+ socket.broadcast.to(roomId).emit(EVENT.someOneLeaveRoom, {
|
|
|
|
+ user,
|
|
|
|
+ roomsPerson: AllRoomUsers,
|
|
|
|
+ });
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 房主关闭房间
|
|
|
|
+ * @param {*} clientRoom
|
|
|
|
+ * @param {*} userUniqueId
|
|
|
|
+ * @param {*} roomUniqueId
|
|
|
|
+ * @param {*} socket
|
|
|
|
+ */
|
|
|
|
+const closeRoomAction = async (roomId, userId, user, socket) => {
|
|
|
|
+ logger.info("房主关闭房间", userId);
|
|
|
|
+ socket.leave(roomId);
|
|
|
|
+ await removeRoomAllUsers(roomId);
|
|
|
|
+ socket.broadcast.emit(EVENT.roomClose, { code: 3002, msg: CODEMEG[3002] });
|
|
|
|
+};
|
|
|
|
+export async function roomController(socket) {
|
|
|
|
+ let user = socket.handshake.query;
|
|
|
|
+ const { roomId, userId, sceneNum, isClient, role, userLimitNum, sceneNumber, roomType, from, enableTalk } = user;
|
|
|
|
+ if (user) {
|
|
|
|
+ // const webRoomId = `${roomId}_${sceneNum}_web`;
|
|
|
|
+ // const clientRoom = `${userId}${roomId}`;
|
|
|
|
+ const oneSceneNum = sceneNumber || sceneNum;
|
|
|
|
+ const userUniqueId = `user-${userId}`;
|
|
|
|
+ const roomUniqueId = `room-${roomId}_${oneSceneNum}_web`;
|
|
|
|
+ const syncId = `sync-${userId}-${roomId}`;
|
|
|
|
+ // const userLimitNum = userLimitNum || process.env.US
|
|
|
|
+ if ("roomId" in user && "userId" in user) {
|
|
|
|
+ user.sig = getSig(userId);
|
|
|
|
+ const userObj = { ...user, isConnected: true, roomType: roomType || "" };
|
|
|
|
+
|
|
|
|
+ updateUser(userUniqueId, userObj);
|
|
|
|
+ // await pubClient.hSet(userUniqueId, user);
|
|
|
|
+ // await pubClient.expire(userUniqueId, 60 * 60 * 24);
|
|
|
|
+ // 房主自动创建房间
|
|
|
|
+
|
|
|
|
+ if (isHoster(role)) {
|
|
|
|
+ if ([FROMTYPE.MiniAPP].includes(Number(from))) {
|
|
|
|
+ logger.debug("房主自动创建房间 :", { roomId: roomUniqueId, userId: userUniqueId, user });
|
|
|
|
+ buildRoom(roomUniqueId, userUniqueId, user);
|
|
|
|
+ await setRoomConfig(roomUniqueId, {
|
|
|
|
+ userLimitNum,
|
|
|
|
+ enableTalk: enableTalk === "true" ? true : false,
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ socket.join(roomUniqueId);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ logger.info("user-query-不存在 :", socket.handshake.query);
|
|
|
|
+ // socket.disconnect();
|
|
|
|
+ }
|
|
|
|
+ // watchRoomStatus(roomUniqueId, socket);
|
|
|
|
+
|
|
|
|
+ socket.on(EVENT.startCall, startCallAction.bind(null, roomUniqueId, userUniqueId, user, socket));
|
|
|
|
+ socket.on(EVENT.stopCall, stopCallAction.bind(null, roomUniqueId, userUniqueId, user, socket));
|
|
|
|
+
|
|
|
|
+ socket.on(EVENT.action, (data) => {
|
|
|
|
+ console.log("room -action");
|
|
|
|
+ socket.broadcast.to(roomUniqueId).emit(EVENT.action, data);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 通知 baseView 减少大量通知
|
|
|
|
+ socket.on(EVENT.webSyncAction, (data) => {
|
|
|
|
+ if ([FROMTYPE.base].includes(Number(from))) {
|
|
|
|
+ socket.broadcast.to(roomUniqueId).emit(EVENT.webSyncAction, data);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ socket.onAny((event, data) => {
|
|
|
|
+ // console.log(`onAny:get ${event}`);
|
|
|
|
+ console.log(`onAny:get ${event}, data:${JSON.stringify(data)}`);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // test
|
|
|
|
+ socket.on(EVENT.changeRoomEnableTalk, async (data) => {
|
|
|
|
+ // this._roomsConfig[roomId].enableTalk = data;
|
|
|
|
+ await setRoomConfig(roomUniqueId, data);
|
|
|
|
+ const roomConfig = await getRoomConfig(roomUniqueId);
|
|
|
|
+ socket.broadcast.to(roomUniqueId).emit(EVENT.changeRoomEnableTalk, roomConfig);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ socket.on(EVENT.changeOnlineStatus, async (data) => {
|
|
|
|
+ user.onlineStatus = data.status;
|
|
|
|
+ const AllRoomUsers = await getAllRoomUsers(roomUniqueId);
|
|
|
|
+ await updateRoomUser(roomUniqueId, userUniqueId, user);
|
|
|
|
+ let actionName = user.onlineStatus ? "inRoom" : "leaveRoom";
|
|
|
|
+ logger.info("changeOnlineStatus", user);
|
|
|
|
+ socket.broadcast.to(roomUniqueId).emit(EVENT.roomPersonChange, {
|
|
|
|
+ roomsPerson: AllRoomUsers,
|
|
|
|
+ actionName,
|
|
|
|
+ user,
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ socket.on("disconnect", async (reason) => {
|
|
|
|
+ // leaveRoom({ clientRoom, userUniqueId, roomUniqueId, socket });
|
|
|
|
+ // watchRoomWithMaster(roomUniqueId, socket);
|
|
|
|
+ console.log("reason", reason);
|
|
|
|
+ if (reason === "transport close") {
|
|
|
|
+ // 主动离开
|
|
|
|
+ shotGunLeaveAction(
|
|
|
|
+ {
|
|
|
|
+ syncId,
|
|
|
|
+ roomId: roomUniqueId,
|
|
|
|
+ userId: userUniqueId,
|
|
|
|
+ },
|
|
|
|
+ socket,
|
|
|
|
+ user,
|
|
|
|
+ );
|
|
|
|
+ } else {
|
|
|
|
+ // 被动离开
|
|
|
|
+ // disconnectAction(
|
|
|
|
+ // {
|
|
|
|
+ // syncId,
|
|
|
|
+ // roomId: roomUniqueId,
|
|
|
|
+ // userId: userUniqueId,
|
|
|
|
+ // },
|
|
|
|
+ // socket,
|
|
|
|
+ // user,
|
|
|
|
+ // );
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ socket.on("reconnect", () => {
|
|
|
|
+ console.log("reconnect");
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const shotGunLeaveAction = async (ids, socket, user) => {
|
|
|
|
+ console.log("主动离开");
|
|
|
|
+ const { syncId, roomId, userId } = ids;
|
|
|
|
+ socket.leave(syncId);
|
|
|
|
+ socket.leave(roomId);
|
|
|
|
+ await pubClient.del(syncId);
|
|
|
|
+ await pubClient.del(userId);
|
|
|
|
+
|
|
|
|
+ // if (isHoster(user.role)) {
|
|
|
|
+ // await pubClient.del(roomId);
|
|
|
|
+ // }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const disconnectAction = async (ids, socket, user) => {
|
|
|
|
+ const { roomId, userId } = ids;
|
|
|
|
+ const userObj = { ...user, isConnected: false };
|
|
|
|
+ updateUser(userId, userObj);
|
|
|
|
+ watchRoomService(roomId, userId, socket);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const startCallAction = async (roomId, userId, user, socket) => {
|
|
|
|
+ try {
|
|
|
|
+ if (!isHoster(user.role)) {
|
|
|
|
+ await joinRoomAction(roomId, userId, user, socket);
|
|
|
|
+ } else {
|
|
|
|
+ const hasRoom = await pubClient.hVals(roomId);
|
|
|
|
+ if (hasRoom.length === 0) {
|
|
|
|
+ logger.debug("房主主动创建房间 :", { roomId, userId });
|
|
|
|
+ await buildRoom(roomId, userId, user);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ user.isInRoom = true;
|
|
|
|
+ const AllRoomUsers = await getAllRoomUsers(roomId);
|
|
|
|
+ const roomConfig = await getRoomConfig(roomId);
|
|
|
|
+ await updateRoomUser(roomId, userId, user);
|
|
|
|
+ logger.info("roomId", roomId);
|
|
|
|
+ logger.info("AllRoomUsers", AllRoomUsers.length);
|
|
|
|
+
|
|
|
|
+ socket.broadcast.to(roomId).emit(EVENT.someOneInRoom, {
|
|
|
|
+ user,
|
|
|
|
+ roomsPerson: AllRoomUsers,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ socket.emit(EVENT.roomIn, {
|
|
|
|
+ user,
|
|
|
|
+ roomsPerson: AllRoomUsers,
|
|
|
|
+ roomsConfig: roomConfig,
|
|
|
|
+ });
|
|
|
|
+ } catch (error) {
|
|
|
|
+ // console.error("startCallAction:", error);
|
|
|
|
+ logger.error("startCallAction:", error);
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const stopCallAction = (roomId, userId, user, socket) => {
|
|
|
|
+ if (!isHoster(user.role)) {
|
|
|
|
+ leaveRoomAction(roomId, userId, user, socket);
|
|
|
|
+ } else {
|
|
|
|
+ closeRoomAction(roomId, userId, user, socket);
|
|
|
|
+ }
|
|
|
|
+};
|