diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2023-10-01 00:00:00 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2023-10-01 00:00:00 +0100 |
| commit | e237328ec611a5891586530c1d3cb26c16c1093b (patch) | |
| tree | 22ac36baa240354d06ae82eb070609fa3e3fcb82 /src/client.rs | |
| parent | 000901c0cbca8464b5a89bcc93c5474f6564bafd (diff) | |
feat(login) fetch user relays and metadata
get user relay list and metadata events from relays when keys are
used and last fetch attempt was more than an hour ago
uses user's write relays if known, otherwise uses fallback relays
to achieve this a method for intergration testing event fetching
from relays was added
Diffstat (limited to 'src/client.rs')
| -rw-r--r-- | src/client.rs | 72 |
1 files changed, 68 insertions, 4 deletions
diff --git a/src/client.rs b/src/client.rs index e0e0494..5ddf742 100644 --- a/src/client.rs +++ b/src/client.rs | |||
| @@ -10,25 +10,32 @@ | |||
| 10 | // which is currently in nightly. alternatively we can use nightly as it looks | 10 | // which is currently in nightly. alternatively we can use nightly as it looks |
| 11 | // certain that the implementation is going to make it to stable but we don't | 11 | // certain that the implementation is going to make it to stable but we don't |
| 12 | // want to inadvertlty use other features of nightly that might be removed. | 12 | // want to inadvertlty use other features of nightly that might be removed. |
| 13 | use anyhow::Result; | 13 | use anyhow::{Context, Result}; |
| 14 | use async_trait::async_trait; | 14 | use async_trait::async_trait; |
| 15 | use futures::future::join_all; | ||
| 15 | #[cfg(test)] | 16 | #[cfg(test)] |
| 16 | use mockall::*; | 17 | use mockall::*; |
| 17 | use nostr::Event; | 18 | use nostr::Event; |
| 18 | 19 | ||
| 19 | pub struct Client { | 20 | pub struct Client { |
| 20 | client: nostr_sdk::Client, | 21 | client: nostr_sdk::Client, |
| 21 | pub fallback_relays: Vec<String>, | 22 | fallback_relays: Vec<String>, |
| 22 | } | 23 | } |
| 23 | 24 | ||
| 24 | #[async_trait] | ||
| 25 | #[cfg_attr(test, automock)] | 25 | #[cfg_attr(test, automock)] |
| 26 | #[async_trait] | ||
| 26 | pub trait Connect { | 27 | pub trait Connect { |
| 27 | fn default() -> Self; | 28 | fn default() -> Self; |
| 28 | fn new(opts: Params) -> Self; | 29 | fn new(opts: Params) -> Self; |
| 29 | async fn connect(&self) -> Result<()>; | 30 | async fn connect(&self) -> Result<()>; |
| 30 | async fn disconnect(&self) -> Result<()>; | 31 | async fn disconnect(&self) -> Result<()>; |
| 32 | fn get_fallback_relays(&self) -> &Vec<String>; | ||
| 31 | async fn send_event_to(&self, url: &str, event: nostr::event::Event) -> Result<nostr::EventId>; | 33 | async fn send_event_to(&self, url: &str, event: nostr::event::Event) -> Result<nostr::EventId>; |
| 34 | async fn get_events( | ||
| 35 | &self, | ||
| 36 | relays: Vec<String>, | ||
| 37 | filters: Vec<nostr::Filter>, | ||
| 38 | ) -> Result<Vec<nostr::Event>>; | ||
| 32 | } | 39 | } |
| 33 | 40 | ||
| 34 | #[async_trait] | 41 | #[async_trait] |
| @@ -37,7 +44,7 @@ impl Connect for Client { | |||
| 37 | Client { | 44 | Client { |
| 38 | client: nostr_sdk::Client::new(&nostr::Keys::generate()), | 45 | client: nostr_sdk::Client::new(&nostr::Keys::generate()), |
| 39 | fallback_relays: vec![ | 46 | fallback_relays: vec![ |
| 40 | "ws://localhost:8080".to_string(), | 47 | "ws://localhost:8051".to_string(), |
| 41 | "ws://localhost:8052".to_string(), | 48 | "ws://localhost:8052".to_string(), |
| 42 | ], | 49 | ], |
| 43 | } | 50 | } |
| @@ -61,9 +68,52 @@ impl Connect for Client { | |||
| 61 | Ok(()) | 68 | Ok(()) |
| 62 | } | 69 | } |
| 63 | 70 | ||
| 71 | fn get_fallback_relays(&self) -> &Vec<String> { | ||
| 72 | &self.fallback_relays | ||
| 73 | } | ||
| 74 | |||
| 64 | async fn send_event_to(&self, url: &str, event: Event) -> Result<nostr::EventId> { | 75 | async fn send_event_to(&self, url: &str, event: Event) -> Result<nostr::EventId> { |
| 65 | Ok(self.client.send_event_to(url, event).await?) | 76 | Ok(self.client.send_event_to(url, event).await?) |
| 66 | } | 77 | } |
| 78 | |||
| 79 | async fn get_events( | ||
| 80 | &self, | ||
| 81 | relays: Vec<String>, | ||
| 82 | filters: Vec<nostr::Filter>, | ||
| 83 | ) -> Result<Vec<nostr::Event>> { | ||
| 84 | // add relays | ||
| 85 | for relay in &relays { | ||
| 86 | self.client | ||
| 87 | .add_relay(relay.as_str(), None) | ||
| 88 | .await | ||
| 89 | .context("cannot add relay")?; | ||
| 90 | } | ||
| 91 | |||
| 92 | let relays_map = self.client.relays().await; | ||
| 93 | |||
| 94 | let relay_results = join_all( | ||
| 95 | relays | ||
| 96 | .clone() | ||
| 97 | .iter() | ||
| 98 | .map(|r| { | ||
| 99 | ( | ||
| 100 | relays_map.get(&nostr::Url::parse(r).unwrap()).unwrap(), | ||
| 101 | filters.clone(), | ||
| 102 | ) | ||
| 103 | }) | ||
| 104 | .map(|(relay, filters)| { | ||
| 105 | relay.get_events_of( | ||
| 106 | filters, | ||
| 107 | // 20 is nostr_sdk default | ||
| 108 | std::time::Duration::from_secs(20), | ||
| 109 | nostr_sdk::FilterOptions::ExitOnEOSE, | ||
| 110 | ) | ||
| 111 | }), | ||
| 112 | ) | ||
| 113 | .await; | ||
| 114 | |||
| 115 | Ok(get_dedup_events(relay_results)) | ||
| 116 | } | ||
| 67 | } | 117 | } |
| 68 | 118 | ||
| 69 | #[derive(Default)] | 119 | #[derive(Default)] |
| @@ -82,3 +132,17 @@ impl Params { | |||
| 82 | self | 132 | self |
| 83 | } | 133 | } |
| 84 | } | 134 | } |
| 135 | |||
| 136 | fn get_dedup_events( | ||
| 137 | relay_results: Vec<Result<Vec<nostr::Event>, nostr_sdk::relay::Error>>, | ||
| 138 | ) -> Vec<Event> { | ||
| 139 | let mut dedup_events: Vec<Event> = vec![]; | ||
| 140 | for events in relay_results.into_iter().flatten() { | ||
| 141 | for event in events { | ||
| 142 | if !dedup_events.iter().any(|e| event.id.eq(&e.id)) { | ||
| 143 | dedup_events.push(event); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | } | ||
| 147 | dedup_events | ||
| 148 | } | ||