From 86ecd08b2829b117e1516b289419e62be15610dc Mon Sep 17 00:00:00 2001 From: 0xNF <0xNF@users.noreply.github.com> Date: Thu, 11 Jul 2024 08:54:31 +0900 Subject: [PATCH] feat: Print location of created config file on first run (#87) Co-authored-by: 0xnf <0xnf@winetech.com> --- Cargo.lock | 43 +++++++++++++++++++++++++++++++++++-------- Cargo.toml | 2 +- src/arg.rs | 29 +++++++++++++++++++++++++++++ src/main.rs | 24 +++++++++--------------- src/settings.rs | 28 ++++++++++++++++++++-------- 5 files changed, 94 insertions(+), 32 deletions(-) create mode 100644 src/arg.rs diff --git a/Cargo.lock b/Cargo.lock index 18f0167..2cc8529 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -577,6 +577,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", + "clap_derive", ] [[package]] @@ -591,6 +592,18 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "clap_lex" version = "0.6.0" @@ -1235,6 +1248,12 @@ dependencies = [ "http", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1663,7 +1682,8 @@ dependencies = [ [[package]] name = "librespot" version = "0.4.2" -source = "git+ssh://git@github.com/oSumAtrIX/free-librespot.git#f28fa264528dc85f8f325c18e8461b0f2b43dca1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4c9952ef48968f8184a4a87f8576982426ebe623342d5a28f7d9c4978e4a44" dependencies = [ "base64 0.13.1", "env_logger 0.9.3", @@ -1689,7 +1709,8 @@ dependencies = [ [[package]] name = "librespot-audio" version = "0.4.2" -source = "git+ssh://git@github.com/oSumAtrIX/free-librespot.git#f28fa264528dc85f8f325c18e8461b0f2b43dca1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c176a31355e1ea8e0b9c4ced19df4947bfe4770661c25c142b6fba2365940d9d" dependencies = [ "aes-ctr", "byteorder", @@ -1704,7 +1725,8 @@ dependencies = [ [[package]] name = "librespot-connect" version = "0.4.2" -source = "git+ssh://git@github.com/oSumAtrIX/free-librespot.git#f28fa264528dc85f8f325c18e8461b0f2b43dca1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ffafb6a443e9445ccb3d5d591573b5b1da3c89a9b8846c63ba2c3710210d3ec" dependencies = [ "form_urlencoded", "futures-util", @@ -1724,7 +1746,8 @@ dependencies = [ [[package]] name = "librespot-core" version = "0.4.2" -source = "git+ssh://git@github.com/oSumAtrIX/free-librespot.git#f28fa264528dc85f8f325c18e8461b0f2b43dca1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046349f25888e644bf02d9c5de0164b2a493d29aa4ce18e1ad0b756da9b55d6d" dependencies = [ "aes", "base64 0.13.1", @@ -1764,7 +1787,8 @@ dependencies = [ [[package]] name = "librespot-discovery" version = "0.4.2" -source = "git+ssh://git@github.com/oSumAtrIX/free-librespot.git#f28fa264528dc85f8f325c18e8461b0f2b43dca1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aa877d18f6150364012cb4be5682d62d7c712c88bae2d0d01720fd7c15e2f06" dependencies = [ "aes-ctr", "base64 0.13.1", @@ -1785,7 +1809,8 @@ dependencies = [ [[package]] name = "librespot-metadata" version = "0.4.2" -source = "git+ssh://git@github.com/oSumAtrIX/free-librespot.git#f28fa264528dc85f8f325c18e8461b0f2b43dca1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b80361fcbcb5092056fd47c08c34d5d51b08385d8efb6941c0d3e46d032c21c" dependencies = [ "async-trait", "byteorder", @@ -1798,7 +1823,8 @@ dependencies = [ [[package]] name = "librespot-playback" version = "0.4.2" -source = "git+ssh://git@github.com/oSumAtrIX/free-librespot.git#f28fa264528dc85f8f325c18e8461b0f2b43dca1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5190a0b9bcc7f70ee4196a6b4a1c731d405ca130d4a6fcd4c561cfdde8b7cfb7" dependencies = [ "byteorder", "cpal", @@ -1823,7 +1849,8 @@ dependencies = [ [[package]] name = "librespot-protocol" version = "0.4.2" -source = "git+ssh://git@github.com/oSumAtrIX/free-librespot.git#f28fa264528dc85f8f325c18e8461b0f2b43dca1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d3ac6196ac0ea67bbe039f56d6730a5d8b31502ef9bce0f504ed729dcb39f" dependencies = [ "glob", "protobuf 2.28.0", diff --git a/Cargo.toml b/Cargo.toml index f3cff0c..1e2673f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ build = "build.rs" winres = "0.1" [dependencies] -clap = "4.2.1" +clap = { version = "4.2.1", features = ["cargo", "derive"] } log = "0.4" url = "2.2" protobuf = "3.1" diff --git a/src/arg.rs b/src/arg.rs new file mode 100644 index 0000000..8cba7ac --- /dev/null +++ b/src/arg.rs @@ -0,0 +1,29 @@ +use crate::settings; +use clap::{crate_authors, crate_version, Args as ClapArgs, Command, FromArgMatches, Parser}; + +#[derive(Parser, Debug)] +pub struct Args { + #[arg( + long_help = "Track / Album / Playlist / Artist / Podcast / Episode / Show / User URL, ID or search term\nFor example, \'Ariana Grande\', \'spotify:track:0KjAxsrYSvN0xGuh3cKPxD\', or \'https://open.spotify.com/playlist/37i9dQZF1DXcxvFzl58uP7\'" + )] + pub input: String, +} + +impl Args { + pub fn from_cli() -> Self { + let cli = get_command(); + Self::from_arg_matches(&cli.get_matches()).unwrap() + } +} + +fn get_command() -> Command { + let cli = Command::new(clap::crate_name!()) + .author(crate_authors!()) + .version(crate_version!()) + .about(format!( + "Settings file located at: {}", + settings::get_config_settings_path().to_string_lossy() + )); + let cli = Args::augment_args(cli); + cli +} diff --git a/src/main.rs b/src/main.rs index cb8bc2a..645194d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate log; +mod arg; mod converter; mod downloader; mod error; @@ -8,6 +9,7 @@ mod settings; mod spotify; mod tag; +use arg::Args; use async_std::task; use colored::Colorize; use downloader::{DownloadState, Downloader}; @@ -35,6 +37,8 @@ async fn main() { async fn start() { env_logger::init(); + let args = Args::from_cli(); + let settings = match Settings::load().await { Ok(settings) => { println!( @@ -52,10 +56,11 @@ async fn start() { ); let default_settings = Settings::new("username", "password", "client_id", "secret"); match default_settings.save().await { - Ok(_) => { + Ok(path) => { println!( - "{}", - "..but default settings have been created successfully. Edit them and run the program again.".green() + "{}{}", + "..but default settings have been created successfully. Edit them and run the program again.\nFind the settings file at: ".green(), + path.to_string_lossy() ); } Err(e) => { @@ -70,15 +75,6 @@ async fn start() { } }; - let args: Vec = env::args().collect(); - if args.len() <= 1 { - println!( - "Usage:\n{} | | | | ", - args[0] - ); - return; - } - let spotify = match Spotify::new( &settings.username, &settings.password, @@ -101,10 +97,8 @@ async fn start() { } }; - let input = args[1..].join(" "); - let downloader = Downloader::new(settings.downloader, spotify); - match downloader.handle_input(&input).await { + match downloader.handle_input(&args.input).await { Ok(search_results) => { if let Some(search_results) = search_results { print!("{esc}[2J{esc}[1;1H", esc = 27 as char); diff --git a/src/settings.rs b/src/settings.rs index d66d815..8006c57 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -40,6 +40,15 @@ fn get_config_folder_path() -> PathBuf { Path::new(&env::var("APPDATA").unwrap()).join("down_on_spot") } +/// Returns the full path to the Settings json +/// +/// Windows: `%APPDATA%\down_on_spot\settings.json` +/// +/// Unix-like: `~/.config/down_on_spot/settings.json` +pub fn get_config_settings_path() -> PathBuf { + get_config_folder_path().join("settings.json") +} + impl Settings { // Create new instance pub fn new(username: &str, password: &str, client_id: &str, client_secret: &str) -> Settings { @@ -53,25 +62,28 @@ impl Settings { } } - // Save config - pub async fn save(&self) -> Result<(), SpotifyError> { + /// Save config + /// + /// Returns the path of the written file if successful + pub async fn save(&self) -> Result { // Get and create config folder path, generate config file path - let config_folder_path = get_config_folder_path(); + let config_file_path = get_config_settings_path(); + let config_folder_path = config_file_path + .parent() + .expect("Configuration file path should have a parent component"); create_dir_all(&config_folder_path).await?; - let config_file_path = config_folder_path.join("settings.json"); // Serialize the settings to a json file let data = serde_json::to_string_pretty(self)?; - let mut file = File::create(config_file_path).await?; + let mut file = File::create(&config_file_path).await?; file.write_all(data.as_bytes()).await?; - Ok(()) + Ok(config_file_path) } // Load config pub async fn load() -> Result { // Get config folder path, generate config file path - let config_folder_path = get_config_folder_path(); - let config_file_path = config_folder_path.join("settings.json"); + let config_file_path = get_config_settings_path(); // Deserialize the settings from a json file let mut file = File::open(config_file_path).await?;