eureka_manager_cli/commands/count/
manga.rs1use clap::{Args, ValueEnum};
2use eureka_mmanager::{
3 files_dirs::messages::pull::manga::MangaListDataPullMessage,
4 prelude::{GetManagerStateData, IntoParamedFilteredStream, MangaListDataPullFilterParams},
5};
6use mangadex_api_types_rust::{
7 ContentRating, Demographic, Language, MangaDexDateTime, MangaStatus,
8};
9use tokio_stream::StreamExt;
10use uuid::Uuid;
11
12use crate::commands::{AsyncRun, AsyncRunContext};
13
14use super::TagSearchModeEnum;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, ValueEnum)]
17pub enum MangaStatusEnum {
18 Ongoing,
20 Completed,
22 Hiatus,
24 Cancelled,
26}
27
28impl From<MangaStatusEnum> for MangaStatus {
29 fn from(value: MangaStatusEnum) -> Self {
30 match value {
31 MangaStatusEnum::Ongoing => Self::Ongoing,
32 MangaStatusEnum::Completed => Self::Completed,
33 MangaStatusEnum::Hiatus => Self::Hiatus,
34 MangaStatusEnum::Cancelled => Self::Cancelled,
35 }
36 }
37}
38
39#[derive(Debug, Args)]
40pub struct CountMangaArgs {
41 #[arg(short, long)]
42 pub title: Option<String>,
43 #[arg(long)]
44 pub author_or_artist: Option<Uuid>,
45 #[arg(long = "author")]
46 pub authors: Vec<Uuid>,
47 #[arg(long = "artist")]
48 pub artists: Vec<Uuid>,
49 #[arg(short, long)]
50 pub year: Option<u16>,
51 #[arg(long)]
52 pub included_tags: Vec<Uuid>,
53 #[arg(long)]
54 pub included_tags_mode: Option<TagSearchModeEnum>,
55 #[arg(long)]
56 pub excluded_tags: Vec<Uuid>,
57 #[arg(long)]
58 pub excluded_tags_mode: Option<TagSearchModeEnum>,
59 #[arg(long)]
60 pub status: Vec<MangaStatusEnum>,
61 #[arg(long)]
62 pub original_language: Vec<Language>,
63 #[arg(long)]
64 pub excluded_original_language: Vec<Language>,
65 #[arg(long)]
66 pub publication_demographic: Vec<Demographic>,
67 #[arg(long)]
68 pub content_rating: Vec<ContentRating>,
69 #[arg(long, value_parser = super::mangadex_time_from_str)]
70 pub created_at_since: Option<MangaDexDateTime>,
71 #[arg(long, value_parser = super::mangadex_time_from_str)]
72 pub updated_at_since: Option<MangaDexDateTime>,
73 #[arg(long)]
74 pub group: Option<Uuid>,
75 #[arg(long)]
77 pub ids: bool,
78}
79
80impl CountMangaArgs {
81 fn filtered_params(&self) -> MangaListDataPullFilterParams {
82 MangaListDataPullFilterParams {
83 title: self.title.clone(),
84 author_or_artist: self.author_or_artist,
85 authors: self.authors.clone(),
86 artists: self.artists.clone(),
87 year: self.year,
88 included_tags: self.included_tags.clone(),
89 included_tags_mode: self.included_tags_mode.map(|m| m.into()),
90 excluded_tags: self.excluded_tags.clone(),
91 excluded_tags_mode: self.excluded_tags_mode.map(|m| m.into()),
92 status: self.status.iter().map(|s| (*s).into()).collect(),
93 original_language: self.original_language.clone(),
94 excluded_original_language: self.excluded_original_language.clone(),
95 publication_demographic: self.publication_demographic.clone(),
96 content_rating: self.content_rating.clone(),
97 created_at_since: self.created_at_since,
98 updated_at_since: self.updated_at_since,
99 group: self.group,
100 }
101 }
102}
103
104impl AsyncRun for CountMangaArgs {
105 async fn run(&self, ctx: AsyncRunContext) -> anyhow::Result<()> {
106 let dir_options = ctx.manager.get_dir_options().await?;
107 let mut stream = dir_options
108 .send(MangaListDataPullMessage)
109 .await??
110 .to_filtered(self.filtered_params());
111 if self.ids {
112 while let Some(manga) = stream.next().await {
113 println!("{}", manga.id);
114 }
115 } else {
116 println!(
117 "Number of title available: {}",
118 stream.fold(0usize, |count, _| count + 1).await
119 );
120 }
121 Ok(())
122 }
123}