use std::path::PathBuf;
use clap::{Args, Parser, Subcommand};
use siteforge::ExportFormat as SiteforgeExportFormat;
use crate::types::{DatasetProvider, Mode, ModelProvider, SiteArchiveProfile};
#[derive(Parser, Clone)]
#[command(
name = "thesa",
version,
about = "A compendium to archive GitHub repositories, ML models, datasets, and websites",
subcommand_precedence_over_arg = true
)]
pub(crate) struct Cli {
#[command(subcommand)]
pub(crate) command: Option<Commands>,
pub(crate) target: Option<String>,
#[arg(short = 'o', long = "output", default_value = "./archives")]
pub(crate) output: PathBuf,
#[arg(short = 't', long = "token")]
pub(crate) token: Option<String>,
#[arg(long = "hf-token")]
pub(crate) hf_token: Option<String>,
#[arg(long = "civitai-token")]
pub(crate) civitai_token: Option<String>,
#[arg(long = "depth")]
pub(crate) depth: Option<u32>,
#[arg(short = 'c', long = "concurrency", default_value_t = 4)]
pub(crate) concurrency: usize,
#[arg(long = "skip-existing")]
pub(crate) skip_existing: bool,
#[arg(long = "filter")]
pub(crate) filter: Option<String>,
#[arg(long = "dry-run")]
pub(crate) dry_run: bool,
#[arg(short = 'T', long = "tui")]
pub(crate) tui: bool,
#[arg(
long = "mode",
value_enum,
default_value_t = Mode::Repos,
help = "Archive mode: repos (GitHub), models, datasets, or sites (Siteforge)"
)]
pub(crate) mode: Mode,
#[arg(long = "provider", value_enum, default_value_t = ModelProvider::Hf)]
pub(crate) provider: ModelProvider,
#[arg(long = "dataset-provider", value_enum, default_value_t = DatasetProvider::Hf)]
pub(crate) dataset_provider: DatasetProvider,
#[arg(long = "hf-mirror")]
pub(crate) hf_mirror: bool,
}
#[derive(Debug, Clone, Subcommand)]
#[allow(clippy::large_enum_variant)]
pub(crate) enum Commands {
Archive {
#[arg(long = "dry-run")]
dry_run: bool,
#[command(subcommand)]
source: ArchiveCommands,
},
Verify {
archive: PathBuf,
#[arg(long)]
json: bool,
},
}
#[derive(Debug, Clone, Subcommand)]
pub(crate) enum ArchiveCommands {
#[command(alias = "update", alias = "pull")]
Refresh(GitRefreshArgs),
Site(SiteArchiveArgs),
Dataset(DatasetArchiveArgs),
Url(SiteArchiveArgs),
List(SiteforgeRootArgs),
Inspect(SiteforgeArchiveIdArgs),
Search(SiteforgeSearchArgs),
Export(SiteforgeExportArgs),
Pack(SiteforgePackArgs),
Verify(SiteforgeArchiveIdArgs),
Resume(SiteforgeArchiveIdArgs),
Diagnostics(SiteforgeDiagnosticsArgs),
}
#[derive(Debug, Clone, Args)]
pub(crate) struct GitRefreshArgs {
#[arg(value_name = "OWNER")]
pub(crate) owner: Option<String>,
#[arg(long = "archive-root", short = 'r', default_value = "./archives")]
pub(crate) archive_root: PathBuf,
#[arg(
long = "owner",
alias = "user",
alias = "username",
value_name = "OWNER"
)]
pub(crate) owner_filter: Option<String>,
#[arg(short = 'c', long = "concurrency", default_value_t = 4)]
pub(crate) concurrency: usize,
#[arg(long = "filter")]
pub(crate) filter: Option<String>,
#[arg(long = "dry-run")]
pub(crate) dry_run: bool,
}
#[derive(Debug, Clone, Args)]
pub(crate) struct SiteforgeRootArgs {
#[arg(long = "archive-root", default_value = "./archives/sites")]
pub(crate) archive_root: PathBuf,
}
#[derive(Debug, Clone, Args)]
pub(crate) struct DatasetArchiveArgs {
pub(crate) target: String,
#[arg(long = "provider", value_enum, default_value_t = DatasetProvider::Hf)]
pub(crate) provider: DatasetProvider,
#[arg(
long = "archive-root",
short = 'r',
default_value = "./archives/datasets"
)]
pub(crate) archive_root: PathBuf,
#[arg(short = 'c', long = "concurrency", default_value_t = 4)]
pub(crate) concurrency: usize,
#[arg(long = "skip-existing")]
pub(crate) skip_existing: bool,
#[arg(long = "filter")]
pub(crate) filter: Option<String>,
#[arg(long = "hf-token")]
pub(crate) hf_token: Option<String>,
#[arg(long = "dry-run")]
pub(crate) dry_run: bool,
}
#[derive(Debug, Clone, Args)]
pub(crate) struct SiteforgeArchiveIdArgs {
pub(crate) archive_id: String,
#[command(flatten)]
pub(crate) root: SiteforgeRootArgs,
}
#[derive(Debug, Clone, Args)]
pub(crate) struct SiteforgeSearchArgs {
pub(crate) query: String,
#[arg(long = "archive-id")]
pub(crate) archive_id: Option<String>,
#[arg(long = "limit", default_value_t = 20)]
pub(crate) limit: usize,
#[command(flatten)]
pub(crate) root: SiteforgeRootArgs,
}
#[derive(Debug, Clone, Args)]
pub(crate) struct SiteforgeExportArgs {
pub(crate) archive_id: String,
#[arg(long = "format", value_enum)]
pub(crate) format: SiteforgeExportFormat,
#[arg(long = "output")]
pub(crate) output: Option<PathBuf>,
#[command(flatten)]
pub(crate) root: SiteforgeRootArgs,
}
#[derive(Debug, Clone, Args)]
pub(crate) struct SiteforgePackArgs {
pub(crate) archive_id: String,
#[arg(long = "max-tokens")]
pub(crate) max_tokens: Option<usize>,
#[command(flatten)]
pub(crate) root: SiteforgeRootArgs,
}
#[derive(Debug, Clone, Args)]
pub(crate) struct SiteforgeDiagnosticsArgs {
pub(crate) archive_id: Option<String>,
#[command(flatten)]
pub(crate) root: SiteforgeRootArgs,
}
#[derive(Debug, Clone, Args)]
pub(crate) struct SiteArchiveArgs {
#[arg(value_name = "URL")]
pub(crate) url: Option<String>,
#[arg(long = "input", value_name = "FILE")]
pub(crate) input: Option<PathBuf>,
#[arg(short = 'o', long = "output", default_value = "./archives/sites")]
pub(crate) output: PathBuf,
#[arg(long = "full-site")]
pub(crate) full_site: bool,
#[arg(long = "allow-cross-domain")]
pub(crate) allow_cross_domain: bool,
#[arg(long = "max-depth")]
pub(crate) max_depth: Option<usize>,
#[arg(long = "max-pages")]
pub(crate) max_pages: Option<usize>,
#[arg(short = 'c', short_alias = 'j', long = "concurrency", alias = "jobs")]
pub(crate) concurrency: Option<usize>,
#[arg(long = "delay-ms")]
pub(crate) delay_ms: Option<u64>,
#[arg(long = "archive-id")]
pub(crate) archive_id: Option<String>,
#[arg(long = "include", value_name = "GLOB")]
pub(crate) include_url_patterns: Vec<String>,
#[arg(long = "exclude", value_name = "GLOB")]
pub(crate) exclude_url_patterns: Vec<String>,
#[arg(long = "archive-profile", value_enum)]
pub(crate) archive_profile: Option<SiteArchiveProfile>,
#[arg(long = "max-page-size-bytes")]
pub(crate) max_page_size_bytes: Option<u64>,
#[arg(long = "max-asset-size-bytes")]
pub(crate) max_asset_size_bytes: Option<u64>,
#[arg(long = "max-total-archive-size-bytes")]
pub(crate) max_total_archive_size_bytes: Option<u64>,
#[arg(long = "render-js")]
pub(crate) render_js: bool,
#[arg(long = "render-js-auto", conflicts_with = "render_js")]
pub(crate) render_js_auto: bool,
#[arg(long = "browser-command", value_name = "COMMAND")]
pub(crate) browser_command: Option<String>,
#[arg(long = "browser-profile", value_name = "DIR")]
pub(crate) browser_profile: Option<PathBuf>,
#[arg(long = "render-wait-ms")]
pub(crate) render_wait_ms: Option<u64>,
#[arg(long = "header", value_name = "NAME: VALUE")]
pub(crate) headers: Vec<String>,
#[arg(long = "cookie", value_name = "COOKIE_HEADER")]
pub(crate) cookie: Option<String>,
#[arg(long = "user-agent", value_name = "VALUE")]
pub(crate) user_agent: Option<String>,
#[arg(long = "timeout-secs")]
pub(crate) timeout_secs: Option<u64>,
#[arg(long = "retry-count")]
pub(crate) retry_count: Option<usize>,
#[arg(long = "ocr")]
pub(crate) ocr_enabled: bool,
#[arg(long = "dry-run")]
pub(crate) dry_run: bool,
}