eureka_mmanager_core/data_push/
chapter.rs

1pub mod image;
2
3use std::{
4    fs::{create_dir_all, File},
5    io::{BufWriter, Write},
6};
7
8use itertools::Itertools;
9use mangadex_api_schema_rust::{v5::ChapterObject, ApiData};
10use mangadex_api_types_rust::{
11    ReferenceExpansionResource, RelationshipType, ResponseType, ResultType,
12};
13use uuid::Uuid;
14
15use crate::{data_pulls::Pull, DirsOptions, ManagerCoreResult};
16
17use super::{seed_rel, Push};
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum ChapterRequiredRelationship {
21    Manga,
22    ScanlationGroup,
23    Uploader,
24}
25
26impl ChapterRequiredRelationship {
27    pub fn get_includes() -> Vec<ReferenceExpansionResource> {
28        vec![
29            ReferenceExpansionResource::Manga,
30            ReferenceExpansionResource::ScanlationGroup,
31            ReferenceExpansionResource::User,
32        ]
33    }
34    fn validate(data: &ChapterObject) -> Vec<Self> {
35        let mut required = Vec::<Self>::new();
36        if data.find_relationships(RelationshipType::Manga).is_empty() {
37            required.push(Self::Manga);
38        }
39        if data.find_relationships(RelationshipType::User).is_empty() {
40            required.push(Self::Uploader);
41        }
42        required
43    }
44    fn seed(mut input: ChapterObject, seed: ChapterObject) -> ChapterObject {
45        let mut required = Self::validate(&input);
46        required.push(ChapterRequiredRelationship::ScanlationGroup);
47        for req in required {
48            seed_rel(&mut input, &seed, req.into());
49        }
50        input
51    }
52}
53
54impl From<ChapterRequiredRelationship> for RelationshipType {
55    fn from(value: ChapterRequiredRelationship) -> Self {
56        match value {
57            ChapterRequiredRelationship::Manga => Self::Manga,
58            ChapterRequiredRelationship::ScanlationGroup => Self::ScanlationGroup,
59            ChapterRequiredRelationship::Uploader => Self::User,
60        }
61    }
62}
63
64impl Push<ChapterObject> for DirsOptions {
65    type Error = crate::Error;
66    fn push(&mut self, data: ChapterObject) -> crate::ManagerCoreResult<()> {
67        let chapter_path = self.chapters_id_add(data.id);
68        create_dir_all(&chapter_path)?;
69        let mut file = BufWriter::new(File::create(chapter_path.join("data.json"))?);
70        serde_json::to_writer(
71            &mut file,
72            &ApiData {
73                response: ResponseType::Entity,
74                result: ResultType::Ok,
75                data,
76            },
77        )?;
78        file.flush()?;
79        Ok(())
80    }
81    fn verify_and_push(&mut self, data: ChapterObject) -> ManagerCoreResult<()> {
82        if let Ok(inner_chapter) = <Self as Pull<ChapterObject, Uuid>>::pull(self, data.id) {
83            self.push(ChapterRequiredRelationship::seed(inner_chapter, data))
84        } else {
85            let required = ChapterRequiredRelationship::validate(&data);
86            if required.is_empty() {
87                self.push(data)
88            } else {
89                Err(crate::Error::MissingRelationships(
90                    required
91                        .into_iter()
92                        .map(RelationshipType::from)
93                        .collect_vec(),
94                ))
95            }
96        }
97    }
98}
99
100impl Push<Vec<ChapterObject>> for DirsOptions {
101    type Error = crate::Error;
102    fn push(&mut self, data: Vec<ChapterObject>) -> ManagerCoreResult<()> {
103        for item in data {
104            self.push(item)?;
105        }
106        Ok(())
107    }
108}