fur_cli/helpers/
insertion.rs1use serde_json::json;
2use std::fs;
3use std::path::Path;
4
5use crate::commands::jot::{self, JotArgs};
6use crate::commands::chat;
7use crate::commands::message::{MsgArgs, detect_id, resolve_target_message};
8
9pub fn run_insert(args: &MsgArgs, insert_before: bool) {
11 let Some(target_pfx) = &args.id_prefix else {
12 eprintln!("❌ Must supply a target message ID prefix.");
13 return;
14 };
15
16 let target_id = detect_id(&Some(target_pfx.clone()))
18 .unwrap_or_else(|| resolve_target_message(Some(target_pfx.clone())));
19
20 let new_id = match create_message_from_passthrough(args) {
22 Ok(id) => id,
23 Err(e) => {
24 eprintln!("❌ {}", e);
25 return;
26 }
27 };
28
29 insert_message_relative_to(&target_id, &new_id, insert_before);
31
32 println!(
33 "➕ Inserted {} {} {}",
34 &new_id[..8],
35 if insert_before { "before" } else { "after" },
36 &target_id[..8]
37 );
38}
39
40fn create_message_from_passthrough(args: &MsgArgs) -> Result<String, String> {
42 if args.rest.is_empty() {
43 return Err("No jot/chat command provided.".into());
44 }
45
46 let cmd = args.rest[0].as_str();
47 let rest = &args.rest[1..];
48
49 match cmd {
50 "jot" => {
51 let avatar = rest.get(0).cloned();
53 let text = rest.get(1).cloned();
54
55 let jargs = JotArgs {
56 avatar,
57 positional_text: text,
58 text: None,
59 markdown: None,
60 img: None,
61 parent: None,
62 };
63
64 jot::run_jot(jargs);
65 Ok(get_current_message_id())
66 }
67
68 "chat" => {
69 let avatar = rest.get(0).cloned();
71 chat::run_chat(avatar);
72 Ok(get_current_message_id())
73 }
74
75 other => Err(format!("Unknown passthrough subcommand: {}", other)),
76 }
77}
78
79fn insert_message_relative_to(target_id: &str, new_id: &str, insert_before: bool) {
81 let fur_dir = Path::new(".fur");
82
83 let index_path = fur_dir.join("index.json");
85 let index: serde_json::Value =
86 serde_json::from_str(&fs::read_to_string(&index_path).unwrap()).unwrap();
87 let convo_id = index["active_thread"].as_str().unwrap();
88
89 let convo_path = fur_dir.join("threads").join(format!("{}.json", convo_id));
91 let mut convo: serde_json::Value =
92 serde_json::from_str(&fs::read_to_string(&convo_path).unwrap()).unwrap();
93
94 let arr = convo["messages"].as_array_mut().unwrap();
95
96 arr.retain(|v| v.as_str() != Some(new_id));
98
99 let idx = arr.iter().position(|v| v.as_str() == Some(target_id));
101
102 if let Some(i) = idx {
103 if insert_before {
104 arr.insert(i, json!(new_id));
105 } else {
106 arr.insert(i + 1, json!(new_id));
107 }
108 } else {
109 eprintln!("❌ Could not find target message {}.", target_id);
110 return;
111 }
112
113 fs::write(&convo_path, serde_json::to_string_pretty(&convo).unwrap()).unwrap();
115}
116
117pub fn get_current_message_id() -> String {
119 let idx_path = Path::new(".fur/index.json");
120 let index: serde_json::Value =
121 serde_json::from_str(&fs::read_to_string(idx_path).unwrap()).unwrap();
122
123 index["current_message"]
124 .as_str()
125 .expect("No current_message after jot/chat")
126 .to_string()
127}