From d55d1634c2073768f1781652bb9f15ebe74be697 Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Mon, 8 Jun 2020 15:35:47 +0200 Subject: add config and subcommands ezau having the watching functionality is nice, but sometimes for scripts you might want to have the old "upload this single log and post it to discord" functionality. As such, ezau has now been split into two subcommands (which use the same core): ezau watch runs the inotify-based directory watcher to zip and upload new logs. Additionally, it now respects the "upload = ..." config settings, which means you can also use it as a zipper only, without having every log uploaded. ezau upload performs a single-shot upload with the discord notification. Furthermore, the discord auth token/channel id have been moved to a configuration file. Switches to override this for single runs might be provided in the future, but for now, it seems more sensible to have it in a persistent configuration. --- src/config.rs | 31 ++++++++++++++++++++++++++ src/main.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 87 insertions(+), 15 deletions(-) create mode 100644 src/config.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..e4203de --- /dev/null +++ b/src/config.rs @@ -0,0 +1,31 @@ +use std::{fs, path::Path}; + +use anyhow::Result; +use serde::Deserialize; + +/// The main configuration. +#[derive(Debug, Clone, Deserialize, Default)] +pub struct Config { + /// Flag indicating whether logs should be uploaded or not. + pub upload: bool, + /// Flag indicating whether logs with an unknown boss should be uploaded. + #[serde(default)] + pub upload_unknown: bool, + /// Option Discord information for bot postings. + pub discord: Option, +} + +/// Configuration pertaining to the Discord posting. +#[derive(Debug, Clone, Deserialize)] +pub struct Discord { + /// Auth token for the Discord bot. + pub auth_token: String, + /// Channel ID in which logs should be posted. + pub channel_id: u64, +} + +/// Attempt to load the configuration from the given file. +pub fn load>(path: P) -> Result { + let content = fs::read(path)?; + Ok(toml::from_slice(&content)?) +} diff --git a/src/main.rs b/src/main.rs index 45ae5e9..199cd9d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,8 @@ use zip::{CompressionMethod, ZipWriter}; mod categories; use categories::Categorizable; - +mod config; +use config::Config; mod discord; const DPS_REPORT_API: &str = "https://dps.report/uploadContent"; @@ -26,14 +27,33 @@ const WATCH_DELAY_SECONDS: u64 = 2; #[derive(Clap, Debug, Clone, PartialEq, Eq, Hash)] #[clap(version = "0.1")] struct Opts { - /// The directory name to watch. + /// The configuration file path. + #[clap(short, long, default_value = "ezau.toml")] + config: PathBuf, + #[clap(subcommand)] + subcmd: SubCommand, +} + +#[derive(Clap, Debug, Clone, PartialEq, Eq, Hash)] +enum SubCommand { + Watch(Watch), + Upload(Upload), +} + +/// Use the watch mode to automatically handle new logs. +/// +/// This watches the given directory for new files and then zips and uploads them. +#[derive(Clap, Debug, Clone, PartialEq, Eq, Hash)] +struct Watch { + /// The directory to watch. dirname: PathBuf, - /// The Discord auth token for the bot account. - #[clap(long)] - discord_token: String, - /// The channel ID where the log message should be posted. - #[clap(long)] - channel_id: u64, +} + +/// Upload a single log, as it would be done by the automatic watcher. +#[derive(Clap, Debug, Clone, PartialEq, Eq, Hash)] +struct Upload { + /// The log to upload. + path: PathBuf, } fn main() { @@ -46,12 +66,28 @@ fn main() { } fn inner_main(opts: &Opts) -> Result<()> { + let config = config::load(&opts.config)?; + match &opts.subcmd { + SubCommand::Watch(w) => watch(w, &config)?, + SubCommand::Upload(u) => { + let permalink = upload_log(&u.path)?; + println!("{}", permalink); + if let Some(d) = &config.discord { + let log = load_log(&u.path)?; + discord::post_link(&d.auth_token, d.channel_id, log, permalink)?; + } + } + } + Ok(()) +} + +fn watch(watch: &Watch, config: &Config) -> Result<()> { let raw_evtc_re = Regex::new(r"\d{8}-\d{6}(\.evtc)?$").unwrap(); let zip_evtc_re = Regex::new(r"(\.zip|\.zevtc)$").unwrap(); let (tx, rx) = channel(); let mut watcher = notify::watcher(tx, Duration::from_secs(WATCH_DELAY_SECONDS))?; - watcher.watch(&opts.dirname, RecursiveMode::Recursive)?; + watcher.watch(&watch.dirname, RecursiveMode::Recursive)?; loop { let event = rx.recv()?; debug!("Event: {:?}", event); @@ -62,7 +98,7 @@ fn inner_main(opts: &Opts) -> Result<()> { info!("Zipping up {}", path_str); zip_file(&path)?; } else if zip_evtc_re.is_match(path_str) { - handle_file(opts, &path)?; + handle_file(config, &path)?; } } } @@ -90,11 +126,14 @@ fn zip_file(filepath: &Path) -> Result<()> { Ok(()) } -fn handle_file(opts: &Opts, filename: &Path) -> Result<()> { +fn handle_file(config: &Config, filename: &Path) -> Result<()> { + if !config.upload { + return Ok(()); + } let log = load_log(filename)?; info!("Loaded log from category {}", log.category()); - if !should_upload(&log) { + if !should_upload(config, &log) { info!("Skipping log, not uploading"); return Ok(()); } @@ -102,14 +141,16 @@ fn handle_file(opts: &Opts, filename: &Path) -> Result<()> { let permalink = upload_log(filename)?; info!("Uploaded log, available at {}", permalink); - discord::post_link(&opts.discord_token, opts.channel_id, log, permalink)?; + if let Some(d) = &config.discord { + discord::post_link(&d.auth_token, d.channel_id, log, permalink)?; + } Ok(()) } -fn should_upload(log: &Log) -> bool { +fn should_upload(config: &Config, log: &Log) -> bool { // Only upload known logs - if log.encounter().is_none() { + if log.encounter().is_none() && !config.upload_unknown { return false; } // Only upload Skorvald if it actually was in 100 CM (and not in in lower-tier or non-CM). -- cgit v1.2.3