shrupl/src/cli.rs

90 lines
2.5 KiB
Rust

use std::{
hash::{DefaultHasher, Hash, Hasher},
time::Duration,
};
use clap::{Parser, builder::PossibleValuesParser};
use super::sharry::{Alias, FileChecked, NewShareRequest, Uri};
#[derive(Parser, Debug, Hash)]
#[command(version, about, long_about = None)]
pub struct Cli {
/// Timeout in seconds for HTTP actions (set 0 or invalid to disable)
#[arg(
short, long,
default_value = "10", value_name = "SECS",
value_parser = parse_seconds,
)]
timeout: Duration,
/// Protocol for Sharry instance
#[arg(
short, long,
default_value = "https", value_name = "VARIANT",
value_parser = PossibleValuesParser::new(["http", "https"]),
)]
protocol: String,
/// Name of the new share
#[arg(short, long, default_value = "ShrUpl Upload", value_name = "TEXT")]
name: String,
/// Description of the new share
#[arg(short, long, value_name = "TEXT")]
description: Option<String>,
/// Maximum number of views for the new share
#[arg(short, long, default_value_t = 100, value_name = "N")]
max_views: u32,
/// Chunk size for uploading, in MiB
#[arg(short, long, default_value_t = 10, value_name = "N")]
pub chunk_size: usize,
/// Base URL for Sharry Instance
url: String,
/// ID of a public alias to use
alias: String,
/// Files to upload to the new share
#[arg(value_name = "FILE", required = true, value_parser = parse_sharry_file)]
pub files: Vec<FileChecked>,
}
fn parse_seconds(data: &str) -> Result<Duration, String> {
data.parse().or(Ok(0)).map(Duration::from_secs)
}
fn parse_sharry_file(data: &str) -> Result<FileChecked, String> {
FileChecked::new(data).map_err(|e| e.to_string())
}
impl Cli {
pub fn get_timeout(&self) -> Option<Duration> {
(!self.timeout.is_zero()).then_some(self.timeout)
}
pub fn get_alias(&self) -> Alias {
Alias::new(Uri::with_protocol(&self.protocol, &self.url), &self.alias)
}
pub fn get_share_request(&self) -> NewShareRequest {
NewShareRequest::new(&self.name, self.description.as_ref(), self.max_views)
}
pub fn get_hash(&self) -> String {
let file_refs = {
let mut refs: Vec<_> = self.files.iter().map(FileChecked::get_path).collect();
refs.sort_unstable();
refs
};
let mut hasher = DefaultHasher::new();
(self.get_alias(), file_refs).hash(&mut hasher);
format!("{:x}", hasher.finish())
}
}