diff --git a/concord-server/src/index.ts b/concord-server/src/index.ts index 1332236..816c3af 100644 --- a/concord-server/src/index.ts +++ b/concord-server/src/index.ts @@ -5,6 +5,7 @@ import { Server } from "socket.io"; import routes from "./routes/index"; import { Scalar } from "@scalar/hono-api-reference"; import { openAPIRouteHandler } from "hono-openapi"; +import { registerSocketHandlers } from "./sockets"; // Routes const app = new Hono(); @@ -13,7 +14,11 @@ app.use( "*", cors({ origin: "http://localhost:5173", - allowHeaders: ["Content-Type", "Authorization", "Access-Control-Allow-Origin"], + allowHeaders: [ + "Content-Type", + "Authorization", + "Access-Control-Allow-Origin", + ], allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], credentials: true, }), @@ -42,19 +47,13 @@ const io = new Server({ cors: { origin: "http://localhost:5173", credentials: true, - } + }, }); const engine = new Engine(); io.bind(engine); // Register socket.io events -io.on("connection", (socket) => { - console.log("connected1"); - socket.on("ping", (c) => { - console.log(c); - socket.emit("pong", c); - }); -}); +registerSocketHandlers(io); const { websocket } = engine.handler(); @@ -68,7 +67,10 @@ export default { if (url.pathname === "/socket.io/") { const response = await engine.handleRequest(req, server); // Add CORS headers explicitly - response.headers.set("Access-Control-Allow-Origin", "http://localhost:5173"); + response.headers.set( + "Access-Control-Allow-Origin", + "http://localhost:5173", + ); response.headers.set("Access-Control-Allow-Credentials", "true"); return response; } else { @@ -76,5 +78,5 @@ export default { } }, - websocket + websocket, }; diff --git a/concord-server/src/sockets/index.ts b/concord-server/src/sockets/index.ts new file mode 100644 index 0000000..816e14d --- /dev/null +++ b/concord-server/src/sockets/index.ts @@ -0,0 +1,16 @@ +import { Server } from "socket.io"; +import { registerVoiceHandlers } from "./voiceHandler"; + +export function registerSocketHandlers(io: Server) { + // bad practice + io.on("connection", (socket) => { + console.log("connected"); + socket.on("ping", (c) => { + console.log(c); + socket.emit("pong", c); + }); + }); + + // good practice + registerVoiceHandlers(io); +} diff --git a/concord-server/src/sockets/voiceHandler.ts b/concord-server/src/sockets/voiceHandler.ts new file mode 100644 index 0000000..1dc0484 --- /dev/null +++ b/concord-server/src/sockets/voiceHandler.ts @@ -0,0 +1,33 @@ +import { Server, Socket } from "socket.io"; + +//TEST IGNORE +export function registerVoiceHandlers(io: Server) { + io.on("connection", (socket: Socket) => { + console.log(`Voice socket connected: ${socket.id}`); + + socket.on("join-voice-channel", (channelId: string) => { + socket.join(channelId); + console.log(`Socket ${socket.id} joined voice channel ${channelId}`); + // Optionally, notify others in the channel + socket.to(channelId).emit("user-joined-voice", socket.id); + }); + + socket.on("leave-voice-channel", (channelId: string) => { + socket.leave(channelId); + console.log(`Socket ${socket.id} left voice channel ${channelId}`); + // Optionally, notify others in the channel + socket.to(channelId).emit("user-left-voice", socket.id); + }); + + socket.on("voice-data", (channelId: string, data: any) => { + // Broadcast voice data to all other clients in the same channel + socket.to(channelId).emit("voice-data", socket.id, data); + }); + + socket.on("disconnect", () => { + console.log(`Voice socket disconnected: ${socket.id}`); + // Handle user leaving all voice channels they were in + // (e.g., iterate through socket.rooms if you need to emit to specific channels) + }); + }); +} diff --git a/concord-server/src/validators/channelValidator.ts b/concord-server/src/validators/channelValidator.ts index 626e1fb..23cb918 100644 --- a/concord-server/src/validators/channelValidator.ts +++ b/concord-server/src/validators/channelValidator.ts @@ -52,5 +52,5 @@ export type GetChannelsByCategoryIdInput = z.infer< export type UpdateChannelInput = z.infer; export type DeleteChannelInput = z.infer; export type DeleteChannelsByCategoryIdInput = z.infer< -typeof deleteChannelsByCategoryIdSchema + typeof deleteChannelsByCategoryIdSchema >; diff --git a/concord-server/src/validators/realtimeValidator.ts b/concord-server/src/validators/realtimeValidator.ts index f9c971d..859b4e8 100644 --- a/concord-server/src/validators/realtimeValidator.ts +++ b/concord-server/src/validators/realtimeValidator.ts @@ -1,16 +1,18 @@ import { z } from "zod"; export const postMessageToChannelSchema = z.object({ - instanceId: z.uuidv7(), - categoryId: z.uuidv7(), - channelId: z.uuidv7(), - userId: z.uuidv7(), - content: z.string().min(1).max(2000), - repliedMessageId: z.uuidv7().optional(), - token: z.string(), + instanceId: z.uuidv7(), + categoryId: z.uuidv7(), + channelId: z.uuidv7(), + userId: z.uuidv7(), + content: z.string().min(1).max(2000), + repliedMessageId: z.uuidv7().optional(), + token: z.string(), }); //TODO: add more realtime related validators as needed -export type PostMessageToChannelInput = z.infer; -//TODO: create more input schemas for other realtime actions \ No newline at end of file +export type PostMessageToChannelInput = z.infer< + typeof postMessageToChannelSchema +>; +//TODO: create more input schemas for other realtime actions