kodik_api/
translations.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    Client,
5    error::Error,
6    types::{
7        AllStatus, AnimeKind, AnimeStatus, DramaStatus, MaterialDataField, MppaRating, ReleaseType,
8        TranslationType,
9    },
10    util::serialize_into_query_parts,
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    pub fn with_year<'b>(&'b mut self, year: &'a [u32]) -> &'b mut TranslationQuery<'a> {
215        self.year = Some(year);
216        self
217    }
218
219    /// Filter content by translation type. Allows you to output only voice translation or only subtitles
220    pub fn with_translation_type<'b>(
221        &'b mut self,
222        translation_type: &'a [TranslationType],
223    ) -> &'b mut TranslationQuery<'a> {
224        self.translation_type = Some(translation_type);
225        self
226    }
227
228    /// 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
229    pub fn with_has_field<'b>(
230        &'b mut self,
231        has_field: &'a [MaterialDataField],
232    ) -> &'b mut TranslationQuery<'a> {
233        self.has_field = Some(has_field);
234        self
235    }
236    /// Filtering materials based on the presence of a specific field. Materials that have all the listed fields are shown
237    pub fn with_has_field_and<'b>(
238        &'b mut self,
239        has_field: &'a [MaterialDataField],
240    ) -> &'b mut TranslationQuery<'a> {
241        self.has_field_and = Some(has_field);
242        self
243    }
244
245    /// 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
246    pub fn with_countries<'b>(
247        &'b mut self,
248        countries: &'a [&'a str],
249    ) -> &'b mut TranslationQuery<'a> {
250        self.countries = Some(countries);
251        self
252    }
253
254    /// 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
255    pub fn with_genres<'b>(&'b mut self, genres: &'a [&'a str]) -> &'b mut TranslationQuery<'a> {
256        self.genres = Some(genres);
257        self
258    }
259    /// 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
260    pub fn with_anime_genres<'b>(
261        &'b mut self,
262        anime_genres: &'a [&'a str],
263    ) -> &'b mut TranslationQuery<'a> {
264        self.anime_genres = Some(anime_genres);
265        self
266    }
267    /// 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
268    pub fn with_drama_genres<'b>(
269        &'b mut self,
270        drama_genres: &'a [&'a str],
271    ) -> &'b mut TranslationQuery<'a> {
272        self.drama_genres = Some(drama_genres);
273        self
274    }
275    /// 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
276    pub fn with_all_genres<'b>(
277        &'b mut self,
278        all_genres: &'a [&'a str],
279    ) -> &'b mut TranslationQuery<'a> {
280        self.all_genres = Some(all_genres);
281        self
282    }
283
284    /// Filtering by duration (in minutes). You can specify either a single value to search for the exact duration, or an interval.
285    pub fn with_duration<'b>(
286        &'b mut self,
287        duration: &'a [&'a str],
288    ) -> &'b mut TranslationQuery<'a> {
289        self.duration = Some(duration);
290        self
291    }
292
293    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
294    pub fn with_kinopoisk_rating<'b>(
295        &'b mut self,
296        kinopoisk_rating: &'a [&'a str],
297    ) -> &'b mut TranslationQuery<'a> {
298        self.kinopoisk_rating = Some(kinopoisk_rating);
299        self
300    }
301    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
302    pub fn with_imdb_rating<'b>(
303        &'b mut self,
304        imdb_rating: &'a [&'a str],
305    ) -> &'b mut TranslationQuery<'a> {
306        self.imdb_rating = Some(imdb_rating);
307        self
308    }
309    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
310    pub fn with_shikimori_rating<'b>(
311        &'b mut self,
312        shikimori_rating: &'a [&'a str],
313    ) -> &'b mut TranslationQuery<'a> {
314        self.shikimori_rating = Some(shikimori_rating);
315        self
316    }
317    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
318    pub fn with_mydramalist_rating<'b>(
319        &'b mut self,
320        mydramalist_rating: &'a [&'a str],
321    ) -> &'b mut TranslationQuery<'a> {
322        self.mydramalist_rating = Some(mydramalist_rating);
323        self
324    }
325
326    /// 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
327    pub fn with_actors<'b>(&'b mut self, actors: &'a [&'a str]) -> &'b mut TranslationQuery<'a> {
328        self.actors = Some(actors);
329        self
330    }
331    /// 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
332    pub fn with_directors<'b>(
333        &'b mut self,
334        directors: &'a [&'a str],
335    ) -> &'b mut TranslationQuery<'a> {
336        self.directors = Some(directors);
337        self
338    }
339    /// 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
340    pub fn with_producers<'b>(
341        &'b mut self,
342        producers: &'a [&'a str],
343    ) -> &'b mut TranslationQuery<'a> {
344        self.producers = Some(producers);
345        self
346    }
347    /// 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
348    pub fn with_writers<'b>(&'b mut self, writers: &'a [&'a str]) -> &'b mut TranslationQuery<'a> {
349        self.writers = Some(writers);
350        self
351    }
352    /// 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
353    pub fn with_composers<'b>(
354        &'b mut self,
355        composers: &'a [&'a str],
356    ) -> &'b mut TranslationQuery<'a> {
357        self.composers = Some(composers);
358        self
359    }
360    /// 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
361    pub fn with_editors<'b>(&'b mut self, editors: &'a [&'a str]) -> &'b mut TranslationQuery<'a> {
362        self.editors = Some(editors);
363        self
364    }
365    /// 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
366    pub fn with_designers<'b>(
367        &'b mut self,
368        designers: &'a [&'a str],
369    ) -> &'b mut TranslationQuery<'a> {
370        self.designers = Some(designers);
371        self
372    }
373    /// 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
374    pub fn with_operators<'b>(
375        &'b mut self,
376        operators: &'a [&'a str],
377    ) -> &'b mut TranslationQuery<'a> {
378        self.operators = Some(operators);
379        self
380    }
381
382    /// Filtering materials by age rating. You can specify a single value or multiple values, separated by commas. The parameter is case-insensitive
383    pub fn with_rating_mpaa<'b>(
384        &'b mut self,
385        rating_mpaa: &'a [MppaRating],
386    ) -> &'b mut TranslationQuery<'a> {
387        self.rating_mpaa = Some(rating_mpaa);
388        self
389    }
390
391    /// Filter content by the minimum age from which it can be viewed. You can specify either a single value or a range of values
392    pub fn with_minimal_age<'b>(
393        &'b mut self,
394        minimal_age: &'a [&'a str],
395    ) -> &'b mut TranslationQuery<'a> {
396        self.minimal_age = Some(minimal_age);
397        self
398    }
399
400    /// 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)
401    pub fn with_anime_kind<'b>(
402        &'b mut self,
403        anime_kind: &'a [AnimeKind],
404    ) -> &'b mut TranslationQuery<'a> {
405        self.anime_kind = Some(anime_kind);
406        self
407    }
408
409    /// 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)
410    pub fn with_mydramalist_tags<'b>(
411        &'b mut self,
412        mydramalist_tags: &'a [&'a str],
413    ) -> &'b mut TranslationQuery<'a> {
414        self.mydramalist_tags = Some(mydramalist_tags);
415        self
416    }
417
418    /// 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)
419    pub fn with_anime_status<'b>(
420        &'b mut self,
421        anime_status: &'a [AnimeStatus],
422    ) -> &'b mut TranslationQuery<'a> {
423        self.anime_status = Some(anime_status);
424        self
425    }
426    /// 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)
427    pub fn with_drama_status<'b>(
428        &'b mut self,
429        drama_status: &'a [DramaStatus],
430    ) -> &'b mut TranslationQuery<'a> {
431        self.drama_status = Some(drama_status);
432        self
433    }
434    /// 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)
435    pub fn with_all_status<'b>(
436        &'b mut self,
437        all_status: &'a [AllStatus],
438    ) -> &'b mut TranslationQuery<'a> {
439        self.all_status = Some(all_status);
440        self
441    }
442
443    /// 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)
444    pub fn with_anime_studios<'b>(
445        &'b mut self,
446        anime_studios: &'a [&'a str],
447    ) -> &'b mut TranslationQuery<'a> {
448        self.anime_studios = Some(anime_studios);
449        self
450    }
451    /// 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)
452    pub fn with_anime_licensed_by<'b>(
453        &'b mut self,
454        anime_licensed_by: &'a [&'a str],
455    ) -> &'b mut TranslationQuery<'a> {
456        self.anime_licensed_by = Some(anime_licensed_by);
457        self
458    }
459
460    /// Execute the query and fetch the results.
461    pub async fn execute<'b>(&'a self, client: &'b Client) -> Result<TranslationResponse, Error> {
462        let payload = serialize_into_query_parts(self)?;
463
464        let response = client
465            .init_post_request("/translations/v2")
466            .query(&payload)
467            .send()
468            .await
469            .map_err(Error::HttpError)?;
470
471        let result = response
472            .json::<TranslationResponseUnion>()
473            .await
474            .map_err(Error::HttpError)?;
475
476        match result {
477            TranslationResponseUnion::Result(result) => Ok(result),
478            TranslationResponseUnion::Error { error } => Err(Error::KodikError(error)),
479        }
480    }
481}
482
483impl<'a> Default for TranslationQuery<'a> {
484    fn default() -> Self {
485        Self::new()
486    }
487}