use crate::user::CaracalUser;
use duration_str::parse as dur_parse;
use nostr_sdk::prelude::*;
use colored::*;
use std::sync::Arc;
pub async fn user_subscribe(user: &CaracalUser) {
let Ok(contacts) =
user.client.get_contact_list(dur_parse("8s").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 mut follow_pubkeys: Vec<PublicKey> = contacts.into_iter().map(|c| c.public_key).collect();
follow_pubkeys.push(signer_pubk);
let subs = vec![
Filter::new()
.kind(Kind::Metadata)
.kind(Kind::RelayList)
.kind(Kind::InboxRelays)
.since(now - dur_parse("6mon").unwrap())
.limit(30),
Filter::new()
.kind(Kind::ContactList)
.kind(Kind::Bookmarks)
.kind(Kind::Custom(10133))
.since(now - dur_parse("90d").unwrap())
.limit(10),
Filter::new()
.kind(Kind::TextNote)
.kind(Kind::LongFormTextNote)
.kind(Kind::Reaction)
.kind(Kind::GenericRepost)
.kind(Kind::Repost)
.since(now - dur_parse("90d").unwrap())
.limit(100)
];
for pubkey in &follow_pubkeys {
for sub in &subs {
if let Err(err) = user
.client
.subscribe_with_id(SubscriptionId::new(format!("{pubkey}")), sub.clone().author(*pubkey), None)
.await
{
eprintln!("Error subscribing: {err}")
}
}
}
}
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
{
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;
};
if let Some(RelayMetadata::Write) = metadata {
println!("{} {}", "=>".cyan(), url.to_string().bold().purple());
}
}
}
Ok(false)
})
.await?;
Ok(())
}