From fe9db7509d2acd5e5e722397d743a07e1eb1400f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Mon, 21 Oct 2024 00:29:53 +0200 Subject: [PATCH] Support pretty URLs for articles, redirect from naddr --- handlers/naddr.ts | 18 ++++------------- handlers/user-event.ts | 45 ++++++++++++++++++++++++++++++++++++++++++ main.ts | 17 ++++++++++++++++ 3 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 handlers/user-event.ts diff --git a/handlers/naddr.ts b/handlers/naddr.ts index cfd3ce7..4f708d6 100644 --- a/handlers/naddr.ts +++ b/handlers/naddr.ts @@ -1,27 +1,17 @@ import { Context } from "@oak/oak"; import { nip19 } from "@nostr/tools"; import { log } from "../log.ts"; -import { articleHtml } from "../html.ts"; -import { fetchProfileEvent, fetchReplaceableEvent } from "../nostr.ts"; +import { lookupUsernameByPubkey } from "../ldap.ts"; const naddrHandler = async function (ctx: Context) { - const { request } = ctx; const naddr = ctx.params.path; try { const r = nip19.decode(naddr); - const articleEvent = await fetchReplaceableEvent( - r.data.pubkey, - r.data.identifier, - ); - const profileEvent = await fetchProfileEvent(r.data.pubkey); - let profile; + const username = await lookupUsernameByPubkey(r.data.pubkey); - if (articleEvent && profileEvent) { - const profile = JSON.parse(profileEvent.content); - const html = articleHtml(articleEvent, profile); - - ctx.response.body = html; + if (username && r.data.identifier) { + ctx.response.redirect(`/@${username}/${r.data.identifier}`); } else { ctx.response.status = 404; ctx.response.body = "Not Found"; diff --git a/handlers/user-event.ts b/handlers/user-event.ts new file mode 100644 index 0000000..b4675b9 --- /dev/null +++ b/handlers/user-event.ts @@ -0,0 +1,45 @@ +import { Context } from "@oak/oak"; +import { log } from "../log.ts"; +import { lookupPubkeyByUsername } from "../ldap.ts"; +import { + fetchProfileEvent, + fetchReplaceableEvent, +} from "../nostr.ts"; +import { articleHtml } from "../html.ts"; + +const userEventHandler = async function (ctx: Context) { + const username = ctx.params.user.replace(/^(@|~)/, ""); + const identifier = ctx.params.identifier; + const pubkey = await lookupPubkeyByUsername(username); + + if (!pubkey) { + ctx.response.status = 404; + ctx.response.body = "Not Found"; + return; + } + + try { + const articleEvent = await fetchReplaceableEvent( + pubkey, + identifier, + ); + const profileEvent = await fetchProfileEvent(pubkey); + let profile; + + if (articleEvent && profileEvent) { + profile = JSON.parse(profileEvent.content); + const html = articleHtml(articleEvent, profile); + + ctx.response.body = html; + } else { + ctx.response.status = 404; + ctx.response.body = "Not Found"; + } + } catch (e) { + log(e, "yellow"); + ctx.response.status = 404; + ctx.response.body = "Not Found"; + } +}; + +export default userEventHandler; diff --git a/main.ts b/main.ts index 2d374b8..140f12d 100644 --- a/main.ts +++ b/main.ts @@ -4,6 +4,7 @@ import naddrHandler from "./handlers/naddr.ts"; import nprofileHandler from "./handlers/nprofile.ts"; import npubHandler from "./handlers/npub.ts"; import usernameHandler from "./handlers/username.ts"; +import userEventHandler from "./handlers/user-event.ts"; const router = new Router(); @@ -29,6 +30,22 @@ router.get("/:path", async (ctx: ctx) => { ); }); +router.get("/:user/:identifier", async (ctx: ctx) => { + const { user } = ctx.params; + + if (user.startsWith("@") || user.startsWith("~")) { + await userEventHandler(ctx); + } else { + ctx.response.status = 404; + ctx.response.body = "Not Found"; + } + + log( + `${ctx.request.method} ${ctx.request.url} - ${ctx.response.status}`, + "gray", + ); +}); + const app = new Application(); app.use(router.routes()); app.use(router.allowedMethods());