feat: Print location of created config file on first run (#87)

Co-authored-by: 0xnf <0xnf@winetech.com>
This commit is contained in:
0xNF 2024-07-11 08:54:31 +09:00 committed by GitHub
parent d91b5dd5ad
commit 86ecd08b28
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 94 additions and 32 deletions

43
Cargo.lock generated
View file

@ -577,6 +577,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive",
] ]
[[package]] [[package]]
@ -591,6 +592,18 @@ dependencies = [
"strsim", "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]] [[package]]
name = "clap_lex" name = "clap_lex"
version = "0.6.0" version = "0.6.0"
@ -1235,6 +1248,12 @@ dependencies = [
"http", "http",
] ]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.1.19"
@ -1663,7 +1682,8 @@ dependencies = [
[[package]] [[package]]
name = "librespot" name = "librespot"
version = "0.4.2" 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 = [ dependencies = [
"base64 0.13.1", "base64 0.13.1",
"env_logger 0.9.3", "env_logger 0.9.3",
@ -1689,7 +1709,8 @@ dependencies = [
[[package]] [[package]]
name = "librespot-audio" name = "librespot-audio"
version = "0.4.2" 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 = [ dependencies = [
"aes-ctr", "aes-ctr",
"byteorder", "byteorder",
@ -1704,7 +1725,8 @@ dependencies = [
[[package]] [[package]]
name = "librespot-connect" name = "librespot-connect"
version = "0.4.2" 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 = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"futures-util", "futures-util",
@ -1724,7 +1746,8 @@ dependencies = [
[[package]] [[package]]
name = "librespot-core" name = "librespot-core"
version = "0.4.2" 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 = [ dependencies = [
"aes", "aes",
"base64 0.13.1", "base64 0.13.1",
@ -1764,7 +1787,8 @@ dependencies = [
[[package]] [[package]]
name = "librespot-discovery" name = "librespot-discovery"
version = "0.4.2" 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 = [ dependencies = [
"aes-ctr", "aes-ctr",
"base64 0.13.1", "base64 0.13.1",
@ -1785,7 +1809,8 @@ dependencies = [
[[package]] [[package]]
name = "librespot-metadata" name = "librespot-metadata"
version = "0.4.2" 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 = [ dependencies = [
"async-trait", "async-trait",
"byteorder", "byteorder",
@ -1798,7 +1823,8 @@ dependencies = [
[[package]] [[package]]
name = "librespot-playback" name = "librespot-playback"
version = "0.4.2" 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 = [ dependencies = [
"byteorder", "byteorder",
"cpal", "cpal",
@ -1823,7 +1849,8 @@ dependencies = [
[[package]] [[package]]
name = "librespot-protocol" name = "librespot-protocol"
version = "0.4.2" 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 = [ dependencies = [
"glob", "glob",
"protobuf 2.28.0", "protobuf 2.28.0",

View file

@ -16,7 +16,7 @@ build = "build.rs"
winres = "0.1" winres = "0.1"
[dependencies] [dependencies]
clap = "4.2.1" clap = { version = "4.2.1", features = ["cargo", "derive"] }
log = "0.4" log = "0.4"
url = "2.2" url = "2.2"
protobuf = "3.1" protobuf = "3.1"

29
src/arg.rs Normal file
View file

@ -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
}

View file

@ -1,6 +1,7 @@
#[macro_use] #[macro_use]
extern crate log; extern crate log;
mod arg;
mod converter; mod converter;
mod downloader; mod downloader;
mod error; mod error;
@ -8,6 +9,7 @@ mod settings;
mod spotify; mod spotify;
mod tag; mod tag;
use arg::Args;
use async_std::task; use async_std::task;
use colored::Colorize; use colored::Colorize;
use downloader::{DownloadState, Downloader}; use downloader::{DownloadState, Downloader};
@ -35,6 +37,8 @@ async fn main() {
async fn start() { async fn start() {
env_logger::init(); env_logger::init();
let args = Args::from_cli();
let settings = match Settings::load().await { let settings = match Settings::load().await {
Ok(settings) => { Ok(settings) => {
println!( println!(
@ -52,10 +56,11 @@ async fn start() {
); );
let default_settings = Settings::new("username", "password", "client_id", "secret"); let default_settings = Settings::new("username", "password", "client_id", "secret");
match default_settings.save().await { match default_settings.save().await {
Ok(_) => { Ok(path) => {
println!( 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) => { Err(e) => {
@ -70,15 +75,6 @@ async fn start() {
} }
}; };
let args: Vec<String> = env::args().collect();
if args.len() <= 1 {
println!(
"Usage:\n{} <search_term> | <track_url> | <album_url> | <playlist_url> | <artist_url>",
args[0]
);
return;
}
let spotify = match Spotify::new( let spotify = match Spotify::new(
&settings.username, &settings.username,
&settings.password, &settings.password,
@ -101,10 +97,8 @@ async fn start() {
} }
}; };
let input = args[1..].join(" ");
let downloader = Downloader::new(settings.downloader, spotify); let downloader = Downloader::new(settings.downloader, spotify);
match downloader.handle_input(&input).await { match downloader.handle_input(&args.input).await {
Ok(search_results) => { Ok(search_results) => {
if let Some(search_results) = search_results { if let Some(search_results) = search_results {
print!("{esc}[2J{esc}[1;1H", esc = 27 as char); print!("{esc}[2J{esc}[1;1H", esc = 27 as char);

View file

@ -40,6 +40,15 @@ fn get_config_folder_path() -> PathBuf {
Path::new(&env::var("APPDATA").unwrap()).join("down_on_spot") 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 { impl Settings {
// Create new instance // Create new instance
pub fn new(username: &str, password: &str, client_id: &str, client_secret: &str) -> Settings { pub fn new(username: &str, password: &str, client_id: &str, client_secret: &str) -> Settings {
@ -53,25 +62,28 @@ impl Settings {
} }
} }
// Save config /// Save config
pub async fn save(&self) -> Result<(), SpotifyError> { ///
/// Returns the path of the written file if successful
pub async fn save(&self) -> Result<PathBuf, SpotifyError> {
// Get and create config folder path, generate config file path // 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?; create_dir_all(&config_folder_path).await?;
let config_file_path = config_folder_path.join("settings.json");
// Serialize the settings to a json file // Serialize the settings to a json file
let data = serde_json::to_string_pretty(self)?; 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?; file.write_all(data.as_bytes()).await?;
Ok(()) Ok(config_file_path)
} }
// Load config // Load config
pub async fn load() -> Result<Settings, SpotifyError> { pub async fn load() -> Result<Settings, SpotifyError> {
// Get config folder path, generate config file path // Get 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_file_path = config_folder_path.join("settings.json");
// Deserialize the settings from a json file // Deserialize the settings from a json file
let mut file = File::open(config_file_path).await?; let mut file = File::open(config_file_path).await?;