kodik_api/
unify_seasons.rs

1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5use crate::types::{EpisodeUnion, Release};
6
7/// Represents a release unified episode object on Kodik
8#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
9pub struct UnifiedEpisode {
10    /// For example, it сan be marked as special
11    pub title: Option<String>,
12
13    /// `"http://kodik.cc/seria/119611/09249413a7eb3c03b15df57cd56a051b/720p"`
14    pub link: String,
15
16    pub screenshots: Vec<String>,
17}
18
19/// Represents a release unified season object on Kodik
20#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
21pub struct UnifiedSeason {
22    /// For example, it can be marked as a recap, special, etc.
23    pub title: Option<String>,
24
25    pub link: String,
26
27    pub episodes: BTreeMap<String, UnifiedEpisode>,
28}
29
30/// Returns seasons and episodes in a unified format for the Kodik release.
31///
32/// Kodik returns different response formats for movies, shows, depending on the parameters and the state of the sun.
33pub fn unify_seasons(release: &Release) -> BTreeMap<String, UnifiedSeason> {
34    let Some(kodik_seasons) = &release.seasons else {
35        return BTreeMap::from([(
36            "1".to_owned(),
37            UnifiedSeason {
38                title: None,
39                link: release.link.clone(),
40                episodes: BTreeMap::from([(
41                    "1".to_owned(),
42                    UnifiedEpisode {
43                        title: None,
44                        link: release.link.clone(),
45                        screenshots: release.screenshots.clone(),
46                    },
47                )]),
48            },
49        )]);
50    };
51
52    let mut seasons = BTreeMap::new();
53
54    for (season_num, kodik_season) in kodik_seasons {
55        let mut episodes = BTreeMap::new();
56
57        for (episode_num, kodik_episode_union) in &kodik_season.episodes {
58            let episode = match kodik_episode_union {
59                EpisodeUnion::Episode(kodik_episode) => UnifiedEpisode {
60                    title: kodik_episode.title.clone(),
61                    link: kodik_episode.link.clone(),
62                    screenshots: kodik_episode.screenshots.clone(),
63                },
64                EpisodeUnion::Link(link) => UnifiedEpisode {
65                    title: None,
66                    link: link.clone(),
67                    screenshots: release.screenshots.clone(),
68                },
69            };
70
71            episodes.insert(episode_num.clone(), episode);
72        }
73
74        seasons.insert(
75            season_num.clone(),
76            UnifiedSeason {
77                title: kodik_season.title.clone(),
78                link: kodik_season.link.clone(),
79                episodes,
80            },
81        );
82    }
83
84    seasons
85}
86
87#[cfg(test)]
88mod tests {
89    use crate::types::{
90        Episode, ReleaseQuality, ReleaseType, Season, Translation, TranslationType,
91    };
92
93    use super::*;
94
95    fn get_default_kodik_release() -> Release {
96        Release {
97            id: "serial-45534".to_owned(),
98            title: "Киберпанк: Бегущие по краю".to_owned(),
99            title_orig: "Cyberpunk: Edgerunners".to_owned(),
100            other_title: Some("サイバーパンク エッジランナーズ".to_owned()),
101            link: "//kodik.info/serial/45534/d8619e900d122ea8eff8b55891b09bac/720p".to_owned(),
102            year: 2022,
103            kinopoisk_id: Some("2000102".to_owned()),
104            imdb_id: Some("tt12590266".to_owned()),
105            mdl_id: None,
106            worldart_link: Some(
107                "http://www.world-art.ru/animation/animation.php?id=10534".to_owned(),
108            ),
109            shikimori_id: Some("42310".to_owned()),
110            release_type: ReleaseType::AnimeSerial,
111            quality: ReleaseQuality::WebDlRip720p,
112            camrip: false,
113            lgbt: false,
114            translation: Translation {
115                id: 610,
116                title: "AniLibria.TV".to_owned(),
117                translation_type: TranslationType::Voice,
118            },
119            created_at: "2022-09-14T10:54:34Z".to_owned(),
120            updated_at: "2022-09-23T22:31:33Z".to_owned(),
121            blocked_seasons: Some(BTreeMap::new()),
122            seasons: None,
123            last_season: Some(1),
124            last_episode: Some(10),
125            episodes_count: Some(10),
126            blocked_countries: vec![],
127            material_data: None,
128            screenshots: vec!["https://i.kodik.biz/screenshots/seria/104981222/1.jpg".to_owned()],
129        }
130    }
131
132    #[test]
133    fn test_unify_kodik_without_seasons() {
134        let kodik_release = get_default_kodik_release();
135
136        let unified_season = unify_seasons(&kodik_release);
137
138        assert_eq!(
139            unified_season,
140            BTreeMap::from([(
141                "1".to_owned(),
142                UnifiedSeason {
143                    title: None,
144                    link: kodik_release.link.clone(),
145                    episodes: BTreeMap::from([(
146                        "1".to_owned(),
147                        UnifiedEpisode {
148                            title: None,
149                            link: kodik_release.link.clone(),
150                            screenshots: kodik_release.screenshots,
151                        }
152                    )]),
153                }
154            )])
155        )
156    }
157
158    #[test]
159    fn test_unify_kodik_with_seasons() {
160        let mut kodik_release = get_default_kodik_release();
161
162        let seasons = BTreeMap::from([(
163            "1".to_owned(),
164            Season {
165                link: kodik_release.link.clone(),
166                title: None,
167                episodes: BTreeMap::from([
168                    (
169                        "1".to_owned(),
170                        EpisodeUnion::Link(
171                            "//kodik.info/serial/45534/d8619e900d122ea8eff8b55891b09bac/720p/1"
172                                .to_owned(),
173                        ),
174                    ),
175                    (
176                        "2".to_owned(),
177                        EpisodeUnion::Episode(Episode {
178                            title: None,
179                            link:
180                                "//kodik.info/serial/45534/d8619e900d122ea8eff8b55891b09bac/720p/2"
181                                    .to_owned(),
182                            screenshots: kodik_release.screenshots.clone(),
183                        }),
184                    ),
185                    (
186                        "3".to_owned(),
187                        EpisodeUnion::Link(
188                            "//kodik.info/serial/45534/d8619e900d122ea8eff8b55891b09bac/720p/3"
189                                .to_owned(),
190                        ),
191                    ),
192                ]),
193            },
194        )]);
195
196        kodik_release.seasons = Some(seasons);
197
198        let unified_season = unify_seasons(&kodik_release);
199
200        assert_eq!(unified_season, BTreeMap::from([
201            ("1".to_owned(), UnifiedSeason {
202                title: None,
203                link: kodik_release.link.clone(),
204                episodes: BTreeMap::from([
205                    ("1".to_owned(), UnifiedEpisode {
206                        title: None,
207                        link: "//kodik.info/serial/45534/d8619e900d122ea8eff8b55891b09bac/720p/1".to_owned(),
208                        screenshots: kodik_release.screenshots.clone(),
209                    }),
210                    ("2".to_owned(), UnifiedEpisode {
211                        title: None,
212                        link: "//kodik.info/serial/45534/d8619e900d122ea8eff8b55891b09bac/720p/2".to_owned(),
213                        screenshots: kodik_release.screenshots.clone(),
214                    }),
215                    ("3".to_owned(), UnifiedEpisode {
216                        title: None,
217                        link: "//kodik.info/serial/45534/d8619e900d122ea8eff8b55891b09bac/720p/3".to_owned(),
218                        screenshots: kodik_release.screenshots,
219                    }),
220                ]),
221            })
222        ]))
223    }
224}