extend documentation for all examples

This commit is contained in:
glyph 2022-02-15 10:26:51 +02:00
parent 506ebec7e4
commit 6a1aa0abda
4 changed files with 167 additions and 21 deletions

View File

@ -2,12 +2,28 @@ use std::process;
use golgi::{messages::SsbMessageContent, GolgiError, Sbot}; use golgi::{messages::SsbMessageContent, GolgiError, Sbot};
// Golgi is an asynchronous library so we must call it from within an
// async function. The `GolgiError` type encapsulates all possible
// error variants for the library.
async fn run() -> Result<(), GolgiError> { async fn run() -> Result<(), GolgiError> {
// Attempt to connect to an sbot instance using the default IP address,
// port and network key (aka. capabilities key).
let mut sbot_client = Sbot::init(None, None).await?; let mut sbot_client = Sbot::init(None, None).await?;
// Alternatively, we could specify a non-standard IP and port.
// let ip_port = "127.0.0.1:8021".to_string();
// let mut sbot_client = Sbot::init(Some(ip_port), None).await?;
// Call the `whoami` RPC method to retrieve the public key for the sbot
// identity. This is our 'local' public key.
let id = sbot_client.whoami().await?; let id = sbot_client.whoami().await?;
// Print the public key (identity) to `stdout`.
println!("whoami: {}", id); println!("whoami: {}", id);
// Compose an SSB `about` message type.
// The `SsbMessageContent` type has many variants and allows for a high
// degree of control when creating messages.
let name = SsbMessageContent::About { let name = SsbMessageContent::About {
about: id.clone(), about: id.clone(),
name: Some("golgi".to_string()), name: Some("golgi".to_string()),
@ -19,27 +35,46 @@ async fn run() -> Result<(), GolgiError> {
start_datetime: None, start_datetime: None,
}; };
// Publish the name message. The `publish` method returns a reference to
// the published message.
let name_msg_ref = sbot_client.publish(name).await?; let name_msg_ref = sbot_client.publish(name).await?;
// Print the message reference to `stdout`.
println!("name_msg_ref: {}", name_msg_ref); println!("name_msg_ref: {}", name_msg_ref);
// Compose an SSB `post` message type.
let post = SsbMessageContent::Post { let post = SsbMessageContent::Post {
text: "golgi go womp womp".to_string(), text: "golgi go womp womp".to_string(),
mentions: None, mentions: None,
}; };
// Publish the post.
let post_msg_ref = sbot_client.publish(post).await?; let post_msg_ref = sbot_client.publish(post).await?;
// Print the post reference to `stdout`.
println!("post_msg_ref: {}", post_msg_ref); println!("post_msg_ref: {}", post_msg_ref);
// Golgi also exposes convenience methods for some of the most common
// message types. Here we see an example of a convenience method for
// posting a description message. The description is for the local
// identity, ie. we are publishing this about "ourself".
let post_msg_ref = sbot_client let post_msg_ref = sbot_client
.publish_description("this is a description") .publish_description("this is a description")
.await?; .await?;
// Print the description message reference to `stdout`.
println!("description: {}", post_msg_ref); println!("description: {}", post_msg_ref);
let author: String = id.clone(); let author: String = id.clone();
println!("author: {:?}", author); println!("author: {:?}", author);
// Retrieve the description for the given public key (identity).
let description = sbot_client.get_description(&author).await?; let description = sbot_client.get_description(&author).await?;
// Print the description to `stdout`.
println!("found description: {:?}", description); println!("found description: {:?}", description);
// Compose and publish another `post` message type.
let post = SsbMessageContent::Post { let post = SsbMessageContent::Post {
text: "golgi go womp womp2".to_string(), text: "golgi go womp womp2".to_string(),
mentions: None, mentions: None,
@ -51,6 +86,9 @@ async fn run() -> Result<(), GolgiError> {
Ok(()) Ok(())
} }
// Enable an async main function and execute the `run()` function,
// catching any errors and printing them to `stderr` before exiting the
// process.
#[async_std::main] #[async_std::main]
async fn main() { async fn main() {
if let Err(e) = run().await { if let Err(e) = run().await {

View File

@ -5,76 +5,114 @@ use golgi::{
GolgiError, Sbot, GolgiError, Sbot,
}; };
// Golgi is an asynchronous library so we must call it from within an
// async function. The `GolgiError` type encapsulates all possible
// error variants for the library.
async fn run() -> Result<(), GolgiError> { async fn run() -> Result<(), GolgiError> {
// Attempt to connect to an sbot instance using the default IP address,
// port and network key (aka. capabilities key).
let mut sbot_client = Sbot::init(None, None).await?; let mut sbot_client = Sbot::init(None, None).await?;
// Call the `whoami` RPC method to retrieve the public key for the sbot
// identity. This is our 'local' public key.
let id = sbot_client.whoami().await?; let id = sbot_client.whoami().await?;
// Print the public key (identity) to `stdout`.
println!("whoami: {}", id); println!("whoami: {}", id);
// test ids to follow and block // Define IDs (public keys) to follow and block.
let to_follow = String::from("@5Pt3dKy2HTJ0mWuS78oIiklIX0gBz6BTfEnXsbvke9c=.ed25519"); let to_follow = String::from("@5Pt3dKy2HTJ0mWuS78oIiklIX0gBz6BTfEnXsbvke9c=.ed25519");
let to_block = String::from("@7Y4nwfQmVtAilEzi5knXdS2gilW7cGKSHXdXoT086LM=.ed25519"); let to_block = String::from("@7Y4nwfQmVtAilEzi5knXdS2gilW7cGKSHXdXoT086LM=.ed25519");
// follow to_follow // Set the relationship of the local identity to the `to_follow` identity.
// In this case, the `set_relationship` method publishes a `contact`
// message which defines following as `true` and blocking as `false`.
// A message reference is returned for the published `contact` message.
let response = sbot_client let response = sbot_client
.set_relationship(&to_follow, true, false) .set_relationship(&to_follow, true, false)
.await?; .await?;
// Print the message reference to `stdout`.
println!("follow_response: {:?}", response); println!("follow_response: {:?}", response);
// block to_block // Set the relationship of the local identity to the `to_block` identity.
// In this case, the `set_relationship` method publishes a `contact`
// message which defines following as `false` and blocking as `true`.
// A message reference is returned for the published `contact` message.
let response = sbot_client.set_relationship(&to_block, false, true).await?; let response = sbot_client.set_relationship(&to_block, false, true).await?;
// Print the message reference to `stdout`.
println!("follow_response: {:?}", response); println!("follow_response: {:?}", response);
// print all users you are following // Golgi also exposes convenience methods for following and blocking.
// Here is an example of a simpler way to follow an identity.
let _follow_response = sbot_client.follow(&to_follow).await?;
// Blocking can be achieved in a similar fashion.
let _block_response = sbot_client.block(&to_block).await?;
// Get a list of peers within 1 hop of the local identity.
let follows = sbot_client let follows = sbot_client
.friends_hops(FriendsHops { .friends_hops(FriendsHops {
max: 1, max: 1,
start: None, start: None,
// doesnt seem like reverse does anything, currently // The `reverse` parameter is not currently implemented in `go-sbot`.
reverse: Some(false), reverse: Some(false),
}) })
.await?; .await?;
// Print the list of peers to `stdout`.
println!("follows: {:?}", follows); println!("follows: {:?}", follows);
// print if you are following to_follow (should be true) // Determine if an identity (`source`) is following a second identity (`dest`).
// This method will return `true` or `false`.
let mref = sbot_client let mref = sbot_client
.friends_is_following(RelationshipQuery { .friends_is_following(RelationshipQuery {
source: id.clone(), source: id.clone(),
dest: to_follow.clone(), dest: to_follow.clone(),
}) })
.await?; .await?;
// Print the follow status to `stdout`.
println!("isfollowingmref: {}", mref); println!("isfollowingmref: {}", mref);
// print if you are blocking to_block (should be true) // Determine if an identity (`source`) is blocking a second identity (`dest`).
let mref = sbot_client let mref = sbot_client
.friends_is_blocking(RelationshipQuery { .friends_is_blocking(RelationshipQuery {
source: id.clone(), source: id.clone(),
dest: to_block.clone(), dest: to_block.clone(),
}) })
.await?; .await?;
// Print the block status to `stdout`.
println!("isblockingmref: {}", mref); println!("isblockingmref: {}", mref);
// print if you are blocking to_follow (should be false)
let mref = sbot_client let mref = sbot_client
.friends_is_blocking(RelationshipQuery { .friends_is_blocking(RelationshipQuery {
source: id.clone(), source: id.clone(),
dest: to_follow, dest: to_follow,
}) })
.await?; .await?;
// Output should be `false`.
println!("isblockingmref(should be false): {}", mref); println!("isblockingmref(should be false): {}", mref);
// print if you are following to_block (should be false)
let mref = sbot_client let mref = sbot_client
.friends_is_following(RelationshipQuery { .friends_is_following(RelationshipQuery {
source: id, source: id,
dest: to_block.clone(), dest: to_block.clone(),
}) })
.await?; .await?;
// Output should be `false`.
println!("isfollowingmref(should be false): {}", mref); println!("isfollowingmref(should be false): {}", mref);
Ok(()) Ok(())
} }
// Enable an async main function and execute the `run()` function,
// catching any errors and printing them to `stderr` before exiting the
// process.
#[async_std::main] #[async_std::main]
async fn main() { async fn main() {
if let Err(e) = run().await { if let Err(e) = run().await {

View File

@ -4,38 +4,69 @@ use kuska_ssb::api::dto::content::PubAddress;
use golgi::{messages::SsbMessageContent, GolgiError, Sbot}; use golgi::{messages::SsbMessageContent, GolgiError, Sbot};
// Golgi is an asynchronous library so we must call it from within an
// async function. The `GolgiError` type encapsulates all possible
// error variants for the library.
async fn run() -> Result<(), GolgiError> { async fn run() -> Result<(), GolgiError> {
// Attempt to connect to an sbot instance using the default IP address,
// port and network key (aka. capabilities key).
let mut sbot_client = Sbot::init(None, None).await?; let mut sbot_client = Sbot::init(None, None).await?;
// Call the `whoami` RPC method to retrieve the public key for the sbot
// identity. This is our 'local' public key.
let id = sbot_client.whoami().await?; let id = sbot_client.whoami().await?;
// Print the public key (identity) to `stdout`.
println!("whoami: {}", id); println!("whoami: {}", id);
// publish a pub address message (in order to test accepting invite from other client) // Compose a `pub` address type message.
let pub_address_msg = SsbMessageContent::Pub { let pub_address_msg = SsbMessageContent::Pub {
address: Some(PubAddress { address: Some(PubAddress {
// IP address.
host: Some("127.0.0.1".to_string()), host: Some("127.0.0.1".to_string()),
// Port.
port: 8009, port: 8009,
// Public key.
key: id, key: id,
}), }),
}; };
// Publish the `pub` address message.
// This step is required for successful invite code creation.
let pub_msg_ref = sbot_client.publish(pub_address_msg).await?; let pub_msg_ref = sbot_client.publish(pub_address_msg).await?;
// Print the message reference to `stdout`.
println!("pub_msg_ref: {}", pub_msg_ref); println!("pub_msg_ref: {}", pub_msg_ref);
// Generate an invite code that can be used 1 time.
let invite_code = sbot_client.invite_create(1).await?; let invite_code = sbot_client.invite_create(1).await?;
// Print the invite code to `stdout`.
println!("invite (1 use): {:?}", invite_code); println!("invite (1 use): {:?}", invite_code);
// Generate an invite code that can be used 7 times.
let invite_code_2 = sbot_client.invite_create(7).await?; let invite_code_2 = sbot_client.invite_create(7).await?;
// Print the invite code to `stdout`.
println!("invite (7 uses): {:?}", invite_code_2); println!("invite (7 uses): {:?}", invite_code_2);
// Define an invite code.
let test_invite = let test_invite =
"net:ssbroom2.commoninternet.net:8009~shs:wm8a1zHWjtESv4XSKMWU/rPRhnAoAiSAe4hQSY0UF5A="; "net:ssbroom2.commoninternet.net:8009~shs:wm8a1zHWjtESv4XSKMWU/rPRhnAoAiSAe4hQSY0UF5A=";
// Redeem an invite code (initiating a mutual follow between the local
// identity and the identity which generated the code (`wm8a1z...`).
let mref = sbot_client.invite_use(test_invite).await?; let mref = sbot_client.invite_use(test_invite).await?;
// Print the message reference to `stdout`.
println!("mref: {:?}", mref); println!("mref: {:?}", mref);
Ok(()) Ok(())
} }
// Enable an async main function and execute the `run()` function,
// catching any errors and printing them to `stderr` before exiting the
// process.
#[async_std::main] #[async_std::main]
async fn main() { async fn main() {
if let Err(e) = run().await { if let Err(e) = run().await {

View File

@ -1,56 +1,85 @@
use std::process; use std::process;
use async_std::stream::StreamExt; use async_std::stream::StreamExt;
use futures::{pin_mut, TryStreamExt}; use futures::TryStreamExt;
use golgi::{ use golgi::{
messages::{SsbMessageContentType, SsbMessageValue}, messages::{SsbMessageContentType, SsbMessageValue},
GolgiError, Sbot, GolgiError, Sbot,
}; };
// Golgi is an asynchronous library so we must call it from within an
// async function. The `GolgiError` type encapsulates all possible
// error variants for the library.
async fn run() -> Result<(), GolgiError> { async fn run() -> Result<(), GolgiError> {
// Attempt to connect to an sbot instance using the default IP address,
// port and network key (aka. capabilities key).
let mut sbot_client = Sbot::init(None, None).await?; let mut sbot_client = Sbot::init(None, None).await?;
// Call the `whoami` RPC method to retrieve the public key for the sbot
// identity. This is our 'local' public key.
let id = sbot_client.whoami().await?; let id = sbot_client.whoami().await?;
// Print the public key (identity) to `stdout`.
println!("whoami: {}", id); println!("whoami: {}", id);
let author = id.clone(); let author = id.clone();
// create a history stream // Create an ordered stream of all messages authored by the `author`
// identity.
let history_stream = sbot_client let history_stream = sbot_client
.create_history_stream(author.to_string()) .create_history_stream(author.to_string())
.await?; .await?;
// loop through the results until the end of the stream // Pin the stream to the stack to allow polling of the `future`.
pin_mut!(history_stream); // needed for iteration futures::pin_mut!(history_stream);
println!("looping through stream"); println!("looping through stream");
// Iterate through each element in the stream and match on the `Result`.
// In this case, each element has type `Result<SsbMessageValue, GolgiError>`.
while let Some(res) = history_stream.next().await { while let Some(res) = history_stream.next().await {
match res { match res {
Ok(value) => { Ok(value) => {
// Print the `SsbMessageValue` of this element to `stdout`.
println!("value: {:?}", value); println!("value: {:?}", value);
} }
Err(err) => { Err(err) => {
println!("err: {:?}", err); // Print the `GolgiError` of this element to `stderr`.
eprintln!("err: {:?}", err);
} }
} }
} }
println!("reached end of stream"); println!("reached end of stream");
// create a history stream and convert it into a Vec<SsbMessageValue> using try_collect // Create an ordered stream of all messages authored by the `author`
// (if there is any error in the results, it will be raised) // identity.
let history_stream = sbot_client let history_stream = sbot_client
.create_history_stream(author.to_string()) .create_history_stream(author.to_string())
.await?; .await?;
// Collect the stream elements into a `Vec<SsbMessageValue>` using
// `try_collect`. A `GolgiError` will be returned from the `run`
// function if any element contains an error.
let results: Vec<SsbMessageValue> = history_stream.try_collect().await?; let results: Vec<SsbMessageValue> = history_stream.try_collect().await?;
// Loop through the `SsbMessageValue` elements, printing each one
// to `stdout`.
for x in results { for x in results {
println!("x: {:?}", x); println!("x: {:?}", x);
} }
// example to create a history stream and use a map to convert stream of SsbMessageValue // Create an ordered stream of all messages authored by the `author`
// into a stream of tuples of (String, SsbMessageContentType) // identity.
let history_stream = sbot_client let history_stream = sbot_client
.create_history_stream(author.to_string()) .create_history_stream(author.to_string())
.await?; .await?;
// Iterate through the elements in the stream and use `map` to convert
// each `SsbMessageValue` element into a tuple of
// `(String, SsbMessageContentType)`. This is an example of stream
// conversion.
let type_stream = history_stream.map(|msg| match msg { let type_stream = history_stream.map(|msg| match msg {
Ok(val) => { Ok(val) => {
let message_type = val.get_message_type()?; let message_type = val.get_message_type()?;
@ -59,8 +88,15 @@ async fn run() -> Result<(), GolgiError> {
} }
Err(err) => Err(err), Err(err) => Err(err),
}); });
pin_mut!(type_stream); // needed for iteration
// Pin the stream to the stack to allow polling of the `future`.
futures::pin_mut!(type_stream);
println!("looping through type stream"); println!("looping through type stream");
// Iterate through each element in the stream and match on the `Result`.
// In this case, each element has type
// `Result<(String, SsbMessageContentType), GolgiError>`.
while let Some(res) = type_stream.next().await { while let Some(res) = type_stream.next().await {
match res { match res {
Ok(value) => { Ok(value) => {
@ -71,12 +107,15 @@ async fn run() -> Result<(), GolgiError> {
} }
} }
} }
println!("reached end of type stream"); println!("reached end of type stream");
// return Ok
Ok(()) Ok(())
} }
// Enable an async main function and execute the `run()` function,
// catching any errors and printing them to `stderr` before exiting the
// process.
#[async_std::main] #[async_std::main]
async fn main() { async fn main() {
if let Err(e) = run().await { if let Err(e) = run().await {