first commit

This commit is contained in:
Oscar
2026-06-02 15:52:22 +03:00
commit dc44cdd639
105 changed files with 14674 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
import {
ConnectedSocket,
MessageBody,
OnGatewayConnection,
OnGatewayDisconnect,
SubscribeMessage,
WebSocketGateway,
WebSocketServer,
WsException,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { JwtService } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';
import { Logger } from '@nestjs/common';
import { ChatService } from '../modules/chat/chat.service';
import { SendMessageDto } from '../modules/chat/dto/send-message.dto';
@WebSocketGateway({
cors: {
origin: '*',
credentials: true,
},
namespace: 'chat',
})
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer()
server: Server;
private readonly logger = new Logger(ChatGateway.name);
private connectedUsers = new Map<string, string>();
constructor(
private readonly jwtService: JwtService,
private readonly configService: ConfigService,
private readonly chatService: ChatService,
) {}
async handleConnection(client: Socket) {
try {
const token =
client.handshake.auth?.token ||
client.handshake.headers?.authorization?.replace('Bearer ', '');
if (!token) {
client.disconnect();
return;
}
const payload = this.jwtService.verify(token, {
secret: this.configService.get<string>('jwt.secret'),
});
client.data.userId = payload.sub;
this.connectedUsers.set(payload.sub, client.id);
this.logger.log(`User ${payload.sub} connected via WebSocket`);
} catch {
client.disconnect();
}
}
handleDisconnect(client: Socket) {
const userId = client.data.userId;
if (userId) {
this.connectedUsers.delete(userId);
this.logger.log(`User ${userId} disconnected`);
}
}
@SubscribeMessage('join_chat')
async handleJoinChat(
@ConnectedSocket() client: Socket,
@MessageBody() data: { chatId: string },
) {
const userId = client.data.userId;
if (!userId) throw new WsException('Unauthorized');
await client.join(`chat:${data.chatId}`);
return { event: 'joined_chat', chatId: data.chatId };
}
@SubscribeMessage('leave_chat')
async handleLeaveChat(
@ConnectedSocket() client: Socket,
@MessageBody() data: { chatId: string },
) {
await client.leave(`chat:${data.chatId}`);
return { event: 'left_chat', chatId: data.chatId };
}
@SubscribeMessage('send_message')
async handleSendMessage(
@ConnectedSocket() client: Socket,
@MessageBody() data: { chatId: string } & SendMessageDto,
) {
const userId = client.data.userId;
if (!userId) throw new WsException('Unauthorized');
const { chatId, ...msgDto } = data;
const newMessage = await this.chatService.sendMessage(userId, chatId, msgDto);
this.server.to(`chat:${chatId}`).emit('new_message', newMessage);
return newMessage;
}
@SubscribeMessage('typing')
handleTyping(
@ConnectedSocket() client: Socket,
@MessageBody() data: { chatId: string; isTyping: boolean },
) {
const userId = client.data.userId;
client.to(`chat:${data.chatId}`).emit('user_typing', {
userId,
isTyping: data.isTyping,
});
}
emitToUser(userId: string, event: string, data: any) {
const socketId = this.connectedUsers.get(userId);
if (socketId) {
this.server.to(socketId).emit(event, data);
}
}
}

View File

@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { ChatGateway } from './chat.gateway';
import { ChatModule } from '../modules/chat/chat.module';
import { AuthModule } from '../auth/auth.module';
@Module({
imports: [ChatModule, AuthModule],
providers: [ChatGateway],
exports: [ChatGateway],
})
export class GatewaysModule {}