eureka_manager_cli/commands/count/
chapter.rs

1use clap::Args;
2use eureka_mmanager::{
3    files_dirs::messages::pull::chapter::ChapterListDataPullMessage,
4    prelude::{
5        ChapterDataPullAsyncTrait, ChapterListDataPullFilterParams, GetManagerStateData,
6        IntoParamedFilteredStream,
7    },
8};
9use mangadex_api_types_rust::{ContentRating, Language, MangaDexDateTime};
10use tokio_stream::StreamExt;
11use uuid::Uuid;
12
13use crate::commands::{AsyncRun, AsyncRunContext};
14
15#[derive(Debug, Args)]
16pub struct CountChapterArgs {
17    #[arg(long)]
18    pub title: Option<String>,
19    #[arg(long = "group")]
20    pub groups: Vec<Uuid>,
21    #[arg(long = "uploader")]
22    pub uploaders: Vec<Uuid>,
23    #[arg(long = "volume")]
24    pub volumes: Vec<String>,
25    #[arg(long = "manga")]
26    pub manga_ids: Vec<Uuid>,
27    /// Chapter number in the series or volume.
28    #[arg(long = "chapter")]
29    pub chapters: Vec<String>,
30    #[arg(long = "translated-language")]
31    pub translated_languages: Vec<Language>,
32    #[arg(long = "original-language")]
33    pub original_languages: Vec<Language>,
34    #[arg(long = "excluded-original-language")]
35    pub excluded_original_languages: Vec<Language>,
36    #[arg(long = "content-rating")]
37    pub content_rating: Vec<ContentRating>,
38    /// Groups to exclude from the results.
39    #[arg(long = "excluded-group")]
40    pub excluded_groups: Vec<Uuid>,
41    /// Uploaders to exclude from the results.
42    #[arg(long = "excluded-uploader")]
43    pub excluded_uploaders: Vec<Uuid>,
44    #[arg(long, value_parser = crate::commands::count::mangadex_time_from_str)]
45    pub created_at_since: Option<MangaDexDateTime>,
46    /// DateTime string with following format: `YYYY-MM-DDTHH:MM:SS`.
47    #[arg(long, value_parser = crate::commands::count::mangadex_time_from_str)]
48    pub updated_at_since: Option<MangaDexDateTime>,
49    /// DateTime string with following format: `YYYY-MM-DDTHH:MM:SS`.
50    #[arg(long, value_parser = crate::commands::count::mangadex_time_from_str)]
51    pub publish_at_since: Option<MangaDexDateTime>,
52    /// Show chapter ids
53    #[arg(short)]
54    pub ids: bool,
55}
56
57impl CountChapterArgs {
58    fn to_params(&self) -> ChapterListDataPullFilterParams {
59        let Self {
60            title,
61            groups,
62            uploaders,
63            volumes,
64            manga_ids,
65            chapters,
66            translated_languages,
67            original_languages,
68            excluded_original_languages,
69            content_rating,
70            excluded_groups,
71            excluded_uploaders,
72            created_at_since,
73            updated_at_since,
74            publish_at_since,
75            ..
76        } = self;
77        ChapterListDataPullFilterParams {
78            title: title.clone(),
79            groups: groups.clone(),
80            uploaders: uploaders.clone(),
81            volumes: volumes.clone(),
82            manga_ids: manga_ids.clone(),
83            chapters: chapters.clone(),
84            translated_languages: translated_languages.clone(),
85            original_languages: original_languages.clone(),
86            excluded_original_languages: excluded_original_languages.clone(),
87            content_rating: content_rating.clone(),
88            excluded_groups: excluded_groups.clone(),
89            excluded_uploaders: excluded_uploaders.clone(),
90            created_at_since: *created_at_since,
91            updated_at_since: *updated_at_since,
92            publish_at_since: *publish_at_since,
93        }
94    }
95}
96
97impl AsyncRun for CountChapterArgs {
98    async fn run(&self, ctx: AsyncRunContext) -> anyhow::Result<()> {
99        let dir_options = ctx.manager.get_dir_options().await?;
100        let mut stream = dir_options
101            .send(ChapterListDataPullMessage)
102            .await??
103            .to_filtered(self.to_params());
104        if self.ids {
105            while let Some(chapter) = stream.next().await {
106                println!("{} [{}]", chapter.id, {
107                    let images = dir_options.get_chapter_images(chapter.id).await?;
108                    match (!images.data.is_empty(), !images.data_saver.is_empty()) {
109                        (true, true) => "data;data-saver".to_string(),
110                        (true, false) => "data".to_string(),
111                        (false, true) => "data-saver".to_string(),
112                        (false, false) => String::new(),
113                    }
114                });
115            }
116        } else {
117            println!(
118                "Number of chapters available: {}",
119                stream.fold(0usize, |count, _| count + 1).await
120            );
121        }
122        Ok(())
123    }
124}