From bad28abf05d6419b88e3698c723d598149e5e1b2 Mon Sep 17 00:00:00 2001 From: aria Date: Mon, 7 Jul 2025 22:17:22 +1000 Subject: [PATCH] feat(main): add csv output --- Cargo.lock | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/main.rs | 47 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 98 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0aa53dd..5f1b76f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -182,6 +182,27 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "csv" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" +dependencies = [ + "memchr", +] + [[package]] name = "dialoguer" version = "0.11.0" @@ -260,6 +281,12 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + [[package]] name = "js-sys" version = "0.3.77" @@ -295,6 +322,7 @@ dependencies = [ "anyhow", "clap", "console 0.16.0", + "csv", "dialoguer", "indicatif", "once_cell", @@ -412,6 +440,32 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "shell-words" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 17b1a70..caa0b33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" anyhow = "1.0.98" clap = { version = "4.5.40", features = ["derive"] } console = "0.16.0" +csv = "1.3.1" dialoguer = "0.11.0" indicatif = "0.18.0" once_cell = "1.21.3" diff --git a/src/main.rs b/src/main.rs index 385e9d7..293871b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,12 @@ -use std::{fs::{self, File}, io::Write, process::exit}; +use std::{ + fs::{self, File}, + io::Write, + process::exit, +}; use anyhow::{Error, Result}; use clap::Parser; +use csv::Writer; use dialoguer::MultiSelect; use once_cell::sync::Lazy; use rayon::{ @@ -82,17 +87,21 @@ fn main() -> Result<()> { .with_prompt("What messages do you want to render?") .items(&extracted) .interact()?; - + match &args.format { OutputFormat::Image => todo!(), - OutputFormat::CSV => todo!(), + OutputFormat::CSV => save_csv_file(&args.output, extracted, selection)?, OutputFormat::TXT => save_txt_file(&args.output, extracted, selection)?, } Ok(()) } -fn save_txt_file(output: &String, extracted: Vec, selection: Vec) -> Result<(), Error> { +fn save_txt_file( + output: &String, + extracted: Vec, + selection: Vec, +) -> Result<(), Error> { let mut out_file = File::create(output)?; Ok(for msg in selection { out_file.write(extracted[msg].as_bytes())?; @@ -100,6 +109,36 @@ fn save_txt_file(output: &String, extracted: Vec, selection: Vec) }) } +fn save_csv_file( + output: &String, + extracted: Vec, + selection: Vec, +) -> Result<(), Error> { + let mut out_file = Writer::from_path(output)?; + out_file.write_record(&["date", "time", "msg"])?; + + Ok(for msg in selection { + let time: Vec<&str> = EXTRACT_TIME + .captures(&extracted[msg]) + .expect("Unable to extract time") + .get(0) + .unwrap() + .as_str() + .strip_prefix("[").expect("Unable to remove time prefix") + .strip_suffix("]").expect("Unable to remove time suffix") + .split(' ').collect(); + out_file.write_record(&[ + time[0], + time[1], + EXTRACT_MSG + .captures(&extracted[msg]) + .expect("Unable to extract time") + .get(0) + .unwrap() + .as_str()])?; + }) +} + fn is_possible_chat_msg(input: &str) -> bool { /// first pass to find all possible lines that could have a chat message static SERVER_MSG_RE: Lazy = Lazy::new(|| {