| Crates.io | boosty_api |
| lib.rs | boosty_api |
| version | 0.25.0 |
| created_at | 2025-06-29 16:15:24.711988+00 |
| updated_at | 2025-12-04 08:35:35.340372+00 |
| description | API client for interacting with Boosty platform |
| homepage | |
| repository | https://github.com/ath31st/boosty_api_rs |
| max_upload_size | |
| id | 1730886 |
| size | 201,800 |
A minimal, async-ready client for getting 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.
This crate is intended for research and personal use only. By using it, you agree to:
The author is not responsible for any misuse of this software.
🚧 This library is under active development.
Breaking changes, refactoring, and architectural updates may occur frequently.
Use with caution in production environments and pin specific versions if needed.
AuthProvider logic.The client automatically retries HTTP requests that fail due to transient network errors or expired access tokens.
get_request() method.get_post(blog, id).get_posts(blog, limit, page_size, start_offset).Post struct with serde support."not available" status gracefully.get_comments_response(blog_name, post_id, limit, reply_limit, order, offset).get_all_comments(blog_name, post_id, limit, reply_limit, order).create_comment(blog_name, post_id, blocks, reply_id).Comment and CommentResponse structs with serde support."not available" status gracefully.get_blog_targets(blog_name).create_blog_target(blog_name, description, target_sum, target_type).update_blog_target(target_id, description, target_sum).delete_blog_target(target_id).get_subscription_levels(blog_name, show_free_level).get_user_subscriptions(limit, with_follow), returning a paginated
SubscriptionsResponse.get_showcase(blog_name, limit, only_visible, offset).change_showcase_status(blog_name, status).ApiClient using reqwest.User-Agent, DNT, Cache-Control, etc.ApiError, AuthError with detailed variants.Add this to your Cargo.toml:
[dependencies]
boosty_api = "0.25.0"
or
cargo add boosty_api
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.get_post("some-blog-name", "post-id").await?;
println!("{:#?}", post);
Ok(())
}
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 = 50;
let page_size = 10;
let posts = api_client.get_posts("blog_name", limit, page_size, None).await?;
println!("{:#?}", posts);
Ok(())
}
Offset can be used to skip already downloaded posts or to start from a specific post. It consists of fields Post: "sortOrder": 1762949608 + "int_id": 9555337 or PostsResponse: extra: {"offset": "1762949608:9555337"}.
use boosty_api::{model::Post, media_content::ContentItem, traits::HasContent};
fn print_content(post: &Post) {
let content_items = post.extract_content();
for item in content_items {
match item {
ContentItem::Image { url, id } => {
println!("Image URL: {url}, ID: {id}");
}
ContentItem::Video { url } => {
println!("Video URL: {url}");
}
ContentItem::OkVideo { url, title, vid } => {
println!("OK Video URL: {url}, Title: {title}, ID: {vid}");
}
ContentItem::Audio {
url,
title,
file_type,
size,
} => {
println!(
"Audio URL: {url}, Title: {title}, Type: {}, Size: {size}",
file_type.as_deref().unwrap_or("unknown")
);
}
ContentItem::Text {
modificator,
content,
} => {
println!("Text: {content}, Modificator: {modificator}");
}
ContentItem::Smile {
small_url,
medium_url,
large_url,
name,
is_animated,
} => {
println!(
"Smile: {name}, Small URL: {small_url}, Medium URL: {medium_url}, Large URL: {large_url}, Animated: {is_animated}"
);
}
ContentItem::Link {
explicit,
content,
url,
} => {
println!("Link: {url}, Content: {content}, Explicit: {explicit}");
}
ContentItem::File { url, title, size } => {
println!("File: {title}, URL: {url}, Size: {size}");
}
ContentItem::List { style, items } => {
println!("List style: {style}");
for (i, group) in items.iter().enumerate() {
println!(" Group {i}:");
for (j, item) in group.iter().enumerate() {
println!(" Item {j}: {item:?}");
}
}
}
ContentItem::Unknown => {
println!("Unknown content type");
}
}
}
}
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:
api_client.set_bearer_token("access-token").await?;
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.
api_client — Main entry point. Handles API requests (e.g. fetching posts), manages HTTP headers, and authentication flow.auth_provider — Internal module responsible for refresh-token and access-token lifecycle management.model — Typed deserialization models for all Boosty API entities (e.g. posts, comments, users, media).error — Unified error types covering API, network, and authorization layers.media_content — Defines ContentItem and provides utilities for extracting structured media content from API responses.traits — Common traits (HasContent, HasTitle, IsAvailable) shared across multiple Boosty entities.All API and auth operations return Result<T, ApiError> or Result<T, AuthError>, depending on context. Errors are
strongly typed and cover:
For detailed documentation, please refer to docs.rs.
Contributions are welcome! Please open an issue or submit a pull request on GitHub.
This project is licensed under the MIT License.