Crate bsky_sdk

Source
Expand description

§Bsky SDK: ATrium-based SDK for Bluesky.

Rust

  • ✔️ APIs for ATProto and Bluesky.
  • ✔️ Session management (same as atrium-api’s AtpAgent).
  • ✔️ Moderation APIs.
  • ✔️ A RichText library.

§Usage

§Session management

Log into a server using these APIs. You’ll need an active session for most methods.

use bsky_sdk::BskyAgent;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let agent = BskyAgent::builder().build().await?;
    let session = agent.login("alice@mail.com", "hunter2").await?;
    Ok(())
}

You can save the agent config (including the session) to a file and load it later:

use bsky_sdk::agent::config::FileStore;
use bsky_sdk::BskyAgent;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let agent = BskyAgent::builder().build().await?;
    agent.login("...", "...").await?;
    agent
        .to_config()
        .await
        .save(&FileStore::new("config.json"))
        .await?;
    Ok(())
}
use bsky_sdk::agent::config::{Config, FileStore};
use bsky_sdk::BskyAgent;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let agent = BskyAgent::builder()
        .config(Config::load(&FileStore::new("config.json")).await?)
        .build()
        .await?;
    let result = agent.api.com.atproto.server.get_session().await;
    assert!(result.is_ok());
    Ok(())
}

§Moderation

The moderation APIs have almost the same functionality as the official SDK (@atproto/api).

use bsky_sdk::moderation::decision::DecisionContext;
use bsky_sdk::BskyAgent;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let agent = BskyAgent::builder().build().await?;
    // log in...

    // First get the user's moderation prefs and their label definitions
    let preferences = agent.get_preferences(true).await?;
    let moderator = agent.moderator(&preferences).await?;

    // in feeds
    let output = agent
        .api
        .app
        .bsky
        .feed
        .get_timeline(
            atrium_api::app::bsky::feed::get_timeline::ParametersData {
                algorithm: None,
                cursor: None,
                limit: None,
            }
            .into(),
        )
        .await?;
    for feed_view_post in &output.feed {
        // We call the appropriate moderation function for the content
        let post_mod = moderator.moderate_post(&feed_view_post.post);
        // don't include in feeds?
        println!(
            "{:?} (filter: {})",
            feed_view_post.post.cid.as_ref(),
            post_mod.ui(DecisionContext::ContentList).filter()
        );
    }
    Ok(())
}

§Posts

Create a Bluesky post:

use atrium_api::types::string::Datetime;
use bsky_sdk::BskyAgent;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let agent = BskyAgent::builder().build().await?;
    agent.login("...", "...").await?;

    agent
        .create_record(atrium_api::app::bsky::feed::post::RecordData {
            created_at: Datetime::now(),
            embed: None,
            entities: None,
            facets: None,
            labels: None,
            langs: None,
            reply: None,
            tags: None,
            text: "Hello world, from Rust!".to_string(),
        })
        .await?;
    Ok(())
}

§RichText

Creating a RichText object from a string:

use bsky_sdk::rich_text::RichText;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let rt = RichText::new_with_detect_facets(
        "Hello @alice.com, check out this link: https://example.com",
    )
    .await?;

    let segments = rt.segments();
    assert_eq!(segments.len(), 4);
    assert!(segments[0].text == "Hello ");
    assert!(segments[1].text == "@alice.com" && segments[1].mention().is_some());
    assert!(segments[2].text == ", check out this link: ");
    assert!(segments[3].text == "https://example.com" && segments[3].link().is_some());

    let record_data = atrium_api::app::bsky::feed::post::RecordData {
        created_at: atrium_api::types::string::Datetime::now(),
        embed: None,
        entities: None,
        facets: rt.facets,
        labels: None,
        langs: None,
        reply: None,
        tags: None,
        text: rt.text,
    };
    println!("{:?}", record_data);
    Ok(())
}

Calculating string lengths:

use bsky_sdk::rich_text::RichText;

fn main() {
    let rt = RichText::new("👨‍👩‍👧‍👧", None);
    assert_eq!(rt.text.len(), 25);
    assert_eq!(rt.grapheme_len(), 1);
}

Re-exports§

pub use agent::BskyAgent;
pub use error::Error;
pub use error::Result;
pub use atrium_api as api;

Modules§

agent
Implementation of BskyAgent and their builders.
error
Error types for the Bsky SDK.
moderation
Moderation module for working with Bluesky’s moderation.
preference
Preferences for Bluesky application.
record
Record operations.
rich_textrich-text
Rich text module for working with text that contains facets.