use chrono::Utc; use clap::Parser; use std::path::Path; mod exporter; mod generator; mod schedule; // 3 weeks by default const DEFAULT: usize = 21 * 24 / 2; // If no start time is specified, use the last even hour pub fn default_timestamp() -> i64 { let now = Utc::now().timestamp(); let block = 2 * 60 * 60; now - (now % block) } #[derive(Parser, Debug)] #[command(name = "ikamaki")] struct Args { // How many rotations to generate #[arg(short, long)] count: Option, // UNIX timestamp to start the schedule from #[arg(short, long)] start: Option, // Output file path #[arg(short, long, default_value = "VSSetting.byaml")] output: String, // Generate YAML in addition to the BYAML #[arg(long)] yml: bool, // Set DisconnectByMemoryHash to true #[arg(long)] hash_kick: bool, } fn main() -> Result<(), Box> { let args = Args::parse(); let count = args.count.unwrap_or(DEFAULT); let start_time = args.start.unwrap_or_else(default_timestamp); let schedule = generator::generate(count, start_time); exporter::export(&schedule, &args.output, args.hash_kick)?; if args.yml { let yml_path = derive_yml_path(&args.output); exporter::export_text(&schedule, &yml_path, args.hash_kick)?; println!( "Successfully generated {} rotation(s) -> {} + {}", count, args.output, yml_path ); } else { println!( "Successfully generated {} rotation(s) -> {}", count, args.output ); } Ok(()) } fn derive_yml_path(output: &str) -> String { let path = Path::new(output); if let Some(stem) = path.file_stem() { if let Some(parent) = path.parent() { return parent .join(format!("{}.yml", stem.to_string_lossy())) .to_string_lossy() .into_owned(); } return format!("{}.yml", stem.to_string_lossy()); } format!("{}.yml", output) }