123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
- import { Socket } from 'socket.io';
- import { SocketGateway } from 'src/socket/socket.gateway';
- import { ActionsService } from './actions/actions.service';
- import { DelayService } from './delay/delay.service';
- import { TempService } from './temp/temp.service';
- import { UsersService } from './users/users.service';
- @Injectable()
- export class RoomService {
- constructor(
- @Inject(forwardRef(() => SocketGateway))
- public readonly socketGateway: SocketGateway,
- // @InjectRedis() private readonly redis: Redis,
- private readonly userService: UsersService,
- private readonly actionsService: ActionsService,
- private readonly delayService: DelayService,
- private readonly tempService: TempService,
- ) { }
- public readonly logger = new Logger('user');
- public _sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
- public _userInfo = {} as UserInfoType;
- /**
- * 初始化当前用户数据
- * @param userInfo
- */
- initUserProfile(userInfo: UserInfoParams): UserInfoType {
- const data = {
- id: userInfo.id,
- RoomId: userInfo.roomId,
- Role: userInfo.role,
- UserId: userInfo.userId,
- Avatar: userInfo.avatar,
- Nickname:
- decodeURIComponent(userInfo.nickname) || `用户[${userInfo.userId}]`,
- IsClient: userInfo.isClient,
- IsMuted: true,
- IsWords: true,
- Order: userInfo.role === 'leader' ? 0 : 1,
- JoinTime: Date.now(),
- InTime: Date.now(),
- IsOnline: true,
- };
- return data;
- }
- async handleUserOnline(socket: Socket) {
- if (socket.data.user) {
- socket.data.user.IsOnline = true;
- await this.userService.updateUserOnlineState(
- socket,
- socket.data.user.RoomId,
- socket.data.user.UserId,
- true,
- );
- }
- }
- async handleUserOffline(socket: Socket) {
- await this._sleep(500);
- if (socket.data?.user) {
- this.delayService.handleOffline(socket);
- const { RoomId, UserId, Role } = socket.data.user;
- await this.userService.setRoomEntranceLog(RoomId, UserId, 1);
- if (RoomId && UserId) {
- //标记主动退出房间
- if (socket.data.isRequestExit !== 1 && socket.data.isKick !== 1) {
- const roomUsers = await this.userService.getRoomUsers(RoomId);
- this.socketGateway.server.to(RoomId).emit('action', {
- type: 'user-leave',
- user: socket.data.user,
- members: roomUsers,
- });
- }
- socket.data.user.IsOnline = false;
- await this.userService.updateUserOnlineState(
- socket,
- socket.data.user.RoomId,
- socket.data.user.UserId,
- false,
- );
- await this.handleRoomStatusAction(socket);
- }
- // 压测试直接去除信息
- if (!!socket.data.isBenmark) {
- if (Role === 'leader') {
- this.handleRoomDismiss(RoomId);
- }
- this.userService.deleteRoomUser(RoomId, UserId);
- }
- }
- }
- /**
- * 加入房间
- * @param userInfo
- */
- async handleUserJoin(
- socket: Socket,
- userInfo: UserInfoParams,
- ): Promise<void> {
- const user = this.initUserProfile(userInfo);
- this._userInfo = user;
- socket.data.user = user;
- socket.data.user.roomConfig = userInfo.roomConfig;
- await this.handleUserOnline(socket);
- await this.delayService.handleOnine(socket);
- let blockJoin = false;
- const { RoomId, UserId, Role, roomConfig } = socket.data.user;
- await this.userService.setRoomEntranceLog(RoomId, UserId, 0);
- const _isLeader = Role === 'leader';
- if (RoomId?.length && UserId?.length) {
- //房主设置房间配置
- if (_isLeader) {
- const isValid = await this.userService.isRoomMaster(RoomId, UserId);
- //检查房主非法性
- if (isValid) {
- roomConfig.masterId = UserId;
- this.logger.log(JSON.stringify(userInfo), 'room-config');
- userInfo.roomConfig &&
- (await this.userService.setRoomConfig(RoomId, roomConfig));
- } else {
- blockJoin = true;
- socket.emit('manager-error', {
- type: 'invalid-master',
- code: 303,
- });
- this.logger.warn(`303:invalid-master`, 'join-error');
- socket.disconnect(true);
- }
- }
- const isExist = await this.userService.isUserInRooms(RoomId, UserId);
- const isMax = await this.userService.isMaxRoom(RoomId);
- // console.log('isMaxRoom', isMax);
- if (isMax && Role !== 'leader' && !isExist) {
- this.logger.warn(`308:room-maxing`, 'join-error');
- socket.emit('manager-error', {
- type: 'room-maxing',
- code: 308,
- });
- socket.disconnect(true);
- return;
- }
- if (!blockJoin) {
- if (!isExist) {
- await this.userService.insertUser(socket.data.user);
- } else {
- const updated = await this.userService.updateUsers(socket.data.user);
- if (!updated) {
- socket.emit('manager-error', {
- type: 'invalid-match-role',
- code: 405,
- });
- this.logger.warn(
- `same userId in room not matchRole `,
- 'join-error',
- );
- socket.disconnect(true);
- return;
- }
- }
- this.tempService.init(socket);
- const roomUsers = await this.userService.getRoomUsers(RoomId);
- socket.emit('join', {
- user: socket.data.user,
- members: roomUsers,
- });
- if (!socket.data.user.IsClient) {
- socket.broadcast.to(socket.data.user.RoomId).emit('action', {
- type: 'user-join',
- user: this._userInfo,
- members: roomUsers,
- });
- }
- // this.isJoin = true;
- this.logger.log(
- JSON.stringify(socket.data.user),
- `join-user-${socket.data.user.Role}`,
- );
- }
- } else {
- socket.emit('manager-error', {
- type: 'invalid-room-params',
- code: 403,
- });
- this.logger.warn(`403:not roomId and userId`, 'join-error');
- socket.disconnect(true);
- return;
- }
- }
- /**
- * 房间action大通道
- * @param message
- */
- async handleUserAction(socket: Socket, message: any) {
- this.actionsService.handleAllAction(socket, message);
- }
- /**
- * 房间sync大通道
- * @param message
- */
- async handleSyncAction(socket: Socket, message: any) {
- if (socket.data?.user) {
- const { RoomId } = socket.data?.user;
- socket.broadcast.to(RoomId).emit('sync', message);
- }
- }
- /**
- * 房间paint大通道
- * @param message
- */
- async handlePaintAction(socket: Socket, message: any) {
- if (socket.data?.user) {
- const { RoomId } = socket.data?.user;
- socket.broadcast.to(RoomId).emit('paint', message);
- }
- }
- /**
- * 房间T人
- * @param message
- */
- async handleKickAction(RoomId: string, userId: string) {
- const delUser = await this.userService.getUsersBy(RoomId, userId);
- const roomUsers = await this.userService.getRoomUsers(RoomId);
- const filterRoomUser = roomUsers.filter((i) => i.UserId !== userId);
- this.logger.warn(
- `RoomId: ${RoomId},userId:${userId} info:${JSON.stringify(delUser)}`,
- 'kick-user',
- );
- if (delUser) {
- const sockets = await this.socketGateway.server.fetchSockets();
- this.logger.warn(`当前有效连接数:${sockets.length}`, 'kick-user');
- sockets.forEach((soc) => {
- const kickAction = () => {
- soc.data.isKick = 1;
- soc.emit('action', {
- type: 'user-be-kicked',
- user: delUser,
- });
- soc.disconnect(true);
- };
- if (soc.data.user) {
- const userId = soc.data.user.UserId;
- if (userId === delUser.UserId) {
- this.logger.warn(`kick by UserId`, 'kick-user');
- kickAction();
- }
- } else {
- const userId = soc.id;
- if (userId === delUser.UserId) {
- this.logger.warn(`kick by SocketID`, 'kick-user');
- kickAction();
- }
- }
- });
- }
- const res = await this.userService.deleteRoomUser(RoomId, userId);
- if (res) {
- this.socketGateway.server.to(RoomId).emit('action', {
- type: 'user-exit',
- user: delUser,
- members: filterRoomUser,
- });
- }
- }
- /**
- * 房间全员状态更新
- * @param message
- */
- async handleRoomStatusAction(socket: Socket) {
- const roomId = socket.data.user.RoomId;
- const roomUsers = await this.userService.getRoomUsers(roomId);
- this.socketGateway.server.to(roomId).emit('action', {
- type: 'rooms-status',
- members: roomUsers,
- });
- }
- /**
- * 房间主动退出逻辑
- * @param message
- */
- async handleExitAction(socket: Socket, message: any) {
- const roomId = message?.roomId || socket.data.user?.RoomId;
- const userId = message?.userId || socket.data.user?.UserId;
- if (roomId && userId) {
- const delUser = await this.userService.getUsersBy(roomId, userId);
- this.logger.warn(
- `RoomId: ${roomId},userId:${userId} socketId:${delUser.id}`,
- 'room-exit',
- );
- socket.data.isRequestExit = 1;
- const roomUsers = await this.userService.getRoomUsers(roomId);
- const filterRoomUser = roomUsers.filter((i) => i.UserId !== userId);
- const res = await this.userService.deleteRoomUser(roomId, userId);
- console.log('user-exit', delUser.id, roomId, userId);
- if (res) {
- if (socket.data.user?.Role === 'leader') {
- this.handleRoomDismiss(roomId);
- } else {
- this.socketGateway.server.to(roomId).emit('action', {
- type: 'user-exit',
- user: delUser,
- members: filterRoomUser,
- });
- }
- socket.disconnect(true);
- }
- }
- }
- /**
- * 解散房间
- */
- async handleRoomDismiss(RoomId: string): Promise<boolean> {
- await this.userService.delRoom(RoomId);
- await this.userService.delRoomConfig(RoomId);
- // await this.userService.delRoomMsgs(RoomId);
- this.socketGateway.server
- .to(RoomId)
- .emit('action', { type: 'leader-dismiss' });
- return Promise.resolve(true);
- }
- }
|