kodik_api/
years.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 YearResult {
15    pub year: i32,
16
17    /// The number of materials with this voice acting
18    pub count: i32,
19}
20
21#[derive(Deserialize, Debug, Clone)]
22pub struct YearResponse {
23    pub time: String,
24    pub total: i32,
25    pub prev_page: Option<String>,
26    pub next_page: Option<String>,
27    pub results: Vec<YearResult>,
28}
29
30/// A struct containing years results and other information about the years
31#[derive(Deserialize, Debug, Clone)]
32#[serde(untagged)]
33enum YearResponseUnion {
34    Result(YearResponse),
35    Error { error: String },
36}
37
38#[derive(Serialize, Deserialize, Debug, Clone)]
39pub enum YearSort {
40    #[serde(rename = "year")]
41    Year,
42    #[serde(rename = "count")]
43    Count,
44}
45
46#[derive(Debug, Serialize, Clone)]
47pub struct YearQuery<'a> {
48    /// What field to sort materials by
49    #[serde(skip_serializing_if = "Option::is_none")]
50    sort: Option<YearSort>,
51
52    /// Maximum number of outputs
53    #[serde(skip_serializing_if = "Option::is_none")]
54    types: Option<&'a [ReleaseType]>,
55
56    ///Filter materials by year If you set this parameter, only materials of the corresponding year will be displayed
57    #[serde(skip_serializing_if = "Option::is_none")]
58    year: Option<&'a [u32]>,
59
60    /// Filtering materials by translation ID
61    #[serde(skip_serializing_if = "Option::is_none")]
62    translation_id: Option<&'a [u32]>,
63    /// Filter content by translation type. Allows you to output only voice translation or only subtitles
64    #[serde(skip_serializing_if = "Option::is_none")]
65    translation_type: Option<&'a [TranslationType]>,
66
67    /// 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
68    #[serde(skip_serializing_if = "Option::is_none")]
69    has_field: Option<&'a [MaterialDataField]>,
70    /// Filtering materials based on the presence of a specific field. Materials that have all the listed fields are shown
71    #[serde(skip_serializing_if = "Option::is_none")]
72    has_field_and: Option<&'a [MaterialDataField]>,
73
74    /// 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
75    #[serde(skip_serializing_if = "Option::is_none")]
76    countries: Option<&'a [&'a str]>,
77
78    /// 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
79    #[serde(skip_serializing_if = "Option::is_none")]
80    genres: Option<&'a [&'a str]>,
81    /// 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
82    #[serde(skip_serializing_if = "Option::is_none")]
83    anime_genres: Option<&'a [&'a str]>,
84    /// 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
85    #[serde(skip_serializing_if = "Option::is_none")]
86    drama_genres: Option<&'a [&'a str]>,
87    /// 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
88    #[serde(skip_serializing_if = "Option::is_none")]
89    all_genres: Option<&'a [&'a str]>,
90
91    /// Filtering by duration (in minutes). You can specify either a single value to search for the exact duration, or an interval.
92    #[serde(skip_serializing_if = "Option::is_none")]
93    duration: Option<&'a [&'a str]>,
94
95    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
96    #[serde(skip_serializing_if = "Option::is_none")]
97    kinopoisk_rating: Option<&'a [&'a str]>,
98    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
99    #[serde(skip_serializing_if = "Option::is_none")]
100    imdb_rating: Option<&'a [&'a str]>,
101    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
102    #[serde(skip_serializing_if = "Option::is_none")]
103    shikimori_rating: Option<&'a [&'a str]>,
104    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
105    #[serde(skip_serializing_if = "Option::is_none")]
106    mydramalist_rating: Option<&'a [&'a str]>,
107
108    /// 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
109    #[serde(skip_serializing_if = "Option::is_none")]
110    actors: Option<&'a [&'a str]>,
111    /// 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
112    #[serde(skip_serializing_if = "Option::is_none")]
113    directors: Option<&'a [&'a str]>,
114    /// 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
115    #[serde(skip_serializing_if = "Option::is_none")]
116    producers: Option<&'a [&'a str]>,
117    /// 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
118    #[serde(skip_serializing_if = "Option::is_none")]
119    writers: Option<&'a [&'a str]>,
120    /// 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
121    #[serde(skip_serializing_if = "Option::is_none")]
122    composers: Option<&'a [&'a str]>,
123    /// 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
124    #[serde(skip_serializing_if = "Option::is_none")]
125    editors: Option<&'a [&'a str]>,
126    /// 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
127    #[serde(skip_serializing_if = "Option::is_none")]
128    designers: Option<&'a [&'a str]>,
129    /// 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
130    #[serde(skip_serializing_if = "Option::is_none")]
131    operators: Option<&'a [&'a str]>,
132
133    /// Filtering materials by age rating. You can specify a single value or multiple values, separated by commas. The parameter is case-insensitive
134    #[serde(skip_serializing_if = "Option::is_none")]
135    rating_mpaa: Option<&'a [MppaRating]>,
136
137    /// Filter content by the minimum age from which it can be viewed. You can specify either a single value or a range of values
138    #[serde(skip_serializing_if = "Option::is_none")]
139    minimal_age: Option<&'a [&'a str]>,
140
141    /// 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)
142    #[serde(skip_serializing_if = "Option::is_none")]
143    anime_kind: Option<&'a [AnimeKind]>,
144
145    /// 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)
146    #[serde(skip_serializing_if = "Option::is_none")]
147    mydramalist_tags: Option<&'a [&'a str]>,
148
149    /// 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)
150    #[serde(skip_serializing_if = "Option::is_none")]
151    anime_status: Option<&'a [AnimeStatus]>,
152    /// 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)
153    #[serde(skip_serializing_if = "Option::is_none")]
154    drama_status: Option<&'a [DramaStatus]>,
155    /// 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)
156    #[serde(skip_serializing_if = "Option::is_none")]
157    all_status: Option<&'a [AllStatus]>,
158
159    /// 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)
160    #[serde(skip_serializing_if = "Option::is_none")]
161    anime_studios: Option<&'a [&'a str]>,
162    /// 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)
163    #[serde(skip_serializing_if = "Option::is_none")]
164    anime_licensed_by: Option<&'a [&'a str]>,
165}
166
167impl<'a> YearQuery<'a> {
168    pub fn new() -> YearQuery<'a> {
169        YearQuery {
170            sort: None,
171            types: None,
172            year: None,
173            translation_id: 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 YearQuery<'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 YearQuery<'a> {
215        self.year = Some(year);
216        self
217    }
218
219    /// Filtering materials by translation ID
220    pub fn with_translation_id<'b>(
221        &'b mut self,
222        translation_id: &'a [u32],
223    ) -> &'b mut YearQuery<'a> {
224        self.translation_id = Some(translation_id);
225        self
226    }
227    /// Filter content by translation type. Allows you to output only voice translation or only subtitles
228    pub fn with_translation_type<'b>(
229        &'b mut self,
230        translation_type: &'a [TranslationType],
231    ) -> &'b mut YearQuery<'a> {
232        self.translation_type = Some(translation_type);
233        self
234    }
235
236    /// 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
237    pub fn with_has_field<'b>(
238        &'b mut self,
239        has_field: &'a [MaterialDataField],
240    ) -> &'b mut YearQuery<'a> {
241        self.has_field = Some(has_field);
242        self
243    }
244    /// Filtering materials based on the presence of a specific field. Materials that have all the listed fields are shown
245    pub fn with_has_field_and<'b>(
246        &'b mut self,
247        has_field: &'a [MaterialDataField],
248    ) -> &'b mut YearQuery<'a> {
249        self.has_field_and = Some(has_field);
250        self
251    }
252
253    /// 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
254    pub fn with_countries<'b>(&'b mut self, countries: &'a [&'a str]) -> &'b mut YearQuery<'a> {
255        self.countries = Some(countries);
256        self
257    }
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_genres<'b>(&'b mut self, genres: &'a [&'a str]) -> &'b mut YearQuery<'a> {
261        self.genres = Some(genres);
262        self
263    }
264    /// 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
265    pub fn with_anime_genres<'b>(
266        &'b mut self,
267        anime_genres: &'a [&'a str],
268    ) -> &'b mut YearQuery<'a> {
269        self.anime_genres = Some(anime_genres);
270        self
271    }
272    /// 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
273    pub fn with_drama_genres<'b>(
274        &'b mut self,
275        drama_genres: &'a [&'a str],
276    ) -> &'b mut YearQuery<'a> {
277        self.drama_genres = Some(drama_genres);
278        self
279    }
280    /// 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
281    pub fn with_all_genres<'b>(&'b mut self, all_genres: &'a [&'a str]) -> &'b mut YearQuery<'a> {
282        self.all_genres = Some(all_genres);
283        self
284    }
285
286    /// Filtering by duration (in minutes). You can specify either a single value to search for the exact duration, or an interval.
287    pub fn with_duration<'b>(&'b mut self, duration: &'a [&'a str]) -> &'b mut YearQuery<'a> {
288        self.duration = Some(duration);
289        self
290    }
291
292    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
293    pub fn with_kinopoisk_rating<'b>(
294        &'b mut self,
295        kinopoisk_rating: &'a [&'a str],
296    ) -> &'b mut YearQuery<'a> {
297        self.kinopoisk_rating = Some(kinopoisk_rating);
298        self
299    }
300    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
301    pub fn with_imdb_rating<'b>(&'b mut self, imdb_rating: &'a [&'a str]) -> &'b mut YearQuery<'a> {
302        self.imdb_rating = Some(imdb_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_shikimori_rating<'b>(
307        &'b mut self,
308        shikimori_rating: &'a [&'a str],
309    ) -> &'b mut YearQuery<'a> {
310        self.shikimori_rating = Some(shikimori_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_mydramalist_rating<'b>(
315        &'b mut self,
316        mydramalist_rating: &'a [&'a str],
317    ) -> &'b mut YearQuery<'a> {
318        self.mydramalist_rating = Some(mydramalist_rating);
319        self
320    }
321
322    /// 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
323    pub fn with_actors<'b>(&'b mut self, actors: &'a [&'a str]) -> &'b mut YearQuery<'a> {
324        self.actors = Some(actors);
325        self
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_directors<'b>(&'b mut self, directors: &'a [&'a str]) -> &'b mut YearQuery<'a> {
329        self.directors = Some(directors);
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_producers<'b>(&'b mut self, producers: &'a [&'a str]) -> &'b mut YearQuery<'a> {
334        self.producers = Some(producers);
335        self
336    }
337    /// 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
338    pub fn with_writers<'b>(&'b mut self, writers: &'a [&'a str]) -> &'b mut YearQuery<'a> {
339        self.writers = Some(writers);
340        self
341    }
342    /// 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
343    pub fn with_composers<'b>(&'b mut self, composers: &'a [&'a str]) -> &'b mut YearQuery<'a> {
344        self.composers = Some(composers);
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_editors<'b>(&'b mut self, editors: &'a [&'a str]) -> &'b mut YearQuery<'a> {
349        self.editors = Some(editors);
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_designers<'b>(&'b mut self, designers: &'a [&'a str]) -> &'b mut YearQuery<'a> {
354        self.designers = Some(designers);
355        self
356    }
357    /// 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
358    pub fn with_operators<'b>(&'b mut self, operators: &'a [&'a str]) -> &'b mut YearQuery<'a> {
359        self.operators = Some(operators);
360        self
361    }
362
363    /// Filtering materials by age rating. You can specify a single value or multiple values, separated by commas. The parameter is case-insensitive
364    pub fn with_rating_mpaa<'b>(
365        &'b mut self,
366        rating_mpaa: &'a [MppaRating],
367    ) -> &'b mut YearQuery<'a> {
368        self.rating_mpaa = Some(rating_mpaa);
369        self
370    }
371
372    /// Filter content by the minimum age from which it can be viewed. You can specify either a single value or a range of values
373    pub fn with_minimal_age<'b>(&'b mut self, minimal_age: &'a [&'a str]) -> &'b mut YearQuery<'a> {
374        self.minimal_age = Some(minimal_age);
375        self
376    }
377
378    /// 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)
379    pub fn with_anime_kind<'b>(&'b mut self, anime_kind: &'a [AnimeKind]) -> &'b mut YearQuery<'a> {
380        self.anime_kind = Some(anime_kind);
381        self
382    }
383
384    /// 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)
385    pub fn with_mydramalist_tags<'b>(
386        &'b mut self,
387        mydramalist_tags: &'a [&'a str],
388    ) -> &'b mut YearQuery<'a> {
389        self.mydramalist_tags = Some(mydramalist_tags);
390        self
391    }
392
393    /// 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)
394    pub fn with_anime_status<'b>(
395        &'b mut self,
396        anime_status: &'a [AnimeStatus],
397    ) -> &'b mut YearQuery<'a> {
398        self.anime_status = Some(anime_status);
399        self
400    }
401    /// 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)
402    pub fn with_drama_status<'b>(
403        &'b mut self,
404        drama_status: &'a [DramaStatus],
405    ) -> &'b mut YearQuery<'a> {
406        self.drama_status = Some(drama_status);
407        self
408    }
409    /// 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)
410    pub fn with_all_status<'b>(&'b mut self, all_status: &'a [AllStatus]) -> &'b mut YearQuery<'a> {
411        self.all_status = Some(all_status);
412        self
413    }
414
415    /// 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)
416    pub fn with_anime_studios<'b>(
417        &'b mut self,
418        anime_studios: &'a [&'a str],
419    ) -> &'b mut YearQuery<'a> {
420        self.anime_studios = Some(anime_studios);
421        self
422    }
423    /// 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)
424    pub fn with_anime_licensed_by<'b>(
425        &'b mut self,
426        anime_licensed_by: &'a [&'a str],
427    ) -> &'b mut YearQuery<'a> {
428        self.anime_licensed_by = Some(anime_licensed_by);
429        self
430    }
431
432    /// Execute the query and fetch the results.
433    pub async fn execute<'b>(&'a self, client: &'b Client) -> Result<YearResponse, Error> {
434        let payload = serialize_into_query_parts(self)?;
435
436        let response = client
437            .init_post_request("/years")
438            .query(&payload)
439            .send()
440            .await
441            .map_err(Error::HttpError)?;
442
443        let result = response
444            .json::<YearResponseUnion>()
445            .await
446            .map_err(Error::HttpError)?;
447
448        match result {
449            YearResponseUnion::Result(result) => Ok(result),
450            YearResponseUnion::Error { error } => Err(Error::KodikError(error)),
451        }
452    }
453}
454
455impl<'a> Default for YearQuery<'a> {
456    fn default() -> Self {
457        Self::new()
458    }
459}