diff options
author | Daniel Schadt <kingdread@gmx.de> | 2020-06-08 11:35:12 +0200 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2020-06-08 11:35:12 +0200 |
commit | 26ba5291c0198a7317e02201a88d53613fcf1854 (patch) | |
tree | 80c50baf2e4a079f5eab696943322c595775c4d2 | |
parent | ccca613d4bd1454fa57d818c2b2a7c3629cf7ec2 (diff) | |
download | ezau-26ba5291c0198a7317e02201a88d53613fcf1854.tar.gz ezau-26ba5291c0198a7317e02201a88d53613fcf1854.tar.bz2 ezau-26ba5291c0198a7317e02201a88d53613fcf1854.zip |
implement watch & zip logic in Rust
evtc-watch consists of three parts at the moment: watch the files, zip
them up and call ezau to upload them. We can now just do all of those
inside of ezau, which saves us the extra script, makes it more
platform-independent (as notify also works on Windows) and makes
configuration and everything easier, as all the data will be inside of
one program and doesn't need to be passed around.
A flag (or subcommand!) to upload a single file might be added later to
retain the previous behaviour of ezau.
-rw-r--r-- | Cargo.lock | 110 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/main.rs | 79 |
3 files changed, 178 insertions, 14 deletions
@@ -302,10 +302,13 @@ dependencies = [ "clap", "evtclib", "log", + "notify", "pretty_env_logger", + "regex", "reqwest", "serde", "serenity", + "zip", ] [[package]] @@ -315,6 +318,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] +name = "filetime" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", +] + +[[package]] name = "flate2" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -348,6 +363,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] +name = "fsevent" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" +dependencies = [ + "bitflags", + "fsevent-sys", +] + +[[package]] +name = "fsevent-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" +dependencies = [ + "libc", +] + +[[package]] name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -619,6 +653,26 @@ dependencies = [ ] [[package]] +name = "inotify" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" +dependencies = [ + "libc", +] + +[[package]] name = "input_buffer" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -668,6 +722,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" + +[[package]] name = "libc" version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -754,6 +814,18 @@ dependencies = [ ] [[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log", + "mio", + "slab", +] + +[[package]] name = "miow" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -795,6 +867,24 @@ dependencies = [ ] [[package]] +name = "notify" +version = "4.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd" +dependencies = [ + "bitflags", + "filetime", + "fsevent", + "fsevent-sys", + "inotify", + "libc", + "mio", + "mio-extras", + "walkdir", + "winapi 0.3.8", +] + +[[package]] name = "num-derive" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1235,6 +1325,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] name = "schannel" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1741,6 +1840,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] +name = "walkdir" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +dependencies = [ + "same-file", + "winapi 0.3.8", + "winapi-util", +] + +[[package]] name = "want" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -16,3 +16,6 @@ evtclib = "0.3.3" reqwest = { version = "0.10.6", features = ["json"] } serde = "1.0.111" chrono = "0.4.11" +notify = "4.0.15" +regex = "1.3.9" +zip = "0.5.5" diff --git a/src/main.rs b/src/main.rs index 627a5c8..45ae5e9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,19 @@ -use std::path::{Path, PathBuf}; - -use anyhow::Result; +use std::{ + fs::{self, File}, + io::{BufWriter, Write}, + path::{Path, PathBuf}, + sync::mpsc::channel, + time::Duration, +}; + +use anyhow::{anyhow, Result}; use clap::Clap; use evtclib::{Boss, Compression, Log}; -use log::{error, info}; +use log::{debug, error, info}; +use notify::{self, DebouncedEvent, RecursiveMode, Watcher}; +use regex::Regex; use serde::Deserialize; +use zip::{CompressionMethod, ZipWriter}; mod categories; use categories::Categorizable; @@ -12,20 +21,18 @@ use categories::Categorizable; mod discord; const DPS_REPORT_API: &str = "https://dps.report/uploadContent"; +const WATCH_DELAY_SECONDS: u64 = 2; #[derive(Clap, Debug, Clone, PartialEq, Eq, Hash)] #[clap(version = "0.1")] struct Opts { - /// The filename to upload. - filename: PathBuf, - /// The configuration file to use. - #[clap(short, long, default_value = "ezau.toml")] - config: PathBuf, + /// The directory name to watch. + dirname: PathBuf, /// The Discord auth token for the bot account. - #[clap(short, long)] + #[clap(long)] discord_token: String, /// The channel ID where the log message should be posted. - #[clap(short, long)] + #[clap(long)] channel_id: u64, } @@ -39,7 +46,52 @@ fn main() { } fn inner_main(opts: &Opts) -> Result<()> { - let log = load_log(&opts.filename)?; + 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)?; + loop { + let event = rx.recv()?; + debug!("Event: {:?}", event); + if let DebouncedEvent::Create(path) = event { + let path_str = path.to_str().unwrap(); + // Check if we need to zip it first. + if raw_evtc_re.is_match(path_str) { + info!("Zipping up {}", path_str); + zip_file(&path)?; + } else if zip_evtc_re.is_match(path_str) { + handle_file(opts, &path)?; + } + } + } +} + +fn zip_file(filepath: &Path) -> Result<()> { + let evtc_content = fs::read(filepath)?; + + let filename = filepath + .file_name() + .ok_or_else(|| anyhow!("Path does not have a file name"))? + .to_str() + .ok_or_else(|| anyhow!("Filename is invalid utf-8"))?; + let outname = filepath.with_extension("zevtc"); + let outfile = BufWriter::new(File::create(&outname)?); + let mut zip = ZipWriter::new(outfile); + let options = + zip::write::FileOptions::default().compression_method(CompressionMethod::Deflated); + + zip.start_file(filename, options)?; + zip.write_all(&evtc_content)?; + zip.finish()?; + + fs::remove_file(filepath)?; + Ok(()) +} + +fn handle_file(opts: &Opts, filename: &Path) -> Result<()> { + let log = load_log(filename)?; info!("Loaded log from category {}", log.category()); if !should_upload(&log) { @@ -47,12 +99,11 @@ fn inner_main(opts: &Opts) -> Result<()> { return Ok(()); } - let permalink = upload_log(&opts.filename)?; + let permalink = upload_log(filename)?; info!("Uploaded log, available at {}", permalink); discord::post_link(&opts.discord_token, opts.channel_id, log, permalink)?; - info!("We done bois, wrapping it up!"); Ok(()) } |