import { Server } from "socket.io"; import { createServer } from "http"; import { prisma } from "./db"; // Function to generate a share token function generateShareToken(length = 8) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } // Store active connections const activeUsers = new Map(); const httpServer = createServer(); const io = new Server(httpServer, { cors: { origin: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000", methods: ["GET", "POST"], }, }); // Set up Socket.IO event handlers io.on('connection', (socket) => { console.log(`New client connected: ${socket.id}`); // Handle user login/registration socket.on('user:register', (userId: string) => { console.log(`User registered: ${userId} (Socket: ${socket.id})`); activeUsers.set(userId, socket.id); // Broadcast updated user list io.emit('users:update', Array.from(activeUsers.keys())); }); // Handle location updates socket.on('location:update', (data: { userId: string; latitude: number; longitude: number; accuracy?: number; timestamp?: string; }) => { console.log(`Location update from ${data.userId}: ${data.latitude}, ${data.longitude}`); // Add timestamp if not provided if (!data.timestamp) { data.timestamp = new Date().toISOString(); } // Broadcast to all connected clients io.emit('location:broadcast', data); }); // Handle direct messages or location shares socket.on('location:share', (data: { fromUserId: string; toUserId: string; latitude: number; longitude: number; accuracy?: number; }) => { console.log(`Location share from ${data.fromUserId} to ${data.toUserId}`); const targetSocketId = activeUsers.get(data.toUserId); if (targetSocketId) { // Send to specific user io.to(targetSocketId).emit('location:shared', { fromUserId: data.fromUserId, latitude: data.latitude, longitude: data.longitude, accuracy: data.accuracy, timestamp: new Date().toISOString() }); } }); // Handle location sharing via token socket.on('share:join', (shareToken: string) => { if (shareToken) { socket.join(`share:${shareToken}`); console.log(`Client ${socket.id} joined room share:${shareToken}`); } }); socket.on('share:leave', (shareToken: string) => { if (shareToken) { socket.leave(`share:${shareToken}`); console.log(`Client ${socket.id} left room share:${shareToken}`); } }); // Handle disconnect socket.on('disconnect', () => { console.log(`Client disconnected: ${socket.id}`); // Remove user from active users for (const [userId, socketId] of activeUsers.entries()) { if (socketId === socket.id) { activeUsers.delete(userId); break; } } // Broadcast updated user list io.emit('users:update', Array.from(activeUsers.keys())); }); }); const PORT = parseInt(process.env.SOCKET_PORT || "3001", 10); export const startSocketServer = () => { httpServer.listen(PORT, () => { console.log(`Socket.IO server running on port ${PORT}`); }); };