eureka_manager_cli/commands/count/
chapter.rs1use 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 #[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 #[arg(long = "excluded-group")]
40 pub excluded_groups: Vec<Uuid>,
41 #[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 #[arg(long, value_parser = crate::commands::count::mangadex_time_from_str)]
48 pub updated_at_since: Option<MangaDexDateTime>,
49 #[arg(long, value_parser = crate::commands::count::mangadex_time_from_str)]
51 pub publish_at_since: Option<MangaDexDateTime>,
52 #[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}