qbt-clean 0.128.0

Automated rules-based cleaning of qBittorrent torrents.
mod args; pub(crate) use args::*;
mod args_config; pub(crate) use args_config::*;
mod cmd_clean; pub(crate) use cmd_clean::*;
mod cmd_group; pub(crate) use cmd_group::*;
mod cmp; pub(crate) use cmp::*;
mod config; pub(crate) use config::*;
mod float; pub(crate) use float::*;
mod fmt; pub(crate) use fmt::*;
mod global; pub(crate) use global::*;
mod group; pub(crate) use group::*;
mod group_torrent; pub(crate) use group_torrent::*;
mod info_hash; pub(crate) use info_hash::*;
mod match_; pub(crate) use match_::*;
mod parse; pub(crate) use parse::*;
mod pin_reason; pub(crate) use pin_reason::*;
mod qbt; pub(crate) use qbt::*;
mod qbt_http; pub(crate) use qbt_http::*;
mod requirement; pub(crate) use requirement::*;
mod rule; pub(crate) use rule::*;
mod rule_result; pub(crate) use rule_result::*;
mod serde_util; pub(crate) use serde_util::*;
mod torrent; pub(crate) use torrent::*;
mod torrent_state; pub(crate) use torrent_state::*;
mod tracker; pub(crate) use tracker::*;
mod units; pub(crate) use units::*;

#[cfg(test)] mod global_test;
#[cfg(test)] mod match_test;
#[cfg(test)] mod qbt_mock;
#[cfg(test)] mod requirement_test;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
	let args: crate::Args = clap::Parser::parse();
	let mut config = args.config.read()?;

	if config.age_d_max_weight == 0.0
		&& config.age_d_min_weight == 0.0
		&& config.copies_weight == 0.0
		&& config.last_activity_d_weight == 0.0
		&& config.no_scored_torrents_weight == 0.0
		&& config.seeder_count_weight == 0.0
		&& config.size_weight == 0.0
	{
		eprintln!("WARN: All weights are zero, setting seeder-count-weight to 1.0");
		config.seeder_count_weight = 1.0;
	}

	let qbt = crate::QbtHttp::new(
		config.qbt_url.clone(),
		(&config.qbt_headers).try_into()?).await?;
	eprintln!("Logged in.");

	let global = crate::Global {
		config,
		now: std::time::SystemTime::now(),
		qbt,
	};

	let main_result = async {
		match args.command {
			crate::Command::Clean => cmd_clean(&global, false).await,
			crate::Command::Group(a) => cmd_group(a, &global).await,
			crate::Command::Simulate => cmd_clean(&global, true).await,
		}
	}.await;

	let crate::Global { qbt, .. } = global;
	if let Err(err) = qbt.logout().await {
		eprintln!("Warning: Failed to log out: {}", err);
	}

	main_result
}