use std::collections::HashSet;
use std::iter::FromIterator;
use clap::Parser;
use uuid::Uuid;
use mangadex_api::v5::MangaDexClient;
use mangadex_api_types::{
ChapterSortOrder, Language, OrderDirection, ReferenceExpansionResource, RelationshipType,
};
#[derive(Parser)]
#[clap(
name = "MangaDex Latest Chapters Updates",
about = "Fetch manga with recent chapter updates"
)]
struct Args {
#[clap(default_value = "en")]
languages: Vec<Language>,
#[clap(short, long, default_value = "1")]
page: u32,
#[clap(short, long, default_value = "10")]
limit: u32,
}
#[tokio::main]
async fn main() {
let args = Args::parse();
if let Err(e) = run(args).await {
use std::process;
eprintln!("Application error: {e}");
process::exit(1);
}
}
async fn run(args: Args) -> anyhow::Result<()> {
println!("The specified chapter languages are: {:?}", args.languages);
let client = MangaDexClient::default();
let chapters = client
.chapter()
.get()
.offset(get_page_offset(args.page, args.limit))
.limit(args.limit)
.translated_languages(args.languages)
.order(ChapterSortOrder::PublishAt(OrderDirection::Descending))
.send()
.await?;
let manga_ids: HashSet<Uuid> = chapters
.data
.iter()
.filter_map(|chapter| {
for r in &chapter.relationships {
if r.type_ == RelationshipType::Manga {
return Some(r.id);
}
}
None
})
.collect();
let manga_ids = Vec::from_iter(manga_ids);
let manga_list_res = client
.manga()
.get()
.include(&ReferenceExpansionResource::CoverArt)
.limit(manga_ids.len() as u32)
.manga_ids(manga_ids)
.send()
.await?;
let manga_list: Vec<(Uuid, String)> = manga_list_res
.data
.into_iter()
.map(|manga| {
(
manga.id,
manga
.attributes
.title
.get(&Language::English)
.unwrap_or(&"<NO ENGLISH TITLE>".to_string())
.clone(),
)
})
.collect();
println!("\n{manga_list:#?}");
Ok(())
}
fn get_page_offset(page: u32, limit: u32) -> u32 {
if page == 0 || limit == 0 {
return 0;
}
limit * (page - 1)
}