diff options
Diffstat (limited to 'src/login.rs')
| -rw-r--r-- | src/login.rs | 124 |
1 files changed, 58 insertions, 66 deletions
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 @@ | |||
| 1 | use std::{fs::create_dir_all, str::FromStr, time::Duration}; | 1 | use std::{collections::HashSet, path::Path, str::FromStr, time::Duration}; |
| 2 | 2 | ||
| 3 | use anyhow::{bail, Context, Result}; | 3 | use anyhow::{bail, Context, Result}; |
| 4 | use nostr::{ | 4 | use nostr::{ |
| 5 | nips::{nip05::get_nip46, nip46::NostrConnectURI}, | 5 | nips::{nip05::get_nip46, nip46::NostrConnectURI}, |
| 6 | PublicKey, | 6 | PublicKey, |
| 7 | }; | 7 | }; |
| 8 | use nostr_database::Order; | ||
| 9 | use nostr_sdk::{ | 8 | use nostr_sdk::{ |
| 10 | Alphabet, FromBech32, JsonUtil, Keys, Kind, NostrDatabase, NostrSigner, SingleLetterTag, | 9 | Alphabet, FromBech32, JsonUtil, Keys, Kind, NostrSigner, SingleLetterTag, ToBech32, Url, |
| 11 | ToBech32, | ||
| 12 | }; | 10 | }; |
| 13 | use nostr_signer::Nip46Signer; | 11 | use nostr_signer::Nip46Signer; |
| 14 | use nostr_sqlite::SQLiteDatabase; | ||
| 15 | 12 | ||
| 16 | #[cfg(not(test))] | 13 | #[cfg(not(test))] |
| 17 | use crate::client::Client; | 14 | use crate::client::Client; |
| @@ -21,8 +18,8 @@ use crate::{ | |||
| 21 | cli_interactor::{ | 18 | cli_interactor::{ |
| 22 | Interactor, InteractorPrompt, PromptConfirmParms, PromptInputParms, PromptPasswordParms, | 19 | Interactor, InteractorPrompt, PromptConfirmParms, PromptInputParms, PromptPasswordParms, |
| 23 | }, | 20 | }, |
| 24 | client::{fetch_public_key, Connect}, | 21 | client::{fetch_public_key, get_event_from_global_cache, Connect}, |
| 25 | config::{get_dirs, UserMetadata, UserRef, UserRelayRef, UserRelays}, | 22 | config::{UserMetadata, UserRef, UserRelayRef, UserRelays}, |
| 26 | git::{Repo, RepoActions}, | 23 | git::{Repo, RepoActions}, |
| 27 | key_handling::encryption::{decrypt_key, encrypt_key}, | 24 | key_handling::encryption::{decrypt_key, encrypt_key}, |
| 28 | }; | 25 | }; |
| @@ -107,7 +104,7 @@ pub async fn launch( | |||
| 107 | 104 | ||
| 108 | fn print_logged_in_as(user_ref: &UserRef, offline_mode: bool) -> Result<()> { | 105 | fn print_logged_in_as(user_ref: &UserRef, offline_mode: bool) -> Result<()> { |
| 109 | if !offline_mode && user_ref.metadata.created_at.eq(&0) { | 106 | if !offline_mode && user_ref.metadata.created_at.eq(&0) { |
| 110 | println!("cannot find your account metadata (name, etc) on relays"); | 107 | println!("cannot find profile..."); |
| 111 | } else if !offline_mode && user_ref.metadata.name.eq(&user_ref.public_key.to_bech32()?) { | 108 | } else if !offline_mode && user_ref.metadata.name.eq(&user_ref.public_key.to_bech32()?) { |
| 112 | println!("cannot extract account name from account metadata..."); | 109 | println!("cannot extract account name from account metadata..."); |
| 113 | } else if !offline_mode && user_ref.relays.created_at.eq(&0) { | 110 | } else if !offline_mode && user_ref.relays.created_at.eq(&0) { |
| @@ -615,20 +612,6 @@ async fn get_user_details( | |||
| 615 | #[cfg(not(test))] client: Option<&Client>, | 612 | #[cfg(not(test))] client: Option<&Client>, |
| 616 | git_repo: &Repo, | 613 | git_repo: &Repo, |
| 617 | ) -> Result<UserRef> { | 614 | ) -> Result<UserRef> { |
| 618 | if client.is_some() { | ||
| 619 | println!("searching for profile and relay updates..."); | ||
| 620 | } | ||
| 621 | let database = SQLiteDatabase::open(if std::env::var("NGITTEST").is_err() { | ||
| 622 | create_dir_all(get_dirs()?.config_dir()).context(format!( | ||
| 623 | "cannot create cache directory in: {:?}", | ||
| 624 | get_dirs()?.config_dir() | ||
| 625 | ))?; | ||
| 626 | get_dirs()?.config_dir().join("cache.sqlite") | ||
| 627 | } else { | ||
| 628 | git_repo.get_path()?.join(".git/test-global-cache.sqlite") | ||
| 629 | }) | ||
| 630 | .await?; | ||
| 631 | let mut events: Vec<nostr::Event> = vec![]; | ||
| 632 | let filters = vec![ | 615 | let filters = vec![ |
| 633 | nostr::Filter::default() | 616 | nostr::Filter::default() |
| 634 | .author(*public_key) | 617 | .author(*public_key) |
| @@ -637,54 +620,63 @@ async fn get_user_details( | |||
| 637 | .author(*public_key) | 620 | .author(*public_key) |
| 638 | .kind(Kind::RelayList), | 621 | .kind(Kind::RelayList), |
| 639 | ]; | 622 | ]; |
| 640 | if let Ok(cached_events) = database.query(filters.clone(), Order::Asc).await { | ||
| 641 | for event in cached_events { | ||
| 642 | events.push(event); | ||
| 643 | } | ||
| 644 | } | ||
| 645 | let mut relays_to_search = if let Some(client) = client { | ||
| 646 | client.get_fallback_relays().clone() | ||
| 647 | } else { | ||
| 648 | vec![] | ||
| 649 | }; | ||
| 650 | let mut relays_searched = vec![]; | ||
| 651 | let user_ref = loop { | ||
| 652 | if let Some(client) = client { | ||
| 653 | for event in client | ||
| 654 | .get_events(relays_to_search.clone(), filters.clone()) | ||
| 655 | .await | ||
| 656 | .unwrap_or(vec![]) | ||
| 657 | { | ||
| 658 | let _ = database.save_event(&event).await; | ||
| 659 | events.push(event); | ||
| 660 | } | ||
| 661 | } | ||
| 662 | 623 | ||
| 663 | #[allow(clippy::clone_on_copy)] | 624 | let mut events = get_event_from_global_cache(git_repo.get_path()?, filters.clone()).await?; |
| 664 | let user_ref = UserRef { | ||
| 665 | public_key: public_key.clone(), | ||
| 666 | metadata: extract_user_metadata(public_key, &events)?, | ||
| 667 | relays: extract_user_relays(public_key, &events), | ||
| 668 | }; | ||
| 669 | 625 | ||
| 670 | if client.is_none() { | 626 | if let Some(client) = client { |
| 671 | break user_ref; | 627 | if events.is_empty() { |
| 672 | } | 628 | let term = console::Term::stderr(); |
| 673 | for r in &relays_to_search { | 629 | term.write_line("searching for profile...")?; |
| 674 | relays_searched.push(r.clone()); | 630 | let (_, progress_reporter) = client |
| 631 | .fetch_all(git_repo.get_path()?, &HashSet::new()) | ||
| 632 | .await?; | ||
| 633 | events = get_event_from_global_cache(git_repo.get_path()?, filters).await?; | ||
| 634 | if !events.is_empty() { | ||
| 635 | progress_reporter.clear()?; | ||
| 636 | // term.clear_last_lines(1)?; | ||
| 637 | } | ||
| 675 | } | 638 | } |
| 639 | } | ||
| 676 | 640 | ||
| 677 | relays_to_search = user_ref | 641 | Ok(UserRef { |
| 678 | .relays | 642 | public_key: public_key.to_owned(), |
| 679 | .write() | 643 | metadata: extract_user_metadata(public_key, &events)?, |
| 680 | .iter() | 644 | relays: extract_user_relays(public_key, &events), |
| 681 | .filter(|r| !relays_searched.iter().any(|or| r.eq(&or))) | 645 | }) |
| 682 | .map(std::clone::Clone::clone) | 646 | } |
| 683 | .collect(); | 647 | |
| 684 | if !relays_to_search.is_empty() { | 648 | pub async fn get_logged_in_user_and_relays_from_cache( |
| 685 | continue; | 649 | git_repo_path: &Path, |
| 650 | ) -> Result<(Option<PublicKey>, HashSet<Url>)> { | ||
| 651 | let git_repo = Repo::from_path(&git_repo_path.to_path_buf())?; | ||
| 652 | let current_user = if let Some(npub) = git_repo.get_git_config_item("nostr.npub", None)? { | ||
| 653 | if let Ok(pubic_key) = PublicKey::parse(npub) { | ||
| 654 | Some(pubic_key) | ||
| 655 | } else { | ||
| 656 | None | ||
| 686 | } | 657 | } |
| 687 | break user_ref; | 658 | } else { |
| 659 | None | ||
| 660 | }; | ||
| 661 | let relays = if let Some(current_user) = current_user { | ||
| 662 | extract_user_relays( | ||
| 663 | ¤t_user, | ||
| 664 | &get_event_from_global_cache( | ||
| 665 | git_repo.get_path()?, | ||
| 666 | vec![ | ||
| 667 | nostr::Filter::default() | ||
| 668 | .author((*current_user).into()) | ||
| 669 | .kind(Kind::RelayList), | ||
| 670 | ], | ||
| 671 | ) | ||
| 672 | .await?, | ||
| 673 | ) | ||
| 674 | .write() | ||
| 675 | .iter() | ||
| 676 | .filter_map(|r| Url::parse(r).ok()) | ||
| 677 | .collect::<HashSet<Url>>() | ||
| 678 | } else { | ||
| 679 | HashSet::new() | ||
| 688 | }; | 680 | }; |
| 689 | Ok(user_ref) | 681 | Ok((current_user, relays)) |
| 690 | } | 682 | } |