1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5use crate::types::{EpisodeUnion, Release};
6
7#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
9pub struct UnifiedEpisode {
10 pub title: Option<String>,
12
13 pub link: String,
15
16 pub screenshots: Vec<String>,
17}
18
19#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
21pub struct UnifiedSeason {
22 pub title: Option<String>,
24
25 pub link: String,
26
27 pub episodes: BTreeMap<String, UnifiedEpisode>,
28}
29
30pub 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}