diff options
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/mod.rs | 3 | ||||
-rw-r--r-- | src/cmd/recommend.rs | 89 |
2 files changed, 92 insertions, 0 deletions
diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 2c4873f..1cbe362 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -1,5 +1,6 @@ mod sql; mod sync; +mod recommend; const _DUMMY_DEPENDENCY: &'static str = include_str!("../../Cargo.toml"); @@ -15,11 +16,13 @@ fn get_command() -> failure::Fallible<Box<Command>> { let matches = app_from_crate!() .subcommand(sync::subcommand()) .subcommand(sql::subcommand()) + .subcommand(recommend::subcommand()) .get_matches(); let command: Box<Command> = match matches.subcommand() { ("sync", Some(matches)) => Box::new(sync::Command::new(matches)), ("sql", Some(matches)) => Box::new(sql::Command::new(matches)), + ("recommend", Some(matches)) => Box::new(recommend::Command::new(matches)?), (name, Some(_)) => bail!("unknown subcommand: {}", name), (_, None) => bail!("no subcommand given"), diff --git a/src/cmd/recommend.rs b/src/cmd/recommend.rs new file mode 100644 index 0000000..6788e0c --- /dev/null +++ b/src/cmd/recommend.rs @@ -0,0 +1,89 @@ +use db; +use util; + +use clap; + +pub struct Command { + count: u64, + random: bool, + album: bool, + include: db::TimeWindow, + exclude: db::TimeWindow, + + db: db::DB, +} + +pub fn subcommand<'a, 'b>() -> clap::App<'a, 'b> { + clap::SubCommand::with_name("recommend") + .about("Recommends an artist or album to listen to") + .arg( + clap::Arg::with_name("count") + .default_value("20") + .help("number of results to return") + ) + .arg( + clap::Arg::with_name("random") + .long("random") + .help("pick a random artist instead of by weight") + ) + .arg( + clap::Arg::with_name("album") + .long("album") + .help("also choose a random album by the chosen artists") + ) + .arg( + clap::Arg::with_name("include") + .long("include") + .default_value("yearly") + .possible_values(&["all", "yearly", "monthly", "weekly"]) + ) + .arg( + clap::Arg::with_name("exclude") + .long("exclude") + .default_value("weekly") + .possible_values(&["all", "yearly", "monthly", "weekly", "none"]) + ) +} + +impl Command { + pub fn new<'a>(matches: &clap::ArgMatches<'a>) -> failure::Fallible<Command> { + Ok(Command { + count: matches.value_of("count").unwrap().parse()?, + random: matches.is_present("random"), + album: matches.is_present("album"), + include: db::parse_timewindow(matches.value_of("include").unwrap()), + exclude: db::parse_timewindow(matches.value_of("exclude").unwrap()), + + db: db::DB::new(&util::db_path()?)?, + }) + } +} + +impl super::Command for Command { + fn run(&self) -> failure::Fallible<()> { + let mut artists = self.db.recommend_artists( + self.count, + self.random, + self.include, + self.exclude + )?; + if self.album { + artists = artists.iter().map(|artist| { + Ok(format!( + "{} - {}", + artist, + self.db.recommend_album( + &artist, + self.random, + self.include, + self.exclude + )? + )) + }).collect::<failure::Fallible<Vec<String>>>()?; + } + for line in artists { + println!("{}", line); + } + Ok(()) + } +} |