mod single_or_list;
use std::io::{BufReader, BufWriter};
use std::path::{Path, PathBuf};
use color_eyre::eyre;
use color_eyre::eyre::bail;
use crate::single_or_list::{MaybeValid, SingleOrList};
use dovemail::outlook::OutlookMessage;
use dovemail::{write_message, MessageWriteError};
fn main() -> eyre::Result<()> {
color_eyre::install()?;
tracing::subscriber::set_global_default(
tracing_subscriber::FmtSubscriber::builder()
.with_max_level(tracing::Level::WARN)
.finish(),
)?;
let arg = get_arg()?;
if &arg == "-h" || &arg == "--help" || &arg == "-help" {
println!("usage: {} output_dir/", std::env::args().nth(0).unwrap());
return Ok(())
}
let output_dir = PathBuf::from(arg);
let messages = read_messages_from_stdin()?;
let mut had_error = false;
for maybe_message in messages {
match maybe_message {
MaybeValid::Valid(message) => {
if message.from.is_none() {
tracing::warn!(
"Skipping message because `From` is missing. id={} subject={}",
message.id,
message.subject
);
} else if let Err(e) = write_message_to_file(message, &output_dir) {
tracing::error!("{:?}", e);
had_error = true;
}
}
MaybeValid::Invalid(value) => {
let result: Result<OutlookMessage, _> = serde_json::from_value(value.clone());
tracing::error!(
"Invalid Outlook message JSON: {:?} --- Result: {:?}",
value,
result
);
had_error = true;
}
}
}
if had_error {
Err(eyre::Error::msg("Errors occurred."))
} else {
Ok(())
}
}
fn write_message_to_file(
message: OutlookMessage,
output_dir: &Path,
) -> Result<(), MessageWriteError> {
let file_name = format!("{:x}", seahash::hash(message.id.as_bytes()));
let output_path = output_dir.join(file_name);
let file = std::fs::File::create(output_path)?;
let mut writer = BufWriter::new(file);
write_message(&message, &mut writer)
}
fn get_arg() -> eyre::Result<String> {
let mut args = std::env::args();
if args.len() != 2 {
bail!("expected 1 positional argument.")
}
args.nth(1).ok_or_else(|| eyre::Error::msg("missing operand"))
}
fn read_messages_from_stdin() -> eyre::Result<Vec<MaybeValid<OutlookMessage>>> {
let reader = BufReader::new(std::io::stdin());
let data: SingleOrList<_> = serde_json::from_reader(reader)?;
Ok(data.into_vec())
}