use std::fs::File;
use crate::Message;
use crate::core::models::OutputConfig;
use crate::error::ChatpackError;
pub fn write_csv(
messages: &[Message],
output_path: &str,
config: &OutputConfig,
) -> Result<(), ChatpackError> {
let file = File::create(output_path)?;
let mut writer = csv::WriterBuilder::new().delimiter(b';').from_writer(file);
let header = build_header(config);
writer.write_record(&header)?;
for msg in messages {
let record = build_record(msg, config);
writer.write_record(&record)?;
}
writer.flush()?;
Ok(())
}
pub fn to_csv(messages: &[Message], config: &OutputConfig) -> Result<String, ChatpackError> {
let mut writer = csv::WriterBuilder::new()
.delimiter(b';')
.from_writer(Vec::new());
let header = build_header(config);
writer.write_record(&header)?;
for msg in messages {
let record = build_record(msg, config);
writer.write_record(&record)?;
}
let bytes = writer
.into_inner()
.map_err(|e| std::io::Error::other(e.to_string()))?;
Ok(String::from_utf8(bytes)?)
}
fn build_header(config: &OutputConfig) -> Vec<&'static str> {
let mut header = Vec::new();
if config.include_ids {
header.push("ID");
}
if config.include_timestamps {
header.push("Timestamp");
}
header.push("Sender");
header.push("Content");
if config.include_replies {
header.push("ReplyTo");
}
if config.include_edited {
header.push("Edited");
}
header
}
fn build_record(msg: &Message, config: &OutputConfig) -> Vec<String> {
let mut record = Vec::new();
if config.include_ids {
record.push(msg.id.map(|id| id.to_string()).unwrap_or_default());
}
if config.include_timestamps {
record.push(
msg.timestamp
.map(|ts| ts.format("%Y-%m-%d %H:%M:%S").to_string())
.unwrap_or_default(),
);
}
record.push(msg.sender.clone());
record.push(msg.content.clone());
if config.include_replies {
record.push(msg.reply_to.map(|id| id.to_string()).unwrap_or_default());
}
if config.include_edited {
record.push(
msg.edited
.map(|ts| ts.format("%Y-%m-%d %H:%M:%S").to_string())
.unwrap_or_default(),
);
}
record
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_to_csv_basic() {
let messages = vec![Message::new("Alice", "Hello")];
let config = OutputConfig::default();
let csv = to_csv(&messages, &config).unwrap();
assert!(csv.contains("Sender;Content"));
assert!(csv.contains("Alice;Hello"));
}
}