aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2025-01-23 12:22:42 -0800
committerAdam Soltys <[email protected]>2025-01-23 12:22:42 -0800
commitaf884d9710dd42c462437c02a53948b09d5d396f (patch)
treed3c97ddddc9192aba60a55ef3202a4ea377e3a96
parent9662c2754834599a1074d12565279674c20af467 (diff)
downloadcoinos-server-af884d9710dd42c462437c02a53948b09d5d396f.tar.gz
coinos-server-af884d9710dd42c462437c02a53948b09d5d396f.zip
follows
-rw-r--r--lib/nostr.ts19
-rw-r--r--lib/strfry.ts5
-rw-r--r--routes/nostr.ts136
3 files changed, 84 insertions, 76 deletions
diff --git a/lib/nostr.ts b/lib/nostr.ts
index 21c254e3..9f31f6ad 100644
--- a/lib/nostr.ts
+++ b/lib/nostr.ts
@@ -151,12 +151,21 @@ export const getProfile = async (pubkey) => {
export const getCount = async (pubkey) => {
try {
- const result = await scan({ authors: [pubkey], kinds: [3] });
- const follows = result.length
- ? result[0].tags.filter((t) => t[0] === "p").length
- : 0;
+ let follows = await g(`${pubkey}:follows:n`);
+
+ if (!follows) {
+ 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 });
+ }
+
+ let followers = await g(`${pubkey}:followers:n`);
+
+ if (!followers) {
+ [followers] = await count({ "#p": [pubkey], kinds: [3] });
+ await db.set(`${pubkey}:followers:n`, followers, { EX: 300 });
+ }
- const [followers] = await count({ "#p": [pubkey], kinds: [3] });
return { follows, followers };
} catch (e) {
console.log(e);
diff --git a/lib/strfry.ts b/lib/strfry.ts
index 926ca429..65b77709 100644
--- a/lib/strfry.ts
+++ b/lib/strfry.ts
@@ -72,7 +72,10 @@ const exec = async (cmd: string, data = ""): Promise<Event[]> =>
// return r;
// };
-export const load = (data) => exec(`echo '${data}' | /app/strfry import --no-verify\n`);
+export const load = (data) =>
+ exec(
+ `echo '${data.replace(/'/g, "'\\''")}' | /app/strfry import --no-verify\n`,
+ );
export const count = (f) =>
exec(`/app/strfry scan --count '${JSON.stringify(f)}'\n`);
export const scan = (f) => exec(`/app/strfry scan '${JSON.stringify(f)}'\n`);
diff --git a/routes/nostr.ts b/routes/nostr.ts
index 0bfe9970..24cb3ed6 100644
--- a/routes/nostr.ts
+++ b/routes/nostr.ts
@@ -1,5 +1,5 @@
import config from "$config";
-import { db } from "$lib/db";
+import { db, g, s } from "$lib/db";
import ln from "$lib/ln";
import {
anon,
@@ -133,56 +133,14 @@ export default {
// if (!relays.includes(config.nostr)) relays.push(config.nostr);
if (!verifyEvent(event)) fail("Invalid event");
await load(JSON.stringify(event));
- if (event.kind === 3) db.del(`${pubkey}:follows`);
- res.send({});
- } catch (e) {
- bail(res, e.message);
- }
- },
-
- async follows(req, res) {
- const {
- params: { pubkey },
- query: { limit = 20, offset = 0, pubkeysOnly },
- } = req;
- try {
- const events = await scan({ authors: [pubkey], kinds: [3] });
- if (!events.length) return res.send([]);
-
- const event = events[0];
- let pubkeys = event.tags
- .filter((tag) => tag[0] === "p")
- .map((tag) => tag[1]);
-
- let follows = [];
- if (pubkeysOnly) follows = pubkeys;
- else {
- pubkeys = pubkeys.slice(limit, offset);
- const profiles = await scan({ authors: pubkeys, kinds: [0] });
- for (const p of profiles) {
- const { content, pubkey } = p;
- let user = await getUser(pubkey, fields);
- user = { ...user, ...JSON.parse(content) };
- user.pubkey = pubkey;
- follows.push(user);
- }
-
- const keys = follows.map((f) => f.pubkey);
- const missing = await Promise.all(
- pubkeys
- .filter((p) => !keys.includes(p))
- .map(
- async (pubkey) => (await getUser(pubkey, fields)) || anon(pubkey),
- ),
- );
-
- follows.push(...missing);
+ if (event.kind === 3) {
+ db.del(`${pubkey}:follows`);
+ db.del(`${pubkey}:follows:n`);
}
- res.send(follows);
+ res.send({});
} catch (e) {
- console.log("follows fail", e);
bail(res, e.message);
}
},
@@ -214,38 +172,76 @@ export default {
}
},
- async followers(req, res) {
+ async follows(req, res) {
const {
params: { pubkey },
- query: { limit = 20, offset = 0 },
+ query: { limit = 20, offset = 0, pubkeysOnly },
} = req;
try {
- const filter = { kinds: [3], "#p": [pubkey] };
- const events = await scan({ ...filter, limit });
- if (!events.length) return res.send([]);
+ let follows = await g(`${pubkey}:follows`);
+ if (follows?.length) return res.send(follows);
+
+ const event = await get({ authors: [pubkey], kinds: [3] });
+ if (!event) return res.send([]);
- const pubkeys = events.map((e) => e.pubkey).slice(offset, limit);
+ let pubkeys = event.tags
+ .filter((tag) => tag[0] === "p")
+ .map((tag) => tag[1]);
- const followers = [];
- const profiles = await scan({ authors: pubkeys, kinds: [0] });
- for (const p of profiles) {
- const { content, pubkey } = p;
- let user = await getUser(pubkey, fields);
- user = { ...user, ...JSON.parse(content) };
- user.pubkey = pubkey;
- followers.push(user);
+ follows = [];
+ if (pubkeysOnly) follows = pubkeys;
+ else {
+ pubkeys = pubkeys.slice(offset, offset + limit);
+ follows = (
+ await Promise.allSettled(
+ pubkeys.map(async (pubkey) => ({
+ ...(await getProfile(pubkey)),
+ pubkey,
+ })),
+ )
+ )
+ .filter((r) => r.status === "fulfilled")
+ .map((r) => r.value);
}
- const keys = followers.map((f) => f.pubkey);
- const missing = await Promise.all(
- pubkeys
- .filter((p) => !keys.includes(p))
- .map(
- async (pubkey) => (await getUser(pubkey, fields)) || anon(pubkey),
- ),
- );
+ await db.set(`${pubkey}:follows`, JSON.stringify(follows), {
+ EX: 300,
+ });
+
+ res.send(follows);
+ } catch (e) {
+ console.log("follows fail", e);
+ bail(res, e.message);
+ }
+ },
+
+ async followers(req, res) {
+ const {
+ params: { pubkey },
+ query: { limit = 20, offset = 0 },
+ } = req;
+ try {
+ let followers = await g(`${pubkey}:followers`);
+ if (followers?.length) return res.send(followers);
+
+ const events = await q({ kinds: [3], "#p": [pubkey], limit });
+ if (!events.length) return res.send([]);
+
+ const pubkeys = events.map((e) => e.pubkey).slice(offset, offset + limit);
+ followers = (
+ await Promise.allSettled(
+ pubkeys.map(async (pubkey) => ({
+ ...(await getProfile(pubkey)),
+ pubkey,
+ })),
+ )
+ )
+ .filter((r) => r.status === "fulfilled")
+ .map((r) => r.value);
- followers.push(...missing);
+ await db.set(`${pubkey}:followers`, JSON.stringify(followers), {
+ EX: 300,
+ });
res.send(followers);
} catch (e) {