From 9e6971423e4beb4861de43984b8b7b1b4b37da8e Mon Sep 17 00:00:00 2001 From: Martti Malmi Date: Thu, 21 Dec 2023 21:50:43 +0200 Subject: [PATCH] webrtc --- packages/app/src/Element/Event/Create/util.ts | 1 - packages/app/src/index.tsx | 2 +- packages/app/src/lang.json | 39 +++++++++++++++++++ packages/app/src/translations/en.json | 13 +++++++ packages/app/src/webrtc/WebRTCConnection.ts | 4 +- packages/app/src/webrtc/WebRTCPool.ts | 5 ++- packages/app/src/webrtc/index.ts | 33 +++++++++------- packages/system/src/index.ts | 2 + packages/system/src/nostr-system.ts | 5 +++ packages/system/src/query.ts | 2 +- 10 files changed, 85 insertions(+), 21 deletions(-) diff --git a/packages/app/src/Element/Event/Create/util.ts b/packages/app/src/Element/Event/Create/util.ts index c104acbf3..eb8f5fa81 100644 --- a/packages/app/src/Element/Event/Create/util.ts +++ b/packages/app/src/Element/Event/Create/util.ts @@ -8,7 +8,6 @@ export async function sendEventToRelays( customRelays?: Array, setResults?: (x: Array) => void, ) { - console.log("sendEventToRelays", ev, customRelays); getWebRtcPool()?.send(ev); if (customRelays) { return removeUndefined( diff --git a/packages/app/src/index.tsx b/packages/app/src/index.tsx index 347a8a4ac..ad144cd46 100644 --- a/packages/app/src/index.tsx +++ b/packages/app/src/index.tsx @@ -104,7 +104,7 @@ export const GetPowWorker = () => (hasWasm ? new WasmPowWorker() : unwrap(Defaul /** * Singleton nostr system */ -const System = new NostrSystem({ +export const System = new NostrSystem({ relayCache: UserRelays, profileCache: UserCache, relayMetrics: RelayMetrics, diff --git a/packages/app/src/lang.json b/packages/app/src/lang.json index 836640cc9..ccd15f99a 100644 --- a/packages/app/src/lang.json +++ b/packages/app/src/lang.json @@ -201,6 +201,9 @@ "4Z3t5i": { "defaultMessage": "Use imgproxy to compress images" }, + "4emo2p": { + "defaultMessage": "Missing Relays" + }, "4rYCjn": { "defaultMessage": "Note to Self" }, @@ -234,6 +237,9 @@ "62nsdy": { "defaultMessage": "Retry" }, + "6559gb": { + "defaultMessage": "New follow list length {length}" + }, "65BmHb": { "defaultMessage": "Failed to proxy image from {host}, click here to load directly" }, @@ -392,6 +398,12 @@ "CHTbO3": { "defaultMessage": "Failed to load invoice" }, + "CM+Cfj": { + "defaultMessage": "Follow List" + }, + "CM0k0d": { + "defaultMessage": "Prune follow list" + }, "CVWeJ6": { "defaultMessage": "Trending People" }, @@ -570,6 +582,9 @@ "HqRNN8": { "defaultMessage": "Support" }, + "I1AoOu": { + "defaultMessage": "Last post {time}" + }, "IEwZvs": { "defaultMessage": "Are you sure you want to unpin this note?" }, @@ -978,6 +993,9 @@ "XICsE8": { "defaultMessage": "File hosts" }, + "XQiFEl": { + "defaultMessage": "Follows Relay Health" + }, "XXm7jJ": { "defaultMessage": "Trending Hashtags" }, @@ -1048,6 +1066,9 @@ "bG00/W": { "defaultMessage": "Service Worker Running" }, + "bJ+wrA": { + "defaultMessage": "Compute prune list" + }, "bLZL5a": { "defaultMessage": "Get Address" }, @@ -1227,6 +1248,9 @@ "h8XMJL": { "defaultMessage": "Badges" }, + "hF6IN2": { + "defaultMessage": "Prune Follow List" + }, "hMzcSq": { "defaultMessage": "Messages" }, @@ -1266,6 +1290,9 @@ "iGT1eE": { "defaultMessage": "Prevent fake accounts from imitating you" }, + "iICVoL": { + "defaultMessage": "{x} follows ({y} duplicates)" + }, "iNWbVV": { "defaultMessage": "Handle" }, @@ -1399,6 +1426,12 @@ "nGGDsi": { "defaultMessage": "Notifications Allowed" }, + "nIchMQ": { + "defaultMessage": "Searching for account activity ({progress})" + }, + "nUT0Lv": { + "defaultMessage": "Tools" + }, "nihgfo": { "defaultMessage": "Listen to this article" }, @@ -1423,6 +1456,9 @@ "p85Uwy": { "defaultMessage": "Active Subscriptions" }, + "p9Ps2l": { + "defaultMessage": "{x}/{y} have relays ({percent})" + }, "pI+77w": { "defaultMessage": "Downloadable backups from Snort relay" }, @@ -1567,6 +1603,9 @@ "vN5UH8": { "defaultMessage": "Profile Image" }, + "vU/Q5i": { + "defaultMessage": "This tool will search for the last event published by all of your follows and remove those who have not posted in 6 months" + }, "vZ4quW": { "defaultMessage": "NIP-05 is a DNS based verification spec which helps to validate you as a real user." }, diff --git a/packages/app/src/translations/en.json b/packages/app/src/translations/en.json index 1ee05b3ba..1ee603a9e 100644 --- a/packages/app/src/translations/en.json +++ b/packages/app/src/translations/en.json @@ -66,6 +66,7 @@ "4OB335": "Dislike", "4Vmpt4": "Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices", "4Z3t5i": "Use imgproxy to compress images", + "4emo2p": "Missing Relays", "4rYCjn": "Note to Self", "5BVs2e": "zap", "5CB6zB": "Zap Splits", @@ -77,6 +78,7 @@ "6/SF6e": "

{n}

Cashu sats", "6/hB3S": "Watch Replay", "62nsdy": "Retry", + "6559gb": "New follow list length {length}", "65BmHb": "Failed to proxy image from {host}, click here to load directly", "6OSOXl": "Reason: {reason}", "6bgpn+": "Not all clients support this, you may still receive some zaps as if zap splits was not configured", @@ -129,6 +131,8 @@ "C81/uG": "Logout", "C8HhVE": "Suggested Follows", "CHTbO3": "Failed to load invoice", + "CM+Cfj": "Follow List", + "CM0k0d": "Prune follow list", "CVWeJ6": "Trending People", "CYkOCI": "and {count} others you follow", "CbM2hK": "Trending hashtags", @@ -188,6 +192,7 @@ "HbefNb": "Open Wallet", "HhcAVH": "You don't follow this person, click here to load media from {link}, or update your preferences to always load media from everybody.", "HqRNN8": "Support", + "I1AoOu": "Last post {time}", "IEwZvs": "Are you sure you want to unpin this note?", "IKKHqV": "Follows", "IOu4Xh": "You must be a {tier} subscriber to access {app} deck", @@ -322,6 +327,7 @@ "X7xU8J": "nsec, npub, nip-05, hex, mnemonic", "XECMfW": "Send usage metrics", "XICsE8": "File hosts", + "XQiFEl": "Follows Relay Health", "XXm7jJ": "Trending Hashtags", "XgWvGA": "Reactions", "XhpBfA": "{site} is an open source project built by passionate people in their free time, your donations are greatly appreciated", @@ -345,6 +351,7 @@ "b5vAk0": "Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address", "bF1MYT": "You are a community leader and are earning {percent} of referred users subscriptions!", "bG00/W": "Service Worker Running", + "bJ+wrA": "Compute prune list", "bLZL5a": "Get Address", "bMphls": "Logged in with read-only access", "bQdA2k": "Sensitive Content", @@ -404,6 +411,7 @@ "grQ+mI": "Proof of Work", "h7jvCs": "{site} is more fun together!", "h8XMJL": "Badges", + "hF6IN2": "Prune Follow List", "hMzcSq": "Messages", "hRTfTR": "PRO", "hY4lzx": "Supports", @@ -417,6 +425,7 @@ "iCqGww": "Reactions ({n})", "iEoXYx": "DeepL translations", "iGT1eE": "Prevent fake accounts from imitating you", + "iICVoL": "{x} follows ({y} duplicates)", "iNWbVV": "Handle", "iXPL0Z": "Can't login with private key on an insecure connection, please use a Nostr key manager extension instead", "iYc3Ld": "Payments", @@ -461,6 +470,8 @@ "nDejmx": "Unblock", "nGBrvw": "Bookmarks", "nGGDsi": "Notifications Allowed", + "nIchMQ": "Searching for account activity ({progress})", + "nUT0Lv": "Tools", "nihgfo": "Listen to this article", "nwZXeh": "{n} blocked", "o7e+nJ": "{n} followers", @@ -469,6 +480,7 @@ "ojzbwv": "Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out {link}", "p4N05H": "Upload", "p85Uwy": "Active Subscriptions", + "p9Ps2l": "{x}/{y} have relays ({percent})", "pI+77w": "Downloadable backups from Snort relay", "pRess9": "ZapPool", "puLNUJ": "Pin", @@ -517,6 +529,7 @@ "v8lolG": "Start chat", "vB3oQ/": "Must be a contact list or pubkey list", "vN5UH8": "Profile Image", + "vU/Q5i": "This tool will search for the last event published by all of your follows and remove those who have not posted in 6 months", "vZ4quW": "NIP-05 is a DNS based verification spec which helps to validate you as a real user.", "vhlWFg": "Poll Options", "vlbWtt": "Get a free one", diff --git a/packages/app/src/webrtc/WebRTCConnection.ts b/packages/app/src/webrtc/WebRTCConnection.ts index db6aaa318..0178599f7 100644 --- a/packages/app/src/webrtc/WebRTCConnection.ts +++ b/packages/app/src/webrtc/WebRTCConnection.ts @@ -17,7 +17,7 @@ export class WebRTCConnection extends EventEmitter { this.setupDataChannel(); } - private log(...args: any[]): void { + private log(...args: T): void { console.log(this.peerId, ...args); } @@ -69,7 +69,7 @@ export class WebRTCConnection extends EventEmitter { } } - public send(data: any): void { + public send(data: string): void { if (this.dataChannel.readyState === "open") { this.log(`<- "${data}"`); this.dataChannel.send(data); diff --git a/packages/app/src/webrtc/WebRTCPool.ts b/packages/app/src/webrtc/WebRTCPool.ts index f51563bd6..f5ed5f65a 100644 --- a/packages/app/src/webrtc/WebRTCPool.ts +++ b/packages/app/src/webrtc/WebRTCPool.ts @@ -1,6 +1,7 @@ import { io, Socket } from "socket.io-client"; import { WebRTCConnection } from "@/webrtc/WebRTCConnection"; import EventEmitter from "eventemitter3"; +import { TaggedNostrEvent } from "@snort/system"; const MAX_CONNECTIONS = 5; @@ -22,7 +23,7 @@ class WebRTCPool extends EventEmitter { this.signalingServer.emit("hello", this.peerId); } - public send(data: any, recipients?: string[]): void { + public send(data: TaggedNostrEvent | string, recipients?: string[]): void { this.peers.forEach(conn => { if (!recipients || recipients.includes(conn.peerId)) { try { @@ -39,7 +40,7 @@ class WebRTCPool extends EventEmitter { throw new Error("Maximum connections reached"); } const connection = new WebRTCConnection(this.signalingServer, this.configuration, peerId); - connection.on("event", (event: any) => this.emit("event", event)); + connection.on("event", (event: TaggedNostrEvent | string) => this.emit("event", event)); this.peers.set(peerId, connection); return connection; } diff --git a/packages/app/src/webrtc/index.ts b/packages/app/src/webrtc/index.ts index bfa5ce2b1..89f5f6068 100644 --- a/packages/app/src/webrtc/index.ts +++ b/packages/app/src/webrtc/index.ts @@ -1,5 +1,7 @@ import { LoginStore } from "@/Login"; import WebRTCPool from "@/webrtc/WebRTCPool"; +import { System } from "@/index"; +import { TaggedNostrEvent } from "@snort/system"; let publicKey: string | undefined; let pool: WebRTCPool | undefined; @@ -7,20 +9,23 @@ let interval: NodeJS.Timeout | undefined; LoginStore.hook(() => { const login = LoginStore.takeSnapshot(); - if (login.publicKey && !login.readonly && login.publicKey !== publicKey) { - publicKey = login.publicKey; - if (location.hostname === "localhost") { - pool?.close(); - interval && clearInterval(interval); - pool = new WebRTCPool( - "http://localhost:3000", - { - iceServers: [{ urls: "stun:localhost:3478" }], - }, - login.publicKey, - ); - interval = setInterval(() => pool?.send("ping"), 10000); - } + if (!login.publicKey || login.readonly || login.publicKey === publicKey) return; + publicKey = login.publicKey; + if (location.hostname === "localhost") { + pool?.close(); + interval && clearInterval(interval); + pool = new WebRTCPool( + "http://localhost:3000", + { + iceServers: [{ urls: "stun:localhost:3478" }], + }, + login.publicKey, + ); + pool.on("event", (event: TaggedNostrEvent) => { + console.log("event from webrtc", event); + System.HandleEvent(event); + }); + interval = setInterval(() => pool?.send("ping"), 10000); } }); diff --git a/packages/system/src/index.ts b/packages/system/src/index.ts index db5655d9f..a417e4795 100644 --- a/packages/system/src/index.ts +++ b/packages/system/src/index.ts @@ -88,6 +88,8 @@ export interface SystemInterface { */ DisconnectRelay(address: string): void; + HandleEvent(ev: TaggedNostrEvent): void; + /** * Send an event to all permanent connections * @param ev Event to broadcast diff --git a/packages/system/src/nostr-system.ts b/packages/system/src/nostr-system.ts index 6d9c8326e..9d2227b94 100644 --- a/packages/system/src/nostr-system.ts +++ b/packages/system/src/nostr-system.ts @@ -387,10 +387,15 @@ export class NostrSystem extends EventEmitter implements Syst return []; } + HandleEvent(ev: TaggedNostrEvent) { + this.#onEvent("*", ev); + } + /** * Send events to writable relays */ async BroadcastEvent(ev: NostrEvent, cb?: (rsp: OkResponse) => void) { + this.HandleEvent({ ...ev, relays: [] }); const socks = [...this.#sockets.values()].filter(a => !a.Ephemeral && a.Settings.write); const replyRelays = await pickRelaysForReply(ev, this); const oks = await Promise.all([ diff --git a/packages/system/src/query.ts b/packages/system/src/query.ts index 656988f29..68e54e08c 100644 --- a/packages/system/src/query.ts +++ b/packages/system/src/query.ts @@ -195,7 +195,7 @@ export class Query extends EventEmitter implements QueryBase { handleEvent(sub: string, e: TaggedNostrEvent) { for (const t of this.#tracing) { - if (t.id === sub) { + if (t.id === sub || sub === "*") { if (t.filters.some(v => eventMatchesFilter(e, v))) { this.feed.add(e); } else {