diff options
author | Daniel Schadt <kingdread@gmx.de> | 2020-06-08 15:35:47 +0200 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2020-06-08 15:35:47 +0200 |
commit | d55d1634c2073768f1781652bb9f15ebe74be697 (patch) | |
tree | d14df97fee5bd166760ec1763cd42b6527668c3a | |
parent | 3bd2201e51b8899305e4c4370a04389611d7d22e (diff) | |
download | ezau-d55d1634c2073768f1781652bb9f15ebe74be697.tar.gz ezau-d55d1634c2073768f1781652bb9f15ebe74be697.tar.bz2 ezau-d55d1634c2073768f1781652bb9f15ebe74be697.zip |
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.
-rw-r--r-- | Cargo.lock | 10 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/config.rs | 31 | ||||
-rw-r--r-- | src/main.rs | 71 |
4 files changed, 98 insertions, 15 deletions
@@ -308,6 +308,7 @@ dependencies = [ "reqwest", "serde", "serenity", + "toml", "zip", ] @@ -1687,6 +1688,15 @@ dependencies = [ ] [[package]] +name = "toml" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" +dependencies = [ + "serde", +] + +[[package]] name = "tower-service" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -20,3 +20,4 @@ chrono = "0.4.11" notify = "4.0.15" regex = "1.3.9" zip = "0.5.5" +toml = "0.5.6" 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<Discord>, +} + +/// 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<P: AsRef<Path>>(path: P) -> Result<Config> { + 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). |