refactor to use Sbot object

This commit is contained in:
glyph 2021-11-04 16:57:27 +02:00
parent 97fc6cd3ff
commit 1c7a3ec39c

View File

@ -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,27 +39,81 @@
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 {
/// The path to the `sbotcli` binary.
pub sbotcli_path: OsString,
/// The working directory of the `go-sbot` instance (where the Scuttlebutt database is stored).
pub sbot_working_dir: OsString,
}
// TODO: file an issue impl Sbot {
// - doesn't seem to be implemented in sbotcli yet /// Initialise an `sbotcli` instance. Sets default path parameters for the `sbotcli` binary and
// - unsure of input type (`file_path`) /// `go-sbot` working directory if none are provided. Alternatively, uses the provided
// - unsure about using `-` to open `stdin` /// parameter(s) to define the path(s).
// ///
/// Add a file to the blob store. /// # Arguments
/// ///
/// 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. /// * `sbotcli_path` - an optional string slice representing a file path
/// /// * `sbot_working_dir` - an optional string slice representing a directory path
/// # Arguments ///
/// pub fn init(
/// * `file_path` - A string slice representing a file path sbotcli_path: Option<&str>,
/// sbot_working_dir: Option<&str>,
pub fn add_blob(file_path: &str) -> Result<String, SbotCliError> { ) -> Result<Self, SbotCliError> {
let output = Command::new("sbotcli") // set default path for sbotcli
let mut path = PathBuf::from(r"/usr/bin/sbotcli");
// overwrite the default path if one has been provided via the `sbotcli_path` arg
if let Some(p) = sbotcli_path {
path = PathBuf::from(p);
};
let mut dir = PathBuf::new();
if let Some(d) = sbot_working_dir {
// define the `sbot_working_dir` using the provided arg
dir.push(d)
} else {
// 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(),
})
}
/* BLOBS */
// TODO: file an issue
// - doesn't seem to be implemented in sbotcli yet
// - unsure of input type (`file_path`)
// - unsure about using `-` to open `stdin`
//
/// 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("blobs")
.arg("add") .arg("add")
.arg(file_path) .arg(file_path)
@ -70,21 +127,21 @@ pub fn add_blob(file_path: &str) -> Result<String, SbotCliError> {
let stderr = std::str::from_utf8(&output.stderr)?; let stderr = std::str::from_utf8(&output.stderr)?;
Err(SbotCliError::Blob(format!("Error adding blob: {}", stderr))) Err(SbotCliError::Blob(format!("Error adding blob: {}", stderr)))
} }
} }
/* CONTACTS */ /* CONTACTS */
/// Follow a peer. /// Follow a peer.
/// ///
/// Calls `sbotcli publish contact --following [id]`. On success: trims the trailing whitespace from `stdout` /// Calls `sbotcli publish contact --following [id]`. On success: trims the trailing whitespace from `stdout`
/// and returns the message reference. On error: returns the `stderr` output with a description. /// and returns the message reference. On error: returns the `stderr` output with a description.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `id` - A string slice representing an id (profile reference / public key) /// * `id` - A string slice representing an id (profile reference / public key)
/// ///
pub fn follow(id: &str) -> Result<String, SbotCliError> { pub fn follow(&self, id: &str) -> Result<String, SbotCliError> {
let output = Command::new("sbotcli") let output = Command::new(&self.sbotcli_path)
.arg("publish") .arg("publish")
.arg("contact") .arg("contact")
.arg("--following") .arg("--following")
@ -102,18 +159,18 @@ pub fn follow(id: &str) -> Result<String, SbotCliError> {
stderr stderr
))) )))
} }
} }
/// Block a peer. /// 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. /// 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 /// # Arguments
/// ///
/// * `id` - A string slice representing an id (profile reference / public key) /// * `id` - A string slice representing an id (profile reference / public key)
/// ///
pub fn block(id: &str) -> Result<String, SbotCliError> { pub fn block(&self, id: &str) -> Result<String, SbotCliError> {
let output = Command::new("sbotcli") let output = Command::new(&self.sbotcli_path)
.arg("publish") .arg("publish")
.arg("contact") .arg("contact")
.arg("--blocking") .arg("--blocking")
@ -131,18 +188,18 @@ pub fn block(id: &str) -> Result<String, SbotCliError> {
stderr stderr
))) )))
} }
} }
/* GET NAME */ /* GET NAME */
/// Return latest name assignment from `about` msgs (the name in this case is for the public key /// Return latest name assignment from `about` msgs (the name in this case is for the public key
/// associated with the local sbot instance). /// associated with the local sbot instance).
/// ///
/// Calls `sbotcli bytype --limit 10 --reverse about`. On success: parses the `stdout` to extract the /// Calls `sbotcli bytype --limit 10 --reverse about`. On success: parses the `stdout` to extract the
/// `name` and returns it. On error: returns the `stderr` output with a description. /// `name` and returns it. On error: returns the `stderr` output with a description.
/// ///
pub fn get_name() -> Result<Option<String>, SbotCliError> { pub fn get_name(&self) -> Result<Option<String>, SbotCliError> {
let output = Command::new("sbotcli") let output = Command::new(&self.sbotcli_path)
.arg("bytype") .arg("bytype")
.arg("--limit") .arg("--limit")
.arg("10") .arg("10")
@ -162,20 +219,20 @@ pub fn get_name() -> Result<Option<String>, SbotCliError> {
stderr stderr
))) )))
} }
} }
/* INVITES */ /* INVITES */
/// Accept an invite code (trigger a mutual follow with the peer who generated the invite). /// Accept an invite code (trigger a mutual follow with the peer who generated the invite).
/// ///
/// 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. /// 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
/// ///
/// * `invite` - A string slice representing an invite code /// * `invite` - A string slice representing an invite code
/// ///
pub fn accept_invite(invite: &str) -> Result<String, SbotCliError> { pub fn accept_invite(&self, invite: &str) -> Result<String, SbotCliError> {
let output = Command::new("sbotcli") let output = Command::new(&self.sbotcli_path)
.arg("invite") .arg("invite")
.arg("accept") .arg("accept")
.arg(invite) .arg(invite)
@ -191,14 +248,14 @@ pub fn accept_invite(invite: &str) -> Result<String, SbotCliError> {
stderr stderr
))) )))
} }
} }
/// Return an invite code from go-sbot. /// Return an invite code from go-sbot.
/// ///
/// 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. /// 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> { pub fn create_invite(&self) -> Result<String, SbotCliError> {
let output = Command::new("sbotcli") let output = Command::new(&self.sbotcli_path)
.arg("invite") .arg("invite")
.arg("create") .arg("create")
.output()?; .output()?;
@ -214,21 +271,21 @@ pub fn create_invite() -> Result<String, SbotCliError> {
stderr stderr
))) )))
} }
} }
/* PUBLISH */ /* PUBLISH */
/// Publish an about message with an image. /// Publish an about message with an image.
/// ///
/// 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 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.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `blob_ref` - A string slice representing a blob reference /// * `blob_ref` - A string slice representing a blob reference
/// * `id` - A string slice representing an id (profile reference / public key) /// * `id` - A string slice representing an id (profile reference / public key)
/// ///
pub fn publish_image(blob_ref: &str, id: &str) -> Result<String, SbotCliError> { pub fn publish_image(&self, blob_ref: &str, id: &str) -> Result<String, SbotCliError> {
let output = Command::new("sbotcli") let output = Command::new(&self.sbotcli_path)
.arg("publish") .arg("publish")
.arg("about") .arg("about")
.arg("--image") .arg("--image")
@ -247,22 +304,22 @@ pub fn publish_image(blob_ref: &str, id: &str) -> Result<String, SbotCliError> {
stderr stderr
))) )))
} }
} }
// TODO: file an issue // TODO: file an issue
// - doesn't seem to be implemented in sbotcli yet // - doesn't seem to be implemented in sbotcli yet
// //
/// Publish an about message with a description. /// Publish an about message with a description.
/// ///
/// 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. /// 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.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `description` - A string slice representing a profile description (bio) /// * `description` - A string slice representing a profile description (bio)
/// * `id` - A string slice representing an id (profile reference / public key) /// * `id` - A string slice representing an id (profile reference / public key)
/// ///
pub fn publish_description(description: &str, id: &str) -> Result<String, SbotCliError> { pub fn publish_description(&self, description: &str, id: &str) -> Result<String, SbotCliError> {
let output = Command::new("sbotcli") let output = Command::new(&self.sbotcli_path)
.arg("publish") .arg("publish")
.arg("about") .arg("about")
.arg("--description") .arg("--description")
@ -281,19 +338,19 @@ pub fn publish_description(description: &str, id: &str) -> Result<String, SbotCl
stderr stderr
))) )))
} }
} }
/// Publish an about message with a name. /// Publish an about message with a name.
/// ///
/// 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 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 /// # Arguments
/// ///
/// * `name` - A string slice representing a profile name (bio) /// * `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)
/// ///
pub fn publish_name(id: &str, name: &str) -> Result<String, SbotCliError> { pub fn publish_name(&self, id: &str, name: &str) -> Result<String, SbotCliError> {
let output = Command::new("sbotcli") let output = Command::new(&self.sbotcli_path)
.arg("publish") .arg("publish")
.arg("about") .arg("about")
.arg("--name") .arg("--name")
@ -312,18 +369,18 @@ pub fn publish_name(id: &str, name: &str) -> Result<String, SbotCliError> {
stderr stderr
))) )))
} }
} }
/// Publish a post (public message). /// 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. /// 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 /// # Arguments
/// ///
/// * `text` - A string slice representing a post (public message) /// * `text` - A string slice representing a post (public message)
/// ///
pub fn publish_post(text: &str) -> Result<String, SbotCliError> { pub fn publish_post(&self, text: &str) -> Result<String, SbotCliError> {
let output = Command::new("sbotcli") let output = Command::new(&self.sbotcli_path)
.arg("publish") .arg("publish")
.arg("post") .arg("post")
.arg(text) .arg(text)
@ -340,21 +397,21 @@ pub fn publish_post(text: &str) -> Result<String, SbotCliError> {
stderr stderr
))) )))
} }
} }
/// Publish a private message. Currently only supports sending the message to a single recipient /// Publish a private message. Currently only supports sending the message to a single recipient
/// (multi-recipient support to be added later). /// (multi-recipient support to be added later).
/// ///
/// Calls `sbotcli publish post --recps [id] [msg]`. On success: trims the trailing whitespace from `stdout` /// 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. /// and returns the message reference. On error: returns the `stderr` output with a description.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `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 /// * `msg` - A string slice representing a private message
/// ///
pub fn publish_private_message(id: &str, msg: &str) -> Result<String, SbotCliError> { pub fn publish_private_message(&self, id: &str, msg: &str) -> Result<String, SbotCliError> {
let output = Command::new("sbotcli") let output = Command::new(&self.sbotcli_path)
.arg("publish") .arg("publish")
.arg("post") .arg("post")
.arg("--recps") .arg("--recps")
@ -373,17 +430,20 @@ pub fn publish_private_message(id: &str, msg: &str) -> Result<String, SbotCliErr
stderr stderr
))) )))
} }
} }
/* WHOAMI */ /* WHOAMI */
/// Return the Scuttlebutt ID from go-sbot using `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. /// 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. /// On error: returns the `stderr` output with a description.
/// ///
pub fn whoami() -> Result<Option<String>, SbotCliError> { pub fn whoami(&self) -> Result<Option<String>, SbotCliError> {
let output = Command::new("sbotcli").arg("call").arg("whoami").output()?; let output = Command::new(&self.sbotcli_path)
.arg("call")
.arg("whoami")
.output()?;
if output.status.success() { if output.status.success() {
let stdout = String::from_utf8(output.stdout)?; let stdout = String::from_utf8(output.stdout)?;
let id = utils::regex_finder(r#""id": "(.*)"\n"#, &stdout)?; let id = utils::regex_finder(r#""id": "(.*)"\n"#, &stdout)?;
@ -396,6 +456,7 @@ pub fn whoami() -> Result<Option<String>, SbotCliError> {
stderr stderr
))) )))
} }
}
} }
#[cfg(test)] #[cfg(test)]