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:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-07-17 10:53:20 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2024-07-17 10:53:20 +0100
commit43a445963968dac7da190b56f7c89ac0ff1f6abd (patch)
tree3c58f17c53de3f6ccc888323d677da12402a7891 /src/login.rs
parent65d5daf6e42683ef116369b4f6a0f99d6971667b (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.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}