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 | |
| 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
| -rw-r--r-- | src/client.rs | 156 | ||||
| -rw-r--r-- | src/git.rs | 8 | ||||
| -rw-r--r-- | src/login.rs | 124 | ||||
| -rw-r--r-- | src/sub_commands/fetch.rs | 11 | ||||
| -rw-r--r-- | tests/init.rs | 2 | ||||
| -rw-r--r-- | tests/login.rs | 20 | ||||
| -rw-r--r-- | tests/push.rs | 4 | ||||
| -rw-r--r-- | tests/send.rs | 6 |
8 files changed, 180 insertions, 151 deletions
diff --git a/src/client.rs b/src/client.rs index 835d69e..b6e93d6 100644 --- a/src/client.rs +++ b/src/client.rs | |||
| @@ -35,6 +35,7 @@ use nostr_sqlite::SQLiteDatabase; | |||
| 35 | 35 | ||
| 36 | use crate::{ | 36 | use crate::{ |
| 37 | config::get_dirs, | 37 | config::get_dirs, |
| 38 | login::get_logged_in_user_and_relays_from_cache, | ||
| 38 | repo_ref::{RepoRef, REPO_REF_KIND}, | 39 | repo_ref::{RepoRef, REPO_REF_KIND}, |
| 39 | sub_commands::{ | 40 | sub_commands::{ |
| 40 | list::status_kinds, | 41 | list::status_kinds, |
| @@ -77,7 +78,7 @@ pub trait Connect { | |||
| 77 | &self, | 78 | &self, |
| 78 | git_repo_path: &Path, | 79 | git_repo_path: &Path, |
| 79 | repo_coordinates: &HashSet<Coordinate>, | 80 | repo_coordinates: &HashSet<Coordinate>, |
| 80 | ) -> Result<FetchReport>; | 81 | ) -> Result<(Vec<Result<FetchReport>>, MultiProgress)>; |
| 81 | async fn fetch_all_from_relay( | 82 | async fn fetch_all_from_relay( |
| 82 | &self, | 83 | &self, |
| 83 | git_repo_path: &Path, | 84 | git_repo_path: &Path, |
| @@ -287,8 +288,7 @@ impl Connect for Client { | |||
| 287 | &self, | 288 | &self, |
| 288 | git_repo_path: &Path, | 289 | git_repo_path: &Path, |
| 289 | repo_coordinates: &HashSet<Coordinate>, | 290 | repo_coordinates: &HashSet<Coordinate>, |
| 290 | ) -> Result<FetchReport> { | 291 | ) -> Result<(Vec<Result<FetchReport>>, MultiProgress)> { |
| 291 | println!("fetching updates..."); | ||
| 292 | let fallback_relays = &self | 292 | let fallback_relays = &self |
| 293 | .fallback_relays | 293 | .fallback_relays |
| 294 | .iter() | 294 | .iter() |
| @@ -305,6 +305,23 @@ impl Connect for Client { | |||
| 305 | let mut relay_reports: Vec<Result<FetchReport>> = vec![]; | 305 | let mut relay_reports: Vec<Result<FetchReport>> = vec![]; |
| 306 | 306 | ||
| 307 | loop { | 307 | loop { |
| 308 | let relays = request | ||
| 309 | .relays | ||
| 310 | .union(&request.current_user_write_relays) | ||
| 311 | // don't look for events on blaster | ||
| 312 | .filter(|&r| !r.as_str().contains("nostr.mutinywallet.com")) | ||
| 313 | .cloned() | ||
| 314 | .collect::<HashSet<Url>>() | ||
| 315 | .difference(&processed_relays) | ||
| 316 | .cloned() | ||
| 317 | .collect::<HashSet<Url>>(); | ||
| 318 | if relays.is_empty() { | ||
| 319 | break; | ||
| 320 | } | ||
| 321 | let only_user_relays = request | ||
| 322 | .current_user_write_relays | ||
| 323 | .difference(&request.relays) | ||
| 324 | .collect::<HashSet<&Url>>(); | ||
| 308 | for relay in &request.relays { | 325 | for relay in &request.relays { |
| 309 | self.client | 326 | self.client |
| 310 | .add_relay(relay.as_str()) | 327 | .add_relay(relay.as_str()) |
| @@ -314,14 +331,26 @@ impl Connect for Client { | |||
| 314 | 331 | ||
| 315 | let dim = Style::new().color256(247); | 332 | let dim = Style::new().color256(247); |
| 316 | 333 | ||
| 317 | let futures: Vec<_> = request | 334 | let futures: Vec<_> = relays |
| 318 | .relays | ||
| 319 | .iter() | 335 | .iter() |
| 320 | // don't look for events on blaster | 336 | .map(|r| { |
| 321 | .filter(|r| !r.as_str().contains("nostr.mutinywallet.com")) | 337 | if only_user_relays.contains(r) { |
| 322 | .map(|r| FetchRequest { | 338 | // if user write relay isn't a repo relay, just filter for user profile |
| 323 | selected_relay: Some(r.clone()), | 339 | FetchRequest { |
| 324 | ..request.clone() | 340 | selected_relay: Some(r.to_owned()), |
| 341 | repo_coordinates: vec![], | ||
| 342 | proposals: HashSet::new(), | ||
| 343 | missing_contributor_profiles: HashSet::from_iter(vec![ | ||
| 344 | request.current_user.unwrap(), | ||
| 345 | ]), | ||
| 346 | ..request.clone() | ||
| 347 | } | ||
| 348 | } else { | ||
| 349 | FetchRequest { | ||
| 350 | selected_relay: Some(r.to_owned()), | ||
| 351 | ..request.clone() | ||
| 352 | } | ||
| 353 | } | ||
| 325 | }) | 354 | }) |
| 326 | .map(|request| async { | 355 | .map(|request| async { |
| 327 | let relay_column_width = request.relay_column_width; | 356 | let relay_column_width = request.relay_column_width; |
| @@ -381,31 +410,20 @@ impl Connect for Client { | |||
| 381 | { | 410 | { |
| 382 | relay_reports.push(report); | 411 | relay_reports.push(report); |
| 383 | } | 412 | } |
| 384 | 413 | processed_relays.extend(relays.clone()); | |
| 385 | for relay in &request.relays { | ||
| 386 | processed_relays.insert(relay.clone()); | ||
| 387 | } | ||
| 388 | 414 | ||
| 389 | if let Ok(repo_ref) = get_repo_ref_from_cache(git_repo_path, repo_coordinates).await { | 415 | if let Ok(repo_ref) = get_repo_ref_from_cache(git_repo_path, repo_coordinates).await { |
| 390 | request.relays = repo_ref | 416 | request.relays = repo_ref |
| 391 | .relays | 417 | .relays |
| 392 | .iter() | 418 | .iter() |
| 393 | .filter_map(|r| Url::parse(r).ok()) | 419 | .filter_map(|r| Url::parse(r).ok()) |
| 394 | .filter(|r| !processed_relays.contains(r)) | ||
| 395 | .collect(); | 420 | .collect(); |
| 396 | if request.relays.is_empty() { | ||
| 397 | break; | ||
| 398 | } | ||
| 399 | } | 421 | } |
| 422 | let (_, current_user_write_relays) = | ||
| 423 | get_logged_in_user_and_relays_from_cache(git_repo_path).await?; | ||
| 424 | request.current_user_write_relays = current_user_write_relays; | ||
| 400 | } | 425 | } |
| 401 | let report = consolidate_fetch_reports(relay_reports); | 426 | Ok((relay_reports, progress_reporter)) |
| 402 | |||
| 403 | if report.to_string().is_empty() { | ||
| 404 | println!("no updates"); | ||
| 405 | } else { | ||
| 406 | println!("updates: {report}"); | ||
| 407 | } | ||
| 408 | Ok(report) | ||
| 409 | } | 427 | } |
| 410 | 428 | ||
| 411 | async fn fetch_all_from_relay( | 429 | async fn fetch_all_from_relay( |
| @@ -420,6 +438,9 @@ impl Connect for Client { | |||
| 420 | } | 438 | } |
| 421 | let mut fresh_proposal_roots = request.proposals.clone(); | 439 | let mut fresh_proposal_roots = request.proposals.clone(); |
| 422 | let mut fresh_contributors = request.missing_contributor_profiles.clone(); | 440 | let mut fresh_contributors = request.missing_contributor_profiles.clone(); |
| 441 | if let Some(user) = request.current_user { | ||
| 442 | fresh_contributors.insert(user); | ||
| 443 | } | ||
| 423 | 444 | ||
| 424 | let mut report = FetchReport::default(); | 445 | let mut report = FetchReport::default(); |
| 425 | 446 | ||
| @@ -486,9 +507,9 @@ impl Connect for Client { | |||
| 486 | "{: <relay_column_width$} {}", | 507 | "{: <relay_column_width$} {}", |
| 487 | relay_url, | 508 | relay_url, |
| 488 | if report.to_string().is_empty() { | 509 | if report.to_string().is_empty() { |
| 489 | "no updates".to_string() | 510 | "no new events".to_string() |
| 490 | } else { | 511 | } else { |
| 491 | format!("updates: {report}") | 512 | format!("new events: {report}") |
| 492 | }, | 513 | }, |
| 493 | )) | 514 | )) |
| 494 | .to_string(), | 515 | .to_string(), |
| @@ -761,37 +782,6 @@ async fn create_relays_request( | |||
| 761 | ) -> Result<FetchRequest> { | 782 | ) -> Result<FetchRequest> { |
| 762 | let repo_ref = get_repo_ref_from_cache(git_repo_path, repo_coordinates).await; | 783 | let repo_ref = get_repo_ref_from_cache(git_repo_path, repo_coordinates).await; |
| 763 | 784 | ||
| 764 | let relays = { | ||
| 765 | let mut relays = fallback_relays; | ||
| 766 | if let Ok(repo_ref) = &repo_ref { | ||
| 767 | for r in &repo_ref.relays { | ||
| 768 | if let Ok(url) = Url::parse(r) { | ||
| 769 | relays.insert(url); | ||
| 770 | } | ||
| 771 | } | ||
| 772 | } | ||
| 773 | relays | ||
| 774 | }; | ||
| 775 | |||
| 776 | let relay_column_width = relays | ||
| 777 | .iter() | ||
| 778 | .reduce(|a, r| { | ||
| 779 | if r.to_string() | ||
| 780 | .chars() | ||
| 781 | .count() | ||
| 782 | .gt(&a.to_string().chars().count()) | ||
| 783 | { | ||
| 784 | r | ||
| 785 | } else { | ||
| 786 | a | ||
| 787 | } | ||
| 788 | }) | ||
| 789 | .unwrap() | ||
| 790 | .to_string() | ||
| 791 | .chars() | ||
| 792 | .count() | ||
| 793 | + 2; | ||
| 794 | |||
| 795 | let repo_coordinates = if let Ok(repo_ref) = &repo_ref { | 785 | let repo_coordinates = if let Ok(repo_ref) = &repo_ref { |
| 796 | repo_ref.coordinates() | 786 | repo_ref.coordinates() |
| 797 | } else { | 787 | } else { |
| @@ -802,7 +792,7 @@ async fn create_relays_request( | |||
| 802 | let mut missing_contributor_profiles: HashSet<PublicKey> = HashSet::new(); | 792 | let mut missing_contributor_profiles: HashSet<PublicKey> = HashSet::new(); |
| 803 | let mut contributors: HashSet<PublicKey> = HashSet::new(); | 793 | let mut contributors: HashSet<PublicKey> = HashSet::new(); |
| 804 | 794 | ||
| 805 | { | 795 | if !repo_coordinates.is_empty() { |
| 806 | if let Ok(repo_ref) = &repo_ref { | 796 | if let Ok(repo_ref) = &repo_ref { |
| 807 | for m in &repo_ref.maintainers { | 797 | for m in &repo_ref.maintainers { |
| 808 | contributors.insert(m.to_owned()); | 798 | contributors.insert(m.to_owned()); |
| @@ -848,6 +838,12 @@ async fn create_relays_request( | |||
| 848 | } | 838 | } |
| 849 | } | 839 | } |
| 850 | 840 | ||
| 841 | let (current_user, current_user_write_relays) = | ||
| 842 | get_logged_in_user_and_relays_from_cache(git_repo_path).await?; | ||
| 843 | if let Some(current_user) = current_user { | ||
| 844 | missing_contributor_profiles.insert(current_user); | ||
| 845 | } | ||
| 846 | |||
| 851 | let existing_events: HashSet<EventId> = { | 847 | let existing_events: HashSet<EventId> = { |
| 852 | let mut existing_events: HashSet<EventId> = HashSet::new(); | 848 | let mut existing_events: HashSet<EventId> = HashSet::new(); |
| 853 | for filter in | 849 | for filter in |
| @@ -863,6 +859,38 @@ async fn create_relays_request( | |||
| 863 | } | 859 | } |
| 864 | existing_events | 860 | existing_events |
| 865 | }; | 861 | }; |
| 862 | |||
| 863 | let relays = { | ||
| 864 | let mut relays = fallback_relays; | ||
| 865 | if let Ok(repo_ref) = &repo_ref { | ||
| 866 | for r in &repo_ref.relays { | ||
| 867 | if let Ok(url) = Url::parse(r) { | ||
| 868 | relays.insert(url); | ||
| 869 | } | ||
| 870 | } | ||
| 871 | } | ||
| 872 | relays | ||
| 873 | }; | ||
| 874 | |||
| 875 | let relay_column_width = relays | ||
| 876 | .union(¤t_user_write_relays) | ||
| 877 | .reduce(|a, r| { | ||
| 878 | if r.to_string() | ||
| 879 | .chars() | ||
| 880 | .count() | ||
| 881 | .gt(&a.to_string().chars().count()) | ||
| 882 | { | ||
| 883 | r | ||
| 884 | } else { | ||
| 885 | a | ||
| 886 | } | ||
| 887 | }) | ||
| 888 | .unwrap() | ||
| 889 | .to_string() | ||
| 890 | .chars() | ||
| 891 | .count() | ||
| 892 | + 2; | ||
| 893 | |||
| 866 | Ok(FetchRequest { | 894 | Ok(FetchRequest { |
| 867 | selected_relay: None, | 895 | selected_relay: None, |
| 868 | relays, | 896 | relays, |
| @@ -876,6 +904,8 @@ async fn create_relays_request( | |||
| 876 | contributors, | 904 | contributors, |
| 877 | missing_contributor_profiles, | 905 | missing_contributor_profiles, |
| 878 | existing_events, | 906 | existing_events, |
| 907 | current_user, | ||
| 908 | current_user_write_relays, | ||
| 879 | }) | 909 | }) |
| 880 | } | 910 | } |
| 881 | 911 | ||
| @@ -972,7 +1002,7 @@ async fn process_fetched_events( | |||
| 972 | Ok(()) | 1002 | Ok(()) |
| 973 | } | 1003 | } |
| 974 | 1004 | ||
| 975 | fn consolidate_fetch_reports(reports: Vec<Result<FetchReport>>) -> FetchReport { | 1005 | pub fn consolidate_fetch_reports(reports: Vec<Result<FetchReport>>) -> FetchReport { |
| 976 | let mut report = FetchReport::default(); | 1006 | let mut report = FetchReport::default(); |
| 977 | for relay_report in reports.into_iter().flatten() { | 1007 | for relay_report in reports.into_iter().flatten() { |
| 978 | for c in relay_report.repo_coordinates { | 1008 | for c in relay_report.repo_coordinates { |
| @@ -1136,7 +1166,7 @@ impl Display for FetchReport { | |||
| 1136 | } | 1166 | } |
| 1137 | if !self.contributor_profiles.is_empty() { | 1167 | if !self.contributor_profiles.is_empty() { |
| 1138 | display_items.push(format!( | 1168 | display_items.push(format!( |
| 1139 | "{} contributor profile{}", | 1169 | "{} user profile{}", |
| 1140 | self.contributor_profiles.len(), | 1170 | self.contributor_profiles.len(), |
| 1141 | if self.contributor_profiles.len() > 1 { | 1171 | if self.contributor_profiles.len() > 1 { |
| 1142 | "s" | 1172 | "s" |
| @@ -1159,4 +1189,6 @@ pub struct FetchRequest { | |||
| 1159 | contributors: HashSet<PublicKey>, | 1189 | contributors: HashSet<PublicKey>, |
| 1160 | missing_contributor_profiles: HashSet<PublicKey>, | 1190 | missing_contributor_profiles: HashSet<PublicKey>, |
| 1161 | existing_events: HashSet<EventId>, | 1191 | existing_events: HashSet<EventId>, |
| 1192 | current_user: Option<PublicKey>, | ||
| 1193 | current_user_write_relays: HashSet<Url>, | ||
| 1162 | } | 1194 | } |
| @@ -1,6 +1,7 @@ | |||
| 1 | #[cfg(test)] | 1 | use std::{ |
| 2 | use std::path::PathBuf; | 2 | env::current_dir, |
| 3 | use std::{env::current_dir, path::Path}; | 3 | path::{Path, PathBuf}, |
| 4 | }; | ||
| 4 | 5 | ||
| 5 | use anyhow::{bail, Context, Result}; | 6 | use anyhow::{bail, Context, Result}; |
| 6 | use git2::{DiffOptions, Oid, Revwalk}; | 7 | use git2::{DiffOptions, Oid, Revwalk}; |
| @@ -18,7 +19,6 @@ impl Repo { | |||
| 18 | git_repo: git2::Repository::discover(current_dir()?)?, | 19 | git_repo: git2::Repository::discover(current_dir()?)?, |
| 19 | }) | 20 | }) |
| 20 | } | 21 | } |
| 21 | #[cfg(test)] | ||
| 22 | pub fn from_path(path: &PathBuf) -> Result<Self> { | 22 | pub fn from_path(path: &PathBuf) -> Result<Self> { |
| 23 | Ok(Self { | 23 | Ok(Self { |
| 24 | git_repo: git2::Repository::open(path)?, | 24 | git_repo: git2::Repository::open(path)?, |
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 | } |
diff --git a/src/sub_commands/fetch.rs b/src/sub_commands/fetch.rs index 07fd6f9..5a6850c 100644 --- a/src/sub_commands/fetch.rs +++ b/src/sub_commands/fetch.rs | |||
| @@ -9,7 +9,7 @@ use crate::client::Client; | |||
| 9 | #[cfg(test)] | 9 | #[cfg(test)] |
| 10 | use crate::client::MockConnect; | 10 | use crate::client::MockConnect; |
| 11 | use crate::{ | 11 | use crate::{ |
| 12 | client::Connect, | 12 | client::{consolidate_fetch_reports, Connect}, |
| 13 | git::{Repo, RepoActions}, | 13 | git::{Repo, RepoActions}, |
| 14 | repo_ref::get_repo_coordinates, | 14 | repo_ref::get_repo_coordinates, |
| 15 | Cli, | 15 | Cli, |
| @@ -38,9 +38,16 @@ pub async fn launch(args: &Cli, command_args: &SubCommandArgs) -> Result<()> { | |||
| 38 | } | 38 | } |
| 39 | repo_coordinates | 39 | repo_coordinates |
| 40 | }; | 40 | }; |
| 41 | client | 41 | println!("fetching updates..."); |
| 42 | let (relay_reports, _) = client | ||
| 42 | .fetch_all(git_repo.get_path()?, &repo_coordinates) | 43 | .fetch_all(git_repo.get_path()?, &repo_coordinates) |
| 43 | .await?; | 44 | .await?; |
| 45 | let report = consolidate_fetch_reports(relay_reports); | ||
| 46 | if report.to_string().is_empty() { | ||
| 47 | println!("no updates"); | ||
| 48 | } else { | ||
| 49 | println!("updates: {report}"); | ||
| 50 | } | ||
| 44 | client.disconnect().await?; | 51 | client.disconnect().await?; |
| 45 | Ok(()) | 52 | Ok(()) |
| 46 | } | 53 | } |
diff --git a/tests/init.rs b/tests/init.rs index c7f26c4..d7ba164 100644 --- a/tests/init.rs +++ b/tests/init.rs | |||
| @@ -3,7 +3,7 @@ use serial_test::serial; | |||
| 3 | use test_utils::{git::GitTestRepo, *}; | 3 | use test_utils::{git::GitTestRepo, *}; |
| 4 | 4 | ||
| 5 | fn expect_msgs_first(p: &mut CliTester) -> Result<()> { | 5 | fn expect_msgs_first(p: &mut CliTester) -> Result<()> { |
| 6 | p.expect("searching for profile and relay updates...\r\n")?; | 6 | p.expect("searching for profile...\r\n")?; |
| 7 | p.expect("logged in as fred\r\n")?; | 7 | p.expect("logged in as fred\r\n")?; |
| 8 | // // p.expect("searching for existing claims on repository...\r\n")?; | 8 | // // p.expect("searching for existing claims on repository...\r\n")?; |
| 9 | p.expect("publishing repostory reference...\r\n")?; | 9 | p.expect("publishing repostory reference...\r\n")?; |
diff --git a/tests/login.rs b/tests/login.rs index 4cc2dbe..3bcfbf9 100644 --- a/tests/login.rs +++ b/tests/login.rs | |||
| @@ -73,7 +73,7 @@ mod with_relays { | |||
| 73 | 73 | ||
| 74 | p.expect("saved login details to local git config\r\n")?; | 74 | p.expect("saved login details to local git config\r\n")?; |
| 75 | 75 | ||
| 76 | p.expect("searching for profile and relay updates...\r\n")?; | 76 | p.expect("searching for profile...\r\n")?; |
| 77 | 77 | ||
| 78 | p.expect_end_with("logged in as fred\r\n")?; | 78 | p.expect_end_with("logged in as fred\r\n")?; |
| 79 | for p in [51, 52] { | 79 | for p in [51, 52] { |
| @@ -113,7 +113,7 @@ mod with_relays { | |||
| 113 | 113 | ||
| 114 | p.expect("saved login details to local git config\r\n")?; | 114 | p.expect("saved login details to local git config\r\n")?; |
| 115 | 115 | ||
| 116 | p.expect("searching for profile and relay updates...\r\n")?; | 116 | p.expect("searching for profile...\r\n")?; |
| 117 | 117 | ||
| 118 | p.expect("cannot extract account name from account metadata...\r\n")?; | 118 | p.expect("cannot extract account name from account metadata...\r\n")?; |
| 119 | 119 | ||
| @@ -422,7 +422,7 @@ mod with_relays { | |||
| 422 | 422 | ||
| 423 | p.expect("saved login details to local git config\r\n")?; | 423 | p.expect("saved login details to local git config\r\n")?; |
| 424 | 424 | ||
| 425 | p.expect("searching for profile and relay updates...\r\n")?; | 425 | p.expect("searching for profile...\r\n")?; |
| 426 | 426 | ||
| 427 | p.expect_end_with("logged in as fred\r\n")?; | 427 | p.expect_end_with("logged in as fred\r\n")?; |
| 428 | for p in [51, 52] { | 428 | for p in [51, 52] { |
| @@ -489,7 +489,7 @@ mod with_relays { | |||
| 489 | ["login", "--password", TEST_PASSWORD], | 489 | ["login", "--password", TEST_PASSWORD], |
| 490 | ); | 490 | ); |
| 491 | 491 | ||
| 492 | p.expect("searching for profile and relay updates...\r\n")?; | 492 | p.expect("searching for profile...\r\n")?; |
| 493 | 493 | ||
| 494 | p.expect_end_with("logged in as fred\r\n")?; | 494 | p.expect_end_with("logged in as fred\r\n")?; |
| 495 | for p in [51, 52] { | 495 | for p in [51, 52] { |
| @@ -551,7 +551,7 @@ mod with_relays { | |||
| 551 | 551 | ||
| 552 | p.expect("saved login details to local git config\r\n")?; | 552 | p.expect("saved login details to local git config\r\n")?; |
| 553 | 553 | ||
| 554 | p.expect("searching for profile and relay updates...\r\n")?; | 554 | p.expect("searching for profile...\r\n")?; |
| 555 | 555 | ||
| 556 | p.expect_end_with("logged in as fred\r\n")?; | 556 | p.expect_end_with("logged in as fred\r\n")?; |
| 557 | for p in [51, 52] { | 557 | for p in [51, 52] { |
| @@ -602,9 +602,9 @@ mod with_relays { | |||
| 602 | 602 | ||
| 603 | p.expect("saved login details to local git config\r\n")?; | 603 | p.expect("saved login details to local git config\r\n")?; |
| 604 | 604 | ||
| 605 | p.expect("searching for profile and relay updates...\r\n")?; | 605 | p.expect("searching for profile...\r\n")?; |
| 606 | 606 | ||
| 607 | p.expect("cannot find your account metadata (name, etc) on relays\r\n")?; | 607 | p.expect("cannot find profile...\r\n")?; |
| 608 | 608 | ||
| 609 | p.expect_end_with(format!("logged in as {TEST_KEY_1_NPUB}\r\n").as_str())?; | 609 | p.expect_end_with(format!("logged in as {TEST_KEY_1_NPUB}\r\n").as_str())?; |
| 610 | for p in [51, 52] { | 610 | for p in [51, 52] { |
| @@ -665,7 +665,7 @@ mod with_relays { | |||
| 665 | 665 | ||
| 666 | p.expect("saved login details to local git config\r\n")?; | 666 | p.expect("saved login details to local git config\r\n")?; |
| 667 | 667 | ||
| 668 | p.expect("searching for profile and relay updates...\r\n")?; | 668 | p.expect("searching for profile...\r\n")?; |
| 669 | 669 | ||
| 670 | p.expect("cannot find your relay list. consider using another nostr client to create one to enhance your nostr experience.\r\n")?; | 670 | p.expect("cannot find your relay list. consider using another nostr client to create one to enhance your nostr experience.\r\n")?; |
| 671 | 671 | ||
| @@ -743,8 +743,6 @@ mod with_relays { | |||
| 743 | ["login", "--password", TEST_PASSWORD], | 743 | ["login", "--password", TEST_PASSWORD], |
| 744 | ); | 744 | ); |
| 745 | 745 | ||
| 746 | p.expect("searching for profile and relay updates...\r\n")?; | ||
| 747 | |||
| 748 | p.expect_end_eventually_with("logged in as fred\r\n")?; | 746 | p.expect_end_eventually_with("logged in as fred\r\n")?; |
| 749 | 747 | ||
| 750 | Ok(()) | 748 | Ok(()) |
| @@ -790,7 +788,7 @@ mod with_relays { | |||
| 790 | 788 | ||
| 791 | p.expect("saved login details to local git config\r\n")?; | 789 | p.expect("saved login details to local git config\r\n")?; |
| 792 | 790 | ||
| 793 | p.expect("searching for profile and relay updates...\r\n")?; | 791 | p.expect("searching for profile...\r\n")?; |
| 794 | 792 | ||
| 795 | p.expect_end_with("logged in as fred\r\n")?; | 793 | p.expect_end_with("logged in as fred\r\n")?; |
| 796 | for p in [51, 52, 53, 55] { | 794 | for p in [51, 52, 53, 55] { |
diff --git a/tests/push.rs b/tests/push.rs index fe711c1..65c92e9 100644 --- a/tests/push.rs +++ b/tests/push.rs | |||
| @@ -346,7 +346,7 @@ mod when_branch_is_checked_out { | |||
| 346 | p.expect( | 346 | p.expect( |
| 347 | "1 commits ahead. preparing to create creating patch events.\r\n", | 347 | "1 commits ahead. preparing to create creating patch events.\r\n", |
| 348 | )?; | 348 | )?; |
| 349 | p.expect("searching for profile and relay updates...\r\n")?; | 349 | p.expect("searching for profile...\r\n")?; |
| 350 | p.expect("logged in as fred\r\n")?; | 350 | p.expect("logged in as fred\r\n")?; |
| 351 | p.expect("pushing 1 commits\r\n")?; | 351 | p.expect("pushing 1 commits\r\n")?; |
| 352 | 352 | ||
| @@ -591,7 +591,7 @@ mod when_branch_is_checked_out { | |||
| 591 | p.expect("creating proposal from 2 commits:\r\n")?; | 591 | p.expect("creating proposal from 2 commits:\r\n")?; |
| 592 | p.expect("355bdf1 add a4.md\r\n")?; | 592 | p.expect("355bdf1 add a4.md\r\n")?; |
| 593 | p.expect("dbd1115 add a3.md\r\n")?; | 593 | p.expect("dbd1115 add a3.md\r\n")?; |
| 594 | p.expect("searching for profile and relay updates...\r\n")?; | 594 | p.expect("searching for profile...\r\n")?; |
| 595 | p.expect("logged in as fred\r\n")?; | 595 | p.expect("logged in as fred\r\n")?; |
| 596 | p.expect("posting 2 patches without a covering letter...\r\n")?; | 596 | p.expect("posting 2 patches without a covering letter...\r\n")?; |
| 597 | 597 | ||
diff --git a/tests/send.rs b/tests/send.rs index 0169c82..87bd54f 100644 --- a/tests/send.rs +++ b/tests/send.rs | |||
| @@ -133,7 +133,7 @@ fn expect_msgs_first(p: &mut CliTester, include_cover_letter: bool) -> Result<() | |||
| 133 | p.expect("creating proposal from 2 commits:\r\n")?; | 133 | p.expect("creating proposal from 2 commits:\r\n")?; |
| 134 | p.expect("fe973a8 add t4.md\r\n")?; | 134 | p.expect("fe973a8 add t4.md\r\n")?; |
| 135 | p.expect("232efb3 add t3.md\r\n")?; | 135 | p.expect("232efb3 add t3.md\r\n")?; |
| 136 | p.expect("searching for profile and relay updates...\r\n")?; | 136 | p.expect("searching for profile...\r\n")?; |
| 137 | p.expect("logged in as fred\r\n")?; | 137 | p.expect("logged in as fred\r\n")?; |
| 138 | p.expect(format!( | 138 | p.expect(format!( |
| 139 | "posting 2 patches {} a covering letter...\r\n", | 139 | "posting 2 patches {} a covering letter...\r\n", |
| @@ -1173,7 +1173,7 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main { | |||
| 1173 | p.expect("creating proposal from 2 commits:\r\n")?; | 1173 | p.expect("creating proposal from 2 commits:\r\n")?; |
| 1174 | p.expect("fe973a8 add t4.md\r\n")?; | 1174 | p.expect("fe973a8 add t4.md\r\n")?; |
| 1175 | p.expect("232efb3 add t3.md\r\n")?; | 1175 | p.expect("232efb3 add t3.md\r\n")?; |
| 1176 | p.expect("searching for profile and relay updates...\r\n")?; | 1176 | p.expect("searching for profile...\r\n")?; |
| 1177 | p.expect("logged in as fred\r\n")?; | 1177 | p.expect("logged in as fred\r\n")?; |
| 1178 | p.expect("posting 2 patches without a covering letter...\r\n")?; | 1178 | p.expect("posting 2 patches without a covering letter...\r\n")?; |
| 1179 | Ok(()) | 1179 | Ok(()) |
| @@ -1367,7 +1367,7 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let | |||
| 1367 | p.expect("creating proposal from 2 commits:\r\n")?; | 1367 | p.expect("creating proposal from 2 commits:\r\n")?; |
| 1368 | p.expect("fe973a8 add t4.md\r\n")?; | 1368 | p.expect("fe973a8 add t4.md\r\n")?; |
| 1369 | p.expect("232efb3 add t3.md\r\n")?; | 1369 | p.expect("232efb3 add t3.md\r\n")?; |
| 1370 | p.expect("searching for profile and relay updates...\r\n")?; | 1370 | p.expect("searching for profile...\r\n")?; |
| 1371 | p.expect("logged in as fred\r\n")?; | 1371 | p.expect("logged in as fred\r\n")?; |
| 1372 | p.expect(format!( | 1372 | p.expect(format!( |
| 1373 | "posting 2 patches {} a covering letter...\r\n", | 1373 | "posting 2 patches {} a covering letter...\r\n", |