Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fe,be/feature/#567 fe,be 소켓 이벤트 타입 공유하기 #571

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions @types/event.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
interface AiSocketEvent {
ServerToClientEvent: {
streamStart: () => void;
streaming: (token: string) => void;
streamEnd: () => void;
tarotCard: () => void; // 타로 카드 펼치기 요청
chatEnd: (resultId: string) => void;
error: (message: string) => void;
};
ClientToServerEvent: {
message: (message: string) => void;
tarotRead: (cardIdx: number) => void; // 타로 카드 해설 요청
};
InterServerEvents: {};
SocketData: {};
}

interface HumanSocketEvent {
ServerToClientEvent: {
connection: (data: {
description?: RTCSessionDescription | null;
candidate?: RTCIceCandidate | null;
}) => void;
welcome: (otherUsers: any) => void;
userExit: (data: { id: string }) => void;
hostExit: () => void;
roomCreated: () => void;
roomNameGenerated: (roomId: string) => void;
joinRoomFailed: () => void;
joinRoomSuccess: (roomId: string) => void;
roomExist: () => void;
roomNotExist: () => void;
roomFull: () => void;
};
ClientToServerEvent: {
connection: (data: {
description?: RTCSessionDescription | null;
candidate?: RTCIceCandidate | null;
roomName: string;
}) => void;
generateRoomName: () => void;
createRoom: (roomId: string, password: string) => void;
joinRoom: (roomId: string, password: string) => void;
checkRoomExist: (roomName: string) => void;
};
InterServerEvents: {};
SocketData: {};
}
6 changes: 0 additions & 6 deletions backend/signal/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion backend/signal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-socket.io": "^10.2.10",
"@nestjs/websockets": "^10.2.10",
"@tarotmilktea/human-socketio-event": "^2.0.2",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"socket.io": "^4.7.2",
Expand Down
96 changes: 44 additions & 52 deletions backend/signal/src/events/events.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import {
WebSocketGateway,
WebSocketServer,
} from '@nestjs/websockets';
import type {
HumanClientEvent,
HumanServerEvent,
} from '@tarotmilktea/human-socketio-event';
import { Server, Socket } from 'socket.io';
import { LoggerService } from 'src/logger/logger.service';
import { v4 } from 'uuid';
import type {
HumanServer,
HumanSocket,
HumanSocketClientEvent,
HumanSocketClientEventParams,
} from './type';

const MAXIMUM = 2;

Expand All @@ -26,20 +27,20 @@ export class EventsGateway
constructor(private readonly logger: LoggerService) {}

@WebSocketServer()
server: Server;
server: HumanServer;

private socketRooms: any = {};
private users: any = {};

afterInit(server: Server) {
afterInit(server: HumanServer) {
this.logger.info('🚀 시그널링 서버 초기화');
}

handleConnection(socket: Socket) {
handleConnection(socket: HumanSocket) {
this.logger.debug(`🚀 Client Connected : ${socket.id}`);
}

handleDisconnect(socket: Socket) {
handleDisconnect(socket: HumanSocket) {
this.logger.debug(`🚀 Client Disconnected : ${socket.id}`);

const userId = socket.id;
Expand All @@ -60,7 +61,7 @@ export class EventsGateway
}

if (role === 'host') {
this.eventEmitToRoom(socket, roomId, 'hostExit');
socket.to(roomId).emit('hostExit');
delete this.socketRooms[roomId];

this.logger.debug(`🚀 host Exit from ${roomId}`);
Expand All @@ -70,42 +71,48 @@ export class EventsGateway
(_userId: string) => _userId !== userId,
);

this.eventEmitToRoom(socket, roomId, 'userExit', { id: userId });
socket.to(roomId).emit('userExit', { id: userId });

this.logger.debug(`🚀 User Exit from ${roomId}`);
}
}

@SubscribeMessage<HumanClientEvent>('generateRoomName')
handleCreateRoomEvent(socket: Socket) {
@SubscribeMessage<HumanSocketClientEvent>('generateRoomName')
handleCreateRoomEvent(socket: HumanSocket) {
const roomId: string = v4();

this.eventEmit(socket, 'roomNameGenerated', roomId);
socket.emit('roomNameGenerated', roomId);

this.logger.debug(`🚀 Room Name Generated : ${roomId}`);
}
@SubscribeMessage<HumanClientEvent>('createRoom')
handleSetRoomPassword(socket: Socket, [roomId, password]: [string, string]) {
@SubscribeMessage<HumanSocketClientEvent>('createRoom')
handleSetRoomPassword(
socket: HumanSocket,
[roomId, password]: HumanSocketClientEventParams<'createRoom'>,
) {
const userId = socket.id;
this.socketRooms[roomId] = { users: [userId], password: password };

this.users[userId] = { roomId, role: 'host' };
socket.join(roomId);
this.eventEmit(socket, 'roomCreated');
socket.emit('roomCreated');

this.logger.debug(`🚀 Room Created : ${roomId}`);
}

@SubscribeMessage<HumanClientEvent>('joinRoom')
handleJoinRoomEvent(socket: Socket, [roomId, password]: [string, string]) {
@SubscribeMessage<HumanSocketClientEvent>('joinRoom')
handleJoinRoomEvent(
socket: HumanSocket,
[roomId, password]: HumanSocketClientEventParams<'joinRoom'>,
) {
const userId = socket.id;

const existRoom: any = this.socketRooms[roomId];
const wrongPassword: boolean =
this.socketRooms[roomId]?.password !== password;

if (!existRoom || wrongPassword) {
this.eventEmit(socket, 'joinRoomFailed');
socket.emit('joinRoomFailed');
const logMessage: string = !existRoom
? `🚀 Invalid Room : ${roomId}`
: `🚀 Wrong Password for ${roomId}`;
Expand All @@ -116,7 +123,7 @@ export class EventsGateway
const fullRoom: boolean = this.socketRooms[roomId].users.length === MAXIMUM;
if (fullRoom) {
this.logger.debug(`🚀 Cannot Join to full room ${roomId}`);
this.eventEmit(socket, 'roomFull');
socket.emit('roomFull');
return;
}

Expand All @@ -128,58 +135,43 @@ export class EventsGateway
const otherUsers = this.socketRooms[roomId].users.filter(
(_userId: string) => _userId !== userId,
);
this.eventEmitToRoom(socket, roomId, 'welcome', otherUsers);
this.eventEmit(socket, 'joinRoomSuccess', roomId);
socket.to(roomId).emit('welcome', otherUsers);
socket.emit('joinRoomSuccess', roomId);
}

@SubscribeMessage('connection')
@SubscribeMessage<HumanSocketClientEvent>('connection')
handleConnectionEvent(
socket: Socket,
{
description,
candidate,
roomName,
}: {
description?: RTCSessionDescription;
candidate?: RTCIceCandidate;
roomName: string;
},
socket: HumanSocket,
[
{ description, candidate, roomName },
]: HumanSocketClientEventParams<'connection'>,
) {
try {
if (description) {
this.logger.debug(`🚀 ${description.type} Received from ${socket.id}`);
this.eventEmitToRoom(socket, roomName, 'connection', { description });
socket.to(roomName).emit('connection', { description });
} else if (candidate) {
this.logger.debug(`🚀 Candidate Received from ${socket.id}`);
this.eventEmitToRoom(socket, roomName, 'connection', { candidate });
socket.to(roomName).emit('connection', { candidate });
}
} catch (error) {
this.logger.error(`🚀 Error in handleMessageEvent : ${error}`);
}
}

@SubscribeMessage<HumanClientEvent>('checkRoomExist')
handleCheckRoomExistEvent(socket: Socket, roomName: string) {
@SubscribeMessage<HumanSocketClientEvent>('checkRoomExist')
handleCheckRoomExistEvent(
socket: HumanSocket,
[roomName]: HumanSocketClientEventParams<'checkRoomExist'>,
) {
const existRoom: any = this.socketRooms[roomName];

if (existRoom) {
this.eventEmit(socket, 'roomExist');
socket.emit('roomExist');
this.logger.debug(`🚀 Room Exist : ${roomName}`);
} else {
this.eventEmit(socket, 'roomNotExist');
socket.emit('roomNotExist');
this.logger.debug(`🚀 Room Not Exist : ${roomName}`);
}
}

public eventEmit(socket: Socket, event: HumanServerEvent, ...args: any[]) {
socket.emit(event, ...args);
}
public eventEmitToRoom(
socket: Socket,
roomName: string,
event: HumanServerEvent | 'connection',
...args: any[]
) {
socket.to(roomName).emit(event, ...args);
}
}
17 changes: 17 additions & 0 deletions backend/signal/src/events/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Server, Socket } from 'socket.io';

export type HumanServer = Server<
HumanSocketEvent['ClientToServerEvent'],
HumanSocketEvent['ServerToClientEvent']
>;

export type HumanSocket = Socket<
HumanSocketEvent['ClientToServerEvent'],
HumanSocketEvent['ServerToClientEvent']
>;

export type HumanSocketClientEvent =
keyof HumanSocketEvent['ClientToServerEvent'];

export type HumanSocketClientEventParams<T extends HumanSocketClientEvent> =
Parameters<HumanSocketEvent['ClientToServerEvent'][T]>;
4 changes: 3 additions & 1 deletion backend/signal/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": true
}
},
"typeRoots": ["../../@types"],
"include": ["src", "../../@types"]
Comment on lines +21 to +22
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍👍

}
11 changes: 0 additions & 11 deletions backend/was/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion backend/was/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
"@sentry/node": "^7.85.0",
"@sentry/profiling-node": "^1.2.6",
"@slack/client": "^5.0.2",
"@tarotmilktea/ai-socketio-event": "^2.0.3",
"cache-manager-redis-store": "^3.0.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
Expand Down
10 changes: 0 additions & 10 deletions backend/was/src/chatbot/clova-studio/clova-studio.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,6 @@ describe('ClovaStudioService', () => {
expect(clovaStudioService).toBeDefined();
});

describe('function getAPIKeys()', () => {
it('getAPIKeys(): clova api key 불러 와서 객체로 만들어서 반환', () => {
const apiKeys = getAPIKeys(configServieMock);

CLOVA_API_KEY_NAMES.forEach((key) => {
expect(apiKeys[key.replaceAll('_', '-')]).toBe(key);
});
});
});

describe('ClovaStudioService.generateTalk()', () => {
it('사용자의 메세지 입력으로 AI의 답변을 생성해서 token stream 형식으로 반환', async () => {
setApiMock(tokens);
Expand Down
19 changes: 17 additions & 2 deletions backend/was/src/common/types/socket.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
import { Socket as originalSocket } from 'socket.io';
import { Server, Socket } from 'socket.io';
import { ChatLog } from './chatbot';

export interface UserInfo {
email: string;
providerId: number;
}
export interface Socket extends originalSocket {

export type AiServer = Server<
AiSocketEvent['ClientToServerEvent'],
AiSocketEvent['ServerToClientEvent']
>;

export interface AiSocket
extends Socket<
AiSocketEvent['ClientToServerEvent'],
AiSocketEvent['ServerToClientEvent']
> {
user?: UserInfo;
chatLog: ChatLog[];
chatEnd: boolean;
}

export type AiSocketClientEvent = keyof AiSocketEvent['ClientToServerEvent'];

export type AiSocketClientEventParams<T extends AiSocketClientEvent> =
Parameters<AiSocketEvent['ClientToServerEvent'][T]>;
Loading
Loading