Skip to main content

romm_cli/commands/
scan.rs

1//! Top-level `scan` command: trigger RomM `scan_library` without uploading.
2
3use std::time::Duration;
4
5use anyhow::Result;
6use clap::Args;
7use serde_json::json;
8
9use crate::cli_presentation::CliPresentation;
10use romm_api::client::RommClient;
11use romm_api::core::interrupt::InterruptContext;
12use romm_api::core::resolve::resolve_platform_id_from_list;
13use romm_api::endpoints::platforms::ListPlatforms;
14
15use super::library_scan::{run_scan_library_flow, ScanCacheInvalidate, ScanLibraryOptions};
16
17#[derive(Args, Debug)]
18#[command(after_help = "Examples:\n  \
19      romm-cli scan\n  \
20      romm-cli scan --wait\n  \
21      romm-cli scan --platform gba --wait --wait-timeout-secs 600")]
22pub struct ScanCommand {
23    /// Restrict scan to one or more platform slugs (comma-separated); passed as `platform_slugs` task kwargs
24    #[arg(long)]
25    pub platform: Option<String>,
26
27    /// Wait until the scan task completes (polls every 2 seconds)
28    #[arg(long)]
29    pub wait: bool,
30
31    /// Max seconds to wait when `--wait` is set (default: 3600)
32    #[arg(long, requires = "wait")]
33    pub wait_timeout_secs: Option<u64>,
34}
35
36pub async fn handle(
37    cmd: ScanCommand,
38    client: &RommClient,
39    presentation: CliPresentation,
40    interrupt: Option<InterruptContext>,
41) -> Result<()> {
42    let slugs: Vec<String> = cmd
43        .platform
44        .as_deref()
45        .map(|s| {
46            s.split(',')
47                .map(|p| p.trim().to_string())
48                .filter(|p| !p.is_empty())
49                .collect()
50        })
51        .unwrap_or_default();
52
53    let task_kwargs = if slugs.is_empty() {
54        None
55    } else {
56        Some(json!({ "platform_slugs": slugs }))
57    };
58
59    let cache_invalidate = if cmd.wait {
60        match cmd.platform.as_deref() {
61            Some(p) if !p.trim().is_empty() && !p.contains(',') => {
62                let platforms = client.call(&ListPlatforms).await?;
63                match resolve_platform_id_from_list(p.trim(), &platforms) {
64                    Ok(pid) => ScanCacheInvalidate::Platform(pid),
65                    Err(_) => ScanCacheInvalidate::AllPlatforms,
66                }
67            }
68            _ => ScanCacheInvalidate::AllPlatforms,
69        }
70    } else {
71        ScanCacheInvalidate::None
72    };
73
74    let options = ScanLibraryOptions {
75        wait: cmd.wait,
76        wait_timeout: Duration::from_secs(cmd.wait_timeout_secs.unwrap_or(3600)),
77        cache_invalidate,
78        task_kwargs,
79    };
80    run_scan_library_flow(client, options, presentation, interrupt.as_ref()).await
81}