romm_cli/commands/
scan.rs1use 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 #[arg(long)]
25 pub platform: Option<String>,
26
27 #[arg(long)]
29 pub wait: bool,
30
31 #[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}