Add relay hints to replies and publish to parent relay hint

This commit is contained in:
Bojan Mojsilovic 2024-04-03 17:31:02 +02:00
parent ded15540a2
commit c77656d6b8
6 changed files with 67 additions and 6 deletions

View File

@ -632,17 +632,21 @@ const EditBox: Component<{
const rep = props.replyToNote; const rep = props.replyToNote;
if (rep) { if (rep) {
const rootTag = rep.post.tags.find(t => t[0] === 'e' && t[3] === 'root'); let rootTag = rep.post.tags.find(t => t[0] === 'e' && t[3] === 'root');
// If the note has a root tag, that meens it is not a root note itself // If the note has a root tag, that meens it is not a root note itself
// So we need to copy the `root` tag and add a `reply` tag // So we need to copy the `root` tag and add a `reply` tag
if (rootTag) { if (rootTag) {
tags.push([...rootTag]); const tagWithHint = rootTag.map((v, i) => i === 2 ?
tags.push(['e', rep.post.id, '', 'reply']); (rep.post.relayHints && rep.post.relayHints[rep.post.id]) || '' :
v,
);
tags.push([...tagWithHint]);
tags.push(['e', rep.post.id, (rep.post.relayHints && rep.post.relayHints[rep.post.id]) || '', 'reply']);
} }
// Otherwise, add the note as the root tag for this reply // Otherwise, add the note as the root tag for this reply
else { else {
tags.push(['e', rep.post.id, '', 'root']); tags.push(['e', rep.post.id, (rep.post.relayHints && rep.post.relayHints[rep.post.id]) || '', 'root']);
} }
// Copy all `p` tags from the note we are repling to // Copy all `p` tags from the note we are repling to

View File

@ -138,6 +138,7 @@ export enum Kind {
SuggestedUsersByCategory = 10_000_134, SuggestedUsersByCategory = 10_000_134,
UploadChunk = 10_000_135, UploadChunk = 10_000_135,
UserRelays=10_000_139, UserRelays=10_000_139,
RelayHint=10_000_141,
WALLET_OPERATION = 10_000_300, WALLET_OPERATION = 10_000_300,
} }

View File

@ -206,6 +206,11 @@ export const ThreadProvider = (props: { children: ContextChildren }) => {
setLinkPreviews(() => ({ [data.url]: preview })); setLinkPreviews(() => ({ [data.url]: preview }));
return; return;
} }
if (content.kind === Kind.RelayHint) {
const hints = JSON.parse(content.content);
updateStore('page', 'relayHints', (rh) => ({ ...rh, ...hints }));
}
}; };
const savePage = (page: FeedPage) => { const savePage = (page: FeedPage) => {

View File

@ -1,6 +1,6 @@
import { A } from "@solidjs/router"; import { A } from "@solidjs/router";
// @ts-ignore Bad types in nostr-tools // @ts-ignore Bad types in nostr-tools
import { Relay } from "nostr-tools"; import { Relay, relayInit } from "nostr-tools";
import { createStore } from "solid-js/store"; import { createStore } from "solid-js/store";
import LinkPreview from "../components/LinkPreview/LinkPreview"; import LinkPreview from "../components/LinkPreview/LinkPreview";
import { appleMusicRegex, emojiRegex, hashtagRegex, interpunctionRegex, Kind, linebreakRegex, lnRegex, mixCloudRegex, nostrNestsRegex, noteRegex, noteRegexLocal, profileRegex, profileRegexG, soundCloudRegex, spotifyRegex, tagMentionRegex, twitchRegex, urlRegex, urlRegexG, wavlakeRegex, youtubeRegex } from "../constants"; import { appleMusicRegex, emojiRegex, hashtagRegex, interpunctionRegex, Kind, linebreakRegex, lnRegex, mixCloudRegex, nostrNestsRegex, noteRegex, noteRegexLocal, profileRegex, profileRegexG, soundCloudRegex, spotifyRegex, tagMentionRegex, twitchRegex, urlRegex, urlRegexG, wavlakeRegex, youtubeRegex } from "../constants";
@ -440,7 +440,21 @@ export const sendEvent = async (event: NostrEvent, relays: Relay[], relaySetting
let responses = []; let responses = [];
let reasons: string[] = []; let reasons: string[] = [];
// Relay hints fromm `e` tags
const hintRelayUrls = event.tags.reduce((acc, t) => {
if (
t[0] === 'e' &&
t[2].length > 0 &&
!relays.find(r => r.url === t[2])
) {
return [ ...acc, t[2] ];
}
return [...acc];
}, []);
for (let i = 0;i < relays.length;i++) { for (let i = 0;i < relays.length;i++) {
const relay = relays[i]; const relay = relays[i];
const settings = (relaySettings && relaySettings[relay.url]) || { read: true, write: true }; const settings = (relaySettings && relaySettings[relay.url]) || { read: true, write: true };
@ -474,6 +488,30 @@ export const sendEvent = async (event: NostrEvent, relays: Relay[], relaySetting
})); }));
} }
for (let i = 0;i < hintRelayUrls.length;i++) {
const url = hintRelayUrls[i];
new Promise<string>(async (resolve, reject) => {
const relay = relayInit(url);
await relay.connect();
try {
logInfo('publishing to relay: ', relay)
await relay.publish(signedNote);
logInfo(`${relay.url} has accepted our event`);
resolve('success');
} catch (e) {
logError(`Failed publishing note to ${relay.url}: `, e);
reject('success');
}
relay.close();
});
}
try { try {
await Promise.any(responses); await Promise.any(responses);

View File

@ -1,3 +1,4 @@
import { propTraps } from "@solid-primitives/props";
import { nip19 } from "nostr-tools"; import { nip19 } from "nostr-tools";
import { Kind } from "../constants"; import { Kind } from "../constants";
import { hexToNpub } from "../lib/keys"; import { hexToNpub } from "../lib/keys";
@ -55,6 +56,7 @@ export const getRepostInfo: RepostInfo = (page, message) => {
satszapped: stat?.satszapped || 0, satszapped: stat?.satszapped || 0,
noteId: nip19.noteEncode(message.id), noteId: nip19.noteEncode(message.id),
noteActions: (page.noteActions && page.noteActions[message.id]) || noActions, noteActions: (page.noteActions && page.noteActions[message.id]) || noActions,
relayHints: page.relayHints,
}, },
} }
}; };
@ -299,6 +301,7 @@ export const convertToNotes: ConvertToNotes = (page) => {
satszapped: stat?.satszapped || 0, satszapped: stat?.satszapped || 0,
noteId: nip19.noteEncode(msg.id), noteId: nip19.noteEncode(msg.id),
noteActions: (page.noteActions && page.noteActions[msg.id]) ?? noActions, noteActions: (page.noteActions && page.noteActions[msg.id]) ?? noActions,
relayHints: page.relayHints,
}, },
repost, repost,
msg, msg,

12
src/types/primal.d.ts vendored
View File

@ -207,6 +207,13 @@ export type NostrBookmarks = {
tags: string[][], tags: string[][],
}; };
export type NostrRelayHint = {
kind: Kind.RelayHint,
content: string,
created_at?: number,
tags: string[][],
};
export type NostrEventContent = export type NostrEventContent =
NostrNoteContent | NostrNoteContent |
NostrUserContent | NostrUserContent |
@ -235,7 +242,8 @@ export type NostrEventContent =
NostrUserZaps | NostrUserZaps |
NostrSuggestedUsers | NostrSuggestedUsers |
PrimalUserRelays | PrimalUserRelays |
NostrBookmarks; NostrBookmarks |
NostrRelayHint;
export type NostrEvent = [ export type NostrEvent = [
type: "EVENT", type: "EVENT",
@ -293,6 +301,7 @@ export type FeedPage = {
postStats: NostrPostStats, postStats: NostrPostStats,
mentions?: Record<string, NostrNoteContent>, mentions?: Record<string, NostrNoteContent>,
noteActions: Record<string, NoteActions>, noteActions: Record<string, NoteActions>,
relayHints?: Record<string, string>,
since?: number, since?: number,
until?: number, until?: number,
}; };
@ -437,6 +446,7 @@ export type PrimalNoteData = {
satszapped: number, satszapped: number,
noteId: string, noteId: string,
noteActions: NoteActions, noteActions: NoteActions,
relayHints?: Record<string, string>,
} }
export type PrimalNote = { export type PrimalNote = {