Skip to content

Commit

Permalink
Merge pull request #100 from modern-agile-team/feature/socket
Browse files Browse the repository at this point in the history
Add(hobiJeong/socket) 채팅 알람기능 로직 추가 및 수정
  • Loading branch information
hobiJeong authored Nov 8, 2023
2 parents ddb124a + 4cedf61 commit 08c5632
Show file tree
Hide file tree
Showing 16 changed files with 379 additions and 154 deletions.
5 changes: 0 additions & 5 deletions src/chat/chat.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import { MongooseModule } from '@nestjs/mongoose';
import { ChatRoom, ChatRoomSchema } from './schemas/chat-room.schemas';
import { Chat, ChatSchema } from './schemas/chat.schemas';
import { ChatImage, ChatImageSchema } from './schemas/chat-image.schemas';
import {
ChatNotification,
ChatNotificationSchema,
} from './schemas/chat-notifiation.schemas';
import { S3Module } from 'src/common/s3/s3.module';
import { ChatRepository } from './repositories/chat.repository';
import { NotificationService } from './services/notification.service';
Expand All @@ -21,7 +17,6 @@ import { AuthModule } from 'src/auth/auth.module';
{ name: ChatRoom.name, schema: ChatRoomSchema },
{ name: Chat.name, schema: ChatSchema },
{ name: ChatImage.name, schema: ChatImageSchema },
{ name: ChatNotification.name, schema: ChatNotificationSchema },
]),
S3Module,
AuthModule,
Expand Down
71 changes: 42 additions & 29 deletions src/chat/controllers/chat.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,97 +3,102 @@ import {
Controller,
Delete,
Get,
Headers,
Param,
ParseIntPipe,
Post,
Query,
Sse,
UploadedFile,
UseGuards,
UseInterceptors,
UsePipes,
ValidationPipe,
} from '@nestjs/common';
import { ChatService } from '../services/chat.service';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiTags } from '@nestjs/swagger';
import { ReceivedUserDto } from '../dto/received-user.dto';
import mongoose from 'mongoose';
import { FileInterceptor } from '@nestjs/platform-express';
import { Users } from 'src/common/decorators/user.decorator';
import { User } from 'src/users/entities/user.entity';
import { ParseObjectIdPipe } from '../parse-object-id.pipe';
import { ApiCreateChatRoom } from '../swagger-decorators/create-chat-room.decorator';
import { ApiGetChatRooms } from '../swagger-decorators/get-chat-rooms.decorator';
import { ApiGetOneChatRoom } from '../swagger-decorators/get-one-chat-room.decorator';
import { ApiDeleteChatRoom } from '../swagger-decorators/delete-chat-room.decorator';
import { ApiGetChats } from '../swagger-decorators/get-chats.decorator';
import { ApiGetChatNotification } from '../swagger-decorators/get-chat-notification.decorator';
import { ApiGetChatUnreadCounts } from '../swagger-decorators/get-chat-unread-counts.decorator';
import { ApiGetChatNotificationSse } from '../swagger-decorators/get-chat-notification-Sse.decorator';
// import { ApiGetChatUnreadCounts } from '../swagger-decorators/get-chat-unread-counts.decorator';
import { TokenService } from 'src/auth/services/token.service';
import { GetUserId } from 'src/common/decorators/get-userId.decorator';
import { JwtAccessTokenGuard } from 'src/config/guards/jwt-access-token.guard';
import { GetNotificationsResponseDto } from '../dto/get-notifications-response.dto';
import { ApiGetChatNotifications } from '../swagger-decorators/get-chat-notifications.decorator';
import { ApiCreateChatImage } from '../swagger-decorators/create-chat-image.decorators';

@ApiTags('CHAT')
@Controller('chat-room')
@UseGuards(JwtAccessTokenGuard)
@UsePipes(ValidationPipe)
@Controller('chat-room')
export class ChatController {
constructor(
private chatService: ChatService,
private tokenService: TokenService,
) {}

@ApiGetChatNotification()
@ApiGetChatNotificationSse()
@Sse('listener')
notificationListener() {
return this.chatService.notificationListener();
}

@ApiGetChatRooms()
@Get()
async getChatRooms(@Users() user: User) {
return this.chatService.getChatRooms(user.id);
async getChatRooms(@GetUserId() userId: number) {
return this.chatService.getChatRooms(userId);
}

@ApiGetOneChatRoom()
@Get(':roomId')
async getOneChatRoom(
@Users() user: User,
@GetUserId() userId: number,
@Param('roomId', ParseObjectIdPipe) roomId: mongoose.Types.ObjectId,
) {
return this.chatService.getOneChatRoom(user.id, roomId);
return this.chatService.getOneChatRoom(userId, roomId);
}

@ApiCreateChatRoom()
@Post()
async createChatRoom(@Users() user: User, @Body() body: ReceivedUserDto) {
return this.chatService.createChatRoom(user.id, body.receiverId);
async createChatRoom(
@GetUserId() userId: number,
@Body() body: ReceivedUserDto,
) {
return this.chatService.createChatRoom(userId, body.receiverId);
}

@ApiDeleteChatRoom()
@Delete(':roomId')
async deleteChatRoom(
@Users() user: User,
@GetUserId() userId: number,
@Param('roomId', ParseObjectIdPipe) roomId: mongoose.Types.ObjectId,
) {
return this.chatService.deleteChatRoom(user.id, roomId);
return this.chatService.deleteChatRoom(userId, roomId);
}

@ApiGetChats()
@Get(':roomId/chat')
async getChats(
@GetUserId() userId: number,
@Param('roomId', ParseObjectIdPipe) roomId: mongoose.Types.ObjectId,
) {
return this.chatService.getChats(roomId);
return this.chatService.getChats(userId, roomId);
}

@ApiOperation({ summary: '특정 채팅방 채팅 이미지 생성' })
@ApiCreateChatImage()
@Post(':roomId/chat/image')
@UseInterceptors(FileInterceptor('file'))
async createChatImage(
@Param('roomId', ParseObjectIdPipe) roomId: mongoose.Types.ObjectId,
@Headers('access_token') accessToken: string,
@GetUserId() senderId: number,
@Body() body: ReceivedUserDto,
@UploadedFile() file: Express.Multer.File,
) {
const senderId = await this.tokenService.decodeToken(accessToken);
return this.chatService.createChatImage(
roomId,
senderId,
Expand All @@ -102,12 +107,20 @@ export class ChatController {
);
}

@ApiGetChatUnreadCounts()
@Get(':roomId/chat/unreads')
async getUnreadCounts(
@Param('roomId', ParseObjectIdPipe) roomId: mongoose.Types.ObjectId,
@Query('after', ParseIntPipe) after: number,
) {
return this.chatService.getUnreadCounts(roomId, after);
@ApiGetChatNotifications()
@Get('chat/notice')
async getChatNotifications(
@GetUserId() userId: number,
): Promise<GetNotificationsResponseDto[]> {
return this.chatService.getChatNotifications(userId);
}

// @ApiGetChatUnreadCounts()
// @Get(':roomId/chat/unreads')
// async getUnreadCounts(
// @Param('roomId', ParseObjectIdPipe) roomId: mongoose.Types.ObjectId,
// @Query('after', ParseIntPipe) after: number,
// ) {
// return this.chatService.getUnreadCounts(roomId, after);
// }
}
19 changes: 19 additions & 0 deletions src/chat/dto/get-notifications-response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import mongoose from 'mongoose';

export class GetNotificationsResponseDto {
_id: mongoose.Types.ObjectId;

chatroom_id: mongoose.Types.ObjectId;

sender: number;

receiver: number;

content: string;

createdAt: Date;

isSeen: false;

count: number;
}
35 changes: 30 additions & 5 deletions src/chat/repositories/chat.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,22 @@ export class ChatRepository {
}

async getChats(roomId: mongoose.Types.ObjectId) {
return this.chatModel.find({ chatroom_id: roomId });
return this.chatModel.find({
chatroom_id: roomId,
});
}

async updateChatIsSeen(receiverId: number, roomId: mongoose.Types.ObjectId) {
await this.chatModel.updateMany(
{
$and: [
{ receiver: receiverId },
{ chatroom_id: roomId },
{ isSeen: false },
],
},
{ $set: { isSeen: true } },
);
}

async createChat(
Expand Down Expand Up @@ -91,9 +106,19 @@ export class ChatRepository {
return returnedChat;
}

async getUnreadCounts(roomId: mongoose.Types.ObjectId, after: number) {
return this.chatModel.count({
$and: [{ chatroom_id: roomId }, { createdAt: { $gt: new Date(after) } }],
});
async getChatNotifications(userId: number) {
const notifications = await this.chatModel
.find({
$and: [{ receiver: userId }, { isSeen: false }],
})
.sort({ createdAt: -1 });

return notifications;
}

// async getUnreadCounts(roomId: mongoose.Types.ObjectId, after: number) {
// return this.chatModel.count({
// $and: [{ chatroom_id: roomId }, { createdAt: { $gt: new Date(after) } }],
// });
// }
}
31 changes: 0 additions & 31 deletions src/chat/schemas/chat-notifiation.schemas.ts

This file was deleted.

6 changes: 5 additions & 1 deletion src/chat/schemas/chat.schemas.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Prop, Schema, SchemaFactory, SchemaOptions } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { ChatRoom } from './chat-room.schemas';
import { IsMongoId, IsNumber, IsString } from 'class-validator';
import { IsBoolean, IsMongoId, IsNumber, IsString } from 'class-validator';

const options: SchemaOptions = {
collection: 'Chat',
Expand All @@ -25,6 +25,10 @@ export class Chat {
@IsString()
@Prop({ required: true })
content: string;

@IsBoolean()
@Prop({ required: true, default: false })
isSeen: boolean;
}

export const ChatSchema = SchemaFactory.createForClass(Chat);
Loading

0 comments on commit 08c5632

Please sign in to comment.