feat: extended screening (#144)
* improve mutual contacts check * . * .
This commit is contained in:
97
Cargo.lock
generated
97
Cargo.lock
generated
@@ -994,7 +994,7 @@ dependencies = [
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1123,7 +1123,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collections"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"rustc-hash 2.1.1",
|
||||
@@ -1564,7 +1564,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "derive_refineable"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2490,7 +2490,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"as-raw-xcb-connection",
|
||||
@@ -2584,7 +2584,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
@@ -2596,7 +2596,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_tokio"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gpui",
|
||||
@@ -2819,7 +2819,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "http_client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -2839,7 +2839,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "http_client_tls"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"rustls",
|
||||
"rustls-platform-verifier",
|
||||
@@ -3397,9 +3397,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lebe"
|
||||
version = "0.5.2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
||||
checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
@@ -3636,7 +3636,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "media"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bindgen 0.71.1",
|
||||
@@ -3884,7 +3884,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr"
|
||||
version = "0.43.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#1c66cfdc883e79ecc36e12c50bfce9e286f8c951"
|
||||
source = "git+https://github.com/rust-nostr/nostr#53751050e317e1b6ab91b80b1dff4c867a519b38"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"base64",
|
||||
@@ -3908,7 +3908,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr-connect"
|
||||
version = "0.43.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#1c66cfdc883e79ecc36e12c50bfce9e286f8c951"
|
||||
source = "git+https://github.com/rust-nostr/nostr#53751050e317e1b6ab91b80b1dff4c867a519b38"
|
||||
dependencies = [
|
||||
"async-utility",
|
||||
"nostr",
|
||||
@@ -3920,7 +3920,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr-database"
|
||||
version = "0.43.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#1c66cfdc883e79ecc36e12c50bfce9e286f8c951"
|
||||
source = "git+https://github.com/rust-nostr/nostr#53751050e317e1b6ab91b80b1dff4c867a519b38"
|
||||
dependencies = [
|
||||
"flatbuffers",
|
||||
"lru",
|
||||
@@ -3931,7 +3931,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr-lmdb"
|
||||
version = "0.43.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#1c66cfdc883e79ecc36e12c50bfce9e286f8c951"
|
||||
source = "git+https://github.com/rust-nostr/nostr#53751050e317e1b6ab91b80b1dff4c867a519b38"
|
||||
dependencies = [
|
||||
"async-utility",
|
||||
"flume",
|
||||
@@ -3945,7 +3945,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr-relay-pool"
|
||||
version = "0.43.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#1c66cfdc883e79ecc36e12c50bfce9e286f8c951"
|
||||
source = "git+https://github.com/rust-nostr/nostr#53751050e317e1b6ab91b80b1dff4c867a519b38"
|
||||
dependencies = [
|
||||
"async-utility",
|
||||
"async-wsocket",
|
||||
@@ -3962,7 +3962,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr-sdk"
|
||||
version = "0.43.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#1c66cfdc883e79ecc36e12c50bfce9e286f8c951"
|
||||
source = "git+https://github.com/rust-nostr/nostr#53751050e317e1b6ab91b80b1dff4c867a519b38"
|
||||
dependencies = [
|
||||
"async-utility",
|
||||
"nostr",
|
||||
@@ -4751,9 +4751,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pxfm"
|
||||
version = "0.1.22"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "376f733579ac4d3b9fbf0afca99bf8f6b698d541118affca554d0b86f73c2470"
|
||||
checksum = "f55f4fedc84ed39cb7a489322318976425e42a147e2be79d8f878e2884f94e84"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
@@ -5076,7 +5076,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "refineable"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"derive_refineable",
|
||||
"workspace-hack",
|
||||
@@ -5230,7 +5230,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "reqwest_client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -5765,7 +5765,7 @@ checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
|
||||
[[package]]
|
||||
name = "semantic_version"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
@@ -6206,7 +6206,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
[[package]]
|
||||
name = "sum_tree"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"log",
|
||||
@@ -7236,7 +7236,7 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
[[package]]
|
||||
name = "util"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#84f166fc85e1675fb76183ad6f212891d596c38d"
|
||||
source = "git+https://github.com/zed-industries/zed#0ef7ee172fd8dd4d0638a9731140cb3a74344918"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-fs",
|
||||
@@ -7707,11 +7707,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7739,7 +7739,7 @@ dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core 0.61.2",
|
||||
"windows-future",
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
@@ -7785,7 +7785,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.0",
|
||||
"windows-interface 0.59.1",
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
"windows-strings 0.4.2",
|
||||
]
|
||||
@@ -7797,7 +7797,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
@@ -7851,6 +7851,12 @@ version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.2.0"
|
||||
@@ -7858,7 +7864,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7878,7 +7884,7 @@ version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
"windows-strings 0.4.2",
|
||||
]
|
||||
@@ -7898,7 +7904,7 @@ version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7907,7 +7913,7 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7916,7 +7922,7 @@ version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7964,6 +7970,15 @@ dependencies = [
|
||||
"windows-targets 0.53.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa"
|
||||
dependencies = [
|
||||
"windows-link 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
@@ -8016,7 +8031,7 @@ version = "0.53.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
"windows_aarch64_gnullvm 0.53.0",
|
||||
"windows_aarch64_msvc 0.53.0",
|
||||
"windows_i686_gnu 0.53.0",
|
||||
@@ -8033,7 +8048,7 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8492,18 +8507,18 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.26"
|
||||
version = "0.8.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
|
||||
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.26"
|
||||
version = "0.8.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
|
||||
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@@ -221,12 +221,12 @@ impl ChatSpace {
|
||||
let nip65 = Filter::new().kind(Kind::RelayList).author(public_key);
|
||||
|
||||
if client.database().count(nip65).await.unwrap_or(0) > 0 {
|
||||
let nip17 = Filter::new().kind(Kind::InboxRelays).author(public_key);
|
||||
let dm_relays = Filter::new().kind(Kind::InboxRelays).author(public_key);
|
||||
|
||||
match client.database().query(nip17).await {
|
||||
match client.database().query(dm_relays).await {
|
||||
Ok(events) => {
|
||||
if let Some(event) = events.first_owned() {
|
||||
let relay_urls = Self::extract_relay_list(&event);
|
||||
let relay_urls = nip17::extract_relay_list(&event).collect_vec();
|
||||
|
||||
if relay_urls.is_empty() {
|
||||
if !is_sent_signal {
|
||||
@@ -374,9 +374,6 @@ impl ChatSpace {
|
||||
let ingester = ingester();
|
||||
let css = css();
|
||||
|
||||
let auto_close =
|
||||
SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE);
|
||||
|
||||
let mut processed_events: HashSet<EventId> = HashSet::new();
|
||||
let mut challenges: HashSet<Cow<'_, str>> = HashSet::new();
|
||||
let mut notifications = client.notifications();
|
||||
@@ -395,7 +392,6 @@ impl ChatSpace {
|
||||
|
||||
match event.kind {
|
||||
Kind::RelayList => {
|
||||
// Get metadata for event's pubkey that matches the current user's pubkey
|
||||
if let Ok(true) = Self::is_self_event(&event).await {
|
||||
// Fetch user's metadata event
|
||||
Self::fetch_single_event(Kind::Metadata, event.pubkey).await;
|
||||
@@ -409,10 +405,10 @@ impl ChatSpace {
|
||||
}
|
||||
Kind::InboxRelays => {
|
||||
if let Ok(true) = Self::is_self_event(&event).await {
|
||||
let relays: Vec<RelayUrl> = Self::extract_relay_list(&event);
|
||||
let relays = nip17::extract_relay_list(&event).collect_vec();
|
||||
|
||||
if !relays.is_empty() {
|
||||
for relay in relays.iter() {
|
||||
for relay in relays.clone().into_iter() {
|
||||
if client.add_relay(relay).await.is_err() {
|
||||
let notice = Notice::RelayFailed(relay.clone());
|
||||
ingester.send(Signal::Notice(notice)).await;
|
||||
@@ -424,7 +420,7 @@ impl ChatSpace {
|
||||
}
|
||||
|
||||
// Subscribe to gift wrap events only in the current user's NIP-17 relays
|
||||
Self::fetch_gift_wrap(&relays, event.pubkey).await;
|
||||
Self::fetch_gift_wrap(relays, event.pubkey).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -437,7 +433,7 @@ impl ChatSpace {
|
||||
Filter::new().limit(limit).authors(public_keys).kinds(kinds);
|
||||
|
||||
client
|
||||
.subscribe_to(BOOTSTRAP_RELAYS, filter, Some(auto_close))
|
||||
.subscribe_to(BOOTSTRAP_RELAYS, filter, css.auto_close_opts)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
@@ -587,20 +583,6 @@ impl ChatSpace {
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_relay_list(event: &Event) -> Vec<RelayUrl> {
|
||||
event
|
||||
.tags
|
||||
.filter_standardized(TagKind::Relay)
|
||||
.filter_map(|t| {
|
||||
if let TagStandard::Relay(url) = t {
|
||||
Some(url.to_owned())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Checks if an event is belong to the current user
|
||||
async fn is_self_event(event: &Event) -> Result<bool, Error> {
|
||||
let client = nostr_client();
|
||||
@@ -613,22 +595,21 @@ impl ChatSpace {
|
||||
/// Fetches a single event by kind and public key
|
||||
pub async fn fetch_single_event(kind: Kind, public_key: PublicKey) {
|
||||
let client = nostr_client();
|
||||
let auto_close =
|
||||
SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE);
|
||||
let css = css();
|
||||
let filter = Filter::new().kind(kind).author(public_key).limit(1);
|
||||
|
||||
if let Err(e) = client.subscribe(filter, Some(auto_close)).await {
|
||||
if let Err(e) = client.subscribe(filter, css.auto_close_opts).await {
|
||||
log::info!("Failed to subscribe: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn fetch_gift_wrap(relays: &[RelayUrl], public_key: PublicKey) {
|
||||
pub async fn fetch_gift_wrap(relays: Vec<&RelayUrl>, public_key: PublicKey) {
|
||||
let client = nostr_client();
|
||||
let sub_id = css().gift_wrap_sub_id.clone();
|
||||
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
|
||||
|
||||
if client
|
||||
.subscribe_with_id_to(relays.to_owned(), sub_id, filter, None)
|
||||
.subscribe_with_id_to(relays.clone(), sub_id, filter, None)
|
||||
.await
|
||||
.is_ok()
|
||||
{
|
||||
@@ -639,8 +620,7 @@ impl ChatSpace {
|
||||
/// Fetches NIP-65 relay list for a given public key
|
||||
pub async fn fetch_nip65_relays(public_key: PublicKey) -> Result<(), Error> {
|
||||
let client = nostr_client();
|
||||
let auto_close =
|
||||
SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE);
|
||||
let css = css();
|
||||
|
||||
let filter = Filter::new()
|
||||
.kind(Kind::RelayList)
|
||||
@@ -648,7 +628,7 @@ impl ChatSpace {
|
||||
.limit(1);
|
||||
|
||||
client
|
||||
.subscribe_to(BOOTSTRAP_RELAYS, filter, Some(auto_close))
|
||||
.subscribe_to(BOOTSTRAP_RELAYS, filter, css.auto_close_opts)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
@@ -656,18 +636,15 @@ impl ChatSpace {
|
||||
|
||||
/// Fetches metadata for a list of public keys
|
||||
async fn fetch_metadata_for_pubkeys(public_keys: HashSet<PublicKey>) {
|
||||
if public_keys.is_empty() {
|
||||
return;
|
||||
};
|
||||
|
||||
let client = nostr_client();
|
||||
let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE);
|
||||
let kinds = vec![Kind::Metadata, Kind::ContactList];
|
||||
let limit = public_keys.len() * kinds.len();
|
||||
let css = css();
|
||||
|
||||
let kinds = vec![Kind::Metadata, Kind::ContactList, Kind::RelayList];
|
||||
let limit = public_keys.len() * kinds.len() + 20; // + 20 to ensure Coop has enough metadata
|
||||
let filter = Filter::new().limit(limit).authors(public_keys).kinds(kinds);
|
||||
|
||||
client
|
||||
.subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts))
|
||||
.subscribe_to(BOOTSTRAP_RELAYS, filter, css.auto_close_opts)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use common::display::{shorten_pubkey, ReadableProfile};
|
||||
use common::nip05::nip05_verify;
|
||||
use global::constants::BOOTSTRAP_RELAYS;
|
||||
use global::nostr_client;
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
div, relative, rems, App, AppContext, Context, Div, Entity, IntoElement, ParentElement, Render,
|
||||
SharedString, Styled, Task, Window,
|
||||
div, px, relative, rems, uniform_list, App, AppContext, Context, Div, Entity,
|
||||
InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Task, Window,
|
||||
};
|
||||
use gpui_tokio::Tokio;
|
||||
use i18n::{shared_t, t};
|
||||
@@ -14,6 +18,7 @@ use smallvec::{smallvec, SmallVec};
|
||||
use theme::ActiveTheme;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::button::{Button, ButtonRounded, ButtonVariants};
|
||||
use ui::indicator::Indicator;
|
||||
use ui::{h_flex, v_flex, ContextModal, Icon, IconName, Sizable, StyledExt};
|
||||
|
||||
pub fn init(public_key: PublicKey, window: &mut Window, cx: &mut App) -> Entity<Screening> {
|
||||
@@ -24,9 +29,10 @@ pub struct Screening {
|
||||
profile: Profile,
|
||||
verified: bool,
|
||||
followed: bool,
|
||||
dm_relays: bool,
|
||||
mutual_contacts: usize,
|
||||
_tasks: SmallVec<[Task<()>; 1]>,
|
||||
dm_relays: Option<bool>,
|
||||
active: Option<bool>,
|
||||
mutual_contacts: Vec<Profile>,
|
||||
_tasks: SmallVec<[Task<()>; 4]>,
|
||||
}
|
||||
|
||||
impl Screening {
|
||||
@@ -37,33 +43,69 @@ impl Screening {
|
||||
|
||||
let mut tasks = smallvec![];
|
||||
|
||||
let check_trust_score: Task<(bool, usize, bool)> = cx.background_spawn(async move {
|
||||
let contact_check: Task<(bool, Vec<Profile>)> = cx.background_spawn(async move {
|
||||
let client = nostr_client();
|
||||
|
||||
let follow = Filter::new()
|
||||
.kind(Kind::ContactList)
|
||||
.author(identity)
|
||||
.pubkey(public_key)
|
||||
// Check if user is in contact list
|
||||
let contacts = client.database().contacts_public_keys(identity).await;
|
||||
let followed = contacts.unwrap_or_default().contains(&public_key);
|
||||
|
||||
// Check mutual contacts
|
||||
let contact_list = Filter::new().kind(Kind::ContactList).pubkey(public_key);
|
||||
let mut mutual_contacts = vec![];
|
||||
|
||||
if let Ok(events) = client.database().query(contact_list).await {
|
||||
for event in events.into_iter().filter(|ev| ev.pubkey != identity) {
|
||||
if let Ok(metadata) = client.database().metadata(event.pubkey).await {
|
||||
let profile = Profile::new(event.pubkey, metadata.unwrap_or_default());
|
||||
mutual_contacts.push(profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(followed, mutual_contacts)
|
||||
});
|
||||
|
||||
let activity_check = cx.background_spawn(async move {
|
||||
let client = nostr_client();
|
||||
let mut activity = false;
|
||||
|
||||
let filter = Filter::new()
|
||||
.author(public_key)
|
||||
.since(Timestamp::now() - Duration::from_secs(172800))
|
||||
.limit(1);
|
||||
|
||||
let contacts = Filter::new()
|
||||
.kind(Kind::ContactList)
|
||||
.pubkey(public_key)
|
||||
.limit(1);
|
||||
if let Ok(mut stream) = client
|
||||
.stream_events_from(BOOTSTRAP_RELAYS, filter, Duration::from_secs(2))
|
||||
.await
|
||||
{
|
||||
while stream.next().await.is_some() {
|
||||
activity = true
|
||||
}
|
||||
}
|
||||
|
||||
let relays = Filter::new()
|
||||
activity
|
||||
});
|
||||
|
||||
let relay_check = cx.background_spawn(async move {
|
||||
let client = nostr_client();
|
||||
let mut relay = false;
|
||||
|
||||
let filter = Filter::new()
|
||||
.kind(Kind::InboxRelays)
|
||||
.author(public_key)
|
||||
.limit(1);
|
||||
|
||||
let is_follow = client.database().count(follow).await.unwrap_or(0) >= 1;
|
||||
let mutual_contacts = client.database().count(contacts).await.unwrap_or(0);
|
||||
let dm_relays = client.database().count(relays).await.unwrap_or(0) >= 1;
|
||||
if let Ok(mut stream) = client.stream_events(filter, Duration::from_secs(2)).await {
|
||||
while stream.next().await.is_some() {
|
||||
relay = true
|
||||
}
|
||||
}
|
||||
|
||||
(is_follow, mutual_contacts, dm_relays)
|
||||
relay
|
||||
});
|
||||
|
||||
let verify_nip05 = if let Some(address) = profile.metadata().nip05 {
|
||||
let addr_check = if let Some(address) = profile.metadata().nip05 {
|
||||
Some(Tokio::spawn(cx, async move {
|
||||
nip05_verify(public_key, &address).await.unwrap_or(false)
|
||||
}))
|
||||
@@ -72,20 +114,49 @@ impl Screening {
|
||||
};
|
||||
|
||||
tasks.push(
|
||||
// Load all necessary data
|
||||
// Run the contact check in the background
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let (followed, mutual_contacts, dm_relays) = check_trust_score.await;
|
||||
let (followed, mutual_contacts) = contact_check.await;
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
this.followed = followed;
|
||||
this.mutual_contacts = mutual_contacts;
|
||||
this.dm_relays = dm_relays;
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
}),
|
||||
);
|
||||
|
||||
// Update the NIP05 verification status if user has NIP05 address
|
||||
if let Some(task) = verify_nip05 {
|
||||
tasks.push(
|
||||
// Run the activity check in the background
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let active = activity_check.await;
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
this.active = Some(active);
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
}),
|
||||
);
|
||||
|
||||
tasks.push(
|
||||
// Run the relay check in the background
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let relay = relay_check.await;
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
this.dm_relays = Some(relay);
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
}),
|
||||
);
|
||||
|
||||
tasks.push(
|
||||
// Run the NIP-05 verification in the background
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if let Some(task) = addr_check {
|
||||
if let Ok(verified) = task.await {
|
||||
this.update(cx, |this, cx| {
|
||||
this.verified = verified;
|
||||
@@ -101,8 +172,9 @@ impl Screening {
|
||||
profile,
|
||||
verified: false,
|
||||
followed: false,
|
||||
dm_relays: false,
|
||||
mutual_contacts: 0,
|
||||
dm_relays: None,
|
||||
active: None,
|
||||
mutual_contacts: vec![],
|
||||
_tasks: tasks,
|
||||
}
|
||||
}
|
||||
@@ -141,12 +213,54 @@ impl Screening {
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn mutual_contacts(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let contacts = self.mutual_contacts.clone();
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
let contacts = contacts.clone();
|
||||
let total = contacts.len();
|
||||
|
||||
this.title(shared_t!("screening.mutual_label")).child(
|
||||
v_flex().gap_1().pb_4().child(
|
||||
uniform_list("contacts", total, move |range, _window, cx| {
|
||||
let mut items = Vec::with_capacity(total);
|
||||
|
||||
for ix in range {
|
||||
if let Some(contact) = contacts.get(ix) {
|
||||
items.push(
|
||||
h_flex()
|
||||
.h_11()
|
||||
.w_full()
|
||||
.px_2()
|
||||
.gap_1p5()
|
||||
.rounded(cx.theme().radius)
|
||||
.text_sm()
|
||||
.hover(|this| {
|
||||
this.bg(cx.theme().elevated_surface_background)
|
||||
})
|
||||
.child(
|
||||
Avatar::new(contact.avatar_url(true)).size(rems(1.75)),
|
||||
)
|
||||
.child(contact.display_name()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
items
|
||||
})
|
||||
.h(px(300.)),
|
||||
),
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Screening {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let proxy = AppSettings::get_proxy_user_avatars(cx);
|
||||
let shorten_pubkey = shorten_pubkey(self.profile.public_key(), 8);
|
||||
let total_mutuals = self.mutual_contacts.len();
|
||||
|
||||
v_flex()
|
||||
.gap_4()
|
||||
@@ -168,12 +282,10 @@ impl Render for Screening {
|
||||
h_flex()
|
||||
.gap_3()
|
||||
.child(
|
||||
div()
|
||||
h_flex()
|
||||
.p_1()
|
||||
.flex_1()
|
||||
.h_7()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.rounded_full()
|
||||
.bg(cx.theme().surface_background)
|
||||
@@ -217,25 +329,54 @@ impl Render for Screening {
|
||||
.items_start()
|
||||
.gap_2()
|
||||
.text_sm()
|
||||
.child(status_badge(self.followed, cx))
|
||||
.child(status_badge(Some(self.followed), cx))
|
||||
.child(
|
||||
v_flex()
|
||||
.text_sm()
|
||||
.child(shared_t!("screening.contact_label"))
|
||||
.child(div().text_color(cx.theme().text_muted).child({
|
||||
if self.followed {
|
||||
shared_t!("screening.contact")
|
||||
} else {
|
||||
shared_t!("screening.not_contact")
|
||||
}
|
||||
})),
|
||||
.child(
|
||||
div()
|
||||
.line_clamp(1)
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child({
|
||||
if self.followed {
|
||||
shared_t!("screening.contact")
|
||||
} else {
|
||||
shared_t!("screening.not_contact")
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.items_start()
|
||||
.gap_2()
|
||||
.child(status_badge(self.verified, cx))
|
||||
.text_sm()
|
||||
.child(status_badge(self.active, cx))
|
||||
.child(
|
||||
v_flex()
|
||||
.text_sm()
|
||||
.child(shared_t!("screening.active_label"))
|
||||
.child(
|
||||
div()
|
||||
.line_clamp(1)
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child({
|
||||
if self.active == Some(true) {
|
||||
shared_t!("screening.active")
|
||||
} else {
|
||||
shared_t!("screening.no_active")
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.items_start()
|
||||
.gap_2()
|
||||
.child(status_badge(Some(self.verified), cx))
|
||||
.child(
|
||||
v_flex()
|
||||
.text_sm()
|
||||
@@ -246,35 +387,61 @@ impl Render for Screening {
|
||||
shared_t!("screening.nip05_label")
|
||||
}
|
||||
})
|
||||
.child(div().text_color(cx.theme().text_muted).child({
|
||||
if self.address(cx).is_some() {
|
||||
if self.verified {
|
||||
shared_t!("screening.nip05_ok")
|
||||
} else {
|
||||
shared_t!("screening.nip05_failed")
|
||||
}
|
||||
} else {
|
||||
shared_t!("screening.nip05_empty")
|
||||
}
|
||||
})),
|
||||
.child(
|
||||
div()
|
||||
.line_clamp(1)
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child({
|
||||
if self.address(cx).is_some() {
|
||||
if self.verified {
|
||||
shared_t!("screening.nip05_ok")
|
||||
} else {
|
||||
shared_t!("screening.nip05_failed")
|
||||
}
|
||||
} else {
|
||||
shared_t!("screening.nip05_empty")
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.items_start()
|
||||
.gap_2()
|
||||
.child(status_badge(self.mutual_contacts > 0, cx))
|
||||
.child(status_badge(Some(total_mutuals > 0), cx))
|
||||
.child(
|
||||
v_flex()
|
||||
.text_sm()
|
||||
.child(shared_t!("screening.mutual_label"))
|
||||
.child(div().text_color(cx.theme().text_muted).child({
|
||||
if self.mutual_contacts > 0 {
|
||||
shared_t!("screening.mutual", u = self.mutual_contacts)
|
||||
} else {
|
||||
shared_t!("screening.no_mutual")
|
||||
}
|
||||
})),
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.child(shared_t!("screening.mutual_label"))
|
||||
.child(
|
||||
Button::new("mutuals")
|
||||
.icon(IconName::Info)
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.rounded(ButtonRounded::Full)
|
||||
.on_click(cx.listener(
|
||||
move |this, _, window, cx| {
|
||||
this.mutual_contacts(window, cx);
|
||||
},
|
||||
)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.line_clamp(1)
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child({
|
||||
if total_mutuals > 0 {
|
||||
shared_t!("screening.mutual", u = total_mutuals)
|
||||
} else {
|
||||
shared_t!("screening.no_mutual")
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
@@ -287,36 +454,43 @@ impl Render for Screening {
|
||||
.w_full()
|
||||
.text_sm()
|
||||
.child({
|
||||
if self.dm_relays {
|
||||
if self.dm_relays == Some(true) {
|
||||
shared_t!("screening.relay_found")
|
||||
} else {
|
||||
shared_t!("screening.relay_empty")
|
||||
}
|
||||
})
|
||||
.child(div().w_full().text_color(cx.theme().text_muted).child(
|
||||
{
|
||||
if self.dm_relays {
|
||||
shared_t!("screening.relay_found_desc")
|
||||
} else {
|
||||
shared_t!("screening.relay_empty_desc")
|
||||
}
|
||||
},
|
||||
)),
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.line_clamp(1)
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child({
|
||||
if self.dm_relays == Some(true) {
|
||||
shared_t!("screening.relay_found_desc")
|
||||
} else {
|
||||
shared_t!("screening.relay_empty_desc")
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn status_badge(status: bool, cx: &App) -> Div {
|
||||
div()
|
||||
.pt_1()
|
||||
.flex_shrink_0()
|
||||
.child(Icon::new(IconName::CheckCircleFill).small().text_color({
|
||||
if status {
|
||||
cx.theme().icon_accent
|
||||
} else {
|
||||
cx.theme().icon_muted
|
||||
}
|
||||
}))
|
||||
fn status_badge(status: Option<bool>, cx: &App) -> Div {
|
||||
div().pt_1().flex_shrink_0().map(|this| {
|
||||
if let Some(status) = status {
|
||||
this.child(Icon::new(IconName::CheckCircleFill).small().text_color({
|
||||
if status {
|
||||
cx.theme().icon_accent
|
||||
} else {
|
||||
cx.theme().icon_muted
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
this.child(Indicator::new().xsmall())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
use global::constants::NIP17_RELAYS;
|
||||
use global::nostr_client;
|
||||
use global::{css, nostr_client};
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
div, px, uniform_list, App, AppContext, Context, Entity, InteractiveElement, IntoElement,
|
||||
@@ -19,8 +19,6 @@ use ui::input::{InputEvent, InputState, TextInput};
|
||||
use ui::modal::ModalButtonProps;
|
||||
use ui::{h_flex, v_flex, ContextModal, IconName, Sizable, StyledExt};
|
||||
|
||||
use crate::chatspace::ChatSpace;
|
||||
|
||||
pub fn init(kind: Kind, window: &mut Window, cx: &mut App) -> Entity<SetupRelay> {
|
||||
cx.new(|cx| SetupRelay::new(kind, window, cx))
|
||||
}
|
||||
@@ -220,7 +218,16 @@ impl SetupRelay {
|
||||
}
|
||||
|
||||
// Fetch gift wrap events
|
||||
ChatSpace::fetch_gift_wrap(&relays, public_key).await;
|
||||
let sub_id = css().gift_wrap_sub_id.clone();
|
||||
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
|
||||
|
||||
if client
|
||||
.subscribe_with_id_to(relays.clone(), sub_id, filter, None)
|
||||
.await
|
||||
.is_ok()
|
||||
{
|
||||
log::info!("Subscribed to messages in: {relays:?}");
|
||||
};
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
@@ -119,6 +119,7 @@ pub struct CoopSimpleStorage {
|
||||
pub init_at: Timestamp,
|
||||
pub gift_wrap_sub_id: SubscriptionId,
|
||||
pub gift_wrap_processing: AtomicBool,
|
||||
pub auto_close_opts: Option<SubscribeAutoCloseOptions>,
|
||||
pub sent_ids: RwLock<HashSet<EventId>>,
|
||||
pub resent_ids: RwLock<Vec<Output<EventId>>>,
|
||||
pub resend_queue: RwLock<HashMap<EventId, RelayUrl>>,
|
||||
@@ -136,6 +137,9 @@ impl CoopSimpleStorage {
|
||||
init_at: Timestamp::now(),
|
||||
gift_wrap_sub_id: SubscriptionId::new("inbox"),
|
||||
gift_wrap_processing: AtomicBool::new(false),
|
||||
auto_close_opts: Some(
|
||||
SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE),
|
||||
),
|
||||
sent_ids: RwLock::new(HashSet::new()),
|
||||
resent_ids: RwLock::new(Vec::new()),
|
||||
resend_queue: RwLock::new(HashMap::new()),
|
||||
|
||||
@@ -219,6 +219,12 @@ screening:
|
||||
en: "This person is one of your contacts."
|
||||
not_contact:
|
||||
en: "This person is not one of your contacts."
|
||||
active_label:
|
||||
en: "Activity"
|
||||
active:
|
||||
en: "This person has activity in the last 2 days"
|
||||
no_active:
|
||||
en: "This person has no activity in the last 2 days"
|
||||
mutual_label:
|
||||
en: "Mutual contacts"
|
||||
mutual:
|
||||
|
||||
Reference in New Issue
Block a user