Message post and get by id + Deps fixed
This commit is contained in:
21
concord-server/src/controller/messageController.ts
Normal file
21
concord-server/src/controller/messageController.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { getMessageInformation, sendMessageToChannel } from "../services/messageService";
|
||||
|
||||
export async function fetchMessageData(id:string) {
|
||||
return await getMessageInformation(id);
|
||||
}
|
||||
|
||||
export async function sendMessage(
|
||||
channelId: string,
|
||||
userId: string,
|
||||
content: string,
|
||||
token: string,
|
||||
repliedMessageId: string | null
|
||||
) {
|
||||
return await sendMessageToChannel(
|
||||
channelId,
|
||||
userId,
|
||||
content,
|
||||
token,
|
||||
repliedMessageId
|
||||
);
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
//place exported routes below this line
|
||||
import { Hono } from "hono";
|
||||
import actions from "./userRoutes";
|
||||
import userRoutes from "./userRoutes";
|
||||
import messageRoutes from "./messageRoutes";
|
||||
|
||||
const routes = new Hono();
|
||||
|
||||
routes.route("/", actions);
|
||||
routes.route("/user", userRoutes);
|
||||
routes.route("/message", messageRoutes);
|
||||
|
||||
export default routes;
|
||||
|
||||
86
concord-server/src/routes/messageRoutes.ts
Normal file
86
concord-server/src/routes/messageRoutes.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { Hono } from "hono";
|
||||
import { describeResponse, describeRoute, resolver } from "hono-openapi";
|
||||
import { getMessageByIdSchema, sendMessageSchema } from "../validators/messageValidator";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { fetchMessageData, sendMessage } from "../controller/messageController";
|
||||
|
||||
const messageRoutes = new Hono();
|
||||
|
||||
messageRoutes.get(
|
||||
"/:id",
|
||||
describeRoute({
|
||||
description: "Get message by id",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Success getting message",
|
||||
content: {
|
||||
"application/json": { schema: resolver(getMessageByIdSchema) }
|
||||
}
|
||||
},
|
||||
404: {
|
||||
description: "Message id not found",
|
||||
content: {
|
||||
"application/json": { schema: resolver(getMessageByIdSchema) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
zValidator("param", getMessageByIdSchema),
|
||||
async (c) => {
|
||||
const id = c.req.param("id");
|
||||
const messageData = await fetchMessageData(id);
|
||||
|
||||
if (messageData) {
|
||||
return c.json(messageData, 200);
|
||||
} else {
|
||||
return c.json({ error: "Message not found" }, 404);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
messageRoutes.post(
|
||||
"",
|
||||
describeRoute({
|
||||
description: "Send a message to a channel",
|
||||
responses: {
|
||||
201: {
|
||||
description: "Message sent successfully",
|
||||
content: {
|
||||
"application/json": { schema: resolver(sendMessageSchema) }
|
||||
}
|
||||
},
|
||||
401: {
|
||||
description: "Unauthorized - invalid token or user credentials",
|
||||
content: {
|
||||
"application/json": { schema: { type: "object", properties: { error: { type: "string" } } } }
|
||||
}
|
||||
},
|
||||
500: {
|
||||
description: "Server error",
|
||||
content: {
|
||||
"application/json": { schema: { type: "object", properties: { error: { type: "string" } } } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
zValidator("json", sendMessageSchema),
|
||||
async (c) => {
|
||||
const { channelId, userId, content, token, repliedMessageId } = await c.req.json();
|
||||
|
||||
const result = await sendMessage(
|
||||
channelId,
|
||||
userId,
|
||||
content,
|
||||
token,
|
||||
repliedMessageId || null
|
||||
);
|
||||
|
||||
if (result) {
|
||||
return c.json(result, 201);
|
||||
} else {
|
||||
return c.json({ error: "Failed to send message. Check your credentials and try again." }, 401);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
export default messageRoutes;
|
||||
@@ -11,10 +11,10 @@ import {
|
||||
} from "../validators/userValidator";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
const actions = new Hono();
|
||||
const userRoutes = new Hono();
|
||||
|
||||
actions.get(
|
||||
"user/:id",
|
||||
userRoutes.get(
|
||||
"/:id",
|
||||
describeRoute({
|
||||
description: "Get user by id",
|
||||
responses: {
|
||||
@@ -44,8 +44,8 @@ actions.get(
|
||||
},
|
||||
);
|
||||
|
||||
actions.get(
|
||||
"user",
|
||||
userRoutes.get(
|
||||
"",
|
||||
describeRoute({
|
||||
description: "Get all users by instance id",
|
||||
responses: {
|
||||
@@ -73,8 +73,8 @@ actions.get(
|
||||
},
|
||||
);
|
||||
|
||||
actions.post(
|
||||
"user",
|
||||
userRoutes.post(
|
||||
"",
|
||||
describeRoute({
|
||||
description: "Create a new user",
|
||||
responses: {
|
||||
@@ -107,4 +107,4 @@ actions.post(
|
||||
},
|
||||
);
|
||||
|
||||
export default actions;
|
||||
export default userRoutes;
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
import {
|
||||
Message,
|
||||
MessagePing,
|
||||
PrismaClient,
|
||||
Role,
|
||||
Reply,
|
||||
} from "@prisma/client";
|
||||
import { CreateUserInput } from "../validators/userValidator";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export async function sendMessageToChannel(
|
||||
channelId: string,
|
||||
userId: string,
|
||||
content: string,
|
||||
repliedMessageId: string | null,
|
||||
): Promise<{
|
||||
id: string;
|
||||
channelId: string;
|
||||
userId: string;
|
||||
text: string;
|
||||
deleted: boolean;
|
||||
replies: null | {
|
||||
messageId: string;
|
||||
repliesToId: string;
|
||||
repliesToText: string;
|
||||
};
|
||||
} | null> {
|
||||
try {
|
||||
const newMessage = await prisma.message.create({
|
||||
data: {
|
||||
channelId: channelId,
|
||||
userId: userId,
|
||||
text: content,
|
||||
deleted: false,
|
||||
},
|
||||
});
|
||||
|
||||
if (!newMessage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let origMessage;
|
||||
if (repliedMessageId) {
|
||||
origMessage = await prisma.message.findUnique({
|
||||
where: {
|
||||
id: repliedMessageId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!origMessage) {
|
||||
throw new Error("could not find original message to reply to");
|
||||
}
|
||||
|
||||
await prisma.reply.create({
|
||||
data: {
|
||||
messageId: newMessage.id,
|
||||
repliesToId: origMessage.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...newMessage,
|
||||
channelId: newMessage.channelId!,
|
||||
userId: newMessage.userId!,
|
||||
replies: origMessage
|
||||
? {
|
||||
messageId: newMessage.id,
|
||||
repliesToId: origMessage?.id,
|
||||
repliesToText: origMessage?.text,
|
||||
}
|
||||
: null,
|
||||
};
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
160
concord-server/src/services/messageService.ts
Normal file
160
concord-server/src/services/messageService.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import {
|
||||
PrismaClient,
|
||||
} from "@prisma/client";
|
||||
import { getUserCredentials } from "./userService";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export async function getMessageInformation(id:string): Promise<{
|
||||
id: string,
|
||||
channelId: string,
|
||||
userId: string,
|
||||
text: string,
|
||||
deleted: boolean,
|
||||
replies: null | {
|
||||
messageId: string;
|
||||
repliesToId: string;
|
||||
repliesToText: string;
|
||||
};
|
||||
} | null> {
|
||||
try {
|
||||
if (!id) {
|
||||
throw new Error("missing messageId");
|
||||
}
|
||||
|
||||
const message = await prisma.message.findUnique({
|
||||
where: {
|
||||
id: id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!message) {
|
||||
throw new Error("could not find message");
|
||||
}
|
||||
|
||||
// Check if this message is a reply to another message
|
||||
const replyData = await prisma.reply.findFirst({
|
||||
where: {
|
||||
messageId: id,
|
||||
},
|
||||
});
|
||||
|
||||
let originalMessage = null;
|
||||
if (replyData) {
|
||||
originalMessage = await prisma.message.findUnique({
|
||||
where: {
|
||||
id: replyData.repliesToId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
id: message.id,
|
||||
channelId: message.channelId!,
|
||||
userId: message.userId!,
|
||||
text: message.text,
|
||||
deleted: message.deleted,
|
||||
replies: originalMessage
|
||||
? {
|
||||
messageId: message.id,
|
||||
repliesToId: originalMessage.id,
|
||||
repliesToText: originalMessage.text,
|
||||
}
|
||||
: null,
|
||||
};
|
||||
} catch (err) {
|
||||
const errMessage = err as Error;
|
||||
|
||||
if (errMessage.message === "missing messageId") {
|
||||
console.log("services::actions::getMessageInformation - missing messageId");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (errMessage.message === "could not find message") {
|
||||
console.log(
|
||||
"services::actions::getMessageInformation - unable to find message"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(
|
||||
"services::actions::getMessageInformation - unknown error",
|
||||
errMessage
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function sendMessageToChannel(
|
||||
channelId: string,
|
||||
userId: string,
|
||||
content: string,
|
||||
token: string,
|
||||
repliedMessageId: string | null,
|
||||
): Promise<{
|
||||
id: string;
|
||||
channelId: string;
|
||||
userId: string;
|
||||
text: string;
|
||||
deleted: boolean;
|
||||
replies: null | {
|
||||
messageId: string;
|
||||
repliesToId: string;
|
||||
repliesToText: string;
|
||||
};
|
||||
} | null> {
|
||||
try {
|
||||
const userCreds = await getUserCredentials(userId);
|
||||
if (!userCreds || userCreds.token != token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const newMessage = await prisma.message.create({
|
||||
data: {
|
||||
channelId: channelId,
|
||||
userId: userId,
|
||||
text: content,
|
||||
deleted: false,
|
||||
},
|
||||
});
|
||||
|
||||
if (!newMessage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let origMessage;
|
||||
if (repliedMessageId) {
|
||||
origMessage = await prisma.message.findUnique({
|
||||
where: {
|
||||
id: repliedMessageId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!origMessage) {
|
||||
throw new Error("could not find original message to reply to");
|
||||
}
|
||||
|
||||
await prisma.reply.create({
|
||||
data: {
|
||||
messageId: newMessage.id,
|
||||
repliesToId: origMessage.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...newMessage,
|
||||
channelId: newMessage.channelId!,
|
||||
userId: newMessage.userId!,
|
||||
replies: origMessage
|
||||
? {
|
||||
messageId: newMessage.id,
|
||||
repliesToId: origMessage?.id,
|
||||
repliesToText: origMessage?.text,
|
||||
}
|
||||
: null,
|
||||
};
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const getMessageByIdSchema = z.object({
|
||||
id: z.uuidv7()
|
||||
})
|
||||
|
||||
export const sendMessageSchema = z.object({
|
||||
channelId: z.uuidv7(),
|
||||
userId: z.uuidv7(),
|
||||
content: z.string(),
|
||||
token: z.string(),
|
||||
repliedMessageId: z.uuidv7().nullable().optional()
|
||||
})
|
||||
Reference in New Issue
Block a user