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