gemercheung преди 2 години
родител
ревизия
f3393c87a8

+ 4 - 4
src/app.controller.ts

@@ -5,8 +5,8 @@ import { AppService } from './app.service';
 export class AppController {
   constructor(private readonly appService: AppService) {}
 
-  @Get()
-  getHello(): string {
-    return this.appService.getHello();
-  }
+  // @Get()
+  // getHello(): string {
+  //   return this.appService.getHello();
+  // }
 }

+ 2 - 1
src/app.module.ts

@@ -12,6 +12,7 @@ import { ThrottlerModule } from '@nestjs/throttler';
 import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
 import { RoomModule } from './room/room.module';
 // import { SocketModule } from './socket/socket.module';
+import { RoomManagerModule } from './room-manager/room-manager.module';
 
 const url = `redis://:${process.env.REDIS_PASSWORD}@${process.env.REDIS_HOST}:${process.env.REDIS_PORT}/${process.env.REDIS_DB}`;
 
@@ -32,7 +33,7 @@ const storeThor = ThrottlerModule.forRootAsync({
   inject: [RedisService],
 });
 @Module({
-  imports: [config, redisMo, storeThor, RoomModule],
+  imports: [config, redisMo, storeThor, RoomModule, RoomManagerModule],
   controllers: [AppController],
   providers: [AppService],
   exports: [],

+ 15 - 0
src/room-manager/dto/danmaku.dto.ts

@@ -0,0 +1,15 @@
+import { ApiProperty } from '@nestjs/swagger';
+
+export class DanmakuDto {
+  @ApiProperty()
+  nickname: string;
+  @ApiProperty()
+  userId: string;
+  @ApiProperty()
+  text: string;
+  @ApiProperty()
+  mode: string;
+}
+export class DanmakuAllDto {
+  data: DanmakuDto[];
+}

+ 52 - 0
src/room-manager/room-manager.controller.ts

@@ -0,0 +1,52 @@
+import {
+  Controller,
+  Get,
+  Post,
+  Body,
+  Patch,
+  Param,
+  Delete,
+} from '@nestjs/common';
+import { RoomManagerService } from './room-manager.service';
+import { DanmakuDto } from './dto/danmaku.dto';
+import { ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger';
+
+@Controller('room-manager')
+export class RoomManagerController {
+  constructor(private readonly roomManagerService: RoomManagerService) {}
+
+  @Get('/danmaku/:id')
+  @ApiOperation({ summary: '获取房间弹幕列表' })
+  @ApiParam({
+    name: 'id',
+    required: true,
+    description: '房间ID',
+    schema: { oneOf: [{ type: 'string' }] },
+    type: 'string',
+  })
+  @ApiResponse({
+    description: 'The record has been successfully created.',
+    type: DanmakuDto,
+  })
+  findDanmakuList(@Param('id') id: string) {
+    return this.roomManagerService.findDanmakuList(id);
+  }
+
+  // @Get(':id')
+  // findOne(@Param('id') id: string) {
+  //   return this.roomManagerService.findOne(+id);
+  // }
+
+  // @Patch(':id')
+  // update(
+  //   @Param('id') id: string,
+  //   @Body() updateRoomManagerDto: UpdateRoomManagerDto,
+  // ) {
+  //   return this.roomManagerService.update(+id, updateRoomManagerDto);
+  // }
+
+  // @Delete(':id')
+  // remove(@Param('id') id: string) {
+  //   return this.roomManagerService.remove(+id);
+  // }
+}

+ 9 - 0
src/room-manager/room-manager.module.ts

@@ -0,0 +1,9 @@
+import { Module } from '@nestjs/common';
+import { RoomManagerService } from './room-manager.service';
+import { RoomManagerController } from './room-manager.controller';
+
+@Module({
+  controllers: [RoomManagerController],
+  providers: [RoomManagerService],
+})
+export class RoomManagerModule {}

+ 44 - 0
src/room-manager/room-manager.service.ts

@@ -0,0 +1,44 @@
+import { InjectRedis } from '@liaoliaots/nestjs-redis';
+import { Injectable } from '@nestjs/common';
+import { Redis } from 'ioredis';
+// import { CreateRoomManagerDto } from './dto/create-room-manager.dto';
+// import { UpdateRoomManagerDto } from './dto/update-room-manager.dto';
+
+@Injectable()
+export class RoomManagerService {
+  constructor(@InjectRedis() private readonly redis: Redis) {}
+  // create(createRoomManagerDto: CreateRoomManagerDto) {
+  //   return 'This action adds a new roomManager';
+  // }
+
+  findAll() {
+    return `This action returns all roomManager`;
+  }
+
+  async findDanmakuList(id: string) {
+    if (id) {
+      const roomList = await this.redis.hgetall(`kankan:socket:roomMsg:${id}`);
+      console.log('roomList', roomList);
+      const data: DanmakuDataType[] = [];
+      Object.keys(roomList).forEach((key, index) => {
+        const temp = {} as DanmakuDataType;
+        temp[`${key}`] = JSON.parse(roomList[key]);
+        data.push(temp);
+      });
+      return data;
+    }
+    return [];
+  }
+
+  findOne(id: number) {
+    return `This action returns a #${id} roomManager`;
+  }
+
+  // update(id: number, updateRoomManagerDto: UpdateRoomManagerDto) {
+  //   return `This action updates a #${id} roomManager`;
+  // }
+
+  // remove(id: number) {
+  //   return `This action removes a #${id} roomManager`;
+  // }
+}

+ 12 - 0
src/room/actions/action.d.ts

@@ -26,3 +26,15 @@ interface DanmakuDataType {
   mode: string;
   text: string;
 }
+
+interface MutedStateType {
+  muted: boolean;
+  type: actionType['users-muted'];
+  userId: string;
+}
+
+interface TypingStateType {
+  words: boolean;
+  type: actionType['users-words'];
+  userId: string;
+}

+ 40 - 2
src/room/actions/actions.service.ts

@@ -2,16 +2,19 @@ import { InjectRedis } from '@liaoliaots/nestjs-redis';
 import { forwardRef, Inject, Injectable } from '@nestjs/common';
 import { Redis } from 'ioredis';
 import { RoomService } from '../room.service';
+import { UsersService } from '../users/users.service';
 @Injectable()
 export class ActionsService {
   constructor(
     @InjectRedis() private readonly redis: Redis,
     @Inject(forwardRef(() => RoomService))
     private roomService: RoomService,
+    @Inject(forwardRef(() => UsersService))
+    private userService: UsersService,
   ) {}
 
   async handleAllAction(data: ActionsParams): Promise<void> {
-    console.log('ActionsParams', data);
+    // console.log('ActionsParams', data);
     switch (data.type) {
       case 'danmumsg':
         const params = {} as DanmakuDataType;
@@ -21,10 +24,28 @@ export class ActionsService {
         params.userId = data.data.UserId;
         this.handleDanmaku(params);
         break;
-
+      case 'users-muted':
+        console.log('users-muted', data);
+        const mutedParams = data as any as MutedStateType;
+        this.roomService._isLeader &&
+          (await this.handleMutedState(mutedParams));
+        break;
+      case 'users-words':
+        const typingParams = data as any as TypingStateType;
+        this.roomService._isLeader &&
+          (await this.handleTypingState(typingParams));
+        break;
       default:
+        this.answer(data);
         break;
     }
+    this.answer(data);
+  }
+  answer(data: any) {
+    // this.roomService.socketGateway._socket
+    //   .to(this.roomService._userInfo.RoomId)
+    //   .emit('action', data);
+    this.roomService.socketGateway._socket.broadcast.emit('action', data);
   }
 
   async handleDanmaku(data: DanmakuDataType) {
@@ -44,4 +65,21 @@ export class ActionsService {
       );
     }
   }
+  async handleMutedState(data: MutedStateType) {
+    if (data) {
+      const roomId = this.roomService._userInfo.RoomId;
+      const userId = data.userId;
+      const mutedState = data.muted;
+
+      await this.userService.updateUserMicState(roomId, userId, mutedState);
+    }
+  }
+  async handleTypingState(data: TypingStateType) {
+    if (data) {
+      const roomId = this.roomService._userInfo.RoomId;
+      const userId = data.userId;
+      const wordsState = data.words;
+      await this.userService.updateUserTypingState(roomId, userId, wordsState);
+    }
+  }
 }

+ 27 - 15
src/room/room.service.ts

@@ -10,7 +10,7 @@ import { UsersService } from './users/users.service';
 export class RoomService {
   constructor(
     @Inject(forwardRef(() => SocketGateway))
-    private readonly socketGateway: SocketGateway,
+    public readonly socketGateway: SocketGateway,
     @InjectRedis() private readonly redis: Redis,
     private readonly userService: UsersService,
     private readonly actionsService: ActionsService,
@@ -25,7 +25,7 @@ export class RoomService {
   private get _userId(): string {
     return this._userInfo.UserId;
   }
-  private get _isLeader(): boolean {
+  public get _isLeader(): boolean {
     return this._userInfo.Role === 'leader';
   }
 
@@ -60,7 +60,7 @@ export class RoomService {
       );
       const roomUsers = await this.userService.getRoomUsers(this._roomId);
       this.isJoin &&
-        this.socketGateway.server.to(this._roomId).emit('action', {
+        this.socketGateway._socket.to(this._roomId).emit('action', {
           type: 'rooms-status',
           members: roomUsers,
         });
@@ -76,7 +76,7 @@ export class RoomService {
         false,
       );
       const roomUsers = await this.userService.getRoomUsers(this._roomId);
-      this.socketGateway.server.to(this._roomId).emit('action', {
+      this.socketGateway._socket.to(this._roomId).emit('action', {
         type: 'rooms-status',
         members: roomUsers,
       });
@@ -106,7 +106,7 @@ export class RoomService {
           );
         } else {
           blockJoin = true;
-          this.socketGateway.server.emit('action', {
+          this.socketGateway._socket.emit('action', {
             type: 'invalid-master',
             code: 303,
           });
@@ -120,17 +120,28 @@ export class RoomService {
 
       if (!blockJoin) {
         if (!isExist) {
-          this.userService.insertUser(this._userInfo);
+          await this.userService.insertUser(this._userInfo);
         } else {
-          this.userService.updateUsers(this._userInfo);
+          const updated = await this.userService.updateUsers(this._userInfo);
+          if (!updated) {
+            this.socketGateway._socket.emit('action', {
+              type: 'error',
+              code: 405,
+            });
+            this.logger.warn(
+              `same userId in room not matchRole `,
+              'join-error',
+            );
+            return;
+          }
         }
         const roomUsers = await this.userService.getRoomUsers(this._roomId);
-        this.socketGateway.server.emit('join', {
+        this.socketGateway._socket.emit('join', {
           user: this._userInfo,
           members: roomUsers,
         });
         if (!this._userInfo.IsClient) {
-          this.socketGateway.server.to(this._roomId).emit('action', {
+          this.socketGateway._socket.broadcast.to(this._roomId).emit('action', {
             type: 'user-join',
             user: this._userInfo,
             members: roomUsers,
@@ -143,7 +154,7 @@ export class RoomService {
         );
       }
     } else {
-      this.socketGateway.server.emit('action', { type: 'error', code: 403 });
+      this.socketGateway._socket.emit('action', { type: 'error', code: 403 });
       this.logger.warn(`403:not roomId and userId`, 'join-error');
     }
   }
@@ -153,7 +164,6 @@ export class RoomService {
    */
   async handleUserAction(message: any) {
     this.actionsService.handleAllAction(message);
-    // this.socketGateway.server.to(this._roomId).emit('action', message);
   }
 
   /**
@@ -161,7 +171,7 @@ export class RoomService {
    * @param message
    */
   async handleSyncAction(message: any) {
-    this.socketGateway.server.to(this._roomId).emit('sync', message);
+    this.socketGateway._socket.broadcast.to(this._roomId).emit('sync', message);
   }
 
   /**
@@ -169,7 +179,9 @@ export class RoomService {
    * @param message
    */
   async handlePaintAction(message: any) {
-    this.socketGateway.server.to(this._roomId).emit('paint', message);
+    this.socketGateway._socket.broadcast
+      .to(this._roomId)
+      .emit('paint', message);
   }
 
   /**
@@ -178,7 +190,7 @@ export class RoomService {
    */
   async handleKickAction(userId: string) {
     await this.userService.deleteRoomUser(this._roomId, userId);
-    this.socketGateway.server.to(this._roomId).emit('action', {
+    this.socketGateway._socket.broadcast.to(this._roomId).emit('action', {
       type: 'kick-user',
       data: {
         userId: userId,
@@ -192,7 +204,7 @@ export class RoomService {
   async handleRoomDismiss(): Promise<void> {
     await this.userService.delRoom(this._roomId);
     await this.userService.delRoomConfig(this._roomId);
-    this.socketGateway.server
+    this.socketGateway._socket
       .to(this._roomId)
       .emit('action', { type: 'leader-dismiss' });
   }

+ 55 - 13
src/room/users/users.service.ts

@@ -21,24 +21,28 @@ export class UsersService {
       JSON.stringify(useInfo),
     );
   }
-  async updateUsers(useInfo: UserInfoType): Promise<void> {
+  async updateUsers(useInfo: UserInfoType): Promise<boolean> {
     const user = await this.redis.hget(
       `kankan:socket:rooms:${useInfo.RoomId}`,
       useInfo.UserId,
     );
     const userObj = JSON.parse(user) as any as UserInfoType;
-    const updateInfo: UserInfoType = Object.assign({}, userObj, {
-      JoinTime: useInfo.JoinTime,
-      InTime: useInfo.InTime,
-      Avatar: useInfo.Avatar,
-      Nickname: useInfo.Nickname,
-    });
-
-    await this.redis.hset(
-      `kankan:socket:rooms:${useInfo.RoomId}`,
-      useInfo.UserId,
-      JSON.stringify(updateInfo),
-    );
+    if (userObj.Role === useInfo.Role) {
+      const updateInfo: UserInfoType = Object.assign({}, userObj, {
+        JoinTime: useInfo.JoinTime,
+        InTime: useInfo.InTime,
+        Avatar: useInfo.Avatar,
+        Nickname: useInfo.Nickname,
+      });
+      await this.redis.hset(
+        `kankan:socket:rooms:${useInfo.RoomId}`,
+        useInfo.UserId,
+        JSON.stringify(updateInfo),
+      );
+      return true;
+    } else {
+      return false;
+    }
   }
 
   async deleteRoomUser(RoomId: string, UserId: string) {
@@ -81,6 +85,7 @@ export class UsersService {
       return false;
     }
   }
+
   async updateUserOnlineState(
     RoomId: string,
     UserId: string,
@@ -99,4 +104,41 @@ export class UsersService {
       );
     }
   }
+
+  async updateUserMicState(
+    RoomId: string,
+    UserId: string,
+    status = true,
+  ): Promise<void> {
+    const user = await this.redis.hget(`kankan:socket:rooms:${RoomId}`, UserId);
+    if (user) {
+      const userObj: UserInfoType = JSON.parse(user);
+      const updateObj: UserInfoType = Object.assign({}, userObj, {
+        IsMuted: status,
+      });
+      this.redis.hset(
+        `kankan:socket:rooms:${RoomId}`,
+        UserId,
+        JSON.stringify(updateObj),
+      );
+    }
+  }
+  async updateUserTypingState(
+    RoomId: string,
+    UserId: string,
+    status = true,
+  ): Promise<void> {
+    const user = await this.redis.hget(`kankan:socket:rooms:${RoomId}`, UserId);
+    if (user) {
+      const userObj: UserInfoType = JSON.parse(user);
+      const updateObj: UserInfoType = Object.assign({}, userObj, {
+        IsWords: status,
+      });
+      this.redis.hset(
+        `kankan:socket:rooms:${RoomId}`,
+        UserId,
+        JSON.stringify(updateObj),
+      );
+    }
+  }
 }

+ 7 - 5
src/socket/socket.gateway.ts

@@ -25,19 +25,21 @@ console.log('SOCKET_PATH-0', process.env.SOCKET_PATH);
   // parser: require('socket.io-msgpack-parser'),
 })
 export class SocketGateway
-  implements OnGatewayInit, OnGatewayDisconnect, OnGatewayConnection
-{
+  implements OnGatewayInit, OnGatewayDisconnect, OnGatewayConnection {
   constructor(
     @InjectRedis() private readonly redis: Redis,
     private readonly roomService: RoomService,
-  ) {}
+  ) { }
 
   @WebSocketServer() server: Server;
-  async handleConnection(client: any, ...args: any[]) {
+  public _socket: Socket;
+  async handleConnection(client: Socket, ...args: any[]) {
     // console.log('handleConnection', client, args);
+    this._socket = client;
     await this.roomService.handleUserOnline();
   }
-  async handleDisconnect(client: any) {
+  async handleDisconnect(client: Socket) {
+    // this._socket = client;
     await this.roomService.handleUserOffline();
     // console.log('handleDisconnect', client);
   }