diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-07-17 10:53:20 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-07-17 10:53:20 +0100 |
| commit | 43a445963968dac7da190b56f7c89ac0ff1f6abd (patch) | |
| tree | 3c58f17c53de3f6ccc888323d677da12402a7891 /src/login.rs | |
| parent | 65d5daf6e42683ef116369b4f6a0f99d6971667b (diff) | |
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
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 | } |