diff --git a/src/apis/alarm/pushAlarm.processor.ts b/src/apis/alarm/pushAlarm.processor.ts index 7521c99..2c4b50c 100644 --- a/src/apis/alarm/pushAlarm.processor.ts +++ b/src/apis/alarm/pushAlarm.processor.ts @@ -4,6 +4,7 @@ import { Job } from 'bull'; import { instanceToPlain, plainToInstance } from 'class-transformer'; import { PUSH_ALARM, PUSH_ALARM_TYPE } from 'src/common/consts/enum'; import { RoomIdDto } from 'src/common/dtos/RoomId.dto'; +import { UserIdDto } from 'src/common/dtos/UserId.dto'; import { FcmService } from 'src/fcm/fcm.service'; import { FCM_ADMIN } from 'src/fcm/fcmAdminProvider'; import { RoomRepository } from 'src/repositories/room.repository'; @@ -75,9 +76,14 @@ export class PushAlarmProcessor { const chatAlarmSubDto = plainToInstance(ChatAlarmSubDto, job.data); - const room = await this.roomRepository.getUserAlarmInfoInRoom( - new RoomIdDto(chatAlarmSubDto.roomId), - ); + const [room, userInfo] = await Promise.all([ + this.roomRepository.getUserAlarmInfoInRoom( + new RoomIdDto(chatAlarmSubDto.roomId), + ), + this.userRepository.findOneByUserId( + new UserIdDto(chatAlarmSubDto.sender), + ), + ]); if (!room) { console.log('chat alarm room does not exist'); @@ -94,12 +100,18 @@ export class PushAlarmProcessor { const TokenArray = roomNameAndUserAlarmInfoArray.userFcmInfoList .filter((e) => { + const checkIfIBlockUser = userInfo?.iBlockUsers.find((user) => + user._id.equals(e._id), + ) + ? false + : true; const checkPushReciverIsSender = !e._id.equals(chatAlarmSubDto.sender); const checkAppAlarmOn = e.appAlarm; const checkChatAlarmOn = e.chatAlarm; const checkRoomJoin = !e.isJoin; const checkFCMTokenValid = e.FCMToken.length === 0 ? false : true; return ( + checkIfIBlockUser && checkRoomJoin && checkPushReciverIsSender && checkChatAlarmOn && diff --git a/src/apis/rooms/dto/myRoomInfo.res.dto.ts b/src/apis/rooms/dto/myRoomInfo.res.dto.ts index eb5ebd3..641dee1 100644 --- a/src/apis/rooms/dto/myRoomInfo.res.dto.ts +++ b/src/apis/rooms/dto/myRoomInfo.res.dto.ts @@ -4,6 +4,7 @@ import { Exclude, Expose, Transform, Type } from 'class-transformer'; import { CATEGORY_TYPE } from 'src/common/consts/enum'; import { TransformObjectIdToString } from 'src/common/decorators/Expose.decorator'; import { toKRTimeZone } from 'src/common/funcs/toKRTimezone'; +import { Chat } from 'src/models/chat.model'; import { Geometry } from 'src/models/room.model'; export class MyRoomInfoDto { @@ -37,29 +38,14 @@ export class MyRoomInfoDto { notReadChatCount: number; // 추가됨 @ApiProperty({ - description: - '마지막 채팅 메시지 채팅이 아예없는 경우에는 아직 아무도 채팅을 치지 않았어요 로 보내드립니다.', - type: String, - default: '아직 아무도 채팅을 치지 않았어요', - }) - @Expose() - lastChatMessage: string; - - @ApiProperty({ - type: String, - description: - '한국시간으로 보정된 시간값 , 최신 채팅의 값 , 최신 채팅이 없으면 null 값으로 보내드립니다.', + description: '최신 채팅 정보 채팅 dto로 하나 또는 null', + type: Chat, nullable: true, + default: null, }) - @Transform( - ({ value }) => { - if (value === null) return null; - else return toKRTimeZone(value); - }, - { toClassOnly: true }, - ) + @Type(() => Chat) @Expose() - lastChatTime: Date | null; + lastChat: Chat | null; @Type(() => Geometry) @Expose({ toClassOnly: true }) diff --git a/src/apis/rooms/rooms.service.ts b/src/apis/rooms/rooms.service.ts index 2866c9e..6d3fecb 100644 --- a/src/apis/rooms/rooms.service.ts +++ b/src/apis/rooms/rooms.service.ts @@ -290,8 +290,20 @@ export class RoomsService { return null; } const recentChatInfo = await this.chatService.makeRecentChatInfo(user); - const myRoomInfoDto = { ...roomInfo, ...recentChatInfo }; - return myRoomInfoDto; + if (recentChatInfo.lastChat) { + const recentChatSenderId = recentChatInfo.lastChat.sender._id; + let iBlock = false; + if (user.iBlockUsers.find((e) => e._id.equals(recentChatSenderId))) { + iBlock = true; + } + + recentChatInfo.lastChat.iBlock = iBlock; + const myRoomInfoDto = { ...roomInfo, ...recentChatInfo }; + return myRoomInfoDto; + } else { + const myRoomInfoDto = { ...roomInfo, ...recentChatInfo }; + return myRoomInfoDto; + } } @returnValueToDto(ResShortCutRoomDto) async getMyFavorite(userId: UserIdDto) { diff --git a/src/chat/chat.service.ts b/src/chat/chat.service.ts index 2557701..7fac584 100644 --- a/src/chat/chat.service.ts +++ b/src/chat/chat.service.ts @@ -12,7 +12,7 @@ export class ChatService { async makeRecentChatInfo(user: User): Promise { if (!user.myRoom) { - return new RecentChatInfoDto(); + return new RecentChatInfoDto(0, null); } // 유저에 lastChat 정보가 없을때 if (!user.lastChat) { @@ -21,13 +21,9 @@ export class ChatService { new RoomIdDto(user.myRoom._id), ); if (!messages.length) { - return new RecentChatInfoDto(); + return new RecentChatInfoDto(0, null); } - return new RecentChatInfoDto( - messages.length, - messages[0].message, - messages[0].createdAt, - ); + return new RecentChatInfoDto(messages.length, messages[0]); } else { // 유저에 lastChat 정보가 있을때 커서기반 @@ -37,24 +33,18 @@ export class ChatService { ); // 오래지나서 채팅이 다 삭제되었을 때 if (!messages.length) { - return new RecentChatInfoDto(); + return new RecentChatInfoDto(0, null); } // 내가 마지막으로 읽은 채팅이 최신 채팅일 때 - console.log(messages); if (messages.length == 1) { - return new RecentChatInfoDto( - 0, - messages[0].message, - messages[0].createdAt, - ); + return new RecentChatInfoDto(0, messages[0]); } // remove first index + + console.log(messages); + messages.pop(); - return new RecentChatInfoDto( - messages.length, - messages[0].message, - messages[0].createdAt, - ); + return new RecentChatInfoDto(messages.length, messages[0]); } // message 길이가 0이면 } diff --git a/src/chat/dto/recentChatInfo.dto.ts b/src/chat/dto/recentChatInfo.dto.ts index ce9c07a..818696d 100644 --- a/src/chat/dto/recentChatInfo.dto.ts +++ b/src/chat/dto/recentChatInfo.dto.ts @@ -1,15 +1,11 @@ +import { Chat } from 'src/models/chat.model'; + export class RecentChatInfoDto { - constructor( - notReadChatCount = 0, - lastChatMessage = '아직 아무도 채팅을 치지 않았어요', - lastChatTime: Date | null = null, - ) { + constructor(notReadChatCount: number, lastChat: Chat | null) { this.notReadChatCount = notReadChatCount; - this.lastChatMessage = lastChatMessage; - this.lastChatTime = lastChatTime; + this.lastChat = lastChat; } notReadChatCount: number; - lastChatMessage: string; - lastChatTime: Date | null; + lastChat: Chat | null; } diff --git a/src/models/chat.model.ts b/src/models/chat.model.ts index 43e0f85..c9fc1b8 100644 --- a/src/models/chat.model.ts +++ b/src/models/chat.model.ts @@ -4,8 +4,11 @@ import { Document, Types } from 'mongoose'; import { IsObjectId } from 'class-validator-mongo-object-id'; import { CHAT_TYPE } from 'src/common/consts/enum'; import { TransformObjectIdToString } from 'src/common/decorators/Expose.decorator'; -import { Transform, Type } from 'class-transformer'; +import { Expose, Transform, Type } from 'class-transformer'; import { toKRTimeZone } from 'src/common/funcs/toKRTimezone'; +import { User } from './user.model'; +import { UserProfileDto } from 'src/common/dtos/UserProfile.dto'; +import { ApiProperty } from '@nestjs/swagger'; const options: SchemaOptions = { collection: 'chat', @@ -16,16 +19,27 @@ const options: SchemaOptions = { export class Chat { @TransformObjectIdToString({ toClassOnly: true }) @Type(() => Types.ObjectId) + @Expose() _id: Types.ObjectId; @Prop({ required: true, type: Types.ObjectId, ref: 'room' }) @IsObjectId() room: Types.ObjectId; - @Prop({ required: true, type: Types.ObjectId, ref: 'user' }) + @ApiProperty({ + description: '채팅 작성자', + type: UserProfileDto, + }) + @Prop({ required: true, type: Types.ObjectId, ref: 'User' }) + @Type(() => UserProfileDto) @IsObjectId() - sender: Types.ObjectId; + @Expose() + sender: User; + @ApiProperty({ + description: '채팅 칠시에 안에 있는지 없는지 정보', + type: Boolean, + }) @Prop({ required: true, }) @@ -33,23 +47,44 @@ export class Chat { @IsBoolean() inside: boolean; + @ApiProperty({ + description: '1 일시 질문 0 일시 기본', + enum: CHAT_TYPE, + }) @Prop({ required: true, }) @IsNotEmpty() @IsEnum(CHAT_TYPE) + @Expose() type: CHAT_TYPE; + @ApiProperty({ + description: '1 일시 질문 0 일시 기본', + type: String, + }) @Prop({ required: true, }) @IsNotEmpty() @IsString() + @Expose() message: string; - // @Transform(({ value }) => toKRTimeZone(value), { toClassOnly: true }) - // @Expose() + @ApiProperty({ + description: '한국시간으로 보정된 시간값', + type: String, + }) + @Transform(({ value }) => toKRTimeZone(value), { toClassOnly: true }) + @Expose() createdAt: Date; + + @ApiProperty({ + description: '내가 차단했는지 정보', + type: Boolean, + }) + @Expose() + iBlock: boolean; } export const ChatSchema = SchemaFactory.createForClass(Chat); diff --git a/src/models/question.model.ts b/src/models/question.model.ts index 2ddcab6..4f61f99 100644 --- a/src/models/question.model.ts +++ b/src/models/question.model.ts @@ -40,7 +40,7 @@ export class Comment { comment: string; @ApiProperty({ - description: '댓글 작성자', + description: '질문 작성자', type: UserProfileDto, }) @Prop({ diff --git a/src/repositories/chat.repository.ts b/src/repositories/chat.repository.ts index a060338..db6e040 100644 --- a/src/repositories/chat.repository.ts +++ b/src/repositories/chat.repository.ts @@ -4,6 +4,7 @@ import { Model } from 'mongoose'; import { Chat } from 'src/models/chat.model'; import { RoomIdDto } from 'src/common/dtos/RoomId.dto'; import { ChatIdDto } from 'src/common/dtos/ChatId.dto'; +import { UserProfileSelect } from 'src/common/dtos/UserProfile.dto'; @Injectable() export class ChatRepository { @@ -22,6 +23,10 @@ export class ChatRepository { room: roomIdDto.roomId, _id: { $gte: chatIdDto.chatId }, }) + .populate({ + path: 'sender', + select: UserProfileSelect, + }) .sort({ createdAt: -1 }) .limit(101) .lean(); @@ -33,6 +38,10 @@ export class ChatRepository { .find({ room: roomIdDto.roomId, }) + .populate({ + path: 'sender', + select: UserProfileSelect, + }) .sort({ createdAt: -1 }) .limit(100) .lean();