aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2020-06-08 11:35:12 +0200
committerDaniel Schadt <kingdread@gmx.de>2020-06-08 11:35:12 +0200
commit26ba5291c0198a7317e02201a88d53613fcf1854 (patch)
tree80c50baf2e4a079f5eab696943322c595775c4d2 /src
parentccca613d4bd1454fa57d818c2b2a7c3629cf7ec2 (diff)
downloadezau-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.
Diffstat (limited to 'src')
-rw-r--r--src/main.rs79
1 files changed, 65 insertions, 14 deletions
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(())
}