Skip to content

Commit

Permalink
feat: /channels/notice 구현 #52
Browse files Browse the repository at this point in the history
  • Loading branch information
yubinquitous committed Dec 15, 2023
1 parent cf8c257 commit 63acf79
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 36 deletions.
74 changes: 73 additions & 1 deletion src/channels/channels.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { AuthGuard } from '@nestjs/passport';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { GetUser } from 'src/auth/get-user.decorator';
import { ChannelType } from 'src/common/enum';
import { ChannelEventType, ChannelType } from 'src/common/enum';
import { User } from 'src/users/entities/user.entity';
import { PositiveIntPipe } from '../common/pipes/positiveInt.pipe';
import { ChannelsGateway } from './channels.gateway';
Expand Down Expand Up @@ -73,6 +73,7 @@ export class ChannelsController {
await this.channelsService.createChannel(user.id, channelInfo);

if (user.channelSocketId) {
// 채널 룸에 join
this.channelsGateway.joinChannelRoom(
createChannelResponseDto.channelId.toString(),
user.channelSocketId,
Expand Down Expand Up @@ -149,10 +150,18 @@ export class ChannelsController {
await this.channelsService.createChannelUser(channelUserParamDto);

if (user.channelSocketId) {
// 채널 룸에 join
this.channelsGateway.joinChannelRoom(
channelId.toString(),
user.channelSocketId,
);

// 기존 채널 유저들에게 새로운 유저가 참여했음을 알림
this.channelsGateway.channelNoticeMessage(channelId, {
channelId,
nickname: user.nickname,
eventType: ChannelEventType.JOIN,
});
}

return channelUsersResponseDto;
Expand All @@ -170,6 +179,20 @@ export class ChannelsController {
) {
console.log(channelId);
await this.channelsService.updateChannelUser(user.id, channelId);

if (user.channelSocketId) {
// 채널 룸에서 leave
this.channelsGateway.leaveChannelRoom(
channelId.toString(),
user.channelSocketId,
);
// 기존 채널 유저들에게 해당 유저가 나갔음을 알림
this.channelsGateway.channelNoticeMessage(channelId, {
channelId,
nickname: user.nickname,
eventType: ChannelEventType.EXIT,
});
}
}

@Post('/invite')
Expand Down Expand Up @@ -211,6 +234,20 @@ export class ChannelsController {
const updateChannelUserTypeResponseDto = {
isAdmin: isAdmin,
};

// channelId를 찾아서 해당 채널에 join한 유저들에게 알림
const channelId =
await this.channelsService.findChannelIdByChannelUserId(
receiverChannelUserId,
);
this.channelsGateway.channelNoticeMessage(channelId, {
channelId,
nickname: user.nickname,
eventType: isAdmin
? ChannelEventType.ADMIN
: ChannelEventType.ADMIN_CANCEL,
});

return updateChannelUserTypeResponseDto;
}

Expand All @@ -230,6 +267,17 @@ export class ChannelsController {
giverUserId,
receiverChannelUserId,
);

// channelId를 찾아서 해당 채널에 join한 유저들에게 알림
const channelId =
await this.channelsService.findChannelIdByChannelUserId(
receiverChannelUserId,
);
this.channelsGateway.channelNoticeMessage(channelId, {
channelId,
nickname: user.nickname,
eventType: ChannelEventType.KICK,
});
}

@Patch('/ban')
Expand All @@ -248,6 +296,17 @@ export class ChannelsController {
giverUserId,
receiverChannelUserId,
);

// channelId를 찾아서 해당 채널에 join한 유저들에게 알림
const channelId =
await this.channelsService.findChannelIdByChannelUserId(
receiverChannelUserId,
);
this.channelsGateway.channelNoticeMessage(channelId, {
channelId,
nickname: user.nickname,
eventType: ChannelEventType.BAN,
});
}

@Patch('/mute')
Expand All @@ -262,6 +321,17 @@ export class ChannelsController {
const receiverChannelUserId = updateChannelUserRequestDto.channelUserId;

await this.channelsService.muteChannelUser(user, receiverChannelUserId);

// channelId를 찾아서 해당 채널에 join한 유저들에게 알림
const channelId =
await this.channelsService.findChannelIdByChannelUserId(
receiverChannelUserId,
);
this.channelsGateway.channelNoticeMessage(channelId, {
channelId,
nickname: user.nickname,
eventType: ChannelEventType.MUTE,
});
}

// 채널 목록 조회
Expand Down Expand Up @@ -318,6 +388,7 @@ export class ChannelsController {
invitedUserId: user.id,
invitationId: invitationId,
};

return await this.channelsService.acceptInvitation(
createChannelUserParamDto,
);
Expand All @@ -337,6 +408,7 @@ export class ChannelsController {
cancelingUserId: user.id,
invitationId: invitationId,
};

await this.channelsService.rejectInvitation(deleteInvitationParamDto);
}
}
49 changes: 15 additions & 34 deletions src/channels/channels.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import Redis from 'ioredis';
import { Server, Socket } from 'socket.io';
import { AuthService } from 'src/auth/auth.service';
import { ChannelEventType, UserStatus } from 'src/common/enum';
import { UserStatus } from 'src/common/enum';
import { EVENT_USER_STATUS } from 'src/common/events';
import { WSBadRequestException } from 'src/common/exception/custom-exception';
import { WsExceptionFilter } from 'src/common/exception/custom-ws-exception.filter';
Expand Down Expand Up @@ -186,44 +186,24 @@ export class ChannelsGateway
socket.join(channelRoomName);
}

//소켓 연결 해제 시, 채널 룸에서 leave하는 메서드
@SubscribeMessage('leaveChannelRoom')
async handleleaveChannelRoom(
@ConnectedSocket() client: Socket,
@MessageBody() data: { channelId: number },
) {
const user = await this.authService.getUserFromSocket(client);
if (!user || !client.id || user.channelSocketId !== client.id) {
return WSBadRequestException('유저 정보가 일치하지 않습니다.');
}

const { channelId } = data;
// 채널을 나간 경우, 해당 소켓을 채널 룸에서 leave하는 메서드
async leaveChannelRoom(channelRoomName: string, channelSocketId: string) {
this.logger.log(
`leaveChannelRoom: ${channelRoomName}, ${channelSocketId}`,
);

// 채널유저 유효성 검사
const channelUser = await this.channelUsersRepository.findOne({
where: { userId: user.id, channelId, isBanned: false },
});
if (!channelUser) {
throw WSBadRequestException('채널에 속해있지 않습니다.');
const socket = (await this.server.fetchSockets()).find(
(s) => s.id === channelSocketId,
);
if (!socket) {
return WSBadRequestException('socket이 존재하지 않습니다.');
}
// 채널에 leave한다.
client.leave(channelId.toString());

// this.server
// .to(channelId.toString())
// .emit('message', `${user.nickname}님이 퇴장하셨습니다.`);
// 채널의 다른 유저들에게 퇴장을 알린다.
this.channelNoticeMessage(channelId, {
nickname: user.nickname,
eventType: ChannelEventType.EXIT,
});

// 어느 채널에 퇴장했는지 알려주기 위해 front에 emit한다.
client.emit('leaveChannelRoom', channelId.toString());
this.logger.log(`socket.id: `, socket.id);
socket.leave(channelRoomName);
}

// 알람 구현을 위한 메소드(한명에게만 알람)
async PrivateAlert(
async privateAlert(
gatewayInvitationDto: GatewayCreateChannelInvitationParamDto,
) {
const invitedUser = await this.usersRepository.findOne({
Expand All @@ -241,6 +221,7 @@ export class ChannelsGateway
invitationId: gatewayInvitationDto.invitationId,
invitingUserId: invitingUser.nickname,
};

if (
!invitedUser ||
!invitingUser ||
Expand Down
14 changes: 13 additions & 1 deletion src/channels/channels.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ export class ChannelsService {
invitingUserId: invitingUserId,
invitedUserId: invitedUserId,
};
await this.ChannelsGateway.PrivateAlert(gatewayInvitationParamDto);
await this.ChannelsGateway.privateAlert(gatewayInvitationParamDto);
}

async updateChannelUser(userId: number, channelId: number) {
Expand Down Expand Up @@ -740,4 +740,16 @@ export class ChannelsService {
if (pwdResult.affected !== 1)
throw DBUpdateFailureException('update channel password failed');
}

async findChannelIdByChannelUserId(channelUserId: number) {
const channelUser = await this.channelUsersRepository.findOne({
where: { id: channelUserId },
});
if (!channelUser) {
throw new BadRequestException(
`channelUser ${channelUserId} does not exist`,
);
}
return channelUser.channelId;
}
}
1 change: 1 addition & 0 deletions src/channels/dto/channel-notice.response.dto.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ChannelEventType } from 'src/common/enum';

export type ChannelNoticeResponseDto = {
channelId: number;
nickname: string;
eventType: ChannelEventType;
};
1 change: 1 addition & 0 deletions src/common/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ export enum ChannelEventType {
KICK = 'KICK',
MUTE = 'MUTE',
ADMIN = 'ADMIN',
ADMIN_CANCEL = 'ADMIN_CANCEL',
}

0 comments on commit 63acf79

Please sign in to comment.