import { Application, Router, send } from "@oak/oak"; import { createSubtrTmpDirectories } from "./utils.ts"; import config, { ensureNecessaryConfigs } from "./config.ts"; import naddrHandler from "./handlers/naddr.ts"; import nprofileHandler from "./handlers/nprofile.ts"; import npubHandler from "./handlers/npub.ts"; import userProfileHandler from "./handlers/user-profile.ts"; import userEventHandler from "./handlers/user-event.ts"; import userAtomFeedHandler from "./handlers/user-atom-feed.ts"; import { badGatewayHandler, internalServerErrorHandler, notFoundHandler, } from "./handlers/errors.ts"; const router = new Router(); router.get("/:path", async (ctx) => { const path = ctx.state.path = ctx.params.path; try { if (path.startsWith("naddr")) { await naddrHandler(ctx); } else if (path.startsWith("nprofile")) { await nprofileHandler(ctx); } else if (path.startsWith("npub")) { await npubHandler(ctx); } else if (path.startsWith("@") || path.startsWith("~")) { await userProfileHandler(ctx); } else { notFoundHandler(ctx); } } catch (e) { console.error(e); if (e instanceof Error && e.message.match(/^connect|relay timeout/)) { badGatewayHandler(ctx); } else { internalServerErrorHandler(ctx); } } }); router.get("/:username/:kind.atom", async (ctx) => { ctx.state.username = ctx.params.username.replace(/^(@|~)/, ""); ctx.state.kind = ctx.params.kind; if ( ctx.state.kind === "articles" && (ctx.params.username.startsWith("@") || ctx.params.username.startsWith("~")) ) { try { await userAtomFeedHandler(ctx); } catch (e) { console.error(e); if (e instanceof Error && e.message.match(/^connect|relay timeout/)) { badGatewayHandler(ctx); } else { internalServerErrorHandler(ctx); } } } else { notFoundHandler(ctx); } }); router.get("/:username/:identifier", async (ctx) => { const username = ctx.state.username = ctx.params.username; ctx.state.identifier = ctx.params.identifier; if (username.startsWith("@") || username.startsWith("~")) { try { await userEventHandler(ctx); } catch (e) { console.error(e); if (e instanceof Error && e.message.match(/^connect|relay timeout/)) { badGatewayHandler(ctx); } else { internalServerErrorHandler(ctx); } } } else { notFoundHandler(ctx); } }); router.get("/assets/:path*", async (ctx) => { try { let filePath = ctx.params.path || ""; let root: string; if (filePath.startsWith("g/img/")) { filePath = filePath.replace(/^g\//, ""); root = "/tmp/substr"; } else { root = `${import.meta.dirname}/assets`; } await send(ctx, filePath, { root }); } catch (e) { if (e instanceof Error && e.name === "NotFoundError") { notFoundHandler(ctx); } else { console.error(e); badGatewayHandler(ctx); } } }); ensureNecessaryConfigs(); await createSubtrTmpDirectories(); const app = new Application(); app.use(router.routes()); app.use(router.allowedMethods()); app.listen({ port: config.port }); console.log(`App listening on http://localhost:${config.port}`);