This commit is contained in:
Martti Malmi 2023-12-21 21:50:43 +02:00
parent 782a2217b4
commit 9e6971423e
10 changed files with 85 additions and 21 deletions

View File

@ -8,7 +8,6 @@ export async function sendEventToRelays(
customRelays?: Array<string>, customRelays?: Array<string>,
setResults?: (x: Array<OkResponse>) => void, setResults?: (x: Array<OkResponse>) => void,
) { ) {
console.log("sendEventToRelays", ev, customRelays);
getWebRtcPool()?.send(ev); getWebRtcPool()?.send(ev);
if (customRelays) { if (customRelays) {
return removeUndefined( return removeUndefined(

View File

@ -104,7 +104,7 @@ export const GetPowWorker = () => (hasWasm ? new WasmPowWorker() : unwrap(Defaul
/** /**
* Singleton nostr system * Singleton nostr system
*/ */
const System = new NostrSystem({ export const System = new NostrSystem({
relayCache: UserRelays, relayCache: UserRelays,
profileCache: UserCache, profileCache: UserCache,
relayMetrics: RelayMetrics, relayMetrics: RelayMetrics,

View File

@ -201,6 +201,9 @@
"4Z3t5i": { "4Z3t5i": {
"defaultMessage": "Use imgproxy to compress images" "defaultMessage": "Use imgproxy to compress images"
}, },
"4emo2p": {
"defaultMessage": "Missing Relays"
},
"4rYCjn": { "4rYCjn": {
"defaultMessage": "Note to Self" "defaultMessage": "Note to Self"
}, },
@ -234,6 +237,9 @@
"62nsdy": { "62nsdy": {
"defaultMessage": "Retry" "defaultMessage": "Retry"
}, },
"6559gb": {
"defaultMessage": "New follow list length {length}"
},
"65BmHb": { "65BmHb": {
"defaultMessage": "Failed to proxy image from {host}, click here to load directly" "defaultMessage": "Failed to proxy image from {host}, click here to load directly"
}, },
@ -392,6 +398,12 @@
"CHTbO3": { "CHTbO3": {
"defaultMessage": "Failed to load invoice" "defaultMessage": "Failed to load invoice"
}, },
"CM+Cfj": {
"defaultMessage": "Follow List"
},
"CM0k0d": {
"defaultMessage": "Prune follow list"
},
"CVWeJ6": { "CVWeJ6": {
"defaultMessage": "Trending People" "defaultMessage": "Trending People"
}, },
@ -570,6 +582,9 @@
"HqRNN8": { "HqRNN8": {
"defaultMessage": "Support" "defaultMessage": "Support"
}, },
"I1AoOu": {
"defaultMessage": "Last post {time}"
},
"IEwZvs": { "IEwZvs": {
"defaultMessage": "Are you sure you want to unpin this note?" "defaultMessage": "Are you sure you want to unpin this note?"
}, },
@ -978,6 +993,9 @@
"XICsE8": { "XICsE8": {
"defaultMessage": "File hosts" "defaultMessage": "File hosts"
}, },
"XQiFEl": {
"defaultMessage": "Follows Relay Health"
},
"XXm7jJ": { "XXm7jJ": {
"defaultMessage": "Trending Hashtags" "defaultMessage": "Trending Hashtags"
}, },
@ -1048,6 +1066,9 @@
"bG00/W": { "bG00/W": {
"defaultMessage": "Service Worker Running" "defaultMessage": "Service Worker Running"
}, },
"bJ+wrA": {
"defaultMessage": "Compute prune list"
},
"bLZL5a": { "bLZL5a": {
"defaultMessage": "Get Address" "defaultMessage": "Get Address"
}, },
@ -1227,6 +1248,9 @@
"h8XMJL": { "h8XMJL": {
"defaultMessage": "Badges" "defaultMessage": "Badges"
}, },
"hF6IN2": {
"defaultMessage": "Prune Follow List"
},
"hMzcSq": { "hMzcSq": {
"defaultMessage": "Messages" "defaultMessage": "Messages"
}, },
@ -1266,6 +1290,9 @@
"iGT1eE": { "iGT1eE": {
"defaultMessage": "Prevent fake accounts from imitating you" "defaultMessage": "Prevent fake accounts from imitating you"
}, },
"iICVoL": {
"defaultMessage": "{x} follows ({y} duplicates)"
},
"iNWbVV": { "iNWbVV": {
"defaultMessage": "Handle" "defaultMessage": "Handle"
}, },
@ -1399,6 +1426,12 @@
"nGGDsi": { "nGGDsi": {
"defaultMessage": "Notifications Allowed" "defaultMessage": "Notifications Allowed"
}, },
"nIchMQ": {
"defaultMessage": "Searching for account activity ({progress})"
},
"nUT0Lv": {
"defaultMessage": "Tools"
},
"nihgfo": { "nihgfo": {
"defaultMessage": "Listen to this article" "defaultMessage": "Listen to this article"
}, },
@ -1423,6 +1456,9 @@
"p85Uwy": { "p85Uwy": {
"defaultMessage": "Active Subscriptions" "defaultMessage": "Active Subscriptions"
}, },
"p9Ps2l": {
"defaultMessage": "{x}/{y} have relays ({percent})"
},
"pI+77w": { "pI+77w": {
"defaultMessage": "Downloadable backups from Snort relay" "defaultMessage": "Downloadable backups from Snort relay"
}, },
@ -1567,6 +1603,9 @@
"vN5UH8": { "vN5UH8": {
"defaultMessage": "Profile Image" "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": { "vZ4quW": {
"defaultMessage": "NIP-05 is a DNS based verification spec which helps to validate you as a real user." "defaultMessage": "NIP-05 is a DNS based verification spec which helps to validate you as a real user."
}, },

View File

@ -66,6 +66,7 @@
"4OB335": "Dislike", "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", "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", "4Z3t5i": "Use imgproxy to compress images",
"4emo2p": "Missing Relays",
"4rYCjn": "Note to Self", "4rYCjn": "Note to Self",
"5BVs2e": "zap", "5BVs2e": "zap",
"5CB6zB": "Zap Splits", "5CB6zB": "Zap Splits",
@ -77,6 +78,7 @@
"6/SF6e": "<h1>{n}</h1> Cashu sats", "6/SF6e": "<h1>{n}</h1> Cashu sats",
"6/hB3S": "Watch Replay", "6/hB3S": "Watch Replay",
"62nsdy": "Retry", "62nsdy": "Retry",
"6559gb": "New follow list length {length}",
"65BmHb": "Failed to proxy image from {host}, click here to load directly", "65BmHb": "Failed to proxy image from {host}, click here to load directly",
"6OSOXl": "Reason: <i>{reason}</i>", "6OSOXl": "Reason: <i>{reason}</i>",
"6bgpn+": "Not all clients support this, you may still receive some zaps as if zap splits was not configured", "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", "C81/uG": "Logout",
"C8HhVE": "Suggested Follows", "C8HhVE": "Suggested Follows",
"CHTbO3": "Failed to load invoice", "CHTbO3": "Failed to load invoice",
"CM+Cfj": "Follow List",
"CM0k0d": "Prune follow list",
"CVWeJ6": "Trending People", "CVWeJ6": "Trending People",
"CYkOCI": "and {count} others you follow", "CYkOCI": "and {count} others you follow",
"CbM2hK": "Trending hashtags", "CbM2hK": "Trending hashtags",
@ -188,6 +192,7 @@
"HbefNb": "Open Wallet", "HbefNb": "Open Wallet",
"HhcAVH": "You don't follow this person, click here to load media from <i>{link}</i>, or update <a><i>your preferences</i></a> to always load media from everybody.", "HhcAVH": "You don't follow this person, click here to load media from <i>{link}</i>, or update <a><i>your preferences</i></a> to always load media from everybody.",
"HqRNN8": "Support", "HqRNN8": "Support",
"I1AoOu": "Last post {time}",
"IEwZvs": "Are you sure you want to unpin this note?", "IEwZvs": "Are you sure you want to unpin this note?",
"IKKHqV": "Follows", "IKKHqV": "Follows",
"IOu4Xh": "You must be a {tier} subscriber to access {app} deck", "IOu4Xh": "You must be a {tier} subscriber to access {app} deck",
@ -322,6 +327,7 @@
"X7xU8J": "nsec, npub, nip-05, hex, mnemonic", "X7xU8J": "nsec, npub, nip-05, hex, mnemonic",
"XECMfW": "Send usage metrics", "XECMfW": "Send usage metrics",
"XICsE8": "File hosts", "XICsE8": "File hosts",
"XQiFEl": "Follows Relay Health",
"XXm7jJ": "Trending Hashtags", "XXm7jJ": "Trending Hashtags",
"XgWvGA": "Reactions", "XgWvGA": "Reactions",
"XhpBfA": "{site} is an open source project built by passionate people in their free time, your donations are greatly appreciated", "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", "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 <b>{percent}</b> of referred users subscriptions!", "bF1MYT": "You are a community leader and are earning <b>{percent}</b> of referred users subscriptions!",
"bG00/W": "Service Worker Running", "bG00/W": "Service Worker Running",
"bJ+wrA": "Compute prune list",
"bLZL5a": "Get Address", "bLZL5a": "Get Address",
"bMphls": "Logged in with read-only access", "bMphls": "Logged in with read-only access",
"bQdA2k": "Sensitive Content", "bQdA2k": "Sensitive Content",
@ -404,6 +411,7 @@
"grQ+mI": "Proof of Work", "grQ+mI": "Proof of Work",
"h7jvCs": "{site} is more fun together!", "h7jvCs": "{site} is more fun together!",
"h8XMJL": "Badges", "h8XMJL": "Badges",
"hF6IN2": "Prune Follow List",
"hMzcSq": "Messages", "hMzcSq": "Messages",
"hRTfTR": "PRO", "hRTfTR": "PRO",
"hY4lzx": "Supports", "hY4lzx": "Supports",
@ -417,6 +425,7 @@
"iCqGww": "Reactions ({n})", "iCqGww": "Reactions ({n})",
"iEoXYx": "DeepL translations", "iEoXYx": "DeepL translations",
"iGT1eE": "Prevent fake accounts from imitating you", "iGT1eE": "Prevent fake accounts from imitating you",
"iICVoL": "{x} follows ({y} duplicates)",
"iNWbVV": "Handle", "iNWbVV": "Handle",
"iXPL0Z": "Can't login with private key on an insecure connection, please use a Nostr key manager extension instead", "iXPL0Z": "Can't login with private key on an insecure connection, please use a Nostr key manager extension instead",
"iYc3Ld": "Payments", "iYc3Ld": "Payments",
@ -461,6 +470,8 @@
"nDejmx": "Unblock", "nDejmx": "Unblock",
"nGBrvw": "Bookmarks", "nGBrvw": "Bookmarks",
"nGGDsi": "Notifications Allowed", "nGGDsi": "Notifications Allowed",
"nIchMQ": "Searching for account activity ({progress})",
"nUT0Lv": "Tools",
"nihgfo": "Listen to this article", "nihgfo": "Listen to this article",
"nwZXeh": "{n} blocked", "nwZXeh": "{n} blocked",
"o7e+nJ": "{n} followers", "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}", "ojzbwv": "Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out {link}",
"p4N05H": "Upload", "p4N05H": "Upload",
"p85Uwy": "Active Subscriptions", "p85Uwy": "Active Subscriptions",
"p9Ps2l": "{x}/{y} have relays ({percent})",
"pI+77w": "Downloadable backups from Snort relay", "pI+77w": "Downloadable backups from Snort relay",
"pRess9": "ZapPool", "pRess9": "ZapPool",
"puLNUJ": "Pin", "puLNUJ": "Pin",
@ -517,6 +529,7 @@
"v8lolG": "Start chat", "v8lolG": "Start chat",
"vB3oQ/": "Must be a contact list or pubkey list", "vB3oQ/": "Must be a contact list or pubkey list",
"vN5UH8": "Profile Image", "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.", "vZ4quW": "NIP-05 is a DNS based verification spec which helps to validate you as a real user.",
"vhlWFg": "Poll Options", "vhlWFg": "Poll Options",
"vlbWtt": "Get a free one", "vlbWtt": "Get a free one",

View File

@ -17,7 +17,7 @@ export class WebRTCConnection extends EventEmitter {
this.setupDataChannel(); this.setupDataChannel();
} }
private log(...args: any[]): void { private log<T extends unknown[]>(...args: T): void {
console.log(this.peerId, ...args); 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") { if (this.dataChannel.readyState === "open") {
this.log(`<- "${data}"`); this.log(`<- "${data}"`);
this.dataChannel.send(data); this.dataChannel.send(data);

View File

@ -1,6 +1,7 @@
import { io, Socket } from "socket.io-client"; import { io, Socket } from "socket.io-client";
import { WebRTCConnection } from "@/webrtc/WebRTCConnection"; import { WebRTCConnection } from "@/webrtc/WebRTCConnection";
import EventEmitter from "eventemitter3"; import EventEmitter from "eventemitter3";
import { TaggedNostrEvent } from "@snort/system";
const MAX_CONNECTIONS = 5; const MAX_CONNECTIONS = 5;
@ -22,7 +23,7 @@ class WebRTCPool extends EventEmitter {
this.signalingServer.emit("hello", this.peerId); 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 => { this.peers.forEach(conn => {
if (!recipients || recipients.includes(conn.peerId)) { if (!recipients || recipients.includes(conn.peerId)) {
try { try {
@ -39,7 +40,7 @@ class WebRTCPool extends EventEmitter {
throw new Error("Maximum connections reached"); throw new Error("Maximum connections reached");
} }
const connection = new WebRTCConnection(this.signalingServer, this.configuration, peerId); 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); this.peers.set(peerId, connection);
return connection; return connection;
} }

View File

@ -1,5 +1,7 @@
import { LoginStore } from "@/Login"; import { LoginStore } from "@/Login";
import WebRTCPool from "@/webrtc/WebRTCPool"; import WebRTCPool from "@/webrtc/WebRTCPool";
import { System } from "@/index";
import { TaggedNostrEvent } from "@snort/system";
let publicKey: string | undefined; let publicKey: string | undefined;
let pool: WebRTCPool | undefined; let pool: WebRTCPool | undefined;
@ -7,20 +9,23 @@ let interval: NodeJS.Timeout | undefined;
LoginStore.hook(() => { LoginStore.hook(() => {
const login = LoginStore.takeSnapshot(); const login = LoginStore.takeSnapshot();
if (login.publicKey && !login.readonly && login.publicKey !== publicKey) { if (!login.publicKey || login.readonly || login.publicKey === publicKey) return;
publicKey = login.publicKey; publicKey = login.publicKey;
if (location.hostname === "localhost") { if (location.hostname === "localhost") {
pool?.close(); pool?.close();
interval && clearInterval(interval); interval && clearInterval(interval);
pool = new WebRTCPool( pool = new WebRTCPool(
"http://localhost:3000", "http://localhost:3000",
{ {
iceServers: [{ urls: "stun:localhost:3478" }], iceServers: [{ urls: "stun:localhost:3478" }],
}, },
login.publicKey, login.publicKey,
); );
interval = setInterval(() => pool?.send("ping"), 10000); pool.on("event", (event: TaggedNostrEvent) => {
} console.log("event from webrtc", event);
System.HandleEvent(event);
});
interval = setInterval(() => pool?.send("ping"), 10000);
} }
}); });

View File

@ -88,6 +88,8 @@ export interface SystemInterface {
*/ */
DisconnectRelay(address: string): void; DisconnectRelay(address: string): void;
HandleEvent(ev: TaggedNostrEvent): void;
/** /**
* Send an event to all permanent connections * Send an event to all permanent connections
* @param ev Event to broadcast * @param ev Event to broadcast

View File

@ -387,10 +387,15 @@ export class NostrSystem extends EventEmitter<NostrSystemEvents> implements Syst
return []; return [];
} }
HandleEvent(ev: TaggedNostrEvent) {
this.#onEvent("*", ev);
}
/** /**
* Send events to writable relays * Send events to writable relays
*/ */
async BroadcastEvent(ev: NostrEvent, cb?: (rsp: OkResponse) => void) { 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 socks = [...this.#sockets.values()].filter(a => !a.Ephemeral && a.Settings.write);
const replyRelays = await pickRelaysForReply(ev, this); const replyRelays = await pickRelaysForReply(ev, this);
const oks = await Promise.all([ const oks = await Promise.all([

View File

@ -195,7 +195,7 @@ export class Query extends EventEmitter<QueryEvents> implements QueryBase {
handleEvent(sub: string, e: TaggedNostrEvent) { handleEvent(sub: string, e: TaggedNostrEvent) {
for (const t of this.#tracing) { for (const t of this.#tracing) {
if (t.id === sub) { if (t.id === sub || sub === "*") {
if (t.filters.some(v => eventMatchesFilter(e, v))) { if (t.filters.some(v => eventMatchesFilter(e, v))) {
this.feed.add(e); this.feed.add(e);
} else { } else {