kodik_api/translations.rs
1use serde::{Deserialize, Serialize};
2
3use crate::{
4 error::Error,
5 types::{
6 AllStatus, AnimeKind, AnimeStatus, DramaStatus, MaterialDataField, MppaRating, ReleaseType,
7 TranslationType,
8 },
9 util::serialize_into_query_parts,
10 Client,
11};
12
13#[derive(Serialize, Deserialize, Debug, Clone)]
14pub struct TranslationResult {
15 pub id: i32,
16
17 /// Name of the translation team
18 pub title: String,
19
20 /// The number of materials with this voice acting
21 pub count: i32,
22}
23
24/// A struct containing translations results and other information about the translations
25#[derive(Deserialize, Debug, Clone)]
26pub struct TranslationResponse {
27 pub time: String,
28 pub total: i32,
29 pub prev_page: Option<String>,
30 pub next_page: Option<String>,
31 pub results: Vec<TranslationResult>,
32}
33
34/// A struct containing search results and other information about the search
35#[derive(Deserialize, Debug, Clone)]
36#[serde(untagged)]
37enum TranslationResponseUnion {
38 Result(TranslationResponse),
39 Error { error: String },
40}
41
42#[derive(Serialize, Deserialize, Debug, Clone)]
43pub enum TranslationSort {
44 #[serde(rename = "title")]
45 Title,
46 #[serde(rename = "count")]
47 Count,
48}
49
50#[derive(Debug, Serialize, Clone)]
51pub struct TranslationQuery<'a> {
52 /// What field to sort materials by
53 #[serde(skip_serializing_if = "Option::is_none")]
54 sort: Option<TranslationSort>,
55
56 /// Maximum number of outputs
57 #[serde(skip_serializing_if = "Option::is_none")]
58 types: Option<&'a [ReleaseType]>,
59
60 ///Filter materials by year If you set this parameter, only materials of the corresponding year will be displayed
61 #[serde(skip_serializing_if = "Option::is_none")]
62 year: Option<&'a [u32]>,
63
64 /// Filter content by translation type. Allows you to output only voice translation or only subtitles
65 #[serde(skip_serializing_if = "Option::is_none")]
66 translation_type: Option<&'a [TranslationType]>,
67
68 /// Filtering materials based on the presence of a specific field. Materials that have at least one of the listed fields are shown. In order to show only materials that have all the listed fields
69 #[serde(skip_serializing_if = "Option::is_none")]
70 has_field: Option<&'a [MaterialDataField]>,
71 /// Filtering materials based on the presence of a specific field. Materials that have all the listed fields are shown
72 #[serde(skip_serializing_if = "Option::is_none")]
73 has_field_and: Option<&'a [MaterialDataField]>,
74
75 /// Filtering materials by country. You can specify a single value or multiple values, separated by commas (then materials with at least one of the listed countries will be displayed). The parameter is case sensitive
76 #[serde(skip_serializing_if = "Option::is_none")]
77 countries: Option<&'a [&'a str]>,
78
79 /// Filtering by genre. You can specify either one value or several values separated by commas (then materials that have at least one of the specified genres will be displayed). You can search by Kinopoisk, Shikimori, MyDramaList or by all genres at once. The parameter is not case sensitive
80 #[serde(skip_serializing_if = "Option::is_none")]
81 genres: Option<&'a [&'a str]>,
82 /// Filtering by genre. You can specify either one value or several values separated by commas (then materials that have at least one of the specified genres will be displayed). You can search by Kinopoisk, Shikimori, MyDramaList or by all genres at once. The parameter is not case sensitive
83 #[serde(skip_serializing_if = "Option::is_none")]
84 anime_genres: Option<&'a [&'a str]>,
85 /// Filtering by genre. You can specify either one value or several values separated by commas (then materials that have at least one of the specified genres will be displayed). You can search by Kinopoisk, Shikimori, MyDramaList or by all genres at once. The parameter is not case sensitive
86 #[serde(skip_serializing_if = "Option::is_none")]
87 drama_genres: Option<&'a [&'a str]>,
88 /// Filtering by genre. You can specify either one value or several values separated by commas (then materials that have at least one of the specified genres will be displayed). You can search by Kinopoisk, Shikimori, MyDramaList or by all genres at once. The parameter is not case sensitive
89 #[serde(skip_serializing_if = "Option::is_none")]
90 all_genres: Option<&'a [&'a str]>,
91
92 /// Filtering by duration (in minutes). You can specify either a single value to search for the exact duration, or an interval.
93 #[serde(skip_serializing_if = "Option::is_none")]
94 duration: Option<&'a [&'a str]>,
95
96 /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
97 #[serde(skip_serializing_if = "Option::is_none")]
98 kinopoisk_rating: Option<&'a [&'a str]>,
99 /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
100 #[serde(skip_serializing_if = "Option::is_none")]
101 imdb_rating: Option<&'a [&'a str]>,
102 /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
103 #[serde(skip_serializing_if = "Option::is_none")]
104 shikimori_rating: Option<&'a [&'a str]>,
105 /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
106 #[serde(skip_serializing_if = "Option::is_none")]
107 mydramalist_rating: Option<&'a [&'a str]>,
108
109 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
110 #[serde(skip_serializing_if = "Option::is_none")]
111 actors: Option<&'a [&'a str]>,
112 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
113 #[serde(skip_serializing_if = "Option::is_none")]
114 directors: Option<&'a [&'a str]>,
115 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
116 #[serde(skip_serializing_if = "Option::is_none")]
117 producers: Option<&'a [&'a str]>,
118 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
119 #[serde(skip_serializing_if = "Option::is_none")]
120 writers: Option<&'a [&'a str]>,
121 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
122 #[serde(skip_serializing_if = "Option::is_none")]
123 composers: Option<&'a [&'a str]>,
124 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
125 #[serde(skip_serializing_if = "Option::is_none")]
126 editors: Option<&'a [&'a str]>,
127 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
128 #[serde(skip_serializing_if = "Option::is_none")]
129 designers: Option<&'a [&'a str]>,
130 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
131 #[serde(skip_serializing_if = "Option::is_none")]
132 operators: Option<&'a [&'a str]>,
133
134 /// Filtering materials by age rating. You can specify a single value or multiple values, separated by commas. The parameter is case-insensitive
135 #[serde(skip_serializing_if = "Option::is_none")]
136 rating_mpaa: Option<&'a [MppaRating]>,
137
138 /// Filter content by the minimum age from which it can be viewed. You can specify either a single value or a range of values
139 #[serde(skip_serializing_if = "Option::is_none")]
140 minimal_age: Option<&'a [&'a str]>,
141
142 /// Filtering materials by anime type. You can specify one value or several values separated by commas (then materials with at least one of these types will be displayed)
143 #[serde(skip_serializing_if = "Option::is_none")]
144 anime_kind: Option<&'a [AnimeKind]>,
145
146 /// Filters materials by MyDramaList tags. You can specify one value or several values separated by commas (then materials with at least one of these types will be displayed)
147 #[serde(skip_serializing_if = "Option::is_none")]
148 mydramalist_tags: Option<&'a [&'a str]>,
149
150 /// Filter materials by Shikimori status, MyDramaList, or by all statuses. You can specify a single value or several values separated by commas (then materials that have at least one of the listed statuses will be displayed)
151 #[serde(skip_serializing_if = "Option::is_none")]
152 anime_status: Option<&'a [AnimeStatus]>,
153 /// Filter materials by Shikimori status, MyDramaList, or by all statuses. You can specify a single value or several values separated by commas (then materials that have at least one of the listed statuses will be displayed)
154 #[serde(skip_serializing_if = "Option::is_none")]
155 drama_status: Option<&'a [DramaStatus]>,
156 /// Filter materials by Shikimori status, MyDramaList, or by all statuses. You can specify a single value or several values separated by commas (then materials that have at least one of the listed statuses will be displayed)
157 #[serde(skip_serializing_if = "Option::is_none")]
158 all_status: Option<&'a [AllStatus]>,
159
160 /// Filtering materials by anime studio. You can specify either one value or several values separated by commas (then materials with at least one of the listed studios will be displayed)
161 #[serde(skip_serializing_if = "Option::is_none")]
162 anime_studios: Option<&'a [&'a str]>,
163 /// Filtering materials by license owner. You can specify a single value or several values separated by commas (then materials that have at least one of the listed owners will be displayed)
164 #[serde(skip_serializing_if = "Option::is_none")]
165 anime_licensed_by: Option<&'a [&'a str]>,
166}
167
168impl<'a> TranslationQuery<'a> {
169 pub fn new() -> TranslationQuery<'a> {
170 TranslationQuery {
171 sort: None,
172 types: None,
173 year: None,
174 translation_type: None,
175 has_field: None,
176 has_field_and: None,
177 countries: None,
178 genres: None,
179 anime_genres: None,
180 drama_genres: None,
181 all_genres: None,
182 duration: None,
183 kinopoisk_rating: None,
184 imdb_rating: None,
185 shikimori_rating: None,
186 mydramalist_rating: None,
187 actors: None,
188 directors: None,
189 producers: None,
190 writers: None,
191 composers: None,
192 editors: None,
193 designers: None,
194 operators: None,
195 rating_mpaa: None,
196 minimal_age: None,
197 anime_kind: None,
198 mydramalist_tags: None,
199 anime_status: None,
200 drama_status: None,
201 all_status: None,
202 anime_studios: None,
203 anime_licensed_by: None,
204 }
205 }
206
207 /// Maximum number of outputs
208 pub fn with_types<'b>(&'b mut self, types: &'a [ReleaseType]) -> &'b mut TranslationQuery<'a> {
209 self.types = Some(types);
210 self
211 }
212
213 ///Filter materials by year If you set this parameter, only materials of the corresponding year will be displayed
214
215 pub fn with_year<'b>(&'b mut self, year: &'a [u32]) -> &'b mut TranslationQuery<'a> {
216 self.year = Some(year);
217 self
218 }
219
220 /// Filter content by translation type. Allows you to output only voice translation or only subtitles
221 pub fn with_translation_type<'b>(
222 &'b mut self,
223 translation_type: &'a [TranslationType],
224 ) -> &'b mut TranslationQuery<'a> {
225 self.translation_type = Some(translation_type);
226 self
227 }
228
229 /// Filtering materials based on the presence of a specific field. Materials that have at least one of the listed fields are shown. In order to show only materials that have all the listed fields
230 pub fn with_has_field<'b>(
231 &'b mut self,
232 has_field: &'a [MaterialDataField],
233 ) -> &'b mut TranslationQuery<'a> {
234 self.has_field = Some(has_field);
235 self
236 }
237 /// Filtering materials based on the presence of a specific field. Materials that have all the listed fields are shown
238 pub fn with_has_field_and<'b>(
239 &'b mut self,
240 has_field: &'a [MaterialDataField],
241 ) -> &'b mut TranslationQuery<'a> {
242 self.has_field_and = Some(has_field);
243 self
244 }
245
246 /// Filtering materials by country. You can specify a single value or multiple values, separated by commas (then materials with at least one of the listed countries will be displayed). The parameter is case sensitive
247 pub fn with_countries<'b>(
248 &'b mut self,
249 countries: &'a [&'a str],
250 ) -> &'b mut TranslationQuery<'a> {
251 self.countries = Some(countries);
252 self
253 }
254
255 /// Filtering by genre. You can specify either one value or several values separated by commas (then materials that have at least one of the specified genres will be displayed). You can search by Kinopoisk, Shikimori, MyDramaList or by all genres at once. The parameter is not case sensitive
256 pub fn with_genres<'b>(&'b mut self, genres: &'a [&'a str]) -> &'b mut TranslationQuery<'a> {
257 self.genres = Some(genres);
258 self
259 }
260 /// Filtering by genre. You can specify either one value or several values separated by commas (then materials that have at least one of the specified genres will be displayed). You can search by Kinopoisk, Shikimori, MyDramaList or by all genres at once. The parameter is not case sensitive
261 pub fn with_anime_genres<'b>(
262 &'b mut self,
263 anime_genres: &'a [&'a str],
264 ) -> &'b mut TranslationQuery<'a> {
265 self.anime_genres = Some(anime_genres);
266 self
267 }
268 /// Filtering by genre. You can specify either one value or several values separated by commas (then materials that have at least one of the specified genres will be displayed). You can search by Kinopoisk, Shikimori, MyDramaList or by all genres at once. The parameter is not case sensitive
269 pub fn with_drama_genres<'b>(
270 &'b mut self,
271 drama_genres: &'a [&'a str],
272 ) -> &'b mut TranslationQuery<'a> {
273 self.drama_genres = Some(drama_genres);
274 self
275 }
276 /// Filtering by genre. You can specify either one value or several values separated by commas (then materials that have at least one of the specified genres will be displayed). You can search by Kinopoisk, Shikimori, MyDramaList or by all genres at once. The parameter is not case sensitive
277 pub fn with_all_genres<'b>(
278 &'b mut self,
279 all_genres: &'a [&'a str],
280 ) -> &'b mut TranslationQuery<'a> {
281 self.all_genres = Some(all_genres);
282 self
283 }
284
285 /// Filtering by duration (in minutes). You can specify either a single value to search for the exact duration, or an interval.
286 pub fn with_duration<'b>(
287 &'b mut self,
288 duration: &'a [&'a str],
289 ) -> &'b mut TranslationQuery<'a> {
290 self.duration = Some(duration);
291 self
292 }
293
294 /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
295 pub fn with_kinopoisk_rating<'b>(
296 &'b mut self,
297 kinopoisk_rating: &'a [&'a str],
298 ) -> &'b mut TranslationQuery<'a> {
299 self.kinopoisk_rating = Some(kinopoisk_rating);
300 self
301 }
302 /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
303 pub fn with_imdb_rating<'b>(
304 &'b mut self,
305 imdb_rating: &'a [&'a str],
306 ) -> &'b mut TranslationQuery<'a> {
307 self.imdb_rating = Some(imdb_rating);
308 self
309 }
310 /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
311 pub fn with_shikimori_rating<'b>(
312 &'b mut self,
313 shikimori_rating: &'a [&'a str],
314 ) -> &'b mut TranslationQuery<'a> {
315 self.shikimori_rating = Some(shikimori_rating);
316 self
317 }
318 /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
319 pub fn with_mydramalist_rating<'b>(
320 &'b mut self,
321 mydramalist_rating: &'a [&'a str],
322 ) -> &'b mut TranslationQuery<'a> {
323 self.mydramalist_rating = Some(mydramalist_rating);
324 self
325 }
326
327 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
328 pub fn with_actors<'b>(&'b mut self, actors: &'a [&'a str]) -> &'b mut TranslationQuery<'a> {
329 self.actors = Some(actors);
330 self
331 }
332 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
333 pub fn with_directors<'b>(
334 &'b mut self,
335 directors: &'a [&'a str],
336 ) -> &'b mut TranslationQuery<'a> {
337 self.directors = Some(directors);
338 self
339 }
340 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
341 pub fn with_producers<'b>(
342 &'b mut self,
343 producers: &'a [&'a str],
344 ) -> &'b mut TranslationQuery<'a> {
345 self.producers = Some(producers);
346 self
347 }
348 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
349 pub fn with_writers<'b>(&'b mut self, writers: &'a [&'a str]) -> &'b mut TranslationQuery<'a> {
350 self.writers = Some(writers);
351 self
352 }
353 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
354 pub fn with_composers<'b>(
355 &'b mut self,
356 composers: &'a [&'a str],
357 ) -> &'b mut TranslationQuery<'a> {
358 self.composers = Some(composers);
359 self
360 }
361 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
362 pub fn with_editors<'b>(&'b mut self, editors: &'a [&'a str]) -> &'b mut TranslationQuery<'a> {
363 self.editors = Some(editors);
364 self
365 }
366 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
367 pub fn with_designers<'b>(
368 &'b mut self,
369 designers: &'a [&'a str],
370 ) -> &'b mut TranslationQuery<'a> {
371 self.designers = Some(designers);
372 self
373 }
374 /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
375 pub fn with_operators<'b>(
376 &'b mut self,
377 operators: &'a [&'a str],
378 ) -> &'b mut TranslationQuery<'a> {
379 self.operators = Some(operators);
380 self
381 }
382
383 /// Filtering materials by age rating. You can specify a single value or multiple values, separated by commas. The parameter is case-insensitive
384 pub fn with_rating_mpaa<'b>(
385 &'b mut self,
386 rating_mpaa: &'a [MppaRating],
387 ) -> &'b mut TranslationQuery<'a> {
388 self.rating_mpaa = Some(rating_mpaa);
389 self
390 }
391
392 /// Filter content by the minimum age from which it can be viewed. You can specify either a single value or a range of values
393 pub fn with_minimal_age<'b>(
394 &'b mut self,
395 minimal_age: &'a [&'a str],
396 ) -> &'b mut TranslationQuery<'a> {
397 self.minimal_age = Some(minimal_age);
398 self
399 }
400
401 /// Filtering materials by anime type. You can specify one value or several values separated by commas (then materials with at least one of these types will be displayed)
402 pub fn with_anime_kind<'b>(
403 &'b mut self,
404 anime_kind: &'a [AnimeKind],
405 ) -> &'b mut TranslationQuery<'a> {
406 self.anime_kind = Some(anime_kind);
407 self
408 }
409
410 /// Filters materials by MyDramaList tags. You can specify one value or several values separated by commas (then materials with at least one of these types will be displayed)
411 pub fn with_mydramalist_tags<'b>(
412 &'b mut self,
413 mydramalist_tags: &'a [&'a str],
414 ) -> &'b mut TranslationQuery<'a> {
415 self.mydramalist_tags = Some(mydramalist_tags);
416 self
417 }
418
419 /// Filter materials by Shikimori status, MyDramaList, or by all statuses. You can specify a single value or several values separated by commas (then materials that have at least one of the listed statuses will be displayed)
420 pub fn with_anime_status<'b>(
421 &'b mut self,
422 anime_status: &'a [AnimeStatus],
423 ) -> &'b mut TranslationQuery<'a> {
424 self.anime_status = Some(anime_status);
425 self
426 }
427 /// Filter materials by Shikimori status, MyDramaList, or by all statuses. You can specify a single value or several values separated by commas (then materials that have at least one of the listed statuses will be displayed)
428 pub fn with_drama_status<'b>(
429 &'b mut self,
430 drama_status: &'a [DramaStatus],
431 ) -> &'b mut TranslationQuery<'a> {
432 self.drama_status = Some(drama_status);
433 self
434 }
435 /// Filter materials by Shikimori status, MyDramaList, or by all statuses. You can specify a single value or several values separated by commas (then materials that have at least one of the listed statuses will be displayed)
436 pub fn with_all_status<'b>(
437 &'b mut self,
438 all_status: &'a [AllStatus],
439 ) -> &'b mut TranslationQuery<'a> {
440 self.all_status = Some(all_status);
441 self
442 }
443
444 /// Filtering materials by anime studio. You can specify either one value or several values separated by commas (then materials with at least one of the listed studios will be displayed)
445 pub fn with_anime_studios<'b>(
446 &'b mut self,
447 anime_studios: &'a [&'a str],
448 ) -> &'b mut TranslationQuery<'a> {
449 self.anime_studios = Some(anime_studios);
450 self
451 }
452 /// Filtering materials by license owner. You can specify a single value or several values separated by commas (then materials that have at least one of the listed owners will be displayed)
453 pub fn with_anime_licensed_by<'b>(
454 &'b mut self,
455 anime_licensed_by: &'a [&'a str],
456 ) -> &'b mut TranslationQuery<'a> {
457 self.anime_licensed_by = Some(anime_licensed_by);
458 self
459 }
460
461 /// Execute the query and fetch the results.
462 pub async fn execute<'b>(&'a self, client: &'b Client) -> Result<TranslationResponse, Error> {
463 let payload = serialize_into_query_parts(self)?;
464
465 let response = client
466 .init_post_request("/translations/v2")
467 .query(&payload)
468 .send()
469 .await
470 .map_err(Error::HttpError)?;
471
472 let result = response
473 .json::<TranslationResponseUnion>()
474 .await
475 .map_err(Error::HttpError)?;
476
477 match result {
478 TranslationResponseUnion::Result(result) => Ok(result),
479 TranslationResponseUnion::Error { error } => Err(Error::KodikError(error)),
480 }
481 }
482}
483
484impl<'a> Default for TranslationQuery<'a> {
485 fn default() -> Self {
486 Self::new()
487 }
488}