upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/login.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/login.rs')
-rw-r--r--src/login.rs124
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 @@
1use std::{fs::create_dir_all, str::FromStr, time::Duration}; 1use std::{collections::HashSet, path::Path, str::FromStr, time::Duration};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{bail, Context, Result};
4use nostr::{ 4use nostr::{
5 nips::{nip05::get_nip46, nip46::NostrConnectURI}, 5 nips::{nip05::get_nip46, nip46::NostrConnectURI},
6 PublicKey, 6 PublicKey,
7}; 7};
8use nostr_database::Order;
9use nostr_sdk::{ 8use 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};
13use nostr_signer::Nip46Signer; 11use nostr_signer::Nip46Signer;
14use nostr_sqlite::SQLiteDatabase;
15 12
16#[cfg(not(test))] 13#[cfg(not(test))]
17use crate::client::Client; 14use 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
108fn print_logged_in_as(user_ref: &UserRef, offline_mode: bool) -> Result<()> { 105fn 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() { 648pub 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 &current_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}