feat(main): add csv output

This commit is contained in:
aria 2025-07-07 22:17:22 +10:00
parent 50b9a8dac4
commit bad28abf05
Signed by: aria
SSH key fingerprint: SHA256:WqtcVnDMrv1lnUlNah5k31iywFUI/DV+5yHzCTO4Vds
3 changed files with 98 additions and 4 deletions

54
Cargo.lock generated
View file

@ -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"

View file

@ -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"

View file

@ -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<String>, selection: Vec<usize>) -> Result<(), Error> {
fn save_txt_file(
output: &String,
extracted: Vec<String>,
selection: Vec<usize>,
) -> 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<String>, selection: Vec<usize>)
})
}
fn save_csv_file(
output: &String,
extracted: Vec<String>,
selection: Vec<usize>,
) -> 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<Regex> = Lazy::new(|| {