Move chat to private authenticated API

This commit is contained in:
Dorian
2026-05-06 21:04:50 +01:00
parent cb21c693d0
commit 0ff7bc46fc
7 changed files with 202 additions and 174 deletions

View File

@@ -0,0 +1,44 @@
import { Router } from "express";
import { z } from "zod";
import { requireAuth } from "../auth/middleware.js";
import { addMessage, addReaction, listChat } from "./store.js";
export const chatRouter = Router();
const MessageBody = z.object({
content: z.string().trim().min(1).max(2000),
replyToId: z.string().max(128).optional(),
replyToPubkey: z.string().max(128).optional(),
});
const ReactionBody = z.object({
messageId: z.string().min(1).max(128),
content: z.string().trim().min(1).max(32),
});
chatRouter.use(requireAuth);
chatRouter.get("/", (_req, res) => {
res.json(listChat());
});
chatRouter.post("/messages", (req, res) => {
const body = MessageBody.parse(req.body);
const message = addMessage({
pubkey: req.session!.pubkey,
content: body.content,
...(body.replyToId ? { replyToId: body.replyToId } : {}),
...(body.replyToPubkey ? { replyToPubkey: body.replyToPubkey } : {}),
});
res.status(201).json(message);
});
chatRouter.post("/reactions", (req, res) => {
const body = ReactionBody.parse(req.body);
const reaction = addReaction({
pubkey: req.session!.pubkey,
messageId: body.messageId,
content: body.content,
});
res.status(201).json(reaction);
});

View File

@@ -0,0 +1,62 @@
export type StoredChatMessage = {
id: string;
pubkey: string;
content: string;
createdAt: number;
replyToId: string;
replyToPubkey: string;
};
export type StoredChatReaction = {
id: string;
pubkey: string;
messageId: string;
content: string;
createdAt: number;
};
const MAX_MESSAGES = 500;
const MAX_REACTIONS = 2000;
const messages: StoredChatMessage[] = [];
const reactions: StoredChatReaction[] = [];
export function listChat(): { messages: StoredChatMessage[]; reactions: StoredChatReaction[] } {
return { messages: [...messages], reactions: [...reactions] };
}
export function addMessage(input: {
pubkey: string;
content: string;
replyToId?: string;
replyToPubkey?: string;
}): StoredChatMessage {
const message: StoredChatMessage = {
id: crypto.randomUUID(),
pubkey: input.pubkey,
content: input.content,
createdAt: Math.floor(Date.now() / 1000),
replyToId: input.replyToId ?? "",
replyToPubkey: input.replyToPubkey ?? "",
};
messages.push(message);
if (messages.length > MAX_MESSAGES) messages.splice(0, messages.length - MAX_MESSAGES);
return message;
}
export function addReaction(input: {
pubkey: string;
messageId: string;
content: string;
}): StoredChatReaction {
const reaction: StoredChatReaction = {
id: crypto.randomUUID(),
pubkey: input.pubkey,
messageId: input.messageId,
content: input.content,
createdAt: Math.floor(Date.now() / 1000),
};
reactions.push(reaction);
if (reactions.length > MAX_REACTIONS) reactions.splice(0, reactions.length - MAX_REACTIONS);
return reaction;
}

View File

@@ -9,6 +9,7 @@ import fs from "node:fs";
import { config } from "./config.js";
import { logger } from "./logger.js";
import { authRouter } from "./auth/routes.js";
import { chatRouter } from "./chat/routes.js";
import { datumRouter } from "./datum/routes.js";
import { errorHandler } from "./errors.js";
@@ -61,6 +62,7 @@ export function buildApp() {
res.json({ ok: true });
});
app.use("/api/auth", authRouter);
app.use("/api/chat", chatRouter);
app.use("/api/datum", datumRouter);
const staticDir = config.staticDir