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::services::{self, PlatformService};
12
13use super::library_scan::{run_scan_library_flow, ScanCacheInvalidate, ScanLibraryOptions};
14use super::OutputFormat;
15
16#[derive(Args, Debug)]
17pub struct ScanCommand {
18    /// Restrict scan to one or more platform slugs (comma-separated); passed as `platform_slugs` task kwargs
19    #[arg(long)]
20    pub platform: Option<String>,
21
22    /// Wait until the scan task completes (polls every 2 seconds)
23    #[arg(long)]
24    pub wait: bool,
25
26    /// Max seconds to wait when `--wait` is set (default: 3600)
27    #[arg(long, requires = "wait")]
28    pub wait_timeout_secs: Option<u64>,
29}
30
31pub async fn handle(
32    cmd: ScanCommand,
33    client: &RommClient,
34    format: OutputFormat,
35    interrupt: Option<InterruptContext>,
36) -> Result<()> {
37    let slugs: Vec<String> = cmd
38        .platform
39        .as_deref()
40        .map(|s| {
41            s.split(',')
42                .map(|p| p.trim().to_string())
43                .filter(|p| !p.is_empty())
44                .collect()
45        })
46        .unwrap_or_default();
47
48    let task_kwargs = if slugs.is_empty() {
49        None
50    } else {
51        Some(json!({ "platform_slugs": slugs }))
52    };
53
54    let cache_invalidate = if cmd.wait {
55        match cmd.platform.as_deref() {
56            Some(p) if !p.trim().is_empty() && !p.contains(',') => {
57                let service = PlatformService::new(client);
58                let platforms = service.list_platforms().await?;
59                match services::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}