use std::collections::{BTreeSet, HashMap, HashSet};
use nostr::prelude::*;
use crate::error::Error;
use crate::{Events, NostrDatabase, Profile, RelaysMap};
pub trait NostrDatabaseExt: NostrDatabase {
fn metadata(&self, public_key: PublicKey) -> BoxedFuture<'_, Result<Option<Metadata>, Error>> {
Box::pin(async move {
let filter = Filter::new()
.author(public_key)
.kind(Kind::Metadata)
.limit(1);
let events: Events = self.query(filter).await?;
match events.first_owned() {
Some(event) => Ok(Some(Metadata::from_json(event.content)?)),
None => Ok(None),
}
})
}
fn contacts_public_keys(
&self,
public_key: PublicKey,
) -> BoxedFuture<'_, Result<HashSet<PublicKey>, Error>> {
Box::pin(async move {
let filter = Filter::new()
.author(public_key)
.kind(Kind::ContactList)
.limit(1);
let events: Events = self.query(filter).await?;
match events.first_owned() {
Some(event) => Ok(event.tags.public_keys().collect()),
None => Ok(HashSet::new()),
}
})
}
fn contacts(&self, public_key: PublicKey) -> BoxedFuture<'_, Result<BTreeSet<Profile>, Error>> {
Box::pin(async move {
let filter = Filter::new()
.author(public_key)
.kind(Kind::ContactList)
.limit(1);
let events: Events = self.query(filter).await?;
match events.first_owned() {
Some(event) => {
let filter = Filter::new()
.authors(event.tags.public_keys())
.kind(Kind::Metadata);
let mut contacts: HashSet<Profile> = self
.query(filter)
.await?
.into_iter()
.map(|e| {
let metadata: Metadata =
Metadata::from_json(&e.content).unwrap_or_default();
Profile::new(e.pubkey, metadata)
})
.collect();
contacts.extend(event.tags.public_keys().map(Profile::from));
Ok(contacts.into_iter().collect())
}
None => Ok(BTreeSet::new()),
}
})
}
fn relay_list(&self, public_key: PublicKey) -> BoxedFuture<'_, Result<RelaysMap, Error>> {
Box::pin(async move {
let filter: Filter = Filter::default()
.author(public_key)
.kind(Kind::RelayList)
.limit(1);
let events: Events = self.query(filter).await?;
match events.first() {
Some(event) => Ok(nip65::extract_relay_list(event).collect()),
None => Ok(HashMap::new()),
}
})
}
fn relay_lists<'a, I>(
&'a self,
public_keys: I,
) -> BoxedFuture<'a, Result<HashMap<PublicKey, RelaysMap>, Error>>
where
I: IntoIterator<Item = PublicKey> + Send + 'a,
{
Box::pin(async move {
let filter: Filter = Filter::default().authors(public_keys).kind(Kind::RelayList);
let events: Events = self.query(filter).await?;
let mut map = HashMap::with_capacity(events.len());
for event in events.iter() {
map.insert(event.pubkey, nip65::extract_relay_list(event).collect());
}
Ok(map)
})
}
}
impl<T: NostrDatabase + ?Sized> NostrDatabaseExt for T {}