eureka_manager_cli/commands/count/
manga.rs

1use 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    /// Manga is still going on.
19    Ongoing,
20    /// Manga is completed.
21    Completed,
22    /// Manga is paused from publishing new chapters.
23    Hiatus,
24    /// Manga has been cancelled.
25    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    /// Shows ids instead of the number
76    #[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}