Skip to content

Commit

Permalink
database: add NostrDatabaseExt::relay_list
Browse files Browse the repository at this point in the history
Signed-off-by: Yuki Kishimoto <[email protected]>
  • Loading branch information
yukibtc committed Apr 9, 2024
1 parent ca4bdb7 commit 965df59
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 4 deletions.
27 changes: 26 additions & 1 deletion crates/nostr-database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ use std::sync::Arc;
pub use async_trait::async_trait;
pub use nostr;
use nostr::nips::nip01::Coordinate;
use nostr::{Event, EventId, Filter, JsonUtil, Kind, Metadata, PublicKey, Timestamp, Url};
use nostr::nips::nip65;
use nostr::{
Event, EventId, Filter, JsonUtil, Kind, Metadata, PublicKey, RelayMetadata, Timestamp, Url,
};

mod error;
#[cfg(feature = "flatbuf")]
Expand Down Expand Up @@ -255,6 +258,28 @@ pub trait NostrDatabaseExt: NostrDatabase {
None => Ok(BTreeSet::new()),
}
}

/// Get relays list for [PublicKey]
///
/// <https://github.com/nostr-protocol/nips/blob/master/65.md>
#[tracing::instrument(skip_all, level = "trace")]
async fn relay_list(
&self,
public_key: PublicKey,
) -> Result<Vec<(Url, Option<RelayMetadata>)>, Self::Err> {
// Query
let filter: Filter = Filter::default()
.author(public_key)
.kind(Kind::RelayList)
.limit(1);
let events: Vec<Event> = self.query(vec![filter], Order::Desc).await?;

// Extract relay list (NIP65)
match events.first() {
Some(event) => Ok(nip65::extract_relay_list(event)),
None => Ok(Vec::new()),
}
}
}

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
Expand Down
7 changes: 4 additions & 3 deletions crates/nostr/src/nips/nip65.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
use alloc::vec::Vec;

use crate::{Event, RelayMetadata, Tag, UncheckedUrl};
use crate::{Event, RelayMetadata, Tag, Url};

/// Extracts the relay info (url, optional read/write flag) from the event
pub fn extract_relay_list(event: &Event) -> Vec<(UncheckedUrl, Option<RelayMetadata>)> {
#[inline]
pub fn extract_relay_list(event: &Event) -> Vec<(Url, Option<RelayMetadata>)> {
event
.iter_tags()
.filter_map(|tag| {
if let Tag::RelayMetadata(url, metadata) = tag {
Some((url.clone(), metadata.clone()))
Some((Url::parse(url.as_str()).ok()?, metadata.clone()))
} else {
None
}
Expand Down
6 changes: 6 additions & 0 deletions crates/nostr/src/types/url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ impl UncheckedUrl {
pub fn empty() -> Self {
Self(String::new())
}

/// Get unchecked url as `&str`
#[inline]
pub fn as_str(&self) -> &str {
&self.0
}
}

impl<S> From<S> for UncheckedUrl
Expand Down

0 comments on commit 965df59

Please sign in to comment.