boosty_api 0.8.4

API client for interacting with Boosty platform
Documentation

Boosty API

A minimal, async-ready client for fetching post data from a remote blogging API that requires either a bearer token or a refresh token + device ID combo for authentication. This crate is designed with resiliency in mind: it transparently handles token expiration and retries requests when needed.

Table of Contents

Disclaimer

This crate is intended for research and personal use only. By using it, you agree to:

  • Access only your own content from the Boosty platform.
  • Refrain from scraping, redistributing, or otherwise misusing content that you do not own.
  • Comply with Boosty's Terms of Service and any applicable copyright laws.

The author is not responsible for any misuse of this software.

Features

  • Simple, high-level API for fetching individual posts or batches of posts.
  • Built-in token management using access and refresh tokens (similar in concept to OAuth2 flows).
  • Automatic token refreshing and retrying failed requests (when tokens are provided).
  • Deserialization into rich, typed Rust structs using serde.
  • Clean separation of concerns between authentication and API interaction.
  • Currently, supports content types: video, audio, image, text, link and file.

Installation

Add this to your Cargo.toml:

[dependencies]
boosty_api = "0.8.4"

or

cargo add boosty_api

Example fetching single post

use boosty_api::api_client::ApiClient;
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new();
    let base_url = "https://api.example.com";

    let api_client = ApiClient::new(client, base_url);

    // Use static bearer token (optional)
    api_client.set_bearer_token("your-access-token").await?;

    // Or use refresh token + device ID
    // api.set_refresh_token_and_device_id("your-refresh-token", "your-device-id").await?;

    let post = api_client.fetch_post("some-blog-name", "post-id").await?;
    println!("{:#?}", post);

    Ok(())
}

Example fetching multiple posts

use boosty_api::api_client::ApiClient;
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new();
    let base_url = "https://api.example.com";

    let api_client = ApiClient::new(client, base_url);

    // Use static bearer token (optional)
    api_client.set_bearer_token("your-access-token").await?;

    // Or use refresh token + device ID
    // api.set_refresh_token_and_device_id("your-refresh-token", "your-device-id").await?;
    let limit = 5;
    let posts = api_client.fetch_posts("blog_name", limit).await?;
    println!("{:#?}", posts);

    Ok(())
}

Extracting content from a post

use boosty_api::post_data_extractor::ContentItem;

let content_items = post.extract_content();
for item in content_items {
  match item {
    ContentItem::Image { url, id } => {
      println ! ("Image URL: {}, ID: {}", url, id);
    }
    ContentItem::Video { url } => {
      println ! ("Video URL: {}", url);
    }
    ContentItem::OkVideo { url, video_title } => {
      println ! ("OK Video URL: {}, Title: {}", url, video_title);
    }
    ContentItem::Audio { url, audio_title, file_type } => {
      println ! ("Audio URL: {}, Title: {}, Type: {}", url, audio_title, file_type);
    }
    ContentItem::Text { modificator, content } => {
      println ! ("Text: {}, Modificator: {}", content, modificator);
    }
    ContentItem::Link { explicit, content, url } => {
      println ! ("Link: {}, Content: {}, Explicit: {}", url, content, explicit);
    }
    ContentItem::File { url, title, size } => {
      println ! ("File: {}, URL: {}, Size: {}", title, url, size);
    }
    ContentItem::Unknown => {
      println ! ("Unknown content type");
    }
  }
}

Authentication

To get access token or refresh token and device_id, you need to log in to the service, then press F12 in the browser and go to the application tab, where you can select local storage. The required keys are _clentId and auth.

There are two options:

1. Static Bearer Token

api_client.set_bearer_token("access-token").await?;

2. Refresh Token Flow

api_client.set_refresh_token_and_device_id("refresh-token", "device-id").await?;

If a post is unavailable and refresh credentials are present, the client will automatically attempt a refresh.

Crate Structure

  • api_client: Main entry point; fetches post(s), manages headers, and authentication logic
  • auth_provider: Refresh-token and access-token management
  • api_response: Deserialization models for all content types (video, image, audio, etc.)
  • error: Uniform error types for API and auth operations
  • post_data_extractor: Utility module

Error Handling

All API and auth operations return Result<T, ApiError> or Result<T, AuthError>, depending on context. Errors are strongly typed and cover:

  • HTTP request failures
  • JSON (de)serialization issues
  • Invalid or expired credentials
  • Unsuccessful API status codes

API Documentation

For detailed documentation, please refer to docs.rs.

Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub.

License

This project is licensed under the MIT License.