From 26ba5291c0198a7317e02201a88d53613fcf1854 Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Mon, 8 Jun 2020 11:35:12 +0200 Subject: 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. --- src/main.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 14 deletions(-) (limited to 'src') 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(()) } -- cgit v1.2.3