feat: custom gossip implementation (#181)
* . * rename global to app_state * refactor event tracker * gossip * . * .
This commit is contained in:
@@ -6,7 +6,7 @@ publish.workspace = true
|
||||
|
||||
[dependencies]
|
||||
common = { path = "../common" }
|
||||
global = { path = "../global" }
|
||||
app_state = { path = "../app_state" }
|
||||
settings = { path = "../settings" }
|
||||
|
||||
gpui.workspace = true
|
||||
|
||||
@@ -2,10 +2,11 @@ use std::cmp::Reverse;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use anyhow::Error;
|
||||
use app_state::nostr_client;
|
||||
use app_state::state::UnwrappingStatus;
|
||||
use common::event::EventUtils;
|
||||
use fuzzy_matcher::skim::SkimMatcherV2;
|
||||
use fuzzy_matcher::FuzzyMatcher;
|
||||
use global::{nostr_client, UnwrappingStatus};
|
||||
use gpui::{App, AppContext, Context, Entity, EventEmitter, Global, Task, WeakEntity, Window};
|
||||
use itertools::Itertools;
|
||||
use nostr_sdk::prelude::*;
|
||||
|
||||
@@ -4,12 +4,11 @@ use std::hash::{Hash, Hasher};
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
use app_state::constants::SEND_RETRY;
|
||||
use app_state::{app_state, nostr_client};
|
||||
use common::display::RenderedProfile;
|
||||
use common::event::EventUtils;
|
||||
use global::constants::SEND_RETRY;
|
||||
use global::{app_state, nostr_client};
|
||||
use gpui::{App, AppContext, Context, EventEmitter, SharedString, SharedUri, Task};
|
||||
use itertools::Itertools;
|
||||
use nostr_sdk::prelude::*;
|
||||
|
||||
use crate::Registry;
|
||||
@@ -358,18 +357,6 @@ impl Room {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn disconnect(&self, relays: Vec<RelayUrl>, cx: &App) -> Task<Result<(), Error>> {
|
||||
cx.background_spawn(async move {
|
||||
let client = nostr_client();
|
||||
|
||||
for relay in relays.into_iter() {
|
||||
client.disconnect_relay(relay).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Loads all messages for this room from the database
|
||||
pub fn load_messages(&self, cx: &App) -> Task<Result<Vec<Event>, Error>> {
|
||||
let members = self.members.clone();
|
||||
@@ -378,13 +365,14 @@ impl Room {
|
||||
let client = nostr_client();
|
||||
let signer = client.signer().await?;
|
||||
let public_key = signer.get_public_key().await?;
|
||||
let sent_ids = app_state()
|
||||
.sent_ids
|
||||
let sent_ids: Vec<EventId> = app_state()
|
||||
.event_tracker
|
||||
.read()
|
||||
.await
|
||||
.sent_ids()
|
||||
.iter()
|
||||
.copied()
|
||||
.collect_vec();
|
||||
.collect();
|
||||
|
||||
// Get seen events from database
|
||||
let filter = Filter::new()
|
||||
@@ -508,12 +496,17 @@ impl Room {
|
||||
let rumor = rumor.clone();
|
||||
let event = EventBuilder::gift_wrap(&signer, &receiver, rumor, vec![]).await?;
|
||||
|
||||
let Ok(relay_urls) = Self::messaging_relays(receiver).await else {
|
||||
let gossip = app_state.gossip.read().await;
|
||||
let urls = gossip.messaging_relays(&receiver);
|
||||
|
||||
// Check if there are any relays to send the event to
|
||||
if urls.is_empty() {
|
||||
reports.push(SendReport::new(receiver).not_found());
|
||||
continue;
|
||||
};
|
||||
}
|
||||
|
||||
match client.send_event_to(relay_urls, &event).await {
|
||||
// Send the event to the relays
|
||||
match client.send_event_to(urls, &event).await {
|
||||
Ok(output) => {
|
||||
let id = output.id().to_owned();
|
||||
let auth_required = output.failed.iter().any(|m| m.1.starts_with("auth-"));
|
||||
@@ -522,7 +515,8 @@ impl Room {
|
||||
if auth_required {
|
||||
// Wait for authenticated and resent event successfully
|
||||
for attempt in 0..=SEND_RETRY {
|
||||
let ids = app_state.resent_ids.read().await;
|
||||
let retry_manager = app_state.event_tracker.read().await;
|
||||
let ids = retry_manager.resent_ids();
|
||||
|
||||
// Check if event was successfully resent
|
||||
if let Some(output) = ids.iter().find(|e| e.id() == &id).cloned() {
|
||||
@@ -555,8 +549,15 @@ impl Room {
|
||||
|
||||
// Only send a backup message to current user if sent successfully to others
|
||||
if reports.iter().all(|r| r.is_sent_success()) && backup {
|
||||
if let Ok(relay_urls) = Self::messaging_relays(public_key).await {
|
||||
match client.send_event_to(relay_urls, &event).await {
|
||||
let gossip = app_state.gossip.read().await;
|
||||
let urls = gossip.messaging_relays(&public_key);
|
||||
|
||||
// Check if there are any relays to send the event to
|
||||
if urls.is_empty() {
|
||||
reports.push(SendReport::new(public_key).not_found());
|
||||
} else {
|
||||
// Send the event to the relays
|
||||
match client.send_event_to(urls, &event).await {
|
||||
Ok(output) => {
|
||||
reports.push(SendReport::new(public_key).status(output));
|
||||
}
|
||||
@@ -564,8 +565,6 @@ impl Room {
|
||||
reports.push(SendReport::new(public_key).error(e.to_string()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reports.push(SendReport::new(public_key).not_found());
|
||||
}
|
||||
} else {
|
||||
reports.push(SendReport::new(public_key).on_hold(event));
|
||||
@@ -583,6 +582,8 @@ impl Room {
|
||||
) -> Task<Result<Vec<SendReport>, Error>> {
|
||||
cx.background_spawn(async move {
|
||||
let client = nostr_client();
|
||||
let app_state = app_state();
|
||||
|
||||
let mut resend_reports = vec![];
|
||||
|
||||
for report in reports.into_iter() {
|
||||
@@ -611,8 +612,15 @@ impl Room {
|
||||
|
||||
// Process the on hold event if it exists
|
||||
if let Some(event) = report.on_hold {
|
||||
if let Ok(relay_urls) = Self::messaging_relays(receiver).await {
|
||||
match client.send_event_to(relay_urls, &event).await {
|
||||
let gossip = app_state.gossip.read().await;
|
||||
let urls = gossip.messaging_relays(&receiver);
|
||||
|
||||
// Check if there are any relays to send the event to
|
||||
if urls.is_empty() {
|
||||
resend_reports.push(SendReport::new(receiver).not_found());
|
||||
} else {
|
||||
// Send the event to the relays
|
||||
match client.send_event_to(urls, &event).await {
|
||||
Ok(output) => {
|
||||
resend_reports.push(SendReport::new(receiver).status(output));
|
||||
}
|
||||
@@ -620,8 +628,6 @@ impl Room {
|
||||
resend_reports.push(SendReport::new(receiver).error(e.to_string()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resend_reports.push(SendReport::new(receiver).not_found());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -629,36 +635,4 @@ impl Room {
|
||||
Ok(resend_reports)
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets messaging relays for public key
|
||||
async fn messaging_relays(public_key: PublicKey) -> Result<Vec<RelayUrl>, Error> {
|
||||
let client = nostr_client();
|
||||
let mut relay_urls = vec![];
|
||||
|
||||
let filter = Filter::new()
|
||||
.kind(Kind::InboxRelays)
|
||||
.author(public_key)
|
||||
.limit(1);
|
||||
|
||||
if let Some(event) = client.database().query(filter).await?.first_owned() {
|
||||
let urls: Vec<RelayUrl> = nip17::extract_owned_relay_list(event).collect();
|
||||
|
||||
// Check if at least one URL exists
|
||||
if urls.is_empty() {
|
||||
return Err(anyhow!("Not found"));
|
||||
}
|
||||
|
||||
// Connect to relays
|
||||
for url in urls.iter() {
|
||||
client.add_relay(url).await?;
|
||||
client.connect_relay(url).await?;
|
||||
}
|
||||
|
||||
relay_urls.extend(urls.into_iter().take(3).unique());
|
||||
} else {
|
||||
return Err(anyhow!("Not found"));
|
||||
}
|
||||
|
||||
Ok(relay_urls)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user