use crate::user::CaracalUser;
use duration_str::parse as dur_parse;
use nostr_sdk::prelude::*;
use std::sync::Arc;
pub async fn user_subscribe(user: &CaracalUser) {
let Ok(contacts) =
user.client.get_contact_list(dur_parse("5s").unwrap()).await
else {
eprintln!("Failed to retrieve contact list");
return;
};
let now = Timestamp::now();
let sub_id = SubscriptionId::new("user");
let Ok(signer_pubk) = user.signer.get_public_key().await else {
eprintln!("Cannot get public key from signer");
return;
};
user.client.connect().await;
user.client.unsubscribe(&sub_id).await;
let subscription = Filter::new()
.kind(Kind::RelayList)
.kind(Kind::InboxRelays)
.kind(Kind::Metadata)
.kind(Kind::ContactList)
.kind(Kind::TextNote)
.kind(Kind::LongFormTextNote)
.kind(Kind::Reaction)
.kind(Kind::Custom(10133))
.since(now - dur_parse("90d").unwrap())
.author(signer_pubk)
.authors(contacts.into_iter().map(|c| c.public_key));
if let Err(e) = user
.client
.subscribe_with_id(sub_id, subscription, None)
.await
{
eprintln!("Error subscribing: {e}")
}
}
pub async fn prepare_nostr_client(client: Arc<Client>) {
client.connect().await;
let _ = client
.subscribe(
Filter::new()
.kind(Kind::Metadata)
.limit(1000)
.since(Timestamp::now() - dur_parse("90d").unwrap()),
None,
)
.await;
}
pub async fn handle_nostr_notifications(
client: Arc<Client>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
client
.handle_notifications(|notification| async {
if let RelayPoolNotification::Event {
relay_url: _,
subscription_id: _,
event,
} = notification
{
match event.kind {
Kind::TextNote => {
if let Err(err) = client
.subscribe(
Filter::new()
.kind(Kind::Metadata)
.author(event.pubkey)
.limit(1),
None,
)
.await
{
eprintln!("Metadata sub failed: {err}");
}
}
Kind::RelayList => {
for (url, _metadata) in
nip65::extract_relay_list(&event)
{
let Ok(_) = client.add_discovery_relay(url).await
else {
continue;
};
let Ok(_) = client.add_read_relay(url).await else {
continue;
};
}
}
_ => {}
}
} else if let RelayPoolNotification::Message {
relay_url: _,
message,
} = notification
&& let RelayMessage::Event {
subscription_id: _,
ref event,
} = message
&& let Kind::RelayList = event.kind
{
let urls: Vec<_> = nip65::extract_relay_list(event)
.map(|(url, _)| url)
.collect();
if !urls.is_empty() {
let _ = client
.subscribe_to(
urls,
Filter::new()
.kind(Kind::Metadata)
.since(
Timestamp::now()
- dur_parse("90d").unwrap(),
)
.limit(200),
None,
)
.await;
}
for (url, _metadata) in nip65::extract_relay_list(event) {
let Ok(_) = client.add_discovery_relay(url).await else {
continue;
};
let Ok(_) = client.add_read_relay(url).await else {
continue;
};
}
}
Ok(false)
})
.await?;
Ok(())
}