The mangadex_api
crate provides a convenient, high-level wrapper
client for the MangaDex API,
written in Rust.
It covers all public endpoints covered by their documentation.
Documentation (Project main
branch)
Please note that as MangaDex is still in beta, this SDK will be subject to sudden breaking changes.
Add mangadex-api
to your dependencies:
```toml [dependencies]
mangadex-api = "1.0.0-alpha.6" ```
If you are using cargo-edit
, run
bash
cargo add mangadex-api
All features are not included by default. To enable them, add any of the following to your project's Cargo.toml
file.
multi-thread
- Enable the MangaDexClient
to be thread-safe, at the cost of operations being slightly more expensive.upload
- Enable endpoints that upload files to MangaDex.For example, to enable the upload
feature, add the following to your Cargo.toml
file:
toml
mangadex-api = { version = "1.0.0-alpha.6", features = ["upload"] }
The mangadex_api::MangaDexClient
is asynchronous, using
reqwest
as the HTTP client.
This example demonstrates how to fetch a random manga.
```rust use mangadex_api::MangaDexClient;
async fn main() -> anyhow::Result<()> { let client = MangaDexClient::default();
let random_manga = client
.manga()
.random()
.build()?
.send()
.await?;
println!("{:?}", random_manga);
Ok(())
} ```
By default, mangadex_api::MangaDexClient
will use the default
reqwest::Client
settings.
You may provide your own reqwest::Client
to customize options such as the
request timeout.
```rust use reqwest::Client;
use mangadex_api::MangaDexClient;
let reqwestclient = Client::builder() .timeout(std::time::Duration::fromsecs(10)) .build()?;
let client = MangaDexClient::new(reqwest_client);
```
```rust use mangadex_api::MangaDexClient;
let client = MangaDexClient::default();
let manga_results = client .manga() .search() .title("full metal") .build()? .send() .await?;
println!("manga results = {:?}", manga_results);
```
```rust // Imports used for downloading the pages to a file. // They are not used because we're just printing the raw bytes. // use std::fs::File; // use std::io::Write;
use reqwest::Url; use uuid::Uuid;
use mangadex_api::MangaDexClient;
let client = MangaDexClient::default();
let chapterid = Uuid::newv4(); let chapter = client .chapter() .get() .chapterid(&chapterid) .build()? .send() .await?;
let athomeurl = client .athome() .server() .chapterid(&chapterid) .build()? .send() .await? .baseurl;
let http_client = reqwest::Client::new();
// Original quality. Use .data.attributes.data_saver
for smaller, compressed images.
let pagefilenames = chapter.data.attributes.data;
for filename in pagefilenames {
let pageurl = athome_url
.join(&format!(
"/data/{}/{}",
chapter.data.attributes.hash, filename
))
.unwrap();
let res = http_client.get(page_url).send().await?;
// The data should be streamed rather than downloading the data all at once.
let bytes = res.bytes().await?;
// This is where you would download the file but for this example,
// we're just printing the raw data.
// let mut file = File::create(&filename)?;
// let _ = file.write_all(&bytes);
println!("Chunk: {:?}", bytes);
}
```
While this example could directly get the cover information by passing in the cover ID, it is not often that one would have the ID off-hand, so the most common method would be from a manga result.
If you want to get all of a manga's cover images, you will need to use the cover list endpoint
and use the manga[]
query parameter.
```rust // Imports used for downloading the cover to a file. // They are not used because we're just printing the raw bytes. // use std::fs::File; // use std::io::Write;
use reqwest::Url; use uuid::Uuid;
use mangadexapi::types::RelationshipType; use mangadexapi::MangaDexClient; use mangadexapi::CDNURL;
let client = MangaDexClient::default();
let mangaid = Uuid::newv4(); let manga = client .manga() .get() .mangaid(&mangaid) .build()? .send() .await?;
let coverid = manga .data .relationships .iter() .find(|related| related.type == RelationshipType::CoverArt) .expect("no cover art found for manga") .id; let cover = client .cover() .get() .coverid(&coverid) .build()? .send() .await?;
// This uses the best quality image. // To use smaller, thumbnail-sized images, append any of the following: // // - .512.jpg // - .256.jpg // // For example, "https://uploads.mangadex.org/covers/8f3e1818-a015-491d-bd81-3addc4d7d56a/4113e972-d228-4172-a885-cb30baffff97.jpg.512.jpg" let coverurl = Url::parse(&format!( "{}/covers/{}/{}", CDNURL, mangaid, cover.data.attributes.filename )) .unwrap();
let http_client = reqwest::Client::new();
let res = httpclient.get(coverurl).send().await?; // The data should be streamed rather than downloading the data all at once. let bytes = res.bytes().await?;
// This is where you would download the file but for this example, we're just printing the raw data. // let mut file = File::create(&filename)?; // let _ = file.write_all(&bytes); println!("Chunk: {:?}", bytes);
```
The changelog can be found here.
Changes are added manually to keep the changelog human-readable with summaries of the changes from each version.
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
We welcome contributions from everyone. There are many ways to contribute and the CONTRIBUTING.md document explains how you can contribute and get started.