use std::sync::Arc;
use actix_web::{test, web, App, HttpServer};
use clap::Parser;
use env_logger::Env;
use log::{error, info};
use std::fs;
use libsubconverter::settings::settings::settings_struct::init_settings;
use libsubconverter::{web_handlers, Settings};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
#[arg(short, long, value_name = "FILE")]
config: Option<String>,
#[arg(short, long, value_name = "ADDRESS")]
address: Option<String>,
#[arg(short, long, value_name = "PORT")]
port: Option<u32>,
#[arg(long, value_name = "URL")]
url: Option<String>,
#[arg(short, long, value_name = "OUTPUT_FILE")]
output: Option<String>,
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(Env::default().default_filter_or("info"));
let args = Args::parse();
if args.url.is_some() != args.output.is_some() {
eprintln!("Error: --url and -o/--output must be used together");
std::process::exit(1);
}
init_settings(args.config.as_deref().unwrap_or(""))
.await
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
if let Some(url) = args.url {
let output_file = args
.output
.as_ref()
.expect("Output file must be provided with URL");
info!(
"Processing subscription from URL: {} to file: {}",
url, output_file
);
let app = test::init_service(App::new().configure(web_handlers::config)).await;
let req = test::TestRequest::get().uri(&url).to_request();
let resp = test::call_service(&app, req).await;
if resp.status().is_success() {
let body = test::read_body(resp).await;
fs::write(output_file, body)?;
info!("Successfully wrote result to {}", output_file);
} else {
error!("API request failed with status: {}", resp.status());
std::process::exit(1);
}
Ok(()) } else {
let listen_address = {
let mut settings_guard = Settings::current_mut();
let settings = Arc::make_mut(&mut *settings_guard);
if let Some(address) = args.address {
settings.listen_address = address;
}
if let Some(port) = args.port {
settings.listen_port = port;
}
if settings.listen_address.trim().is_empty() {
error!("Empty listen_address in settings, defaulting to 127.0.0.1");
format!("127.0.0.1:{}", settings.listen_port)
} else {
if settings.listen_address.contains(':') {
settings.listen_address.clone()
} else {
format!("{}:{}", settings.listen_address, settings.listen_port)
}
}
};
let max_concur_threads = Settings::current().max_concur_threads;
info!("Subconverter starting on {}", listen_address);
HttpServer::new(move || {
App::new()
.configure(web_handlers::config)
.route("/", web::get().to(|| async { "Subconverter is running!" }))
})
.bind(listen_address)?
.workers(max_concur_threads as usize)
.run()
.await
}
}