use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::fs;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Message {
pub id: String,
pub channel_id: String,
pub channel_name: String,
pub author_id: String,
pub author_name: String,
pub content: String,
pub timestamp: String,
pub reply_to: String,
}
#[derive(Serialize, Deserialize, Default)]
struct Store {
schema_version: u32,
messages: Vec<Message>,
}
pub fn load(path: &str) -> Result<Vec<Message>> {
if !std::path::Path::new(path).exists() {
return Ok(vec![]);
}
let raw = fs::read_to_string(path)?;
let store: Store = toml::from_str(&raw)?;
Ok(store.messages)
}
pub fn save(path: &str, messages: &[Message]) -> Result<()> {
let store = Store {
schema_version: 1,
messages: messages.to_vec(),
};
let raw = toml::to_string(&store)?;
fs::write(path, raw)?;
Ok(())
}
pub fn merge(existing: &mut Vec<Message>, incoming: Vec<Message>) {
let known: std::collections::HashSet<String> =
existing.iter().map(|m| m.id.clone()).collect();
for msg in incoming {
if !known.contains(&msg.id) {
existing.push(msg);
}
}
}
pub fn thread(msg_id: &str, messages: &[Message], depth: usize) -> Vec<Message> {
let mut chain = vec![];
let mut current_id = msg_id.to_string();
for _ in 0..depth {
let found = messages.iter().find(|m| m.id == current_id);
match found {
Some(m) => {
chain.push(m.clone());
if m.reply_to.is_empty() { break; }
current_id = m.reply_to.clone();
}
None => break,
}
}
chain.reverse();
chain
}