1 个版本 (0 个不稳定版本)
2.0.0-rc.1 | 2023 年 3 月 3 日 |
---|
在 网页开发 中排名第 2375
每月下载量 56
1MB
18K SLoC
mangadex-api
重要
这个 git 仓库只是从 gondolyr/mangadex-api 分支出来的,但由于项目已经下架,所以现在将维护这个 crate 以支持 special-eureka 和 eureka-manager
mangadex-api
crate 为 MangaDex API 提供了一个方便的、高级的包装 客户端,用 Rust 编写。
它涵盖了 他们的文档 中涵盖的所有公共端点。
请注意,由于 MangaDex 仍在测试阶段,此 SDK 可能会突然发生重大变化。
免责声明
mangadex-api
与 MangaDex 无关。
目录
需求
如何安装
将 mangadex-api
添加到您的依赖项
[dependencies]
# ...
mangadex-api = "2.0.0-rc.1"
如果您正在使用 cargo-edit
,请运行
cargo add mangadex-api
依赖项理由
依赖项 | 用于 | 包含 |
---|---|---|
anyhow |
捕获意外错误。 | always |
clap |
展示库功能的示例 | dev 构建 |
derive_builder |
方便地为 API 端点构建器生成设置器。 | always |
fake |
为单元测试生成随机数据。 | dev 构建 |
期货 |
异步请求处理。 | always |
reqwest |
向MangaDex API发送HTTP请求。 | always |
serde |
将HTTP响应体序列化为结构体。 | always |
serde_json |
为单元测试创建JSON对象。 | dev 构建 |
serde_qs |
HTTP请求的查询字符串序列化。 | always |
thiserror |
自定义错误处理。 | always |
time |
处理时间字段的便利类型。 | always |
tokio |
异步运行时,用于在示例中处理futures(不是库)。 | dev 构建 |
url |
方便的Url 类型,用于验证和包含URL。 |
always |
uuid |
方便的Uuid 类型,用于验证和包含请求和响应的UUID。也用于测试中随机生成UUID。 |
always |
wiremock |
HTTP模拟以测试MangaDex API。 | dev 构建 |
功能
默认情况下不包括所有功能。要启用它们,请将以下任何一个添加到项目的Cargo.toml
文件中。
-
multi-thread
启用
MangaDexClient
的线程安全,但会稍微增加操作成本。
例如,要启用multi-thread
功能,请将以下内容添加到您的Cargo.toml
文件中
mangadex-api = { version = "2.0.0-rc.1", features = ["multi-thread"] }
HTTP 客户端
mangadex_api::MangaDexClient
是异步的,使用reqwest
作为HTTP客户端。
响应结构体
响应结构体可以在schemas
模块中找到,并包含JSON响应中的字段。
入门
此示例演示了如何获取一本随机漫画。
use mangadex_api::v5::MangaDexClient;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = MangaDexClient::default();
let random_manga = client
.manga()
.random()
.build()?
.send()
.await?;
println!("{:?}", random_manga);
Ok(())
}
使用自定义 reqwest 客户端
默认情况下,mangadex_api::MangaDexClient
将使用默认的reqwest::Client
设置。
您可以为自定义选项(如请求超时)提供自己的reqwest::Client
。
use reqwest::Client;
use mangadex_api::v5::MangaDexClient;
# async fn run() -> anyhow::Result<()> {
let reqwest_client = Client::builder()
.timeout(std::time::Duration::from_secs(10))
.build()?;
let client = MangaDexClient::new(reqwest_client);
# Ok(())
# }
通过标题搜索漫画
参考:https://api.mangadex.org/swagger.html#/Manga/get-search-manga
use mangadex_api::v5::MangaDexClient;
# async fn run() -> anyhow::Result<()> {
let client = MangaDexClient::default();
let manga_results = client
.manga()
.search()
.title("full metal")
.build()?
.send()
.await?;
println!("manga results = {:?}", manga_results);
# Ok(())
# }
使用参考扩展通过标题搜索漫画
每次获取都会包括所有关系,但只包含最小信息,如关系类型和ID。参考扩展将在请求中添加的类型的结果中包含完整的JSON对象。
在下面的示例中,列表中的任何关联作者都将提供详细的信息,如作者姓名、传记和网站。
参考
- https://api.mangadex.org/docs/reference-expansion/
- 端点:https://api.mangadex.org/swagger.html#/Manga/get-search-manga
- 作者对象:https://api.mangadex.org/swagger.html#/Author/get-author-id
use mangadex_api::types::{ReferenceExpansionResource, RelationshipType};
use mangadex_api::v5::schema::RelatedAttributes;
use mangadex_api::v5::MangaDexClient;
# async fn run() -> anyhow::Result<()> {
let client = MangaDexClient::default();
let manga_results = client
.manga()
.search()
.title("full metal")
.include(&ReferenceExpansionResource::Author)
.build()?
.send()
.await?;
println!("manga results = {:?}", manga_results);
let authors = manga_results.data.iter().filter_map(|manga| {
for rel in &manga.relationships {
if rel.type_ == RelationshipType::Author {
return Some(rel);
}
}
None
});
for author in authors {
if let Some(RelatedAttributes::Author(author_attributes)) = &author.attributes {
println!("{} - {}", author.id, author_attributes.name);
}
}
# Ok(())
# }
下载章节页面
参考:https://api.mangadex.org/docs/reading-chapter/
// 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::v5::MangaDexClient;
# async fn run() -> anyhow::Result<()> {
let client = MangaDexClient::default();
let chapter_id = Uuid::new_v4();
let at_home = client
.at_home()
.server()
.chapter_id(&chapter_id)
.build()?
.send()
.await?;
let http_client = reqwest::Client::new();
// Original quality. Use `.data.attributes.data_saver` for smaller, compressed images.
let page_filenames = at_home.chapter.data;
for filename in page_filenames {
// If using the data-saver option, use "/data-saver/" instead of "/data/" in the URL.
let page_url = at_home
.base_url
.join(&format!(
"/{quality_mode}/{chapter_hash}/{page_filename}",
quality_mode = "data",
chapter_hash = at_home.chapter.hash,
page_filename = 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);
}
# Ok(())
# }
下载漫画的主要封面图像
虽然此示例可以直接通过传递封面ID来获取封面信息,但通常不会手头有ID,因此最常见的方法是从漫画结果中获取。
如果您想获取某部漫画的所有封面图片,您需要使用封面列表端点,并使用manga[]
查询参数。
// 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 mangadex_api::types::RelationshipType;
use mangadex_api::v5::MangaDexClient;
use mangadex_api::CDN_URL;
# async fn run() -> anyhow::Result<()> {
let client = MangaDexClient::default();
let manga_id = Uuid::new_v4();
let manga = client
.manga()
.get()
.manga_id(&manga_id)
.build()?
.send()
.await?;
let cover_id = manga
.data
.relationships
.iter()
.find(|related| related.type_ == RelationshipType::CoverArt)
.expect("no cover art found for manga")
.id;
let cover = client
.cover()
.get()
.cover_id(&cover_id)
.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 cover_url = Url::parse(&format!(
"{}/covers/{}/{}",
CDN_URL, manga_id, cover.data.attributes.file_name
))
.unwrap();
let http_client = reqwest::Client::new();
let res = http_client.get(cover_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);
# Ok(())
# }
变更日志
变更日志可以在这里找到。
手动添加变更以保持变更日志易于阅读,包含每个版本变更的摘要。
许可证
根据您的选择,许可协议为以下之一:
- Apache许可证,版本2.0(LICENSE-APACHE或https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT或http://opensource.org/licenses/MIT)
。
贡献
除非您明确说明,否则根据Apache-2.0许可证定义的,您有意提交以包含在作品中的任何贡献,将按照上述方式双许可,不附加任何额外的条款或条件。
贡献
我们欢迎所有人的贡献。有许多贡献的方式,CONTRIBUTING.md文档解释了您可以如何贡献以及如何开始。
依赖项
~6–21MB
~299K SLoC