From 43a445963968dac7da190b56f7c89ac0ff1f6abd Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Wed, 17 Jul 2024 10:53:20 +0100 Subject: feat(login): use fetch to get user profile fetch automatically gets updates to logged in user profile / relays fetching without specifying repo pointers will just fetch user profiles so that can be used during login, if user profile isn't in cache login now uses fetch --- src/login.rs | 124 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 58 insertions(+), 66 deletions(-) (limited to 'src/login.rs') diff --git a/src/login.rs b/src/login.rs index d580969..0a20a90 100644 --- a/src/login.rs +++ b/src/login.rs @@ -1,17 +1,14 @@ -use std::{fs::create_dir_all, str::FromStr, time::Duration}; +use std::{collections::HashSet, path::Path, str::FromStr, time::Duration}; use anyhow::{bail, Context, Result}; use nostr::{ nips::{nip05::get_nip46, nip46::NostrConnectURI}, PublicKey, }; -use nostr_database::Order; use nostr_sdk::{ - Alphabet, FromBech32, JsonUtil, Keys, Kind, NostrDatabase, NostrSigner, SingleLetterTag, - ToBech32, + Alphabet, FromBech32, JsonUtil, Keys, Kind, NostrSigner, SingleLetterTag, ToBech32, Url, }; use nostr_signer::Nip46Signer; -use nostr_sqlite::SQLiteDatabase; #[cfg(not(test))] use crate::client::Client; @@ -21,8 +18,8 @@ use crate::{ cli_interactor::{ Interactor, InteractorPrompt, PromptConfirmParms, PromptInputParms, PromptPasswordParms, }, - client::{fetch_public_key, Connect}, - config::{get_dirs, UserMetadata, UserRef, UserRelayRef, UserRelays}, + client::{fetch_public_key, get_event_from_global_cache, Connect}, + config::{UserMetadata, UserRef, UserRelayRef, UserRelays}, git::{Repo, RepoActions}, key_handling::encryption::{decrypt_key, encrypt_key}, }; @@ -107,7 +104,7 @@ pub async fn launch( fn print_logged_in_as(user_ref: &UserRef, offline_mode: bool) -> Result<()> { if !offline_mode && user_ref.metadata.created_at.eq(&0) { - println!("cannot find your account metadata (name, etc) on relays"); + println!("cannot find profile..."); } else if !offline_mode && user_ref.metadata.name.eq(&user_ref.public_key.to_bech32()?) { println!("cannot extract account name from account metadata..."); } else if !offline_mode && user_ref.relays.created_at.eq(&0) { @@ -615,20 +612,6 @@ async fn get_user_details( #[cfg(not(test))] client: Option<&Client>, git_repo: &Repo, ) -> Result { - if client.is_some() { - println!("searching for profile and relay updates..."); - } - let database = SQLiteDatabase::open(if std::env::var("NGITTEST").is_err() { - create_dir_all(get_dirs()?.config_dir()).context(format!( - "cannot create cache directory in: {:?}", - get_dirs()?.config_dir() - ))?; - get_dirs()?.config_dir().join("cache.sqlite") - } else { - git_repo.get_path()?.join(".git/test-global-cache.sqlite") - }) - .await?; - let mut events: Vec = vec![]; let filters = vec![ nostr::Filter::default() .author(*public_key) @@ -637,54 +620,63 @@ async fn get_user_details( .author(*public_key) .kind(Kind::RelayList), ]; - if let Ok(cached_events) = database.query(filters.clone(), Order::Asc).await { - for event in cached_events { - events.push(event); - } - } - let mut relays_to_search = if let Some(client) = client { - client.get_fallback_relays().clone() - } else { - vec![] - }; - let mut relays_searched = vec![]; - let user_ref = loop { - if let Some(client) = client { - for event in client - .get_events(relays_to_search.clone(), filters.clone()) - .await - .unwrap_or(vec![]) - { - let _ = database.save_event(&event).await; - events.push(event); - } - } - #[allow(clippy::clone_on_copy)] - let user_ref = UserRef { - public_key: public_key.clone(), - metadata: extract_user_metadata(public_key, &events)?, - relays: extract_user_relays(public_key, &events), - }; + let mut events = get_event_from_global_cache(git_repo.get_path()?, filters.clone()).await?; - if client.is_none() { - break user_ref; - } - for r in &relays_to_search { - relays_searched.push(r.clone()); + if let Some(client) = client { + if events.is_empty() { + let term = console::Term::stderr(); + term.write_line("searching for profile...")?; + let (_, progress_reporter) = client + .fetch_all(git_repo.get_path()?, &HashSet::new()) + .await?; + events = get_event_from_global_cache(git_repo.get_path()?, filters).await?; + if !events.is_empty() { + progress_reporter.clear()?; + // term.clear_last_lines(1)?; + } } + } - relays_to_search = user_ref - .relays - .write() - .iter() - .filter(|r| !relays_searched.iter().any(|or| r.eq(&or))) - .map(std::clone::Clone::clone) - .collect(); - if !relays_to_search.is_empty() { - continue; + Ok(UserRef { + public_key: public_key.to_owned(), + metadata: extract_user_metadata(public_key, &events)?, + relays: extract_user_relays(public_key, &events), + }) +} + +pub async fn get_logged_in_user_and_relays_from_cache( + git_repo_path: &Path, +) -> Result<(Option, HashSet)> { + let git_repo = Repo::from_path(&git_repo_path.to_path_buf())?; + let current_user = if let Some(npub) = git_repo.get_git_config_item("nostr.npub", None)? { + if let Ok(pubic_key) = PublicKey::parse(npub) { + Some(pubic_key) + } else { + None } - break user_ref; + } else { + None + }; + let relays = if let Some(current_user) = current_user { + extract_user_relays( + ¤t_user, + &get_event_from_global_cache( + git_repo.get_path()?, + vec![ + nostr::Filter::default() + .author((*current_user).into()) + .kind(Kind::RelayList), + ], + ) + .await?, + ) + .write() + .iter() + .filter_map(|r| Url::parse(r).ok()) + .collect::>() + } else { + HashSet::new() }; - Ok(user_ref) + Ok((current_user, relays)) } -- cgit v1.2.3