kodik_api/
years.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 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
215    pub fn with_year<'b>(&'b mut self, year: &'a [u32]) -> &'b mut YearQuery<'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 YearQuery<'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 YearQuery<'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 YearQuery<'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 YearQuery<'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 YearQuery<'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 YearQuery<'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 YearQuery<'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 YearQuery<'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>(&'b mut self, all_genres: &'a [&'a str]) -> &'b mut YearQuery<'a> {
283        self.all_genres = Some(all_genres);
284        self
285    }
286
287    /// Filtering by duration (in minutes). You can specify either a single value to search for the exact duration, or an interval.
288    pub fn with_duration<'b>(&'b mut self, duration: &'a [&'a str]) -> &'b mut YearQuery<'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 YearQuery<'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>(&'b mut self, imdb_rating: &'a [&'a str]) -> &'b mut YearQuery<'a> {
303        self.imdb_rating = Some(imdb_rating);
304        self
305    }
306    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
307    pub fn with_shikimori_rating<'b>(
308        &'b mut self,
309        shikimori_rating: &'a [&'a str],
310    ) -> &'b mut YearQuery<'a> {
311        self.shikimori_rating = Some(shikimori_rating);
312        self
313    }
314    /// Filtering by Kinopoisk, IMDb, Shikimori, or MyDramaList ratings. You can specify either a single value to search for the exact rating, or an interval
315    pub fn with_mydramalist_rating<'b>(
316        &'b mut self,
317        mydramalist_rating: &'a [&'a str],
318    ) -> &'b mut YearQuery<'a> {
319        self.mydramalist_rating = Some(mydramalist_rating);
320        self
321    }
322
323    /// 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
324    pub fn with_actors<'b>(&'b mut self, actors: &'a [&'a str]) -> &'b mut YearQuery<'a> {
325        self.actors = Some(actors);
326        self
327    }
328    /// 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
329    pub fn with_directors<'b>(&'b mut self, directors: &'a [&'a str]) -> &'b mut YearQuery<'a> {
330        self.directors = Some(directors);
331        self
332    }
333    /// 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
334    pub fn with_producers<'b>(&'b mut self, producers: &'a [&'a str]) -> &'b mut YearQuery<'a> {
335        self.producers = Some(producers);
336        self
337    }
338    /// 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
339    pub fn with_writers<'b>(&'b mut self, writers: &'a [&'a str]) -> &'b mut YearQuery<'a> {
340        self.writers = Some(writers);
341        self
342    }
343    /// 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
344    pub fn with_composers<'b>(&'b mut self, composers: &'a [&'a str]) -> &'b mut YearQuery<'a> {
345        self.composers = Some(composers);
346        self
347    }
348    /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
349    pub fn with_editors<'b>(&'b mut self, editors: &'a [&'a str]) -> &'b mut YearQuery<'a> {
350        self.editors = Some(editors);
351        self
352    }
353    /// Filtering materials by personas. You can specify a single value or multiple values, separated by commas (then materials that have at least one of the specified personas will be displayed). This parameter is case-independent. You can specify filters for several professions at once
354    pub fn with_designers<'b>(&'b mut self, designers: &'a [&'a str]) -> &'b mut YearQuery<'a> {
355        self.designers = Some(designers);
356        self
357    }
358    /// 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
359    pub fn with_operators<'b>(&'b mut self, operators: &'a [&'a str]) -> &'b mut YearQuery<'a> {
360        self.operators = Some(operators);
361        self
362    }
363
364    /// Filtering materials by age rating. You can specify a single value or multiple values, separated by commas. The parameter is case-insensitive
365    pub fn with_rating_mpaa<'b>(
366        &'b mut self,
367        rating_mpaa: &'a [MppaRating],
368    ) -> &'b mut YearQuery<'a> {
369        self.rating_mpaa = Some(rating_mpaa);
370        self
371    }
372
373    /// Filter content by the minimum age from which it can be viewed. You can specify either a single value or a range of values
374    pub fn with_minimal_age<'b>(&'b mut self, minimal_age: &'a [&'a str]) -> &'b mut YearQuery<'a> {
375        self.minimal_age = Some(minimal_age);
376        self
377    }
378
379    /// 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)
380    pub fn with_anime_kind<'b>(&'b mut self, anime_kind: &'a [AnimeKind]) -> &'b mut YearQuery<'a> {
381        self.anime_kind = Some(anime_kind);
382        self
383    }
384
385    /// 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)
386    pub fn with_mydramalist_tags<'b>(
387        &'b mut self,
388        mydramalist_tags: &'a [&'a str],
389    ) -> &'b mut YearQuery<'a> {
390        self.mydramalist_tags = Some(mydramalist_tags);
391        self
392    }
393
394    /// 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)
395    pub fn with_anime_status<'b>(
396        &'b mut self,
397        anime_status: &'a [AnimeStatus],
398    ) -> &'b mut YearQuery<'a> {
399        self.anime_status = Some(anime_status);
400        self
401    }
402    /// 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)
403    pub fn with_drama_status<'b>(
404        &'b mut self,
405        drama_status: &'a [DramaStatus],
406    ) -> &'b mut YearQuery<'a> {
407        self.drama_status = Some(drama_status);
408        self
409    }
410    /// 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)
411    pub fn with_all_status<'b>(&'b mut self, all_status: &'a [AllStatus]) -> &'b mut YearQuery<'a> {
412        self.all_status = Some(all_status);
413        self
414    }
415
416    /// 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)
417    pub fn with_anime_studios<'b>(
418        &'b mut self,
419        anime_studios: &'a [&'a str],
420    ) -> &'b mut YearQuery<'a> {
421        self.anime_studios = Some(anime_studios);
422        self
423    }
424    /// 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)
425    pub fn with_anime_licensed_by<'b>(
426        &'b mut self,
427        anime_licensed_by: &'a [&'a str],
428    ) -> &'b mut YearQuery<'a> {
429        self.anime_licensed_by = Some(anime_licensed_by);
430        self
431    }
432
433    /// Execute the query and fetch the results.
434    pub async fn execute<'b>(&'a self, client: &'b Client) -> Result<YearResponse, Error> {
435        let payload = serialize_into_query_parts(self)?;
436
437        let response = client
438            .init_post_request("/years")
439            .query(&payload)
440            .send()
441            .await
442            .map_err(Error::HttpError)?;
443
444        let result = response
445            .json::<YearResponseUnion>()
446            .await
447            .map_err(Error::HttpError)?;
448
449        match result {
450            YearResponseUnion::Result(result) => Ok(result),
451            YearResponseUnion::Error { error } => Err(Error::KodikError(error)),
452        }
453    }
454}
455
456impl<'a> Default for YearQuery<'a> {
457    fn default() -> Self {
458        Self::new()
459    }
460}