fur_cli/commands/status/
core.rs

1use std::fs;
2use std::path::Path;
3use serde_json::Value;
4use std::collections::HashMap;
5
6pub fn load_index_and_thread(fur_dir: &Path)
7    -> (Value, Value, String)
8{
9    let index_path = fur_dir.join("index.json");
10    let index: Value = read_json(&index_path);
11
12    let thread_id = index["active_thread"].as_str().unwrap_or("");
13    let current = index["current_message"].as_str().unwrap_or("").to_string();
14
15    let thread_path = fur_dir.join("threads").join(format!("{}.json", thread_id));
16    let thread: Value = read_json(&thread_path);
17
18    (index, thread, current)
19}
20
21
22/// Preload all reachable messages
23pub fn build_id_to_message(
24    fur_dir: &Path,
25    thread: &Value
26) -> HashMap<String, Value> {
27    let mut id_to_message = HashMap::new();
28
29    let mut stack: Vec<String> = thread["messages"]
30        .as_array().unwrap_or(&vec![])
31        .iter()
32        .filter_map(|id| id.as_str().map(|s| s.to_string()))
33        .collect();
34
35    while let Some(mid) = stack.pop() {
36        let msg_path = fur_dir.join("messages").join(format!("{}.json", mid));
37        if let Ok(content) = fs::read_to_string(&msg_path) {
38            if let Ok(obj) = serde_json::from_str::<Value>(&content) {
39
40                // enqueue children
41                if let Some(children) = obj["children"].as_array() {
42                    for c in children {
43                        if let Some(cid) = c.as_str() {
44                            stack.push(cid.to_string());
45                        }
46                    }
47                }
48
49                // enqueue branch blocks
50                if let Some(blocks) = obj["branches"].as_array() {
51                    for block in blocks {
52                        if let Some(arr) = block.as_array() {
53                            for c in arr {
54                                if let Some(cid) = c.as_str() {
55                                    stack.push(cid.to_string());
56                                }
57                            }
58                        }
59                    }
60                }
61
62                id_to_message.insert(mid.clone(), obj);
63            }
64        }
65    }
66
67    id_to_message
68}
69
70/// If current_message missing, use first in thread.messages
71pub fn first_message_fallback(thread: &Value) -> String {
72    thread["messages"]
73        .as_array()
74        .and_then(|arr| arr.get(0))
75        .and_then(|v| v.as_str())
76        .unwrap_or("")
77        .to_string()
78}
79
80fn read_json(path: &Path) -> Value {
81    serde_json::from_str(
82        &fs::read_to_string(path)
83            .expect("❌ Cannot read JSON")
84    ).unwrap()
85}