rustfm_scraper/app/
fetch.rs

1use anyhow::Result;
2use num_format::ToFormattedString;
3
4use crate::app::Fetch;
5use crate::config::Config;
6use crate::models::saved_scrobbles::SavedScrobbles;
7use crate::{files, lastfm, utils};
8
9pub async fn fetch(f: Fetch, config: Config) -> Result<()> {
10    let username = match f.username {
11        Some(username) => username,
12        None => config.default_username,
13    };
14
15    println!("Fetching user profile `{}`...", &username);
16    let user = lastfm::profile::fetch_profile(&username, &config.api_key).await?;
17
18    println!("Username: {}", user.name);
19    println!("Number of scrobbles: {}", user.play_count_formatted());
20
21    let file_format = match f.file_format {
22        Some(format) => format,
23        None => "json".to_string(),
24    };
25
26    let mut saved_tracks = if !f.new_file {
27        match files::load_from_file(&user.name, &file_format) {
28            Ok(saved_scrobbles) => saved_scrobbles,
29            Err(_) => {
30                println!(
31                    "Existing file for `{}` not found. Creating new file...",
32                    &user.name
33                );
34                SavedScrobbles::default()
35            }
36        }
37    } else {
38        println!("Creating new file...");
39        SavedScrobbles::default()
40    };
41
42    let page = match f.page {
43        Some(page) => {
44            if page <= 0 {
45                1
46            } else {
47                page
48            }
49        }
50        None => 1,
51    };
52
53    let limit = match f.limit {
54        Some(limit) => {
55            if limit <= 0 {
56                50
57            } else if limit > 1000 {
58                1000
59            } else {
60                limit
61            }
62        }
63        None => 1000,
64    };
65
66    let from = match f.from {
67        Some(from) => from,
68        None => 0,
69    };
70
71    let to = match f.to {
72        Some(to) => to,
73        None => utils::get_current_unix_timestamp(),
74    };
75
76    let min_timestamp = if f.current_day {
77        use chrono::prelude::*;
78
79        Utc::now().date().and_hms(0, 0, 0).timestamp()
80    } else if !saved_tracks.is_empty() {
81        match saved_tracks.most_recent_scrobble() {
82            Some(track) => track.timestamp_utc + 10,
83            None => 0,
84        }
85    } else {
86        from
87    };
88
89    let new_tracks = lastfm::recently_played::fetch_tracks(
90        &user,
91        &config.api_key,
92        page,
93        limit,
94        min_timestamp,
95        to,
96    )
97    .await?;
98
99    if new_tracks.is_empty() {
100        println!("No new tracks were retrieved from Last.fm");
101        return Ok(());
102    }
103
104    let new_tracks_len = &new_tracks.len();
105    let new_total = if !saved_tracks.is_empty() {
106        match new_tracks_len {
107            1 => println!("Saving one new track to existing file..."),
108            _ => println!(
109                "Saving {} new tracks to existing file...",
110                new_tracks_len.to_formatted_string(&utils::get_locale())
111            ),
112        }
113        files::append_to_file(&new_tracks, &mut saved_tracks, &user.name, &file_format)?
114    } else {
115        println!(
116            "Saving {} tracks to file...",
117            &new_tracks.len().to_formatted_string(&utils::get_locale())
118        );
119        files::save_to_file(&new_tracks, &user.name, &file_format)?
120    };
121
122    if new_total != user.play_count() && !f.current_day {
123        println!(
124            "{} scrobbles were saved to the file, when {} scrobbles were expected.",
125            new_total.to_formatted_string(&utils::get_locale()),
126            user.play_count().to_formatted_string(&utils::get_locale())
127        );
128        println!("Please consider creating a new file with the new file flag. `-n`");
129    } else {
130        match new_total {
131            1 => println!("One scrobble saved"),
132            _ => println!(
133                "{} scrobbles saved.",
134                new_total.to_formatted_string(&utils::get_locale())
135            ),
136        }
137    }
138
139    Ok(())
140}