// methods for interacting with tilde sbot use std::collections::HashMap; pub use crate::error::TildeError; use serde_json::{json, Value}; use std::process::{Command, exit}; mod error; pub struct TildeClient { pub name: String, pub port: String, pub binary_path: String, } pub fn init_sbot() { println!("++ init sbot!"); } impl TildeClient { pub fn run_tilde_command(&self, args: Vec<&str>) -> Result { let mut command = Command::new(&self.binary_path); command.args(args); let output = command .output().map_err(|e| TildeError { message: format!("Command execution failed: {}", e), })?; if !output.status.success() { println!("command: {:?}", command); println!("stderr: {:?}", String::from_utf8_lossy(&output.stderr).to_string()); println!("stdout: {:?}", String::from_utf8_lossy(&output.stdout).to_string()); return Err(TildeError { message: format!("Command failed with status: {}", output.status) }) } let result = String::from_utf8_lossy(&output.stdout).to_string(); println!("Command output: {}", result); Ok(result) } pub async fn tilde_command_to_value(&self, args: Vec<&str>) -> Result { let result = self.run_tilde_command(args)?; let value = serde_json::from_str(&result).map_err(|e| TildeError { message: format!("Failed to parse JSON: {}", e), })?; Ok(value) } pub async fn whoami(&self) -> Result { self.run_tilde_command(vec!["get_identity"]).map(|val| val.trim_end().to_string()) } pub async fn get_profile_info(&self, key: &str) -> Result { self.tilde_command_to_value(vec!["get_profile", "-i", key]).await } pub async fn latest_sequence_number(&self) -> Result { let key = self.whoami().await?; // let num = self.run_tilde_command(vec!["get_sequence", "-i", &key])?.parse::().map_err(|e| TildeError { // message: format!("Failed to parse u64 from sequence number: {}", e), // })?; let num = self.run_tilde_command(vec!["get_sequence", "-i", &key])?; println!("NUM: {}", num); Ok(num) } pub async fn is_following(&self, from_id: &str, to_id: &str) -> Result { todo!(); } pub async fn create_block(&self, key: &str) -> Result { todo!(); } pub async fn get_blocks(&self, key: &str) -> Result, TildeError> { todo!(); } pub async fn get_follows(&self, key: &str) -> Result, TildeError> { todo!(); } pub async fn get_friends(&self, key: &str) -> Result, TildeError> { todo!(); } pub async fn publish(&self, post: Value) -> Result { let json_string = post.to_string(); let key = self.whoami().await?; self.run_tilde_command(vec!["publish", "-u", ":admin", "-i", &key, "-c", &json_string]) } pub async fn publish_name(&self, name: &str) -> Result { let key = self.whoami().await?; let about_post = json!({ "type": "about", "about": key, "name": name }); self.publish(about_post).await } pub async fn publish_description(&self, description: &str) -> Result { let key = self.whoami().await?; let about_post = json!({ "type": "about", "about": key, "description": description }); self.publish(about_post).await } pub async fn publish_image(&self, image_blob_id: &str) -> Result { let key = self.whoami().await?; let about_post = json!({ "type": "about", "about": key, "image": image_blob_id }); self.publish(about_post).await } pub async fn store_blob(&self, blob_file_path: &str) -> Result { self.run_tilde_command(vec!["store_blob", "-f", blob_file_path]) } pub async fn private_message(&self, recipient_key: &str, message: &str) -> Result { let self_key = self.whoami().await?; self.run_tilde_command(vec!["private", "-u", ":admin", "-i", &self_key, "-r", recipient_key, "-t", message]) } pub async fn create_invite(&self, num_uses: i32) -> Result { // TODO: look up ip/domain from config let key = self.whoami().await?; self.run_tilde_command(vec!["create_invite", "-u", &num_uses.to_string(), "-i", &key, "-p", &self.port, "-a", "127.0.0.1", "-e", "-1"]) } }