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