1use crate::api::client::MoltbookClient;
7use crate::api::error::ApiError;
8use crate::api::types::{Submolt, SubmoltFeedResponse};
9use crate::display;
10use colored::Colorize;
11use serde_json::json;
12
13
14pub async fn list_submolts(
16 client: &MoltbookClient,
17 sort: &str,
18 limit: u64,
19) -> Result<(), ApiError> {
20
21 let response: serde_json::Value = client
22 .get(&format!("/submolts?sort={}&limit={}", sort, limit))
23 .await?;
24 let submolts: Vec<Submolt> = if let Some(s) = response.get("submolts") {
25 serde_json::from_value(s.clone())?
26 } else {
27 serde_json::from_value(response)?
28 };
29 println!(
30 "\n{} ({})",
31 "Available Submolts".bright_green().bold(),
32 sort
33 );
34 println!("{}", "=".repeat(60));
35 for s in submolts {
36 display::display_submolt(&s);
37 }
38 Ok(())
39}
40
41pub async fn view_submolt(
43 client: &MoltbookClient,
44 name: &str,
45 sort: &str,
46 limit: u64,
47) -> Result<(), ApiError> {
48
49 let response: SubmoltFeedResponse = client
50 .get(&format!(
51 "/submolts/{}/feed?sort={}&limit={}",
52 name, sort, limit
53 ))
54 .await?;
55 println!("\nSubmolt m/{} ({})", name, sort);
56 println!("{}", "=".repeat(60));
57 if response.posts.is_empty() {
58 display::info("No posts in this submolt yet.");
59 } else {
60 for (i, post) in response.posts.iter().enumerate() {
61 display::display_post(post, Some(i + 1));
62 }
63 }
64 Ok(())
65}
66
67pub async fn create_submolt(
68 client: &MoltbookClient,
69 name: &str,
70 display_name: &str,
71 description: Option<String>,
72 allow_crypto: bool,
73) -> Result<(), ApiError> {
74 let body = json!({
75 "name": name,
76 "display_name": display_name,
77 "description": description,
78 "allow_crypto": allow_crypto,
79 });
80 let result: serde_json::Value = client.post("/submolts", &body).await?;
81
82 if !crate::cli::verification::handle_verification(&result, "submolt") {
83 if result["success"].as_bool().unwrap_or(false) {
84 display::success(&format!("Submolt m/{} created successfully! 🦞", name));
85 }
86 }
87 Ok(())
88}
89
90pub async fn subscribe(client: &MoltbookClient, name: &str) -> Result<(), ApiError> {
91 let result: serde_json::Value = client
92 .post(&format!("/submolts/{}/subscribe", name), &json!({}))
93 .await?;
94 if !crate::cli::verification::handle_verification(&result, "subscription") {
95 if result["success"].as_bool().unwrap_or(false) {
96 display::success(&format!("Subscribed to m/{}", name));
97 }
98 }
99 Ok(())
100}
101
102pub async fn unsubscribe(client: &MoltbookClient, name: &str) -> Result<(), ApiError> {
103 let result: serde_json::Value = client
104 .delete(&format!("/submolts/{}/subscribe", name))
105 .await?;
106 if !crate::cli::verification::handle_verification(&result, "unsubscription") {
107 if result["success"].as_bool().unwrap_or(false) {
108 display::success(&format!("Unsubscribed from m/{}", name));
109 }
110 }
111 Ok(())
112}
113
114pub async fn pin_post(client: &MoltbookClient, post_id: &str) -> Result<(), ApiError> {
115 let result: serde_json::Value = client
116 .post(&format!("/posts/{}/pin", post_id), &json!({}))
117 .await?;
118 if !crate::cli::verification::handle_verification(&result, "pin action") {
119 if result["success"].as_bool().unwrap_or(false) {
120 display::success("Post pinned successfully! 📌");
121 }
122 }
123 Ok(())
124}
125
126pub async fn unpin_post(client: &MoltbookClient, post_id: &str) -> Result<(), ApiError> {
127 let result: serde_json::Value = client.delete(&format!("/posts/{}/pin", post_id)).await?;
128 if !crate::cli::verification::handle_verification(&result, "unpin action") {
129 if result["success"].as_bool().unwrap_or(false) {
130 display::success("Post unpinned");
131 }
132 }
133 Ok(())
134}
135
136pub async fn update_settings(
137 client: &MoltbookClient,
138 name: &str,
139 description: Option<String>,
140 banner_color: Option<String>,
141 theme_color: Option<String>,
142) -> Result<(), ApiError> {
143 let mut body = json!({});
144 if let Some(d) = description {
145 body["description"] = json!(d);
146 }
147 if let Some(bc) = banner_color {
148 body["banner_color"] = json!(bc);
149 }
150 if let Some(tc) = theme_color {
151 body["theme_color"] = json!(tc);
152 }
153
154 let result: serde_json::Value = client
155 .patch(&format!("/submolts/{}/settings", name), &body)
156 .await?;
157 if !crate::cli::verification::handle_verification(&result, "settings update") {
158 if result["success"].as_bool().unwrap_or(false) {
159 display::success(&format!("m/{} settings updated!", name));
160 }
161 }
162 Ok(())
163}
164
165pub async fn list_moderators(client: &MoltbookClient, name: &str) -> Result<(), ApiError> {
167
168 let response: serde_json::Value = client
169 .get(&format!("/submolts/{}/moderators", name))
170 .await?;
171 println!("\nModerators for m/{}", name.cyan());
172 if let Some(mods) = response["moderators"].as_array() {
173 for m in mods {
174 let agent = m["agent_name"].as_str().unwrap_or("unknown");
175 let role = m["role"].as_str().unwrap_or("moderator");
176 println!(" - {} ({})", agent.yellow(), role.dimmed());
177 }
178 }
179 Ok(())
180}
181
182pub async fn add_moderator(
183 client: &MoltbookClient,
184 name: &str,
185 agent_name: &str,
186 role: &str,
187) -> Result<(), ApiError> {
188 let body = json!({ "agent_name": agent_name, "role": role });
189 let result: serde_json::Value = client
190 .post(&format!("/submolts/{}/moderators", name), &body)
191 .await?;
192 if !crate::cli::verification::handle_verification(&result, "add moderator") {
193 if result["success"].as_bool().unwrap_or(false) {
194 display::success(&format!(
195 "Added {} as a moderator to m/{}",
196 agent_name, name
197 ));
198 }
199 }
200 Ok(())
201}
202
203pub async fn remove_moderator(
204 client: &MoltbookClient,
205 name: &str,
206 agent_name: &str,
207) -> Result<(), ApiError> {
208 let result: serde_json::Value = client
209 .delete(&format!("/submolts/{}/moderators/{}", name, agent_name))
210 .await?;
211 if !crate::cli::verification::handle_verification(&result, "remove moderator") {
212 if result["success"].as_bool().unwrap_or(false) {
213 display::success(&format!(
214 "Removed {} from moderators of m/{}",
215 agent_name, name
216 ));
217 }
218 }
219 Ok(())
220}