Update environment configuration for local development, add new dependencies for WebRTC functionality, and refactor user session management components. Remove deprecated SessionUsersPanel and enhance SessionUsersPanel2 with improved user handling and controls. Integrate socket.io for real-time communication in the server.

This commit is contained in:
2025-10-24 18:17:12 +05:00
parent fb2d9258ac
commit f70e8f88b2
40 changed files with 4558 additions and 811 deletions
+195
View File
@@ -6,6 +6,8 @@ import { companyController } from "./controllers/company";
import { branchController } from "./controllers/branch";
import { serverController } from "./controllers/server";
import { serverSessionService } from "./services/serverSession";
import { Server } from "socket.io";
import { createServer } from "http";
const app = new Elysia();
@@ -28,6 +30,199 @@ console.log(
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
);
// Setup Socket.IO для WebRTC на отдельном порту
const httpServer = createServer();
const io = new Server(httpServer, {
cors: {
origin: "*",
},
});
httpServer.listen(3001, () => {
console.log("🎥 WebRTC Socket.IO server running on port 3001");
});
interface Room {
id: string;
participants: Set<string>;
}
interface User {
id: string;
roomId?: string;
socketId: string;
}
const rooms = new Map<string, Room>();
const users = new Map<string, User>();
// Вспомогательные функции
function findUserBySocketId(socketId: string): User | undefined {
for (const [userId, user] of users.entries()) {
if (user.socketId === socketId) {
return user;
}
}
return undefined;
}
function findSocketIdByUserId(userId: string): string | undefined {
const user = users.get(userId);
return user?.socketId;
}
io.on("connection", (socket) => {
console.log(`[WebRTC] User connected: ${socket.id}`);
// Присоединение к комнате
socket.on("join-room", ({ roomId, userId }) => {
console.log(`[WebRTC] User ${userId} (socket: ${socket.id}) joining room ${roomId}`);
// Покинуть предыдущую комнату если была
const existingUser = users.get(userId);
if (existingUser?.roomId) {
console.log(
`[WebRTC] User ${userId} leaving previous room ${existingUser.roomId}`
);
socket.leave(existingUser.roomId);
const prevRoom = rooms.get(existingUser.roomId);
if (prevRoom) {
prevRoom.participants.delete(userId);
socket.to(existingUser.roomId).emit("user-left", userId);
}
}
// Присоединиться к новой комнате
socket.join(roomId);
// Создать комнату если не существует
if (!rooms.has(roomId)) {
console.log(`[WebRTC] Creating new room: ${roomId}`);
rooms.set(roomId, {
id: roomId,
participants: new Set(),
});
}
const room = rooms.get(roomId)!;
room.participants.add(userId);
// Сохранить пользователя
users.set(userId, {
id: userId,
roomId,
socketId: socket.id,
});
console.log(
`[WebRTC] Room ${roomId} now has participants:`,
Array.from(room.participants)
);
// Уведомить других участников
socket.to(roomId).emit("user-joined", userId);
console.log(`[WebRTC] Notified room ${roomId} about user ${userId} joining`);
// Отправить список участников новому пользователю
const participants = Array.from(room.participants).filter(
(id) => id !== userId
);
console.log(`[WebRTC] Sending participant list to ${userId}:`, participants);
socket.emit("room-participants", participants);
});
// Покидание комнаты
socket.on("leave-room", ({ roomId, userId }) => {
console.log(`[WebRTC] User ${userId} leaving room ${roomId}`);
socket.leave(roomId);
const room = rooms.get(roomId);
if (room) {
room.participants.delete(userId);
socket.to(roomId).emit("user-left", userId);
// Удалить пустую комнату
if (room.participants.size === 0) {
rooms.delete(roomId);
console.log(`[WebRTC] Deleted empty room ${roomId}`);
}
}
const user = users.get(userId);
if (user) {
user.roomId = undefined;
}
});
// WebRTC сигнализация
socket.on("offer", ({ target, offer }) => {
console.log(`[WebRTC] Offer from ${socket.id} to ${target}`);
const targetSocketId = findSocketIdByUserId(target);
const senderUser = findUserBySocketId(socket.id);
if (targetSocketId && senderUser) {
socket.to(targetSocketId).emit("offer", {
offer,
sender: senderUser.id,
});
}
});
socket.on("answer", ({ target, answer }) => {
console.log(`[WebRTC] Answer from ${socket.id} to ${target}`);
const targetSocketId = findSocketIdByUserId(target);
const senderUser = findUserBySocketId(socket.id);
if (targetSocketId && senderUser) {
socket.to(targetSocketId).emit("answer", {
answer,
sender: senderUser.id,
});
}
});
socket.on("ice-candidate", ({ target, candidate }) => {
console.log(`[WebRTC] ICE candidate from ${socket.id} to ${target}`);
const targetSocketId = findSocketIdByUserId(target);
const senderUser = findUserBySocketId(socket.id);
if (targetSocketId && senderUser) {
socket.to(targetSocketId).emit("ice-candidate", {
candidate,
sender: senderUser.id,
});
}
});
// Отключение
socket.on("disconnect", () => {
console.log(`[WebRTC] User disconnected: ${socket.id}`);
// Найти пользователя по socket ID
const disconnectedUser = findUserBySocketId(socket.id);
if (disconnectedUser) {
users.delete(disconnectedUser.id);
if (disconnectedUser.roomId) {
const room = rooms.get(disconnectedUser.roomId);
if (room) {
room.participants.delete(disconnectedUser.id);
socket
.to(disconnectedUser.roomId)
.emit("user-left", disconnectedUser.id);
// Удалить пустую комнату
if (room.participants.size === 0) {
rooms.delete(disconnectedUser.roomId);
console.log(`[WebRTC] Deleted empty room ${disconnectedUser.roomId}`);
}
}
}
}
});
});
// Запуск фоновой задачи для автоматического назначения серверов
const AUTO_ASSIGN_INTERVAL_MS = parseInt(
process.env.AUTO_ASSIGN_INTERVAL_MS || "1000",