use std::collections::HashMap;
use fast_config::FastConfig;
use nostr::nips::nip46::NostrConnectURI;
use nostr::{Keys, NostrSigner};
use nostr_sdk::prelude::*;
use once_cell::sync::Lazy;
use std::ops::DerefMut;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::mpsc::{Receiver, Sender};
use crate::config::BaseRelaysConfig;
use crate::relays::default_relays;
use crate::storage::Storage;
pub struct CaracalUser {
pub identity_path: PathBuf,
pub client: Arc<Client>,
pub upload_keys: Keys,
pub signer: Arc<dyn NostrSigner>,
pub connect_uri: Option<NostrConnectURI>,
pub storage: Storage,
pub tx: Sender<u8>,
pub rx: Receiver<u8>,
}
impl CaracalUser {
pub fn path_relay_list(&self) -> PathBuf {
self.identity_path.join("nip65_relays.json")
}
pub async fn configure(&self) {
if !self.path_relay_list().is_file() {
let config = BaseRelaysConfig::default();
if let Err(_) =
config.save(self.path_relay_list(), fast_config::Format::JSON)
{
eprintln!("Failed to save config");
}
}
if let Err(err) = self.advertise_relay_list().await {
eprintln!("Failed to advertise relay list: {err}");
}
}
pub fn save_relay_list(
&self,
config: &BaseRelaysConfig,
) -> Result<(), fast_config::Error> {
config.save(self.path_relay_list(), fast_config::Format::JSON)
}
pub fn relay_list_config(&self) -> BaseRelaysConfig {
let mut config = BaseRelaysConfig::default();
let _ = config.load(self.path_relay_list(), fast_config::Format::JSON);
config
}
pub async fn advertise_relay_list(
&self,
) -> Result<(), Box<dyn std::error::Error>> {
let relay_config = self.relay_list_config();
let mut relay_metadata: HashMap<RelayUrl, Option<RelayMetadata>> =
HashMap::new();
for rurl in relay_config.read_relays {
let _ = self.client.add_read_relay(&rurl).await;
relay_metadata.insert(rurl, Some(RelayMetadata::Read));
}
for wurl in relay_config.write_relays {
let _ = self.client.add_write_relay(&wurl).await;
relay_metadata.insert(wurl, Some(RelayMetadata::Write));
}
let relay_list_builder = EventBuilder::relay_list(relay_metadata);
self.client
.send_event_builder_to(default_relays(), relay_list_builder)
.await?;
let inboxr: Vec<&str> =
vec!["wss://relay.damus.io", "wss://nostr.bitcoiner.social"];
let inbox_relays_builder = EventBuilder::new(Kind::InboxRelays, "")
.tags(
inboxr
.into_iter()
.map(|ir| Tag::custom(TagKind::Relay, vec![ir])),
);
self.client
.send_event_builder_to(default_relays(), inbox_relays_builder)
.await?;
Ok(())
}
}
pub static mut USERS: Lazy<HashMap<String, CaracalUser>> =
Lazy::new(HashMap::new);
pub fn lookup_user(fingerprint: String) -> Option<&'static CaracalUser> {
#[allow(static_mut_refs)]
unsafe {
let us = USERS.deref_mut();
us.get(&fingerprint.clone())
}
}
pub fn lookup_user_mut(
fingerprint: String,
) -> Option<&'static mut CaracalUser> {
#[allow(static_mut_refs)]
unsafe {
let us = USERS.deref_mut();
us.get_mut(&fingerprint.clone())
}
}