1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
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<string, string>();
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}`);
});
};
|