diff options
| -rw-r--r-- | db/models/users.js | 6 | ||||
| -rw-r--r-- | lib/nostr.js | 21 | ||||
| -rw-r--r-- | lib/sockets.js | 7 | ||||
| -rw-r--r-- | lib/utils.js | 7 | ||||
| -rw-r--r-- | lib/whitelist.js | 4 | ||||
| -rw-r--r-- | routes/events.js | 5 | ||||
| -rw-r--r-- | routes/users.js | 59 |
7 files changed, 80 insertions, 29 deletions
diff --git a/db/models/users.js b/db/models/users.js index 72680fd8..fce79537 100644 --- a/db/models/users.js +++ b/db/models/users.js @@ -250,6 +250,12 @@ const attributes = { }, locktime: { type: DataTypes.INTEGER(11) + }, + prompt: { + type: DataTypes.BOOLEAN + }, + display: { + type: DataTypes.STRING(255) } }; diff --git a/lib/nostr.js b/lib/nostr.js index 4730883f..4ee5cb13 100644 --- a/lib/nostr.js +++ b/lib/nostr.js @@ -25,20 +25,24 @@ export let coinos; let now = () => Math.round(Date.now() / 1000); let timeouts = {}; -export let q = async (sub, query, timeout = 20000) => +export let q = async (sub, query, timeout = 20000, since = 3600, eager = 200) => new Promise(async (r, j) => { let start = Date.now(); let seen = []; let rejected; query.since = await redis.get(`since:${sub}`); - if (now() - query.since < 3600) return r(); + if (now() - query.since < since) return r(); let done = { [sub]: [] }; let check = s => { let elapsed = Date.now() - start; if (rejected) return true; - if (done[s].length === pool.relays.length || elapsed > 200) { + if ( + done[s] && + (done[s].length === pool.relays.length || + (done[s].length && elapsed > eager)) + ) { r(); if (timeouts[s]) timeouts[s].clear(); return true; @@ -78,7 +82,7 @@ export let q = async (sub, query, timeout = 20000) => }); try { - await wait(() => check(sub)); + await wait(() => check(sub), 100, 200); } catch (e) { console.log(e); } @@ -137,6 +141,7 @@ pool.on("event", async (relay, sub, ev) => { await redis.set(`user:${pubkey}`, JSON.stringify(user)); await redis.set(`user:${user.username}`, JSON.stringify(user)); + coinos.send(ev); } else if (sub.includes("follows")) { let pubkey = sub.split(":")[0]; await redis.set(`${pubkey}:follows`, JSON.stringify(ev.tags)); @@ -144,14 +149,14 @@ pool.on("event", async (relay, sub, ev) => { let [_, followPubkey] = f; await redis.sAdd(`${followPubkey}:followers`, pubkey); } + coinos.send(ev); } else if (sub.includes("followers")) { let followed = sub.split(":")[0]; let { pubkey } = ev; await redis.sAdd(`${followed}:followers`, pubkey); - } else { - if (!relay.url.includes("coinos")) return; - - let pubkey = sub; + coinos.send(ev); + } else if (sub.includes("notes")) { + let pubkey = sub.split(":")[0]; ev.user = await getUser(pubkey); if (!ev.user.updated) { diff --git a/lib/sockets.js b/lib/sockets.js index 3bd0c2c2..82cf3f51 100644 --- a/lib/sockets.js +++ b/lib/sockets.js @@ -85,6 +85,7 @@ app.register(async function(app) { break; case "login": + let user; let token = data; if (lastSeen[token] > subtractSeconds(5)) return; lastSeen[token] = new Date(); @@ -92,7 +93,9 @@ app.register(async function(app) { try { if (!token || token === "null" || !jwt.decode(token)) return ws.close(code, `bad token ${token}`); - const { username, uuid } = jwt.decode(token); + let { username, uuid } = jwt.decode(token); + if (uuid) user = await getUser(uuid); + username = user.username; if (!(username || uuid)) throw new Error("Invalid JWT token"); if (!store.sockets[username]) store.sockets[username] = {}; @@ -110,7 +113,7 @@ app.register(async function(app) { store.sockets[username][id] = ws; names[id] = username; - let user = await getUser(username); + if (!user) user = await getUser(username); let { haspin } = user; diff --git a/lib/utils.js b/lib/utils.js index 748b2a74..95ee5fb1 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -11,6 +11,8 @@ import ln from "$lib/ln"; const { Op } = sequelize; +export const nada = () => {}; + export const sleep = n => new Promise(r => setTimeout(r, n)); export const wait = async (f, s = 300, n = 50) => { let i = 0; @@ -33,7 +35,10 @@ export const getUser = async (username, transaction) => { } ], where: { - username: { [Op.or]: [username, username.replace(/ /g, "")] } + [Op.or]: { + username: { [Op.or]: [username, username.replace(/ /g, "")] }, + uuid: { [Op.or]: [username, username.replace(/ /g, "")] } + } } }; diff --git a/lib/whitelist.js b/lib/whitelist.js index 4e4dc14e..96db6cdc 100644 --- a/lib/whitelist.js +++ b/lib/whitelist.js @@ -8,6 +8,7 @@ export default [ "cipher", "currencies", "currency", + "display", "email", "fiat", "follows", @@ -18,8 +19,9 @@ export default [ "keys", "locktime", "payments", - "pubkey", "profile", + "prompt", + "pubkey", "salt", "seed", "symbol", diff --git a/routes/events.js b/routes/events.js index 1734af24..bbdd8891 100644 --- a/routes/events.js +++ b/routes/events.js @@ -26,14 +26,15 @@ app.get("/nostr/:pubkey", async (req, res) => { followers: [] }; - await q(pubkey, { + q(`${pubkey}:notes`, { kinds: [1], authors: [pubkey] - }); + }).catch(console.log); await redis.set(`user:${pubkey}`, JSON.stringify(user)); let ids = await redis.sMembers(pubkey); + console.log("IDS", ids); let events = ids.length ? (await redis.mGet(ids.map(k => "ev:" + k))).map(JSON.parse) diff --git a/routes/users.js b/routes/users.js index d2cb1540..d209c3d9 100644 --- a/routes/users.js +++ b/routes/users.js @@ -3,7 +3,7 @@ import redis from "$lib/redis"; import config from "$config"; import store from "$lib/store"; import { auth, optionalAuth } from "$lib/passport"; -import { getUser, uniq, wait } from "$lib/utils"; +import { getUser, nada, uniq, wait } from "$lib/utils"; import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import { authenticator } from "otplib"; @@ -74,7 +74,9 @@ app.get("/users/:username", async (req, res) => { "profile", "address", "currency", - "pubkey" + "pubkey", + "display", + "prompt" ], where: { [Sequelize.Op.or]: [ @@ -214,9 +216,11 @@ app.post("/user", auth, async (req, res) => { "cipher", "currencies", "currency", + "display", "email", "fiat", "locktime", + "prompt", "pubkey", "salt", "seed", @@ -654,11 +658,17 @@ app.get("/:pubkey/follows", async (req, res) => { let { tagsonly } = req.query; let sub = `${pubkey}:follows`; - await q(sub, { - limit: 1, - kinds: [3], - authors: [pubkey] - }); + q( + sub, + { + limit: 1, + kinds: [3], + authors: [pubkey] + }, + 60000, + 3600, + 60000 + ).catch(nada); let tags = JSON.parse(await redis.get(`${pubkey}:follows`)) || []; if (tagsonly) return res.send(tags); @@ -667,14 +677,22 @@ app.get("/:pubkey/follows", async (req, res) => { for (let f of tags) { let [_, pubkey] = f; - await q(`${pubkey}:profile:f1`, { + q(`${pubkey}:profile:f1`, { limit: 1, kinds: [0], authors: [pubkey] - }); + }).catch(nada); let user = JSON.parse(await redis.get(`user:${pubkey}`)); - if (user) follows.push(user); + + if (!user) + user = { + username: pubkey.substr(0, 6), + pubkey, + anon: true + }; + + follows.push(user); } follows = uniq(follows, e => e.pubkey); @@ -691,20 +709,31 @@ app.get("/:pubkey/followers", async (req, res) => { try { let { pubkey } = req.params; - let pubkeys = await got( - `${config.nostr}/followers?pubkey=${pubkey}` - ).json(); + let pubkeys = [ + ...new Set([ + ...(await got(`${config.nostr}/followers?pubkey=${pubkey}`).json()), + ...(await redis.sMembers(`${pubkey}:followers`)) + ]) + ]; let followers = []; + q( + `${pubkey}:followers`, + { kinds: [3], "#p": [pubkey] }, + 60000, + 3600, + 60000 + ).catch(nada); + for (let pubkey of pubkeys) { let user = JSON.parse(await redis.get(`user:${pubkey}`)); if (!user || !user.updated) { - await q(`${pubkey}:profile:f2`, { + q(`${pubkey}:profile:f2`, { limit: 1, kinds: [0], authors: [pubkey] - }); + }).catch(nada); user = JSON.parse(await redis.get(`user:${pubkey}`)); } |
