diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cli.rs | 13 | ||||
-rw-r--r-- | src/cmd/sync.rs | 5 | ||||
-rw-r--r-- | src/lastfm/mod.rs | 49 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/paths.rs | 7 |
5 files changed, 55 insertions, 20 deletions
@@ -7,7 +7,6 @@ pub enum Command { pub struct Options { pub command: Command, pub username: Option<String>, - pub api_key: Option<String>, } pub fn get_options() -> failure::Fallible<Options> { @@ -17,20 +16,9 @@ pub fn get_options() -> failure::Fallible<Options> { .about("Updates the local copy of track data from last.fm") .arg( clap::Arg::with_name("username") - .short("u") - .long("username") - .value_name("USERNAME") .required(true) .help("last.fm username to fetch tracks for") ) - .arg( - clap::Arg::with_name("api-key") - .short("k") - .long("api-key") - .value_name("API_KEY") - .required(true) - .help("last.fm api key") - ) ) .get_matches(); @@ -43,6 +31,5 @@ pub fn get_options() -> failure::Fallible<Options> { Ok(Options { command: command, username: sub_matches.value_of("username").map(|s| s.to_string()), - api_key: sub_matches.value_of("api-key").map(|s| s.to_string()), }) } diff --git a/src/cmd/sync.rs b/src/cmd/sync.rs index 65b48b7..9dfb11f 100644 --- a/src/cmd/sync.rs +++ b/src/cmd/sync.rs @@ -4,11 +4,10 @@ use lastfm; use paths; pub fn run(opts: &cli::Options) -> failure::Fallible<()> { - let db = db::DB::new(&paths::dbpath()?)?; + let db = db::DB::new(&paths::db_path()?)?; let lastfm = lastfm::LastFMClient::new( - opts.api_key.as_ref().unwrap(), opts.username.as_ref().unwrap() - ); + )?; let from = db.most_recent_timestamp()?.map(|x| x + 1); let to_fetch = lastfm.track_count(from)?; diff --git a/src/lastfm/mod.rs b/src/lastfm/mod.rs index fc2eb5b..b5888cc 100644 --- a/src/lastfm/mod.rs +++ b/src/lastfm/mod.rs @@ -1,3 +1,8 @@ +use paths; + +use failure::Fail; +use std::io::{Read, Write}; + mod api_types; const API_ROOT: &'static str = "https://ws.audioscrobbler.com/2.0/"; @@ -98,12 +103,12 @@ impl<'a> Iterator for Tracks<'a> { } impl LastFMClient { - pub fn new(api_key: &str, user: &str) -> LastFMClient { - LastFMClient { + pub fn new(user: &str) -> failure::Fallible<LastFMClient> { + Ok(LastFMClient { client: reqwest::Client::new(), - api_key: api_key.to_string(), + api_key: find_api_key()?, user: user.to_string(), - } + }) } pub fn track_count(&self, from: Option<i64>) -> failure::Fallible<u64> { @@ -151,3 +156,39 @@ impl LastFMClient { } } } + +fn find_api_key() -> failure::Fallible<String> { + let api_key_path = paths::api_key_path() + .map_err(|e| e.context("failed to determine api key path"))?; + let api_key = if api_key_path.exists() { + let mut api_key = String::new(); + let mut f = std::fs::File::open(&api_key_path) + .map_err(|e| { + e.context(format!("failed to open {}", api_key_path.display())) + })?; + f.read_to_string(&mut api_key) + .map_err(|e| { + e.context(format!("failed to read from {}", api_key_path.display())) + })?; + api_key + } + else { + let api_key = rpassword::prompt_password_stderr( + &format!( + "last.fm api key (will be stored in {}): ", + api_key_path.display() + ) + )?; + std::fs::create_dir_all(api_key_path.parent().unwrap())?; + let mut f = std::fs::File::create(&api_key_path) + .map_err(|e| { + e.context(format!("failed to open {}", api_key_path.display())) + })?; + f.write_all(api_key.as_bytes()) + .map_err(|e| { + e.context(format!("failed to write to {}", api_key_path.display())) + })?; + api_key + }; + Ok(api_key.trim_end().to_string()) +} diff --git a/src/main.rs b/src/main.rs index 2518e55..d7d80fd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ extern crate directories; extern crate failure; extern crate indicatif; extern crate reqwest; +extern crate rpassword; extern crate rusqlite; extern crate serde; extern crate serde_json; diff --git a/src/paths.rs b/src/paths.rs index a3f1eb8..badb783 100644 --- a/src/paths.rs +++ b/src/paths.rs @@ -4,3 +4,10 @@ pub fn db_path() -> failure::Fallible<std::path::PathBuf> { .data_dir() .join("tracks.sqlite")) } + +pub fn api_key_path() -> failure::Fallible<std::path::PathBuf> { + Ok(directories::ProjectDirs::from("", "", "lastfm-query") + .ok_or_else(|| failure::err_msg("couldn't determine config directory"))? + .config_dir() + .join("lastfm-api-key")) +} |