From 9f713a693d818e60090016b874212b58726cd906 Mon Sep 17 00:00:00 2001 From: Lynn Zenn <1zenn0@proton.me> Date: Wed, 26 Apr 2023 19:58:37 +0200 Subject: [PATCH 1/2] pubsub: use relay hints Follows referred events' relay hints. Adds relay hints to `e` tags. In theory it'd also work for `p` tags, however the profiles are found via the iris.to API and thus there isn't any trace about where the profile came from. Fixes published events incorrectly showing up as "Found by Iris.to API". --- src/js/nostr/Events.ts | 32 ++++++++++++++++++++++++++++++++ src/js/nostr/PubSub.ts | 8 +++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/js/nostr/Events.ts b/src/js/nostr/Events.ts index bf6991c2a..0cae8ecb2 100644 --- a/src/js/nostr/Events.ts +++ b/src/js/nostr/Events.ts @@ -538,8 +538,26 @@ const Events = { if (!id) { return; } + const hints = Events._getHintedRelays(event); + Object.entries(hints).forEach(([id, relays]) => { + this.eventsMetaDb.upsert(id, { relays }); + }); this.eventsMetaDb.upsert(id, { relays: new Set([url]) }); }, + _getHintedRelays(event: Event) { + const tagsWanted = ['e', 'p']; + const ids = event.tags.reduce<{ [id: string]: Set }>((acc, [tag, id, relay]) => { + if (!tagsWanted.includes(tag) || !relay?.startsWith('wss://')) { + return acc; + } + if (!acc[id]) { + acc[id] = new Set(); + } + acc[id].add(relay.trim()); + return acc; + }, {}); + return ids; + }, handleNextFutureEvent() { if (this.futureEventIds.size === 0) { return; @@ -645,6 +663,7 @@ const Events = { console.log('publishing event', event); this.handle(event as Event); + this.handleEventMetadata({ event: event as Event, url: Relays.enabledRelays()[0] }); // also publish at most 10 events referred to in tags const referredEvents = event.tags @@ -665,6 +684,7 @@ const Events = { if (!event.tags) { event.tags = []; } + Events.addRelayHints(event as Event); event.content = event.content || ''; event.created_at = event.created_at || Math.floor(Date.now() / 1000); event.pubkey = Key.getPubKey(); @@ -762,6 +782,18 @@ const Events = { unsub2(); }; }, + addRelayHints(event: { tags: string[][] }) { + event.tags.forEach((tag) => { + // Only for 'e' and 'p', and if already exists then out. + if (!['e', 'p'].includes(tag[0]) || tag[2]) { + return; + } + const hints = this.eventsMetaDb.getRelays(tag[1]); + if (hints.length > 0) { + tag[2] = hints[0]; + } + }); + }, }; export default Events; diff --git a/src/js/nostr/PubSub.ts b/src/js/nostr/PubSub.ts index 53ea060e2..3cbc3896a 100644 --- a/src/js/nostr/PubSub.ts +++ b/src/js/nostr/PubSub.ts @@ -1,4 +1,4 @@ -import { throttle } from 'lodash'; +import { throttle, uniq } from 'lodash'; import { RelayPool } from 'nostr-relaypool'; import { Event, Filter, matchFilter } from '../lib/nostr-tools'; @@ -204,6 +204,8 @@ const PubSub = { relays = Array.from(Relays.searchRelays.keys()); } else if (mergeSubscriptions || filter.authors?.length !== 1) { relays = Relays.enabledRelays(); + const hints = this._getHintedRelays(filter); + relays = uniq([...relays, ...hints]); } if (dev.indexed03 !== false && filter.kinds?.every((k) => k === 0 || k === 3)) { relays = ['wss://us.rbr.bio', 'wss://eu.rbr.bio']; @@ -234,6 +236,10 @@ const PubSub = { }, ); }, + _getHintedRelays(filter: Filter) { + const idsWanted = [...(filter.ids || []), ...(filter.authors || [])]; + return idsWanted.flatMap((id) => Events.eventsMetaDb.getRelays(id)); + }, }; export default PubSub; From d9e2957ae9b6df62131565ac2506cbbf90711bd9 Mon Sep 17 00:00:00 2001 From: Lynn Zenn <1zenn0@proton.me> Date: Sun, 30 Apr 2023 19:12:18 +0200 Subject: [PATCH 2/2] messageform: add relay hint tags in nprofile/nevent --- src/js/Helpers.tsx | 7 +++++++ src/js/Main.tsx | 2 +- src/js/components/MessageForm.js | 5 ++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/js/Helpers.tsx b/src/js/Helpers.tsx index baeadb39f..79fb61713 100644 --- a/src/js/Helpers.tsx +++ b/src/js/Helpers.tsx @@ -19,8 +19,13 @@ const emojiRegex = /([\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}-\u{27bf}\u{1f1e6}-\u{1f1ff}\u{1f191}-\u{1f251}\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}]+)/gu; const pubKeyRegex = /(?:^|\s|nostr:|(?:https?:\/\/[\w./]+)|iris\.to\/|snort\.social\/p\/|damus\.io\/)+((?:@)?npub[a-zA-Z0-9]{59,60})(?![\w/])/gi; +const nprofileRegex = + /(?:^|\s|nostr:|(?:https?:\/\/[\w./]+)|iris\.to\/|snort\.social\/p\/|damus\.io\/)+((?:@)?nprofile[a-zA-Z0-9]{59,})(?![\w/])/gi; const noteRegex = /(?:^|\s|nostr:|(?:https?:\/\/[\w./]+)|iris\.to\/|snort\.social\/e\/|damus\.io\/)+((?:@)?note[a-zA-Z0-9]{59,60})(?![\w/])/gi; +// No max length of 60. +const neventRegex = + /(?:^|\s|nostr:|(?:https?:\/\/[\w./]+)|iris\.to\/|snort\.social\/e\/|damus\.io\/)+((?:@)?nevent[a-zA-Z0-9]{59,})(?![\w/])/gi; const nip19Regex = /\bnostr:(n(?:event|profile)1\w+)\b/g; const hashtagRegex = /(#\w+)/g; @@ -877,4 +882,6 @@ export default { pubKeyRegex, noteRegex, hashtagRegex, + nprofileRegex, + neventRegex, }; diff --git a/src/js/Main.tsx b/src/js/Main.tsx index e35679465..086aeb5fa 100644 --- a/src/js/Main.tsx +++ b/src/js/Main.tsx @@ -110,7 +110,7 @@ class Main extends Component { // if id begins with "note", it's a post. otherwise it's a profile. const NoteOrProfile = (params: { id?: string; path: string }) => { - if (params.id.startsWith('note')) { + if (params.id.match(/^(note|nevent)/)) { return ; } return ; diff --git a/src/js/components/MessageForm.js b/src/js/components/MessageForm.js index 9c62eb2dd..24d109755 100644 --- a/src/js/components/MessageForm.js +++ b/src/js/components/MessageForm.js @@ -41,7 +41,8 @@ export default class MessageForm extends Component { if (taggedItems) { event.tags = event.tags || []; for (const tag of taggedItems) { - const hexTag = Key.toNostrHexAddress(tag.match(/npub[a-zA-Z0-9]{59,60}/)[0]); + const link = tag.match(/(?:npub|nprofile)[a-zA-Z0-9]{59,}/)[0]; + const hexTag = Key.toNostrHexAddress(link); if (!hexTag) { continue; } @@ -55,7 +56,9 @@ export default class MessageForm extends Component { } handleTagged(Helpers.pubKeyRegex, 'p'); + handleTagged(Helpers.nprofileRegex, 'p'); handleTagged(Helpers.noteRegex, 'e'); + handleTagged(Helpers.neventRegex, 'e'); const hashtags = [...msg.text.matchAll(Helpers.hashtagRegex)].map((m) => m[0].slice(1)); if (hashtags.length) {