kodik_api/
countries.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 CountryResult {
15    // Name of the country
16    pub title: String,
17
18    /// The number of materials with this voice acting
19    pub count: i32,
20}
21
22/// A struct containing countries results and other information about the countries
23#[derive(Deserialize, Debug, Clone)]
24pub struct CountryResponse {
25    pub time: String,
26    pub total: i32,
27    pub prev_page: Option<String>,
28    pub next_page: Option<String>,
29    pub results: Vec<CountryResult>,
30}
31
32#[derive(Deserialize, Debug, Clone)]
33#[serde(untagged)]
34enum CountryResponseUnion {
35    Result(CountryResponse),
36    Error { error: String },
37}
38
39#[derive(Serialize, Deserialize, Debug, Clone)]
40pub enum CountrySort {
41    #[serde(rename = "title")]
42    Title,
43    #[serde(rename = "count")]
44    Count,
45}
46
47#[derive(Debug, Serialize, Clone)]
48pub struct CountryQuery<'a> {
49    /// What field to sort materials by
50    #[serde(skip_serializing_if = "Option::is_none")]
51    sort: Option<CountrySort>,
52
53    /// Maximum number of outputs
54    #[serde(skip_serializing_if = "Option::is_none")]
55    types: Option<&'a [ReleaseType]>,
56
57    ///Filter materials by year If you set this parameter, only materials of the corresponding year will be displayed
58    #[serde(skip_serializing_if = "Option::is_none")]
59    year: Option<&'a [u32]>,
60
61    /// Filtering materials by translation ID
62    #[serde(skip_serializing_if = "Option::is_none")]
63    translation_id: Option<&'a [u32]>,
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> CountryQuery<'a> {
169    pub fn new() -> CountryQuery<'a> {
170        CountryQuery {
171            sort: None,
172            types: None,
173            year: None,
174            translation_id: None,
175            translation_type: None,
176            has_field: None,
177            has_field_and: None,
178            countries: None,
179            genres: None,
180            anime_genres: None,
181            drama_genres: None,
182            all_genres: None,
183            duration: None,
184            kinopoisk_rating: None,
185            imdb_rating: None,
186            shikimori_rating: None,
187            mydramalist_rating: None,
188            actors: None,
189            directors: None,
190            producers: None,
191            writers: None,
192            composers: None,
193            editors: None,
194            designers: None,
195            operators: None,
196            rating_mpaa: None,
197            minimal_age: None,
198            anime_kind: None,
199            mydramalist_tags: None,
200            anime_status: None,
201            drama_status: None,
202            all_status: None,
203            anime_studios: None,
204            anime_licensed_by: None,
205        }
206    }
207
208    /// Maximum number of outputs
209    pub fn with_types<'b>(&'b mut self, types: &'a [ReleaseType]) -> &'b mut CountryQuery<'a> {
210        self.types = Some(types);
211        self
212    }
213
214    ///Filter materials by year If you set this parameter, only materials of the corresponding year will be displayed
215
216    pub fn with_year<'b>(&'b mut self, year: &'a [u32]) -> &'b mut CountryQuery<'a> {
217        self.year = Some(year);
218        self
219    }
220
221    /// Filtering materials by translation ID
222    pub fn with_translation_id<'b>(
223        &'b mut self,
224        translation_id: &'a [u32],
225    ) -> &'b mut CountryQuery<'a> {
226        self.translation_id = Some(translation_id);
227        self
228    }
229    /// Filter content by translation type. Allows you to output only voice translation or only subtitles
230    pub fn with_translation_type<'b>(
231        &'b mut self,
232        translation_type: &'a [TranslationType],
233    ) -> &'b mut CountryQuery<'a> {
234        self.translation_type = Some(translation_type);
235        self
236    }
237
238    /// 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
239    pub fn with_has_field<'b>(
240        &'b mut self,
241        has_field: &'a [MaterialDataField],
242    ) -> &'b mut CountryQuery<'a> {
243        self.has_field = Some(has_field);
244        self
245    }
246    /// Filtering materials based on the presence of a specific field. Materials that have all the listed fields are shown
247    pub fn with_has_field_and<'b>(
248        &'b mut self,
249        has_field: &'a [MaterialDataField],
250    ) -> &'b mut CountryQuery<'a> {
251        self.has_field_and = Some(has_field);
252        self
253    }
254
255    /// 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
256    pub fn with_countries<'b>(&'b mut self, countries: &'a [&'a str]) -> &'b mut CountryQuery<'a> {
257        self.countries = Some(countries);
258        self
259    }
260
261    /// 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
262    pub fn with_genres<'b>(&'b mut self, genres: &'a [&'a str]) -> &'b mut CountryQuery<'a> {
263        self.genres = Some(genres);
264        self
265    }
266    /// 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
267    pub fn with_anime_genres<'b>(
268        &'b mut self,
269        anime_genres: &'a [&'a str],
270    ) -> &'b mut CountryQuery<'a> {
271        self.anime_genres = Some(anime_genres);
272        self
273    }
274    /// 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
275    pub fn with_drama_genres<'b>(
276        &'b mut self,
277        drama_genres: &'a [&'a str],
278    ) -> &'b mut CountryQuery<'a> {
279        self.drama_genres = Some(drama_genres);
280        self
281    }
282    /// 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
283    pub fn with_all_genres<'b>(
284        &'b mut self,
285        all_genres: &'a [&'a str],
286    ) -> &'b mut CountryQuery<'a> {
287        self.all_genres = Some(all_genres);
288        self
289    }
290
291    /// Filtering by duration (in minutes). You can specify either a single value to search for the exact duration, or an interval.
292    pub fn with_duration<'b>(&'b mut self, duration: &'a [&'a str]) -> &'b mut CountryQuery<'a> {
293        self.duration = Some(duration);
294        self
295    }
296
297    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
298    pub fn with_kinopoisk_rating<'b>(
299        &'b mut self,
300        kinopoisk_rating: &'a [&'a str],
301    ) -> &'b mut CountryQuery<'a> {
302        self.kinopoisk_rating = Some(kinopoisk_rating);
303        self
304    }
305    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
306    pub fn with_imdb_rating<'b>(
307        &'b mut self,
308        imdb_rating: &'a [&'a str],
309    ) -> &'b mut CountryQuery<'a> {
310        self.imdb_rating = Some(imdb_rating);
311        self
312    }
313    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
314    pub fn with_shikimori_rating<'b>(
315        &'b mut self,
316        shikimori_rating: &'a [&'a str],
317    ) -> &'b mut CountryQuery<'a> {
318        self.shikimori_rating = Some(shikimori_rating);
319        self
320    }
321    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
322    pub fn with_mydramalist_rating<'b>(
323        &'b mut self,
324        mydramalist_rating: &'a [&'a str],
325    ) -> &'b mut CountryQuery<'a> {
326        self.mydramalist_rating = Some(mydramalist_rating);
327        self
328    }
329
330    /// 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
331    pub fn with_actors<'b>(&'b mut self, actors: &'a [&'a str]) -> &'b mut CountryQuery<'a> {
332        self.actors = Some(actors);
333        self
334    }
335    /// 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
336    pub fn with_directors<'b>(&'b mut self, directors: &'a [&'a str]) -> &'b mut CountryQuery<'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>(&'b mut self, producers: &'a [&'a str]) -> &'b mut CountryQuery<'a> {
342        self.producers = Some(producers);
343        self
344    }
345    /// 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
346    pub fn with_writers<'b>(&'b mut self, writers: &'a [&'a str]) -> &'b mut CountryQuery<'a> {
347        self.writers = Some(writers);
348        self
349    }
350    /// 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
351    pub fn with_composers<'b>(&'b mut self, composers: &'a [&'a str]) -> &'b mut CountryQuery<'a> {
352        self.composers = Some(composers);
353        self
354    }
355    /// 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
356    pub fn with_editors<'b>(&'b mut self, editors: &'a [&'a str]) -> &'b mut CountryQuery<'a> {
357        self.editors = Some(editors);
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_designers<'b>(&'b mut self, designers: &'a [&'a str]) -> &'b mut CountryQuery<'a> {
362        self.designers = Some(designers);
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_operators<'b>(&'b mut self, operators: &'a [&'a str]) -> &'b mut CountryQuery<'a> {
367        self.operators = Some(operators);
368        self
369    }
370
371    /// Filtering materials by age rating. You can specify a single value or multiple values, separated by commas. The parameter is case-insensitive
372    pub fn with_rating_mpaa<'b>(
373        &'b mut self,
374        rating_mpaa: &'a [MppaRating],
375    ) -> &'b mut CountryQuery<'a> {
376        self.rating_mpaa = Some(rating_mpaa);
377        self
378    }
379
380    /// Filter content by the minimum age from which it can be viewed. You can specify either a single value or a range of values
381    pub fn with_minimal_age<'b>(
382        &'b mut self,
383        minimal_age: &'a [&'a str],
384    ) -> &'b mut CountryQuery<'a> {
385        self.minimal_age = Some(minimal_age);
386        self
387    }
388
389    /// 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)
390    pub fn with_anime_kind<'b>(
391        &'b mut self,
392        anime_kind: &'a [AnimeKind],
393    ) -> &'b mut CountryQuery<'a> {
394        self.anime_kind = Some(anime_kind);
395        self
396    }
397
398    /// 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)
399    pub fn with_mydramalist_tags<'b>(
400        &'b mut self,
401        mydramalist_tags: &'a [&'a str],
402    ) -> &'b mut CountryQuery<'a> {
403        self.mydramalist_tags = Some(mydramalist_tags);
404        self
405    }
406
407    /// 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)
408    pub fn with_anime_status<'b>(
409        &'b mut self,
410        anime_status: &'a [AnimeStatus],
411    ) -> &'b mut CountryQuery<'a> {
412        self.anime_status = Some(anime_status);
413        self
414    }
415    /// 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)
416    pub fn with_drama_status<'b>(
417        &'b mut self,
418        drama_status: &'a [DramaStatus],
419    ) -> &'b mut CountryQuery<'a> {
420        self.drama_status = Some(drama_status);
421        self
422    }
423    /// 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)
424    pub fn with_all_status<'b>(
425        &'b mut self,
426        all_status: &'a [AllStatus],
427    ) -> &'b mut CountryQuery<'a> {
428        self.all_status = Some(all_status);
429        self
430    }
431
432    /// 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)
433    pub fn with_anime_studios<'b>(
434        &'b mut self,
435        anime_studios: &'a [&'a str],
436    ) -> &'b mut CountryQuery<'a> {
437        self.anime_studios = Some(anime_studios);
438        self
439    }
440    /// 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)
441    pub fn with_anime_licensed_by<'b>(
442        &'b mut self,
443        anime_licensed_by: &'a [&'a str],
444    ) -> &'b mut CountryQuery<'a> {
445        self.anime_licensed_by = Some(anime_licensed_by);
446        self
447    }
448
449    /// Execute the query and fetch the results.
450    pub async fn execute<'b>(&'a self, client: &'b Client) -> Result<CountryResponse, Error> {
451        let payload = serialize_into_query_parts(self)?;
452
453        let response = client
454            .init_post_request("/countries")
455            .query(&payload)
456            .send()
457            .await
458            .map_err(Error::HttpError)?;
459
460        let result = response
461            .json::<CountryResponseUnion>()
462            .await
463            .map_err(Error::HttpError)?;
464
465        match result {
466            CountryResponseUnion::Result(result) => Ok(result),
467            CountryResponseUnion::Error { error } => Err(Error::KodikError(error)),
468        }
469    }
470}
471
472impl<'a> Default for CountryQuery<'a> {
473    fn default() -> Self {
474        Self::new()
475    }
476}