From 072bd7f0d7ad2ac6c894b296a9ad352c5730cdf6 Mon Sep 17 00:00:00 2001 From: PrimarchPaul Date: Sat, 27 Sep 2025 14:23:19 -0400 Subject: [PATCH] added realtime post/deleteFromChannel serv+controller --- concord-server/src/controller/realtime.ts | 128 ++++++++++++++++++++++ concord-server/src/services/realtime.ts | 88 +++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 concord-server/src/controller/realtime.ts create mode 100644 concord-server/src/services/realtime.ts diff --git a/concord-server/src/controller/realtime.ts b/concord-server/src/controller/realtime.ts new file mode 100644 index 0000000..0151393 --- /dev/null +++ b/concord-server/src/controller/realtime.ts @@ -0,0 +1,128 @@ +import { Context } from "hono"; +import { sendMessageToChannel, removeMessageFromChannel } from "../services/realtime.js" +import { success } from "zod"; + + + +export async function postMessageToChannel( + io: any, + c: Context +) { + try { + io = c.get("io"); + + const instanceId = c.req.param("instanceId"); + const categoryId = c.req.param("categoryId"); + const channelId = c.req.param("channelId"); + const message = await c.req.json(); + + const result = await sendMessageToChannel( + instanceId, + categoryId, + channelId, + message, + "new_channel_message", + io + ) + + if(result === "Event not implemented"){ + console.log("controller::realtime::postMessageToChannel - Failed to send message") + return c.json({ + success: false, + message: "Event not implemented or recognized", + status: 400 + }) + } + + if(result === "no acknowledgment"){ + console.log("controller::realtime::postMessageToChannel - No acknowledgment received from client") + return c.json({ + success: false, + message: "No acknowledgment received from client", + status: 500 + }) + } + + if(!result){ + throw new Error("failed to send message"); + } + + return c.json({ + success: true, + message: "Message sent successfully", + status: 200 + }) + + + } catch (err) { + const errMessage = err as Error; + console.log("controller::realtime::postMessageToChannel - ", errMessage); + return c.json({ + success: false, + message: errMessage.message, + status: 500 + }); + } +} + +export async function deleteMessageFromChannel( + io: any, + c: Context +){ + try { + + io = c.get("io"); + + const instanceId = c.req.param("instanceId"); + const categoryId = c.req.param("categoryId"); + const channelId = c.req.param("channelId"); + const messageId = c.req.param("messageId"); + + const result = await removeMessageFromChannel( + instanceId, + categoryId, + channelId, + messageId, + "delete_channel_message", + io + ) + + if(result === "event not implemented"){ + console.log("controller::realtime::deleteMessageFromChannel - Event not implemented") + return c.json({ + success: false, + message: "Event not implemented or recognized", + status: 400 + }); + } + + if(result === "no acknowledgment"){ + console.log("controller::realtime::deleteMessageFromChannel - No acknowledgment received from client") + return c.json({ + success: false, + message: "No acknowledgment received from client", + status: 500 + }); + } + + if(!result){ + throw new Error("failed to delete message"); + } + + c.json({ + success: true, + message: "Message deleted successfully", + status: 200 + }) + + } catch (err) { + + const errMessage = err as Error; + console.log("services::realtime::deleteMessageFromChannel - ", errMessage); + return c.json({ + success: false, + message: errMessage.message, + status: 500 + }); + } +} \ No newline at end of file diff --git a/concord-server/src/services/realtime.ts b/concord-server/src/services/realtime.ts new file mode 100644 index 0000000..b99c5cd --- /dev/null +++ b/concord-server/src/services/realtime.ts @@ -0,0 +1,88 @@ +import { readonly } from "zod"; + +const EVENTS = { + NEW_CHANNEL_MESSAGE: "new_channel_message", + DELETE_CHANNEL_MESSAGE: "delete_channel_message", +} + + + +export async function sendMessageToChannel( + instanceId: string, + categoryId: string, + channelId: string, + message: any, + event: string, + io: any, +): Promise { + try { + + //TODO: implement middleware to replace this + if(EVENTS.NEW_CHANNEL_MESSAGE === event){ + throw new Error("Event not implemented"); + } + + //TODO: add prisma to save channel message to DB + + return new Promise((resolve) => { + io.to(instanceId).emit(event, message, (ack: any) => { + if (ack && ack.status === 'received') { + console.log(`Message ${ack.messageId} acknowledged by client.`); + resolve(true); + } else { + console.log('services::realtime::sendMessageToChannel No acknowledgment received from client.'); + resolve("no acknowledgment"); + } + }); + }); + } catch (err) { + const errMessage = err as Error; + if (errMessage.message === "Event not implemented") { + console.log(`services::realtime::sendMessageToChannel - Event not implemented. Attempted event: ${event}`) + return "event not implemented" + } + console.log("services::realtime::sendMessageToChannel - ", errMessage); + return false; + + } +} + +export async function removeMessageFromChannel( + instanceId: string, + categoryId: string, + channelId: string, + messageId: string, + event: string, + io: any +): Promise{ + try { + + //TODO: implement middleware to replace this + if(EVENTS.DELETE_CHANNEL_MESSAGE === event){ + throw new Error("event not implemented"); + } + + //TODO: add prisma to flag a channel message as deleted + + return new Promise((resolve) => { + io.to(instanceId).emit(event, { messageId }, (ack: any) => { + if (ack && ack.status === 'received') { + console.log(`Message ${ack.messageId} acknowledged by client.`); + resolve(true); + } else { + console.log('services::realtime::deleteMessageFromChannel No acknowledgment received from client.'); + resolve("no acknowledgment"); + } + }); + }); + } catch (err) { + const errMessage = err as Error; + if (errMessage.message === "Event not implemented") { + console.log(`services::realtime::deleteMessageFromChannel - Event not implemented. Attempted event: ${event}`) + return false; + } + console.log("services::realtime::deleteMessageFromChannel - ", errMessage); + return false; + + } +} \ No newline at end of file