1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! # booru-rs
//!
//! An async Rust client for various booru image board APIs.
//!
//! This library provides a unified interface for querying multiple booru sites
//! including Danbooru, Gelbooru, and Safebooru.
//!
//! ## Features
//!
//! - **Type-safe API**: Compile-time checks ensure you use the correct rating types for each booru
//! - **Async/await**: Built on tokio and reqwest for efficient async I/O
//! - **Connection pooling**: Shared HTTP client with automatic connection reuse
//! - **Proper error handling**: No panics, all errors are returned as `Result` types
//! - **Automatic retries**: Transient failures are retried with exponential backoff
//! - **Async streams**: Paginate through results with async iterators
//! - **Common trait**: Use the [`Post`] trait for generic code across booru sites
//!
//! ## Quick Start
//!
//! The easiest way to get started is with the [`prelude`]:
//!
//! ```no_run
//! use booru_rs::prelude::*;
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//! let posts = DanbooruClient::builder()
//! .tag("cat_ears")?
//! .rating(DanbooruRating::General)
//! .sort(Sort::Score)
//! .limit(10)
//! .build()
//! .get()
//! .await?;
//!
//! for post in posts {
//! println!("Post {}: {:?}", post.id, post.file_url);
//! }
//!
//! Ok(())
//! }
//! ```
//!
//! ## Supported Sites
//!
//! | Site | Client | Tag Limit | Auth Required |
//! |------|--------|-----------|---------------|
//! | [Danbooru](https://danbooru.donmai.us) | [`DanbooruClient`] | 2 | No |
//! | [Gelbooru](https://gelbooru.com) | [`GelbooruClient`] | Unlimited | Yes |
//! | [Safebooru](https://safebooru.org) | [`SafebooruClient`] | Unlimited | No |
//! | [Rule34](https://rule34.xxx) | [`Rule34Client`] | Unlimited | Yes |
//!
//! ## Pagination with Async Streams
//!
//! Use [`stream::PostStream`] to iterate through all results:
//!
//! ```no_run
//! use booru_rs::prelude::*;
//!
//! # async fn example() -> Result<()> {
//! let mut stream = SafebooruClient::builder()
//! .tag("landscape")?
//! .limit(100)
//! .into_post_stream()
//! .max_posts(500);
//!
//! while let Some(post) = stream.next().await {
//! println!("Post #{}", post?.id);
//! }
//! # Ok(())
//! # }
//! ```
//!
//! ## Generic Code with the Post Trait
//!
//! Use the [`Post`] trait to write code that works with any booru:
//!
//! ```no_run
//! use booru_rs::prelude::*;
//! use booru_rs::model::Post;
//!
//! fn print_post(post: &impl Post) {
//! println!("#{}: {}x{}", post.id(), post.width(), post.height());
//! }
//! ```
// Re-export core types at crate root for convenience
pub use Client;
pub use ClientBuilder;
pub use DanbooruClient;
pub use GelbooruClient;
pub use Rule34Client;
pub use SafebooruClient;
pub use Sort;
pub use ;
pub use Post;
/// Danbooru client and model types.
/// Gelbooru client and model types.
/// Rule34 client and model types.
/// Safebooru client and model types.