diff options
| author | Adam Soltys <[email protected]> | 2025-01-23 16:39:52 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2025-01-23 16:39:52 -0800 |
| commit | 615e3d3de3ea9af086ecded723e8a2a5787ac8c7 (patch) | |
| tree | bde16aa6de78d2bd0ee9f87cab5ef369ffda1f65 | |
| parent | a1f4ed6408655dde0f1e6d71f7a571571b9cc826 (diff) | |
| download | coinos-server-615e3d3de3ea9af086ecded723e8a2a5787ac8c7.tar.gz coinos-server-615e3d3de3ea9af086ecded723e8a2a5787ac8c7.zip | |
unified event endpoint
| -rw-r--r-- | index.ts | 1 | ||||
| -rw-r--r-- | lib/nostr.ts | 20 | ||||
| -rw-r--r-- | routes/nostr.ts | 77 |
3 files changed, 75 insertions, 23 deletions
@@ -55,6 +55,7 @@ app.get("/:pubkey/followers", nostr.followers); app.get("/:pubkey/follows", nostr.follows); app.get("/:pubkey/events", nostr.events); app.get("/event/:id", nostr.event); +app.get("/event/:id/full", nostr.event); app.post("/event", auth, nostr.publish); app.post("/parseEvent", nostr.parse); app.get("/zaps/:id", nostr.zaps); diff --git a/lib/nostr.ts b/lib/nostr.ts index 9f31f6ad..aca518b6 100644 --- a/lib/nostr.ts +++ b/lib/nostr.ts @@ -7,6 +7,8 @@ import { finalizeEvent, getPublicKey, nip19 } from "nostr-tools"; import { AbstractSimplePool } from "nostr-tools/abstract-pool"; import { Relay } from "nostr-tools/relay"; +export const EX = 60 * 60 * 24; + export const serverPubkey = getPublicKey( nip19.decode(config.nostrKey).data as Uint8Array, ); @@ -144,7 +146,7 @@ export const getProfile = async (pubkey) => { profile = anon(pubkey); } - await db.set(`profile:${pubkey}`, JSON.stringify(profile), { EX: 300 }); + await db.set(`profile:${pubkey}`, JSON.stringify(profile), { EX }); return profile; }; @@ -153,17 +155,21 @@ export const getCount = async (pubkey) => { try { let follows = await g(`${pubkey}:follows:n`); - if (!follows) { + if (follows === null) { const result = await get({ authors: [pubkey], kinds: [3] }); follows = result ? result.tags.filter((t) => t[0] === "p").length : 0; - await db.set(`${pubkey}:follows:n`, follows, { EX: 300 }); + await db.set(`${pubkey}:follows:n`, follows, { EX }); } - let followers = await g(`${pubkey}:followers:n`); + const k = `${pubkey}:followers:n`; + let followers = await g(k); - if (!followers) { - [followers] = await count({ "#p": [pubkey], kinds: [3] }); - await db.set(`${pubkey}:followers:n`, followers, { EX: 300 }); + if (followers === null) { + [followers] = await count({ + "#p": [pubkey], + kinds: [3], + }); + await db.set(k, followers, { EX }); } return { follows, followers }; diff --git a/routes/nostr.ts b/routes/nostr.ts index 64ada29e..962e45f9 100644 --- a/routes/nostr.ts +++ b/routes/nostr.ts @@ -1,15 +1,12 @@ -import config from "$config"; import { db, g, s } from "$lib/db"; import ln from "$lib/ln"; import { - anon, + EX, get, getCount, getNostrUser, getProfile, - getRelays, q, - send, serverPubkey, } from "$lib/nostr"; import { parseContent } from "$lib/notes"; @@ -24,14 +21,63 @@ import { getZapEndpoint, makeZapRequest } from "nostr-tools/nip57"; export default { async event(req, res) { - let { id } = req.params; - if (id.startsWith("nevent")) id = decode(id).data.id; - if (id.startsWith("note")) id = decode(id).data; - const events = await q({ ids: [id] }); + try { + let { id } = req.params; + const full = req.url.endsWith("full"); + + if (id.startsWith("nevent")) id = decode(id).data.id; + if (id.startsWith("note")) id = decode(id).data; - if (!events.length) return bail(res, "event not found"); + const k = `event:${id}${full ? ":full" : ""}`; + let event = await g(k); + if (event) return res.send(event); + + event = await get({ ids: [id] }); + if (!full) return res.send(event); + + const parts = parseContent(event); + const names = {}; + + for (const { type, value } of parts) { + if (type.includes("nprofile") || type.includes("npub")) { + const { name } = await getProfile(value.pubkey); + names[value.pubkey] = name; + } + } - res.send(events[0]); + event.parts = parts; + event.names = names; + event.author = await getProfile(event.pubkey); + + const zapEvents = await scan({ kinds: [9735], "#e": [id] }); + const zaps = []; + for (const { tags } of zapEvents) { + const bolt11 = tags.find((t) => t[0] === "bolt11")?.[1]; + const description = tags.find((t) => t[0] === "description")?.[1]; + const { pubkey } = JSON.parse(description); + let amount = 0; + try { + const { amount_msat } = await ln.decode(bolt11); + if (amount_msat) amount = Math.round(amount_msat / 1000); + } catch (e) {} + + let user; + if (pubkey) { + try { + user = await getNostrUser(pubkey); + zaps.push({ amount, user }); + } catch (e) {} + } + } + + event.zaps = zaps.filter((z) => z.amount > 0); + await db.set(k, JSON.stringify(event), { EX }); + + res.send(event); + } catch (e) { + console.log(e); + bail(res, e.message); + } }, async parse(req, res) { @@ -67,7 +113,7 @@ export default { for (const t of thread) { const e = t as any; - e.author = await getNostrUser(e.pubkey); + e.author = await getProfile(e.pubkey); e.parts = parseContent(e); e.names = {}; for (const { type, value } of e.parts) { @@ -154,7 +200,7 @@ export default { for (const v of events) { const e = v as any; - e.author = await getNostrUser(e.pubkey); + e.author = await getProfile(e.pubkey); e.parts = parseContent(e); e.names = {}; for (const { type, value } of e.parts) { @@ -205,7 +251,7 @@ export default { .map((r) => r.value); } - await db.set(k, JSON.stringify(follows), { EX: 300 }); + await db.set(k, JSON.stringify(follows), { EX }); res.send(follows); } catch (e) { @@ -238,9 +284,7 @@ export default { .filter((r) => r.status === "fulfilled") .map((r) => r.value); - await db.set(`${pubkey}:followers`, JSON.stringify(followers), { - EX: 300, - }); + await db.set(`${pubkey}:followers`, JSON.stringify(followers), { EX }); res.send(followers); } catch (e) { @@ -252,6 +296,7 @@ export default { async count(req, res) { try { const { pubkey } = req.params; + // res.send({ followers: 0, follows: 0 }); res.send(await getCount(pubkey)); } catch (e) { console.log(e); |
