use std::path::{Path, PathBuf}; use anyhow::Result; use clap::Clap; use evtclib::{Boss, Compression, Log}; use log::{error, info}; use serde::Deserialize; mod categories; use categories::Categorizable; mod discord; const DPS_REPORT_API: &str = "https://dps.report/uploadContent"; #[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 Discord auth token for the bot account. #[clap(short, long)] discord_token: String, /// The channel ID where the log message should be posted. #[clap(short, long)] channel_id: u64, } fn main() { pretty_env_logger::init(); let opts = Opts::parse(); if let Err(e) = inner_main(&opts) { error!("{}", e); } } fn inner_main(opts: &Opts) -> Result<()> { let log = load_log(&opts.filename)?; info!("Loaded log from category {}", log.category()); if !should_upload(&log) { info!("Skipping log, not uploading"); return Ok(()); } let permalink = upload_log(&opts.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(()) } fn should_upload(log: &Log) -> bool { // Only upload known logs if log.encounter().is_none() { return false; } // Only upload Skorvald if it actually was in 100 CM (and not in in lower-tier or non-CM). if log.encounter() == Some(Boss::Skorvald) && !log.is_cm() { return false; } true } fn load_log(path: &Path) -> Result { evtclib::process_file(path, Compression::Zip).map_err(Into::into) } fn upload_log(file: &Path) -> Result { #[derive(Debug, Deserialize)] struct ApiResponse { permalink: String, } let client = reqwest::blocking::Client::new(); let form = reqwest::blocking::multipart::Form::new().file("file", file)?; let resp: ApiResponse = client .post(DPS_REPORT_API) .query(&[("json", 1)]) .multipart(form) .send()? .json()?; Ok(resp.permalink) }