55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
/**
|
|
* The chat history route.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
import { Router } from "@oak/oak";
|
|
import type { APIResponse } from "../../shared/api.ts";
|
|
import type { ChatMessage } from "../../shared/chat.ts";
|
|
import { authMiddleware } from "../middleware/auth.ts";
|
|
import {
|
|
getChatMessagesAfter,
|
|
getRecentChatMessages,
|
|
} from "../services/chat-service.ts";
|
|
|
|
/**
|
|
* The chat history route; messages are posted and edited over the socket (see
|
|
* routes/ws.ts):
|
|
*
|
|
* - `GET /api/chat?limit=&before=&beforeId=&after=&afterId=` — signed in.
|
|
* Answers messages in ascending order: the most recent by default; with
|
|
* `before`, the page of older messages preceding that cursor ("load older");
|
|
* with `after`, the messages following it (resync after a reconnect). A
|
|
* cursor is an ISO `created_at` plus the message id to break ties; without
|
|
* `afterId` the `after` timestamp itself is included.
|
|
*/
|
|
const router: Router = new Router({ prefix: "/api/chat" });
|
|
|
|
router.get("/", authMiddleware, (ctx) => {
|
|
const params = ctx.request.url.searchParams;
|
|
const limitParam = params.get("limit");
|
|
const limit = limitParam ? Number(limitParam) : NaN;
|
|
const cappedLimit = Number.isFinite(limit) ? limit : undefined;
|
|
const before = params.get("before");
|
|
const after = params.get("after");
|
|
const messages = after
|
|
? getChatMessagesAfter(
|
|
{ createdAt: after, id: params.get("afterId") ?? undefined },
|
|
cappedLimit,
|
|
)
|
|
: getRecentChatMessages(
|
|
cappedLimit,
|
|
before
|
|
? { createdAt: before, id: params.get("beforeId") ?? undefined }
|
|
: undefined,
|
|
);
|
|
const responseBody: APIResponse<ChatMessage[]> = {
|
|
success: true,
|
|
data: messages,
|
|
};
|
|
ctx.response.body = responseBody;
|
|
});
|
|
|
|
export default router;
|