177 lines
4.5 KiB
JavaScript
177 lines
4.5 KiB
JavaScript
import { wsManager } from "../utils/websocket.js";
|
|
import { authenticate } from "../middleware/auth.js";
|
|
|
|
/**
|
|
* WebSocket routes and handlers
|
|
* @param {FastifyInstance} fastify - Fastify instance
|
|
*/
|
|
export default async function websocketRoutes(fastify, options) {
|
|
// WebSocket endpoint
|
|
fastify.get("/ws", { websocket: true }, (connection, request) => {
|
|
// In @fastify/websocket, the connection parameter IS the WebSocket directly
|
|
// It has properties like _socket, _readyState, etc.
|
|
wsManager.handleConnection(connection, request.raw || request);
|
|
});
|
|
|
|
// Get WebSocket stats (authenticated endpoint)
|
|
fastify.get(
|
|
"/ws/stats",
|
|
{
|
|
preHandler: authenticate,
|
|
},
|
|
async (request, reply) => {
|
|
const stats = {
|
|
totalConnections: wsManager.getTotalSocketCount(),
|
|
authenticatedUsers: wsManager.getAuthenticatedUserCount(),
|
|
userConnected: wsManager.isUserConnected(request.user._id.toString()),
|
|
};
|
|
|
|
return reply.send({
|
|
success: true,
|
|
stats: stats,
|
|
});
|
|
}
|
|
);
|
|
|
|
// Broadcast to all users (admin only - requires staff level 3+)
|
|
fastify.post(
|
|
"/ws/broadcast",
|
|
{
|
|
preHandler: [
|
|
authenticate,
|
|
async (request, reply) => {
|
|
if (request.user.staffLevel < 3) {
|
|
return reply.status(403).send({
|
|
error: "Forbidden",
|
|
message: "Insufficient permissions",
|
|
});
|
|
}
|
|
},
|
|
],
|
|
schema: {
|
|
body: {
|
|
type: "object",
|
|
required: ["type", "data"],
|
|
properties: {
|
|
type: { type: "string" },
|
|
data: { type: "object" },
|
|
excludeUsers: { type: "array", items: { type: "string" } },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
async (request, reply) => {
|
|
try {
|
|
const { type, data, excludeUsers = [] } = request.body;
|
|
|
|
const count = wsManager.broadcastToAll(
|
|
{
|
|
type,
|
|
data,
|
|
timestamp: Date.now(),
|
|
},
|
|
excludeUsers
|
|
);
|
|
|
|
return reply.send({
|
|
success: true,
|
|
message: `Broadcast sent to ${count} clients`,
|
|
recipientCount: count,
|
|
});
|
|
} catch (error) {
|
|
console.error("Error broadcasting:", error);
|
|
return reply.status(500).send({
|
|
error: "InternalServerError",
|
|
message: "Failed to broadcast message",
|
|
});
|
|
}
|
|
}
|
|
);
|
|
|
|
// Send message to specific user (admin only)
|
|
fastify.post(
|
|
"/ws/send/:userId",
|
|
{
|
|
preHandler: [
|
|
authenticate,
|
|
async (request, reply) => {
|
|
if (request.user.staffLevel < 2) {
|
|
return reply.status(403).send({
|
|
error: "Forbidden",
|
|
message: "Insufficient permissions",
|
|
});
|
|
}
|
|
},
|
|
],
|
|
schema: {
|
|
body: {
|
|
type: "object",
|
|
required: ["type", "data"],
|
|
properties: {
|
|
type: { type: "string" },
|
|
data: { type: "object" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
async (request, reply) => {
|
|
try {
|
|
const { userId } = request.params;
|
|
const { type, data } = request.body;
|
|
|
|
const sent = wsManager.sendToUser(userId, {
|
|
type,
|
|
data,
|
|
timestamp: Date.now(),
|
|
});
|
|
|
|
if (!sent) {
|
|
return reply.status(404).send({
|
|
error: "NotFound",
|
|
message: "User not connected",
|
|
});
|
|
}
|
|
|
|
return reply.send({
|
|
success: true,
|
|
message: "Message sent to user",
|
|
});
|
|
} catch (error) {
|
|
console.error("Error sending message:", error);
|
|
return reply.status(500).send({
|
|
error: "InternalServerError",
|
|
message: "Failed to send message",
|
|
});
|
|
}
|
|
}
|
|
);
|
|
|
|
// Check if user is online
|
|
fastify.get(
|
|
"/ws/status/:userId",
|
|
{
|
|
preHandler: authenticate,
|
|
},
|
|
async (request, reply) => {
|
|
try {
|
|
const { userId } = request.params;
|
|
const isConnected = wsManager.isUserConnected(userId);
|
|
const metadata = wsManager.getUserMetadata(userId);
|
|
|
|
return reply.send({
|
|
success: true,
|
|
userId: userId,
|
|
online: isConnected,
|
|
metadata: metadata || null,
|
|
});
|
|
} catch (error) {
|
|
console.error("Error checking user status:", error);
|
|
return reply.status(500).send({
|
|
error: "InternalServerError",
|
|
message: "Failed to check user status",
|
|
});
|
|
}
|
|
}
|
|
);
|
|
}
|