Refactor to use an object-oriented pattern for Sbot #2
| @ -10,4 +10,5 @@ readme = "README.md" | |||||||
| license = "AGPL-3.0-only" | license = "AGPL-3.0-only" | ||||||
|  |  | ||||||
| [dependencies] | [dependencies] | ||||||
|  | dirs = "4.0.0" | ||||||
| regex = "1.5.4" | regex = "1.5.4" | ||||||
|  | |||||||
							
								
								
									
										17
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								README.md
									
									
									
									
									
								
							| @ -5,12 +5,21 @@ Rust wrapper around the Go `sbotcli` ScuttleButt tool ([cryptoscope/ssb](https:/ | |||||||
| ## Example | ## Example | ||||||
|  |  | ||||||
| ```rust | ```rust | ||||||
| let id = "@p13zSAiOpguI9nsawkGijsnMfWmFd5rlUNpzekEE+vI=.ed25519"; | use peach_sbotcli::{Sbot, SbotCliError}; | ||||||
|  |  | ||||||
| let follow_ref = peach_sbotcli::follow(id)?; | fn example() -> Result<(), SbotCliError> { | ||||||
| let block_ref = peach_sbotcli::block(id)?; |     // uses default paths for `sbotcli` and `go-sbot` working directory | ||||||
|  |     let sbot = Sbot::init(None, None)?; | ||||||
|  |  | ||||||
| let invite_code = peach_sbotcli::create_invite()?; |     let id = "@p13zSAiOpguI9nsawkGijsnMfWmFd5rlUNpzekEE+vI=.ed25519"; | ||||||
|  |  | ||||||
|  |     let follow_ref = sbot.follow(id)?; | ||||||
|  |     let block_ref = sbot.block(id)?; | ||||||
|  |  | ||||||
|  |     let invite_code = sbot.create_invite()?; | ||||||
|  |  | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ## Documentation | ## Documentation | ||||||
|  | |||||||
| @ -1,3 +1,5 @@ | |||||||
|  | //! Custom error implementations. | ||||||
|  |  | ||||||
| use core::str::Utf8Error; | use core::str::Utf8Error; | ||||||
| use regex::Error as RegexError; | use regex::Error as RegexError; | ||||||
| use std::{error, fmt, io::Error as IoError, string::FromUtf8Error}; | use std::{error, fmt, io::Error as IoError, string::FromUtf8Error}; | ||||||
| @ -20,6 +22,7 @@ pub enum SbotCliError { | |||||||
|     InvalidUtf8(Utf8Error), |     InvalidUtf8(Utf8Error), | ||||||
|     // external errors |     // external errors | ||||||
|     InvalidRegex(RegexError), |     InvalidRegex(RegexError), | ||||||
|  |     NoHomeDir, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl error::Error for SbotCliError {} | impl error::Error for SbotCliError {} | ||||||
| @ -57,6 +60,12 @@ impl fmt::Display for SbotCliError { | |||||||
|             SbotCliError::InvalidRegex(ref err) => { |             SbotCliError::InvalidRegex(ref err) => { | ||||||
|                 write!(f, "{}", err) |                 write!(f, "{}", err) | ||||||
|             } |             } | ||||||
|  |             SbotCliError::NoHomeDir => { | ||||||
|  |                 write!( | ||||||
|  |                     f, | ||||||
|  |                     "Error initialising sbotcli: no home directory could be determined" | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										711
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										711
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -5,15 +5,18 @@ | |||||||
| //! ## Example | //! ## Example | ||||||
| //! | //! | ||||||
| //! ```rust | //! ```rust | ||||||
| //! use peach_sbotcli::SbotCliError; | //! use peach_sbotcli::{Sbot, SbotCliError}; | ||||||
| //! | //! | ||||||
| //! fn example() -> Result<(), SbotCliError> { | //! fn example() -> Result<(), SbotCliError> { | ||||||
|  | //!     // uses default paths for `sbotcli` and `go-sbot` working directory | ||||||
|  | //!     let sbot = Sbot::init(None, None)?; | ||||||
|  | //! | ||||||
| //!     let id = "@p13zSAiOpguI9nsawkGijsnMfWmFd5rlUNpzekEE+vI=.ed25519"; | //!     let id = "@p13zSAiOpguI9nsawkGijsnMfWmFd5rlUNpzekEE+vI=.ed25519"; | ||||||
| //! | //! | ||||||
| //!     let follow_ref = peach_sbotcli::follow(id)?; | //!     let follow_ref = sbot.follow(id)?; | ||||||
| //!     let block_ref = peach_sbotcli::block(id)?; | //!     let block_ref = sbot.block(id)?; | ||||||
| //! | //! | ||||||
| //!     let invite_code = peach_sbotcli::create_invite()?; | //!     let invite_code = sbot.create_invite()?; | ||||||
| //! | //! | ||||||
| //!     Ok(()) | //!     Ok(()) | ||||||
| //! } | //! } | ||||||
| @ -36,365 +39,423 @@ | |||||||
| pub mod error; | pub mod error; | ||||||
| mod utils; | mod utils; | ||||||
|  |  | ||||||
| use std::{process::Command, result::Result}; |  | ||||||
|  |  | ||||||
| pub use crate::error::SbotCliError; | pub use crate::error::SbotCliError; | ||||||
|  | use std::{ffi::OsString, path::PathBuf, process::Command, result::Result}; | ||||||
|  |  | ||||||
| /* BLOBS */ | /// An `sbotcli` instance with associated methods for querying a Go sbot server. | ||||||
|  | pub struct Sbot { | ||||||
| // TODO: file an issue |     /// The path to the `sbotcli` binary. | ||||||
| //  - doesn't seem to be implemented in sbotcli yet |     pub sbotcli_path: OsString, | ||||||
| //  - unsure of input type (`file_path`) |     /// The working directory of the `go-sbot` instance (where the Scuttlebutt database is stored). | ||||||
| //  - unsure about using `-` to open `stdin` |     pub sbot_working_dir: OsString, | ||||||
| // |  | ||||||
| /// Add a file to the blob store. |  | ||||||
| /// |  | ||||||
| /// Calls `sbotcli blobs add [file_path]`. On success: trims the trailing whitespace from `stdout` and returns the blob reference. On error: returns the `stderr` output with a description. |  | ||||||
| /// |  | ||||||
| /// # Arguments |  | ||||||
| /// |  | ||||||
| /// * `file_path` - A string slice representing a file path |  | ||||||
| /// |  | ||||||
| pub fn add_blob(file_path: &str) -> Result<String, SbotCliError> { |  | ||||||
|     let output = Command::new("sbotcli") |  | ||||||
|         .arg("blobs") |  | ||||||
|         .arg("add") |  | ||||||
|         .arg(file_path) |  | ||||||
|         .output()?; |  | ||||||
|     if output.status.success() { |  | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |  | ||||||
|         let msg_ref = stdout.trim_end().to_string(); |  | ||||||
|  |  | ||||||
|         Ok(msg_ref) |  | ||||||
|     } else { |  | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |  | ||||||
|         Err(SbotCliError::Blob(format!("Error adding blob: {}", stderr))) |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* CONTACTS */ | impl Sbot { | ||||||
|  |     /// Initialise an `sbotcli` instance. Sets default path parameters for the `sbotcli` binary and | ||||||
|  |     /// `go-sbot` working directory if none are provided. Alternatively, uses the provided | ||||||
|  |     /// parameter(s) to define the path(s). | ||||||
|  |     /// | ||||||
|  |     /// # Arguments | ||||||
|  |     /// | ||||||
|  |     /// * `sbotcli_path` - an optional string slice representing a file path | ||||||
|  |     /// * `sbot_working_dir` - an optional string slice representing a directory path | ||||||
|  |     /// | ||||||
|  |     pub fn init( | ||||||
|  |         sbotcli_path: Option<&str>, | ||||||
|  |         sbot_working_dir: Option<&str>, | ||||||
|  |     ) -> Result<Self, SbotCliError> { | ||||||
|  |         // set default path for sbotcli | ||||||
|  |         let mut path = PathBuf::from(r"/usr/bin/sbotcli"); | ||||||
|  |  | ||||||
| /// Follow a peer. |         // overwrite the default path if one has been provided via the `sbotcli_path` arg | ||||||
| /// |         if let Some(p) = sbotcli_path { | ||||||
| /// Calls `sbotcli publish contact --following [id]`. On success: trims the trailing whitespace from `stdout` |             path = PathBuf::from(p); | ||||||
| /// and returns the message reference. On error: returns the `stderr` output with a description. |         }; | ||||||
| /// |  | ||||||
| /// # Arguments |  | ||||||
| /// |  | ||||||
| /// * `id` - A string slice representing an id (profile reference / public key) |  | ||||||
| /// |  | ||||||
| pub fn follow(id: &str) -> Result<String, SbotCliError> { |  | ||||||
|     let output = Command::new("sbotcli") |  | ||||||
|         .arg("publish") |  | ||||||
|         .arg("contact") |  | ||||||
|         .arg("--following") |  | ||||||
|         .arg(id) |  | ||||||
|         .output()?; |  | ||||||
|     if output.status.success() { |  | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |  | ||||||
|         let msg_ref = stdout.trim_end().to_string(); |  | ||||||
|  |  | ||||||
|         Ok(msg_ref) |         let mut dir = PathBuf::new(); | ||||||
|     } else { |         if let Some(d) = sbot_working_dir { | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |             // define the `sbot_working_dir` using the provided arg | ||||||
|         Err(SbotCliError::Contact(format!( |             dir.push(d) | ||||||
|             "Error following peer: {}", |         } else { | ||||||
|             stderr |             // set default path for go-sbot working directory if no arg is provided | ||||||
|         ))) |             // returns `Option<PathBuf>` | ||||||
|  |             let home_dir = dirs::home_dir(); | ||||||
|  |             // it's possible that the home directory cannot be determined, hence the `match` | ||||||
|  |             match home_dir { | ||||||
|  |                 Some(home_dir_path) => { | ||||||
|  |                     dir.push(home_dir_path); | ||||||
|  |                     dir.push(".ssb-go"); | ||||||
|  |                 } | ||||||
|  |                 // return an error if the home directory could not be determined | ||||||
|  |                 None => return Err(SbotCliError::NoHomeDir), | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         Ok(Self { | ||||||
|  |             sbotcli_path: path.into_os_string(), | ||||||
|  |             sbot_working_dir: dir.into_os_string(), | ||||||
|  |         }) | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Block a peer. |     /* BLOBS */ | ||||||
| /// |  | ||||||
| /// Calls `sbotcli publish contact --blocking [id]`. On success: trims the trailing whitespace from `stdout` and returns the message reference. On error: returns the `stderr` output with a description. |  | ||||||
| /// |  | ||||||
| /// # Arguments |  | ||||||
| /// |  | ||||||
| /// * `id` - A string slice representing an id (profile reference / public key) |  | ||||||
| /// |  | ||||||
| pub fn block(id: &str) -> Result<String, SbotCliError> { |  | ||||||
|     let output = Command::new("sbotcli") |  | ||||||
|         .arg("publish") |  | ||||||
|         .arg("contact") |  | ||||||
|         .arg("--blocking") |  | ||||||
|         .arg(id) |  | ||||||
|         .output()?; |  | ||||||
|     if output.status.success() { |  | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |  | ||||||
|         let msg_ref = stdout.trim_end().to_string(); |  | ||||||
|  |  | ||||||
|         Ok(msg_ref) |     // TODO: file an issue | ||||||
|     } else { |     //  - doesn't seem to be implemented in sbotcli yet | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |     //  - unsure of input type (`file_path`) | ||||||
|         Err(SbotCliError::Contact(format!( |     //  - unsure about using `-` to open `stdin` | ||||||
|             "Error blocking peer: {}", |     // | ||||||
|             stderr |     /// Add a file to the blob store. | ||||||
|         ))) |     /// | ||||||
|  |     /// Calls `sbotcli blobs add [file_path]`. On success: trims the trailing whitespace from `stdout` and returns the blob reference. On error: returns the `stderr` output with a description. | ||||||
|  |     /// | ||||||
|  |     /// # Arguments | ||||||
|  |     /// | ||||||
|  |     /// * `file_path` - A string slice representing a file path | ||||||
|  |     /// | ||||||
|  |     pub fn add_blob(&self, file_path: &str) -> Result<String, SbotCliError> { | ||||||
|  |         let output = Command::new(&self.sbotcli_path) | ||||||
|  |             .arg("blobs") | ||||||
|  |             .arg("add") | ||||||
|  |             .arg(file_path) | ||||||
|  |             .output()?; | ||||||
|  |         if output.status.success() { | ||||||
|  |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|  |             let msg_ref = stdout.trim_end().to_string(); | ||||||
|  |  | ||||||
|  |             Ok(msg_ref) | ||||||
|  |         } else { | ||||||
|  |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
|  |             Err(SbotCliError::Blob(format!("Error adding blob: {}", stderr))) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| /* GET NAME */ |     /* CONTACTS */ | ||||||
|  |  | ||||||
| /// Return latest name assignment from `about` msgs (the name in this case is for the public key |     /// Follow a peer. | ||||||
| /// associated with the local sbot instance). |     /// | ||||||
| /// |     /// Calls `sbotcli publish contact --following [id]`. On success: trims the trailing whitespace from `stdout` | ||||||
| /// Calls `sbotcli bytype --limit 10 --reverse about`. On success: parses the `stdout` to extract the |     /// and returns the message reference. On error: returns the `stderr` output with a description. | ||||||
| /// `name` and returns it. On error: returns the `stderr` output with a description. |     /// | ||||||
| /// |     /// # Arguments | ||||||
| pub fn get_name() -> Result<Option<String>, SbotCliError> { |     /// | ||||||
|     let output = Command::new("sbotcli") |     /// * `id` - A string slice representing an id (profile reference / public key) | ||||||
|         .arg("bytype") |     /// | ||||||
|         .arg("--limit") |     pub fn follow(&self, id: &str) -> Result<String, SbotCliError> { | ||||||
|         .arg("10") |         let output = Command::new(&self.sbotcli_path) | ||||||
|         .arg("--reverse") |             .arg("publish") | ||||||
|         .arg("about") |             .arg("contact") | ||||||
|         .output()?; |             .arg("--following") | ||||||
|     if output.status.success() { |             .arg(id) | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |             .output()?; | ||||||
|         let name = utils::regex_finder(r#""name": "(.*)""#, &stdout)?; |         if output.status.success() { | ||||||
|  |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|  |             let msg_ref = stdout.trim_end().to_string(); | ||||||
|  |  | ||||||
|         Ok(name) |             Ok(msg_ref) | ||||||
|     } else { |         } else { | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
|         // TODO: create a more generic error variant |             Err(SbotCliError::Contact(format!( | ||||||
|         Err(SbotCliError::GetAboutMsgs(format!( |                 "Error following peer: {}", | ||||||
|             "Error fetching about messages: {}", |                 stderr | ||||||
|             stderr |             ))) | ||||||
|         ))) |         } | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| /* INVITES */ |     /// Block a peer. | ||||||
|  |     /// | ||||||
|  |     /// Calls `sbotcli publish contact --blocking [id]`. On success: trims the trailing whitespace from `stdout` and returns the message reference. On error: returns the `stderr` output with a description. | ||||||
|  |     /// | ||||||
|  |     /// # Arguments | ||||||
|  |     /// | ||||||
|  |     /// * `id` - A string slice representing an id (profile reference / public key) | ||||||
|  |     /// | ||||||
|  |     pub fn block(&self, id: &str) -> Result<String, SbotCliError> { | ||||||
|  |         let output = Command::new(&self.sbotcli_path) | ||||||
|  |             .arg("publish") | ||||||
|  |             .arg("contact") | ||||||
|  |             .arg("--blocking") | ||||||
|  |             .arg(id) | ||||||
|  |             .output()?; | ||||||
|  |         if output.status.success() { | ||||||
|  |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|  |             let msg_ref = stdout.trim_end().to_string(); | ||||||
|  |  | ||||||
| /// Accept an invite code (trigger a mutual follow with the peer who generated the invite). |             Ok(msg_ref) | ||||||
| /// |         } else { | ||||||
| /// Calls `sbotcli invite accept [invite_code]`. On success: trims the trailing whitespace from `stdout` and returns the follow message reference. On error: returns the `stderr` output with a description. |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
| /// |             Err(SbotCliError::Contact(format!( | ||||||
| /// # Arguments |                 "Error blocking peer: {}", | ||||||
| /// |                 stderr | ||||||
| /// * `invite` - A string slice representing an invite code |             ))) | ||||||
| /// |         } | ||||||
| pub fn accept_invite(invite: &str) -> Result<String, SbotCliError> { |  | ||||||
|     let output = Command::new("sbotcli") |  | ||||||
|         .arg("invite") |  | ||||||
|         .arg("accept") |  | ||||||
|         .arg(invite) |  | ||||||
|         .output()?; |  | ||||||
|     if output.status.success() { |  | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |  | ||||||
|         let msg_ref = stdout.trim_end().to_string(); |  | ||||||
|         Ok(msg_ref) |  | ||||||
|     } else { |  | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |  | ||||||
|         Err(SbotCliError::Invite(format!( |  | ||||||
|             "Error accepting invite: {}", |  | ||||||
|             stderr |  | ||||||
|         ))) |  | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Return an invite code from go-sbot. |     /* GET NAME */ | ||||||
| /// |  | ||||||
| /// Calls `sbotcli invite create`. On success: trims the trailing whitespace from `stdout` and returns the invite code. On error: returns the `stderr` output with a description. |  | ||||||
| /// |  | ||||||
| pub fn create_invite() -> Result<String, SbotCliError> { |  | ||||||
|     let output = Command::new("sbotcli") |  | ||||||
|         .arg("invite") |  | ||||||
|         .arg("create") |  | ||||||
|         .output()?; |  | ||||||
|     if output.status.success() { |  | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |  | ||||||
|         let invite = stdout.trim_end().to_string(); |  | ||||||
|  |  | ||||||
|         Ok(invite) |     /// Return latest name assignment from `about` msgs (the name in this case is for the public key | ||||||
|     } else { |     /// associated with the local sbot instance). | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |     /// | ||||||
|         Err(SbotCliError::Invite(format!( |     /// Calls `sbotcli bytype --limit 10 --reverse about`. On success: parses the `stdout` to extract the | ||||||
|             "Error creating invite: {}", |     /// `name` and returns it. On error: returns the `stderr` output with a description. | ||||||
|             stderr |     /// | ||||||
|         ))) |     pub fn get_name(&self) -> Result<Option<String>, SbotCliError> { | ||||||
|  |         let output = Command::new(&self.sbotcli_path) | ||||||
|  |             .arg("bytype") | ||||||
|  |             .arg("--limit") | ||||||
|  |             .arg("10") | ||||||
|  |             .arg("--reverse") | ||||||
|  |             .arg("about") | ||||||
|  |             .output()?; | ||||||
|  |         if output.status.success() { | ||||||
|  |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|  |             let name = utils::regex_finder(r#""name": "(.*)""#, &stdout)?; | ||||||
|  |  | ||||||
|  |             Ok(name) | ||||||
|  |         } else { | ||||||
|  |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
|  |             // TODO: create a more generic error variant | ||||||
|  |             Err(SbotCliError::GetAboutMsgs(format!( | ||||||
|  |                 "Error fetching about messages: {}", | ||||||
|  |                 stderr | ||||||
|  |             ))) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| /* PUBLISH */ |     /* INVITES */ | ||||||
|  |  | ||||||
| /// Publish an about message with an image. |     /// Accept an invite code (trigger a mutual follow with the peer who generated the invite). | ||||||
| /// |     /// | ||||||
| /// Calls `sbotcli publish about --image [blob_reference] [id]`. On success: trims the trailing whitespace from `stdout` and returns the message reference. On error: returns the `stderr` output with a description. |     /// Calls `sbotcli invite accept [invite_code]`. On success: trims the trailing whitespace from `stdout` and returns the follow message reference. On error: returns the `stderr` output with a description. | ||||||
| /// |     /// | ||||||
| /// # Arguments |     /// # Arguments | ||||||
| /// |     /// | ||||||
| /// * `blob_ref` - A string slice representing a blob reference |     /// * `invite` - A string slice representing an invite code | ||||||
| /// * `id` - A string slice representing an id (profile reference / public key) |     /// | ||||||
| /// |     pub fn accept_invite(&self, invite: &str) -> Result<String, SbotCliError> { | ||||||
| pub fn publish_image(blob_ref: &str, id: &str) -> Result<String, SbotCliError> { |         let output = Command::new(&self.sbotcli_path) | ||||||
|     let output = Command::new("sbotcli") |             .arg("invite") | ||||||
|         .arg("publish") |             .arg("accept") | ||||||
|         .arg("about") |             .arg(invite) | ||||||
|         .arg("--image") |             .output()?; | ||||||
|         .arg(blob_ref) |         if output.status.success() { | ||||||
|         .arg(id) |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|         .output()?; |             let msg_ref = stdout.trim_end().to_string(); | ||||||
|     if output.status.success() { |             Ok(msg_ref) | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |         } else { | ||||||
|         let msg_ref = stdout.trim_end().to_string(); |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
|  |             Err(SbotCliError::Invite(format!( | ||||||
|         Ok(msg_ref) |                 "Error accepting invite: {}", | ||||||
|     } else { |                 stderr | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |             ))) | ||||||
|         Err(SbotCliError::Publish(format!( |         } | ||||||
|             "Error publishing image: {}", |  | ||||||
|             stderr |  | ||||||
|         ))) |  | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| // TODO: file an issue |     /// Return an invite code from go-sbot. | ||||||
| //  - doesn't seem to be implemented in sbotcli yet |     /// | ||||||
| // |     /// Calls `sbotcli invite create`. On success: trims the trailing whitespace from `stdout` and returns the invite code. On error: returns the `stderr` output with a description. | ||||||
| /// Publish an about message with a description. |     /// | ||||||
| /// |     pub fn create_invite(&self) -> Result<String, SbotCliError> { | ||||||
| /// Calls `sbotcli publish about --description [description] [id]`. On success: trims the trailing whitespace from `stdout` and returns the message reference. On error: returns the `stderr` output with a description. |         let output = Command::new(&self.sbotcli_path) | ||||||
| /// |             .arg("invite") | ||||||
| /// # Arguments |             .arg("create") | ||||||
| /// |             .output()?; | ||||||
| /// * `description` - A string slice representing a profile description (bio) |         if output.status.success() { | ||||||
| /// * `id` - A string slice representing an id (profile reference / public key) |             let stdout = String::from_utf8(output.stdout)?; | ||||||
| /// |             let invite = stdout.trim_end().to_string(); | ||||||
| pub fn publish_description(description: &str, id: &str) -> Result<String, SbotCliError> { |  | ||||||
|     let output = Command::new("sbotcli") |  | ||||||
|         .arg("publish") |  | ||||||
|         .arg("about") |  | ||||||
|         .arg("--description") |  | ||||||
|         .arg(description) |  | ||||||
|         .arg(id) |  | ||||||
|         .output()?; |  | ||||||
|     if output.status.success() { |  | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |  | ||||||
|         let msg_ref = stdout.trim_end().to_string(); |  | ||||||
|  |  | ||||||
|         Ok(msg_ref) |             Ok(invite) | ||||||
|     } else { |         } else { | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
|         Err(SbotCliError::Publish(format!( |             Err(SbotCliError::Invite(format!( | ||||||
|             "Error publishing description: {}", |                 "Error creating invite: {}", | ||||||
|             stderr |                 stderr | ||||||
|         ))) |             ))) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Publish an about message with a name. |     /* PUBLISH */ | ||||||
| /// |  | ||||||
| /// Calls `sbotcli publish about --name [name] [id]`. On success: trims the trailing whitespace from `stdout` and returns the message reference. On error: returns the `stderr` output with a description. |  | ||||||
| /// |  | ||||||
| /// # Arguments |  | ||||||
| /// |  | ||||||
| /// * `name` - A string slice representing a profile name (bio) |  | ||||||
| /// * `id` - A string slice representing an id (profile reference / public key) |  | ||||||
| /// |  | ||||||
| pub fn publish_name(id: &str, name: &str) -> Result<String, SbotCliError> { |  | ||||||
|     let output = Command::new("sbotcli") |  | ||||||
|         .arg("publish") |  | ||||||
|         .arg("about") |  | ||||||
|         .arg("--name") |  | ||||||
|         .arg(name) |  | ||||||
|         .arg(id) |  | ||||||
|         .output()?; |  | ||||||
|     if output.status.success() { |  | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |  | ||||||
|         let msg_ref = stdout.trim_end().to_string(); |  | ||||||
|  |  | ||||||
|         Ok(msg_ref) |     /// Publish an about message with an image. | ||||||
|     } else { |     /// | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |     /// Calls `sbotcli publish about --image [blob_reference] [id]`. On success: trims the trailing whitespace from `stdout` and returns the message reference. On error: returns the `stderr` output with a description. | ||||||
|         Err(SbotCliError::Publish(format!( |     /// | ||||||
|             "Error publishing name: {}", |     /// # Arguments | ||||||
|             stderr |     /// | ||||||
|         ))) |     /// * `blob_ref` - A string slice representing a blob reference | ||||||
|  |     /// * `id` - A string slice representing an id (profile reference / public key) | ||||||
|  |     /// | ||||||
|  |     pub fn publish_image(&self, blob_ref: &str, id: &str) -> Result<String, SbotCliError> { | ||||||
|  |         let output = Command::new(&self.sbotcli_path) | ||||||
|  |             .arg("publish") | ||||||
|  |             .arg("about") | ||||||
|  |             .arg("--image") | ||||||
|  |             .arg(blob_ref) | ||||||
|  |             .arg(id) | ||||||
|  |             .output()?; | ||||||
|  |         if output.status.success() { | ||||||
|  |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|  |             let msg_ref = stdout.trim_end().to_string(); | ||||||
|  |  | ||||||
|  |             Ok(msg_ref) | ||||||
|  |         } else { | ||||||
|  |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
|  |             Err(SbotCliError::Publish(format!( | ||||||
|  |                 "Error publishing image: {}", | ||||||
|  |                 stderr | ||||||
|  |             ))) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Publish a post (public message). |     // TODO: file an issue | ||||||
| /// |     //  - doesn't seem to be implemented in sbotcli yet | ||||||
| /// Calls `sbotcli publish post [text]". On success: trims the trailing whitespace from `stdout` and returns the message reference. On error: returns the `stderr` output with a description. |     // | ||||||
| /// |     /// Publish an about message with a description. | ||||||
| /// # Arguments |     /// | ||||||
| /// |     /// Calls `sbotcli publish about --description [description] [id]`. On success: trims the trailing whitespace from `stdout` and returns the message reference. On error: returns the `stderr` output with a description. | ||||||
| /// * `text` - A string slice representing a post (public message) |     /// | ||||||
| /// |     /// # Arguments | ||||||
| pub fn publish_post(text: &str) -> Result<String, SbotCliError> { |     /// | ||||||
|     let output = Command::new("sbotcli") |     /// * `description` - A string slice representing a profile description (bio) | ||||||
|         .arg("publish") |     /// * `id` - A string slice representing an id (profile reference / public key) | ||||||
|         .arg("post") |     /// | ||||||
|         .arg(text) |     pub fn publish_description(&self, description: &str, id: &str) -> Result<String, SbotCliError> { | ||||||
|         .output()?; |         let output = Command::new(&self.sbotcli_path) | ||||||
|     if output.status.success() { |             .arg("publish") | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |             .arg("about") | ||||||
|         let msg_ref = stdout.trim_end().to_string(); |             .arg("--description") | ||||||
|  |             .arg(description) | ||||||
|  |             .arg(id) | ||||||
|  |             .output()?; | ||||||
|  |         if output.status.success() { | ||||||
|  |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|  |             let msg_ref = stdout.trim_end().to_string(); | ||||||
|  |  | ||||||
|         Ok(msg_ref) |             Ok(msg_ref) | ||||||
|     } else { |         } else { | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
|         Err(SbotCliError::Publish(format!( |             Err(SbotCliError::Publish(format!( | ||||||
|             "Error publishing public post: {}", |                 "Error publishing description: {}", | ||||||
|             stderr |                 stderr | ||||||
|         ))) |             ))) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Publish a private message. Currently only supports sending the message to a single recipient |     /// Publish an about message with a name. | ||||||
| /// (multi-recipient support to be added later). |     /// | ||||||
| /// |     /// Calls `sbotcli publish about --name [name] [id]`. On success: trims the trailing whitespace from `stdout` and returns the message reference. On error: returns the `stderr` output with a description. | ||||||
| /// Calls `sbotcli publish post --recps [id] [msg]`. On success: trims the trailing whitespace from `stdout` |     /// | ||||||
| /// and returns the message reference. On error: returns the `stderr` output with a description. |     /// # Arguments | ||||||
| /// |     /// | ||||||
| /// # Arguments |     /// * `name` - A string slice representing a profile name (bio) | ||||||
| /// |     /// * `id` - A string slice representing an id (profile reference / public key) | ||||||
| /// * `id` - A string slice representing an id (profile reference / public key) |     /// | ||||||
| /// * `msg` - A string slice representing a private message |     pub fn publish_name(&self, id: &str, name: &str) -> Result<String, SbotCliError> { | ||||||
| /// |         let output = Command::new(&self.sbotcli_path) | ||||||
| pub fn publish_private_message(id: &str, msg: &str) -> Result<String, SbotCliError> { |             .arg("publish") | ||||||
|     let output = Command::new("sbotcli") |             .arg("about") | ||||||
|         .arg("publish") |             .arg("--name") | ||||||
|         .arg("post") |             .arg(name) | ||||||
|         .arg("--recps") |             .arg(id) | ||||||
|         .arg(id) |             .output()?; | ||||||
|         .arg(msg) |         if output.status.success() { | ||||||
|         .output()?; |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|     if output.status.success() { |             let msg_ref = stdout.trim_end().to_string(); | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |  | ||||||
|         let msg_ref = stdout.trim_end().to_string(); |  | ||||||
|  |  | ||||||
|         Ok(msg_ref) |             Ok(msg_ref) | ||||||
|     } else { |         } else { | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
|         Err(SbotCliError::Publish(format!( |             Err(SbotCliError::Publish(format!( | ||||||
|             "Error publishing private message: {}", |                 "Error publishing name: {}", | ||||||
|             stderr |                 stderr | ||||||
|         ))) |             ))) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| /* WHOAMI */ |     /// Publish a post (public message). | ||||||
|  |     /// | ||||||
|  |     /// Calls `sbotcli publish post [text]". On success: trims the trailing whitespace from `stdout` and returns the message reference. On error: returns the `stderr` output with a description. | ||||||
|  |     /// | ||||||
|  |     /// # Arguments | ||||||
|  |     /// | ||||||
|  |     /// * `text` - A string slice representing a post (public message) | ||||||
|  |     /// | ||||||
|  |     pub fn publish_post(&self, text: &str) -> Result<String, SbotCliError> { | ||||||
|  |         let output = Command::new(&self.sbotcli_path) | ||||||
|  |             .arg("publish") | ||||||
|  |             .arg("post") | ||||||
|  |             .arg(text) | ||||||
|  |             .output()?; | ||||||
|  |         if output.status.success() { | ||||||
|  |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|  |             let msg_ref = stdout.trim_end().to_string(); | ||||||
|  |  | ||||||
| /// Return the Scuttlebutt ID from go-sbot using `whoami`. |             Ok(msg_ref) | ||||||
| /// |         } else { | ||||||
| /// Calls `sbotcli call whoami`. On success: parses the `stdout` to extract the ID and returns it. |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
| /// On error: returns the `stderr` output with a description. |             Err(SbotCliError::Publish(format!( | ||||||
| /// |                 "Error publishing public post: {}", | ||||||
| pub fn whoami() -> Result<Option<String>, SbotCliError> { |                 stderr | ||||||
|     let output = Command::new("sbotcli").arg("call").arg("whoami").output()?; |             ))) | ||||||
|     if output.status.success() { |         } | ||||||
|         let stdout = String::from_utf8(output.stdout)?; |     } | ||||||
|         let id = utils::regex_finder(r#""id": "(.*)"\n"#, &stdout)?; |  | ||||||
|  |  | ||||||
|         Ok(id) |     /// Publish a private message. Currently only supports sending the message to a single recipient | ||||||
|     } else { |     /// (multi-recipient support to be added later). | ||||||
|         let stderr = std::str::from_utf8(&output.stderr)?; |     /// | ||||||
|         Err(SbotCliError::WhoAmI(format!( |     /// Calls `sbotcli publish post --recps [id] [msg]`. On success: trims the trailing whitespace from `stdout` | ||||||
|             "Error calling whoami: {}", |     /// and returns the message reference. On error: returns the `stderr` output with a description. | ||||||
|             stderr |     /// | ||||||
|         ))) |     /// # Arguments | ||||||
|  |     /// | ||||||
|  |     /// * `id` - A string slice representing an id (profile reference / public key) | ||||||
|  |     /// * `msg` - A string slice representing a private message | ||||||
|  |     /// | ||||||
|  |     pub fn publish_private_message(&self, id: &str, msg: &str) -> Result<String, SbotCliError> { | ||||||
|  |         let output = Command::new(&self.sbotcli_path) | ||||||
|  |             .arg("publish") | ||||||
|  |             .arg("post") | ||||||
|  |             .arg("--recps") | ||||||
|  |             .arg(id) | ||||||
|  |             .arg(msg) | ||||||
|  |             .output()?; | ||||||
|  |         if output.status.success() { | ||||||
|  |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|  |             let msg_ref = stdout.trim_end().to_string(); | ||||||
|  |  | ||||||
|  |             Ok(msg_ref) | ||||||
|  |         } else { | ||||||
|  |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
|  |             Err(SbotCliError::Publish(format!( | ||||||
|  |                 "Error publishing private message: {}", | ||||||
|  |                 stderr | ||||||
|  |             ))) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* WHOAMI */ | ||||||
|  |  | ||||||
|  |     /// Return the Scuttlebutt ID from go-sbot using `whoami`. | ||||||
|  |     /// | ||||||
|  |     /// Calls `sbotcli call whoami`. On success: parses the `stdout` to extract the ID and returns it. | ||||||
|  |     /// On error: returns the `stderr` output with a description. | ||||||
|  |     /// | ||||||
|  |     pub fn whoami(&self) -> Result<Option<String>, SbotCliError> { | ||||||
|  |         let output = Command::new(&self.sbotcli_path) | ||||||
|  |             .arg("call") | ||||||
|  |             .arg("whoami") | ||||||
|  |             .output()?; | ||||||
|  |         if output.status.success() { | ||||||
|  |             let stdout = String::from_utf8(output.stdout)?; | ||||||
|  |             let id = utils::regex_finder(r#""id": "(.*)"\n"#, &stdout)?; | ||||||
|  |  | ||||||
|  |             Ok(id) | ||||||
|  |         } else { | ||||||
|  |             let stderr = std::str::from_utf8(&output.stderr)?; | ||||||
|  |             Err(SbotCliError::WhoAmI(format!( | ||||||
|  |                 "Error calling whoami: {}", | ||||||
|  |                 stderr | ||||||
|  |             ))) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user