Skip to main content

avatarr_cli/
cli_types.rs

1//! Clap-derived CLI type definitions.
2//!
3//! These live in their own module (rather than `main.rs`) so the integration
4//! test crate at `crates/cli/tests/` can `use avatarr_cli::{Cli, Commands,
5//! SearchType}` and exercise flag parsing directly via
6//! `Cli::try_parse_from(...)`.
7
8use clap::{Parser, Subcommand, ValueEnum};
9
10#[derive(Parser, Debug)]
11#[command(
12    name = "avatarr-cli",
13    version,
14    about = "Avatarr CLI — torrent search, download, and Plex organisation"
15)]
16pub struct Cli {
17    #[command(subcommand)]
18    pub command: Option<Commands>,
19
20    /// Run parser verification tests
21    #[arg(long)]
22    pub test_parse: bool,
23}
24
25/// CLI-facing media type. Mirrors `avatarr_core::metadata::MediaType`
26/// but lives here so clap derive can use `ValueEnum` without touching
27/// the core crate.
28#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
29pub enum SearchType {
30    Movie,
31    Tv,
32}
33
34#[derive(Subcommand, Debug)]
35pub enum Commands {
36    /// Search for torrents
37    Search {
38        /// Search query
39        query: Option<String>,
40        /// Media type (required with a query; ignored with --file since list
41        /// files carry their own per-entry type notation)
42        #[arg(
43            long = "type",
44            value_enum,
45            required_unless_present = "file",
46            value_name = "TYPE"
47        )]
48        kind: Option<SearchType>,
49        /// Force a complete-series search (TV only)
50        #[arg(long, conflicts_with = "season", requires = "kind")]
51        complete: bool,
52        /// Force a single-season search (TV only)
53        #[arg(long, value_name = "N", conflicts_with = "complete", requires = "kind")]
54        season: Option<u32>,
55        /// Quality filter (e.g., 1080p, 2160p)
56        #[arg(long)]
57        quality: Option<String>,
58        /// Auto-select best result
59        #[arg(long)]
60        auto: bool,
61        /// Show what would happen without doing anything
62        #[arg(long)]
63        dry_run: bool,
64        /// Read queries from file (one per line)
65        #[arg(long)]
66        file: Option<String>,
67    },
68    /// Monitor qBittorrent for completed torrents
69    Monitor {
70        /// Process completed torrents and exit
71        #[arg(long)]
72        once: bool,
73        /// Show what would happen without making changes
74        #[arg(long)]
75        dry_run: bool,
76        /// Run live resolver tests
77        #[arg(long)]
78        test_resolve: bool,
79        /// Path to config file
80        #[arg(long)]
81        config: Option<String>,
82    },
83}