MINGLEHUB / server.ts
VISHAL18for4's picture
Upload server.ts
9e9a382 verified
import express from "express";
import { createServer } from "http";
import { Server } from "socket.io";
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
async function startServer() {
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, {
cors: {
origin: "*",
methods: ["GET", "POST"],
},
// FIX: Force websocket only - prevents the rapid connect/disconnect loop
// that happens when Socket.io keeps falling back to HTTP polling on HF Spaces
transports: ["websocket"],
pingTimeout: 60000,
pingInterval: 25000,
});
const PORT = parseInt(process.env.PORT || "7860");
let videoQueue: string[] = [];
let textQueue: string[] = [];
const partners = new Map<string, string>();
let activeCount = 0;
io.on("connection", (socket) => {
console.log("User connected:", socket.id);
socket.on("join-queue", ({ type }) => {
// FIX: If already in queue, do nothing - prevents spam joining on reconnect
if (videoQueue.includes(socket.id) || textQueue.includes(socket.id)) {
console.log(`${socket.id} already in queue, ignoring duplicate`);
socket.emit("waiting");
return;
}
// If already matched with someone, do nothing
if (partners.has(socket.id)) {
console.log(`${socket.id} already matched, ignoring join-queue`);
return;
}
console.log(`${socket.id} joining ${type} queue`);
activeCount++;
io.emit("online_count", activeCount);
const queue = type === "video" ? videoQueue : textQueue;
if (queue.length > 0) {
const partnerId = queue.shift()!;
partners.set(socket.id, partnerId);
partners.set(partnerId, socket.id);
console.log(`✅ Matched ${socket.id} with ${partnerId}`);
io.to(socket.id).emit("matched", { partnerId, type, role: "initiator" });
io.to(partnerId).emit("matched", { partnerId: socket.id, type, role: "receiver" });
} else {
queue.push(socket.id);
socket.emit("waiting");
console.log(`${socket.id} waiting in ${type} queue (queue size: ${queue.length})`);
}
});
socket.on("send-message", (text) => {
const partnerId = partners.get(socket.id);
if (partnerId) {
io.to(partnerId).emit("receive-message", text);
}
});
socket.on("signal", (data) => {
const partnerId = partners.get(socket.id);
if (partnerId) {
io.to(partnerId).emit("signal", data);
}
});
socket.on("leave-chat", () => {
handleLeave(socket.id);
});
socket.on("disconnect", () => {
console.log("User disconnected:", socket.id);
handleLeave(socket.id);
});
function handleLeave(socketId: string) {
const wasActive =
videoQueue.includes(socketId) ||
textQueue.includes(socketId) ||
partners.has(socketId);
if (wasActive) {
activeCount = Math.max(0, activeCount - 1);
io.emit("online_count", activeCount);
}
const partnerId = partners.get(socketId);
if (partnerId) {
io.to(partnerId).emit("partner-disconnected");
partners.delete(partnerId);
}
partners.delete(socketId);
videoQueue = videoQueue.filter((id) => id !== socketId);
textQueue = textQueue.filter((id) => id !== socketId);
}
});
const distPath = path.join(process.cwd(), "dist");
app.use(express.static(distPath));
app.get("*", (req, res) => {
res.sendFile(path.join(distPath, "index.html"));
});
httpServer.listen(PORT, "0.0.0.0", () => {
console.log(`MingleHub server running on port ${PORT}`);
});
}
startServer();