first commit
This commit is contained in:
176
routes/websocket.js
Normal file
176
routes/websocket.js
Normal file
@@ -0,0 +1,176 @@
|
||||
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",
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user