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