diff options
Diffstat (limited to 'src/cli.rs')
-rw-r--r-- | src/cli.rs | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..4835fc4 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,244 @@ +// yt - A fully featured command line YouTube client +// +// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de> +// SPDX-License-Identifier: GPL-3.0-or-later +// +// This file is part of Yt. +// +// You should have received a copy of the License along with this program. +// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. + +use std::path::PathBuf; + +use chrono::NaiveDate; +use clap::{ArgAction, Args, Parser, Subcommand}; +use url::Url; + +use crate::{ + constants, select::selection_file::duration::Duration, + storage::video_database::extractor_hash::LazyExtractorHash, +}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +/// An command line interface to select, download and watch videos +pub struct CliArgs { + #[command(subcommand)] + /// The subcommand to execute [default: select] + pub command: Option<Command>, + + /// Increase message verbosity + #[arg(long="verbose", short = 'v', action = ArgAction::Count)] + pub verbosity: u8, + + /// Silence all output + #[arg(long, short = 'q')] + pub quiet: bool, +} + +#[derive(Subcommand, Debug)] +pub enum Command { + /// Download and cache URLs + Download { + /// Forcefully re-download all cached videos (i.e. delete the cache path, then download). + #[arg(short, long)] + force: bool, + }, + + /// Watch the already cached (and selected) videos + Watch {}, + + /// Show, which videos have been selected to be watched (and their cache status) + Status {}, + + /// Perform various tests + Check { + #[command(subcommand)] + command: CheckCommand, + }, + + /// Display the comments of the currently playing video + Comments {}, + /// Display the description of the currently playing video + Description {}, + + /// Manipulate the video cache in the database + #[command(visible_alias = "db")] + Database { + #[command(subcommand)] + command: CacheCommand, + }, + + /// Change the state of videos in the database (the default) + Select { + #[command(subcommand)] + cmd: Option<SelectCommand>, + }, + + /// Update the video database + Update { + #[arg(short, long, default_value = "20")] + /// The number of videos to updating + max_backlog: u32, + + #[arg(short, long)] + /// The subscriptions to update (can be given multiple times) + subscriptions: Vec<String>, + + #[arg(short, long, default_value = "6")] + /// How many processes to spawn at the same time + concurrent_processes: usize, + }, + + /// Manipulate subscription + #[command(visible_alias = "subs")] + Subscriptions { + #[command(subcommand)] + cmd: SubscriptionCommand, + }, +} + +impl Default for Command { + fn default() -> Self { + Self::Select { + cmd: Some(SelectCommand::default()), + } + } +} + +#[derive(Subcommand, Clone, Debug)] +pub enum SubscriptionCommand { + /// Subscribe to an URL + Add { + #[arg(short, long)] + /// The human readable name of the subscription + name: Option<String>, + + /// The URL to listen to + url: Url, + }, + + /// Unsubscribe from an URL + Remove { + /// The human readable name of the subscription + name: String, + }, + + /// Import a bunch of URLs as subscriptions. + Import { + /// The file containing the URLs. Will use Stdin otherwise. + file: Option<PathBuf>, + + /// Remove any previous subscriptions + #[arg(short, long)] + force: bool + }, + + /// List all subscriptions + List { + /// Only show the URLs + #[arg(short, long)] + url: bool, + }, +} + +#[derive(Clone, Debug, Args)] +#[command(infer_subcommands = true)] +/// Mark the video given by the hash to be watched +pub struct SharedSelectionCommandArgs { + /// The short extractor hash + pub hash: LazyExtractorHash, + + pub title: String, + + pub date: NaiveDate, + + pub publisher: String, + + pub duration: Duration, + + pub url: Url, +} + +#[derive(Subcommand, Clone, Debug)] +#[command(infer_subcommands = true)] +// NOTE: Keep this in sync with the [`constants::HELP_STR`] constant. <2024-08-20> +pub enum SelectCommand { + /// Open a `git rebase` like file to select the videos to watch (the default) + File { + /// Include done (watched, dropped) videos + #[arg(long, short)] + done: bool, + }, + + Watch { + #[command(flatten)] + shared: SharedSelectionCommandArgs, + + /// The ordering priority (higher means more at the top) + #[arg(short, long)] + priority: Option<i64>, + + /// The subtitles to download (e.g. 'en,de,sv') + #[arg(short = 'l', long, default_value = constants::DEFAULT_SUBTITLE_LANGS)] + subtitle_langs: String, + + /// The speed to set mpv to + #[arg(short, long, default_value = "2.7")] + speed: f64, + }, + + /// Mark the video given by the hash to be dropped + Drop { + #[command(flatten)] + shared: SharedSelectionCommandArgs, + }, + + /// Open the video URL in Firefox's `timesinks.youtube` profile + Url { + #[command(flatten)] + shared: SharedSelectionCommandArgs, + }, + + /// Reset the videos status to 'Pick' + Pick { + #[command(flatten)] + shared: SharedSelectionCommandArgs, + }, +} +impl Default for SelectCommand { + fn default() -> Self { + Self::File { done: false } + } +} + +#[derive(Subcommand, Clone, Debug)] +pub enum CheckCommand { + /// Check if the given info.json is deserializable + InfoJson { path: PathBuf }, + + /// Check if the given update info.json is deserializable + UpdateInfoJson { path: PathBuf }, +} + +#[derive(Subcommand, Clone, Copy, Debug)] +pub enum CacheCommand { + /// Invalidate all cache entries + Invalidate { + /// Also delete the cache path + #[arg(short, long)] + hard: bool, + }, + + /// Perform basic maintenance operations on the database. + /// This helps recovering from invalid db states after a crash (or force exit via CTRL+C). + /// + /// 1. Check every path for validity (removing all invalid cache entries) + /// 2. Reset all `status_change` bits of videos to false. + #[command(verbatim_doc_comment)] + Maintain { + /// Check every video (otherwise only the videos to be watched are checked) + #[arg(short, long)] + all: bool, + }, +} |