Skip to main content

ferrex_model/
details.rs

1use crate::image::MediaImages;
2use std::fmt;
3use std::path::PathBuf;
4use uuid::Uuid;
5
6use super::{ids::LibraryId, library::LibraryType};
7
8#[derive(Debug, Clone, PartialEq, Default)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[cfg_attr(
11    feature = "rkyv",
12    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
13)]
14#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
15pub struct ReleaseDateEntry {
16    pub certification: Option<String>,
17    pub release_date: Option<String>,
18    pub release_type: Option<i32>,
19    pub note: Option<String>,
20    pub iso_639_1: Option<String>,
21    #[cfg_attr(feature = "serde", serde(default))]
22    pub descriptors: Vec<String>,
23}
24
25#[derive(Debug, Clone, PartialEq, Default)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27#[cfg_attr(
28    feature = "rkyv",
29    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
30)]
31#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
32pub struct ReleaseDatesByCountry {
33    pub iso_3166_1: String,
34    #[cfg_attr(feature = "serde", serde(default))]
35    pub release_dates: Vec<ReleaseDateEntry>,
36}
37
38#[derive(Debug, Clone, PartialEq, Default)]
39#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
40#[cfg_attr(
41    feature = "rkyv",
42    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
43)]
44#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
45pub struct ContentRating {
46    pub iso_3166_1: String,
47    pub rating: Option<String>,
48    pub rating_system: Option<String>,
49    #[cfg_attr(feature = "serde", serde(default))]
50    pub descriptors: Vec<String>,
51}
52
53#[derive(Debug, Clone, PartialEq, Default)]
54#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
55#[cfg_attr(
56    feature = "rkyv",
57    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
58)]
59#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
60pub struct AlternativeTitle {
61    pub title: String,
62    pub iso_3166_1: Option<String>,
63    pub title_type: Option<String>,
64}
65
66#[derive(Debug, Clone, PartialEq, Default)]
67#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
68#[cfg_attr(
69    feature = "rkyv",
70    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
71)]
72#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
73pub struct Translation {
74    pub iso_3166_1: String,
75    pub iso_639_1: String,
76    pub name: Option<String>,
77    pub english_name: Option<String>,
78    pub title: Option<String>,
79    pub overview: Option<String>,
80    pub homepage: Option<String>,
81    pub tagline: Option<String>,
82}
83
84#[derive(Debug, Clone, PartialEq, Default)]
85#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
86#[cfg_attr(
87    feature = "rkyv",
88    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
89)]
90#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
91pub struct CollectionInfo {
92    pub id: u64,
93    pub name: String,
94    pub poster_path: Option<String>,
95    pub backdrop_path: Option<String>,
96}
97
98#[derive(Debug, Clone, PartialEq, Default)]
99#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
100#[cfg_attr(
101    feature = "rkyv",
102    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
103)]
104#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq, Hash)))]
105pub struct Keyword {
106    pub id: u64,
107    pub name: String,
108}
109
110#[derive(Debug, Clone, PartialEq)]
111#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
112#[cfg_attr(
113    feature = "rkyv",
114    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
115)]
116#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
117pub struct EpisodeGroupMembership {
118    pub id: String,
119    pub name: String,
120    pub description: Option<String>,
121    pub group_type: Option<String>,
122}
123
124#[derive(Debug, Clone, PartialEq)]
125#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
126#[cfg_attr(
127    feature = "rkyv",
128    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
129)]
130#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
131pub struct GenreInfo {
132    pub id: u64,
133    pub name: String,
134}
135
136#[derive(Debug, Clone, PartialEq)]
137#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
138#[cfg_attr(
139    feature = "rkyv",
140    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
141)]
142#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
143pub struct ProductionCompany {
144    pub id: u64,
145    pub name: String,
146    pub origin_country: Option<String>,
147}
148
149#[derive(Debug, Clone, PartialEq)]
150#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
151#[cfg_attr(
152    feature = "rkyv",
153    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
154)]
155#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
156pub struct ProductionCountry {
157    pub iso_3166_1: String,
158    pub name: String,
159}
160
161#[derive(Debug, Clone, PartialEq)]
162#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
163#[cfg_attr(
164    feature = "rkyv",
165    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
166)]
167#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
168pub struct SpokenLanguage {
169    pub iso_639_1: Option<String>,
170    pub name: String,
171}
172
173#[derive(Debug, Clone, PartialEq)]
174#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
175#[cfg_attr(
176    feature = "rkyv",
177    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
178)]
179#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
180pub struct NetworkInfo {
181    pub id: u64,
182    pub name: String,
183    pub origin_country: Option<String>,
184}
185
186#[derive(Debug, Clone, PartialEq)]
187#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
188#[cfg_attr(
189    feature = "rkyv",
190    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
191)]
192#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
193pub struct RelatedMediaRef {
194    pub tmdb_id: u64,
195    pub title: Option<String>,
196}
197
198#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
199#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
200#[cfg_attr(
201    feature = "rkyv",
202    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
203)]
204#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq, Hash)))]
205pub struct PersonExternalIds {
206    pub imdb_id: Option<String>,
207    pub facebook_id: Option<String>,
208    pub instagram_id: Option<String>,
209    pub twitter_id: Option<String>,
210    pub wikidata_id: Option<String>,
211    pub tiktok_id: Option<String>,
212    pub youtube_id: Option<String>,
213}
214
215#[derive(Debug, Clone, PartialEq)]
216#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
217#[cfg_attr(
218    feature = "rkyv",
219    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
220)]
221#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
222pub enum TmdbDetails {
223    Movie(EnhancedMovieDetails),
224    Series(EnhancedSeriesDetails),
225    Season(SeasonDetails),
226    Episode(EpisodeDetails),
227}
228
229/// Enhanced metadata that includes images, credits, and additional information
230#[derive(Clone, PartialEq)]
231#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
232#[cfg_attr(
233    feature = "rkyv",
234    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
235)]
236#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
237pub struct EnhancedMovieDetails {
238    // Basic details
239    pub id: u64,
240    pub title: String,
241    pub original_title: Option<String>,
242    pub overview: Option<String>,
243    pub release_date: Option<String>,
244    pub runtime: Option<u32>,
245    pub vote_average: Option<f32>,
246    pub vote_count: Option<u32>,
247    pub popularity: Option<f32>,
248    pub content_rating: Option<String>,
249    #[cfg_attr(feature = "serde", serde(default))]
250    pub content_ratings: Vec<ContentRating>,
251    #[cfg_attr(feature = "serde", serde(default))]
252    pub release_dates: Vec<ReleaseDatesByCountry>,
253    #[cfg_attr(feature = "serde", serde(default))]
254    pub genres: Vec<GenreInfo>,
255    #[cfg_attr(feature = "serde", serde(default))]
256    pub spoken_languages: Vec<SpokenLanguage>,
257    #[cfg_attr(feature = "serde", serde(default))]
258    pub production_companies: Vec<ProductionCompany>,
259    #[cfg_attr(feature = "serde", serde(default))]
260    pub production_countries: Vec<ProductionCountry>,
261    pub homepage: Option<String>,
262    pub status: Option<String>,
263    pub tagline: Option<String>,
264    pub budget: Option<u64>,
265    pub revenue: Option<u64>,
266
267    // Media assets
268    pub poster_path: Option<String>,
269    pub backdrop_path: Option<String>,
270    pub logo_path: Option<String>,
271    /// Primary poster image variant id (`tmdb_image_variants.id`).
272    pub primary_poster_iid: Option<uuid::Uuid>,
273    /// Primary backdrop image variant id (`tmdb_image_variants.id`).
274    #[cfg_attr(feature = "serde", serde(default))]
275    pub primary_backdrop_iid: Option<uuid::Uuid>,
276    pub images: MediaImages,
277
278    // Credits
279    pub cast: Vec<CastMember>,
280    pub crew: Vec<CrewMember>,
281
282    // Additional
283    #[cfg_attr(feature = "serde", serde(default))]
284    pub videos: Vec<Video>,
285    #[cfg_attr(feature = "serde", serde(default))]
286    pub keywords: Vec<Keyword>,
287    pub external_ids: ExternalIds,
288    #[cfg_attr(feature = "serde", serde(default))]
289    pub alternative_titles: Vec<AlternativeTitle>,
290    #[cfg_attr(feature = "serde", serde(default))]
291    pub translations: Vec<Translation>,
292    pub collection: Option<CollectionInfo>,
293    #[cfg_attr(feature = "serde", serde(default))]
294    pub recommendations: Vec<RelatedMediaRef>,
295    #[cfg_attr(feature = "serde", serde(default))]
296    pub similar: Vec<RelatedMediaRef>,
297}
298
299#[derive(Clone, PartialEq)]
300#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
301#[cfg_attr(
302    feature = "rkyv",
303    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
304)]
305#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
306pub struct EnhancedSeriesDetails {
307    // Basic details
308    pub id: u64,
309    pub name: String,
310    pub original_name: Option<String>,
311    pub overview: Option<String>,
312    pub first_air_date: Option<String>,
313    pub last_air_date: Option<String>,
314    pub number_of_seasons: Option<u16>,
315    pub number_of_episodes: Option<u16>,
316    pub available_seasons: Option<u16>,
317    pub available_episodes: Option<u16>,
318    pub vote_average: Option<f32>,
319    pub vote_count: Option<u32>,
320    pub popularity: Option<f32>,
321    pub content_rating: Option<String>,
322    #[cfg_attr(feature = "serde", serde(default))]
323    pub content_ratings: Vec<ContentRating>,
324    #[cfg_attr(feature = "serde", serde(default))]
325    pub release_dates: Vec<ReleaseDatesByCountry>,
326    #[cfg_attr(feature = "serde", serde(default))]
327    pub genres: Vec<GenreInfo>,
328    #[cfg_attr(feature = "serde", serde(default))]
329    pub networks: Vec<NetworkInfo>,
330    #[cfg_attr(feature = "serde", serde(default))]
331    pub origin_countries: Vec<String>,
332    #[cfg_attr(feature = "serde", serde(default))]
333    pub spoken_languages: Vec<SpokenLanguage>,
334    #[cfg_attr(feature = "serde", serde(default))]
335    pub production_companies: Vec<ProductionCompany>,
336    #[cfg_attr(feature = "serde", serde(default))]
337    pub production_countries: Vec<ProductionCountry>,
338    pub homepage: Option<String>,
339    pub status: Option<String>,
340    pub tagline: Option<String>,
341    pub in_production: Option<bool>,
342
343    // Media assets
344    pub poster_path: Option<String>,
345    pub backdrop_path: Option<String>,
346    pub logo_path: Option<String>,
347    /// Primary poster image variant id (`tmdb_image_variants.id`).
348    #[cfg_attr(feature = "serde", serde(default))]
349    pub primary_poster_iid: Option<uuid::Uuid>,
350    /// Primary backdrop image variant id (`tmdb_image_variants.id`).
351    #[cfg_attr(feature = "serde", serde(default))]
352    pub primary_backdrop_iid: Option<uuid::Uuid>,
353    pub images: MediaImages,
354
355    // Credits
356    pub cast: Vec<CastMember>,
357    pub crew: Vec<CrewMember>,
358
359    // Additional
360    #[cfg_attr(feature = "serde", serde(default))]
361    pub videos: Vec<Video>,
362    #[cfg_attr(feature = "serde", serde(default))]
363    pub keywords: Vec<Keyword>,
364    pub external_ids: ExternalIds,
365    #[cfg_attr(feature = "serde", serde(default))]
366    pub alternative_titles: Vec<AlternativeTitle>,
367    #[cfg_attr(feature = "serde", serde(default))]
368    pub translations: Vec<Translation>,
369    #[cfg_attr(feature = "serde", serde(default))]
370    pub episode_groups: Vec<EpisodeGroupMembership>,
371    #[cfg_attr(feature = "serde", serde(default))]
372    pub recommendations: Vec<RelatedMediaRef>,
373    #[cfg_attr(feature = "serde", serde(default))]
374    pub similar: Vec<RelatedMediaRef>,
375}
376
377#[derive(Clone, PartialEq)]
378#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
379#[cfg_attr(
380    feature = "rkyv",
381    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
382)]
383#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
384pub struct SeasonDetails {
385    pub id: u64,
386    pub season_number: u16,
387    pub name: String,
388    pub overview: Option<String>,
389    pub air_date: Option<String>,
390    pub episode_count: u16,
391    pub poster_path: Option<String>,
392    /// Primary season poster image variant id (`tmdb_image_variants.id`).
393    #[cfg_attr(feature = "serde", serde(default))]
394    pub primary_poster_iid: Option<uuid::Uuid>,
395    pub runtime: Option<u32>,
396    #[cfg_attr(feature = "serde", serde(default))]
397    pub external_ids: ExternalIds,
398    #[cfg_attr(feature = "serde", serde(default))]
399    pub images: MediaImages,
400    #[cfg_attr(feature = "serde", serde(default))]
401    pub videos: Vec<Video>,
402    #[cfg_attr(feature = "serde", serde(default))]
403    pub keywords: Vec<Keyword>,
404    #[cfg_attr(feature = "serde", serde(default))]
405    pub translations: Vec<Translation>,
406}
407
408#[derive(Clone, PartialEq)]
409#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
410#[cfg_attr(
411    feature = "rkyv",
412    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
413)]
414#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
415pub struct EpisodeDetails {
416    pub id: u64,
417    pub episode_number: u16,
418    pub season_number: u16,
419    pub name: String,
420    pub overview: Option<String>,
421    pub air_date: Option<String>,
422    pub runtime: Option<u32>,
423    pub still_path: Option<String>,
424    /// Primary episode still image variant id (`tmdb_image_variants.id`).
425    #[cfg_attr(feature = "serde", serde(default))]
426    pub primary_still_iid: Option<uuid::Uuid>,
427    pub vote_average: Option<f32>,
428    pub vote_count: Option<u32>,
429    #[cfg_attr(feature = "serde", serde(default))]
430    pub production_code: Option<String>,
431    #[cfg_attr(feature = "serde", serde(default))]
432    pub external_ids: ExternalIds,
433    #[cfg_attr(feature = "serde", serde(default))]
434    pub images: MediaImages,
435    #[cfg_attr(feature = "serde", serde(default))]
436    pub videos: Vec<Video>,
437    #[cfg_attr(feature = "serde", serde(default))]
438    pub keywords: Vec<Keyword>,
439    #[cfg_attr(feature = "serde", serde(default))]
440    pub translations: Vec<Translation>,
441    #[cfg_attr(feature = "serde", serde(default))]
442    pub guest_stars: Vec<CastMember>,
443    #[cfg_attr(feature = "serde", serde(default))]
444    pub crew: Vec<CrewMember>,
445    #[cfg_attr(feature = "serde", serde(default))]
446    pub content_ratings: Vec<ContentRating>,
447}
448
449impl fmt::Debug for EnhancedMovieDetails {
450    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
451        f.debug_struct("EnhancedMovieDetails")
452            .field("id", &self.id)
453            .field("title", &self.title)
454            .field("release_date", &self.release_date)
455            .field("runtime", &self.runtime)
456            .field("vote_average", &self.vote_average)
457            .field("vote_count", &self.vote_count)
458            .field("popularity", &self.popularity)
459            .field("content_rating", &self.content_rating)
460            .field("collection", &self.collection.as_ref().map(|c| &c.name))
461            .field("genre_count", &self.genres.len())
462            .field("spoken_language_count", &self.spoken_languages.len())
463            .field("production_company_count", &self.production_companies.len())
464            .field("production_country_count", &self.production_countries.len())
465            .field("cast_count", &self.cast.len())
466            .field("crew_count", &self.crew.len())
467            .field("video_count", &self.videos.len())
468            .field("keyword_count", &self.keywords.len())
469            .field("alternative_title_count", &self.alternative_titles.len())
470            .field("translation_count", &self.translations.len())
471            .field("recommendation_count", &self.recommendations.len())
472            .field("similar_count", &self.similar.len())
473            .field("images", &self.images)
474            .finish()
475    }
476}
477
478impl fmt::Debug for EnhancedSeriesDetails {
479    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
480        f.debug_struct("EnhancedSeriesDetails")
481            .field("id", &self.id)
482            .field("name", &self.name)
483            .field("first_air_date", &self.first_air_date)
484            .field("last_air_date", &self.last_air_date)
485            .field("season_count", &self.number_of_seasons)
486            .field("episode_count", &self.number_of_episodes)
487            .field("vote_average", &self.vote_average)
488            .field("vote_count", &self.vote_count)
489            .field("popularity", &self.popularity)
490            .field("content_rating", &self.content_rating)
491            .field("genre_count", &self.genres.len())
492            .field("network_count", &self.networks.len())
493            .field("origin_country_count", &self.origin_countries.len())
494            .field("spoken_language_count", &self.spoken_languages.len())
495            .field("production_company_count", &self.production_companies.len())
496            .field("production_country_count", &self.production_countries.len())
497            .field("cast_count", &self.cast.len())
498            .field("crew_count", &self.crew.len())
499            .field("video_count", &self.videos.len())
500            .field("keyword_count", &self.keywords.len())
501            .field("alternative_title_count", &self.alternative_titles.len())
502            .field("translation_count", &self.translations.len())
503            .field("episode_group_count", &self.episode_groups.len())
504            .field("recommendation_count", &self.recommendations.len())
505            .field("similar_count", &self.similar.len())
506            .field("images", &self.images)
507            .finish()
508    }
509}
510
511impl fmt::Debug for SeasonDetails {
512    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
513        let has_external_ids = self.external_ids != ExternalIds::default();
514        f.debug_struct("SeasonDetails")
515            .field("id", &self.id)
516            .field("season_number", &self.season_number)
517            .field("episode_count", &self.episode_count)
518            .field("runtime", &self.runtime)
519            .field("air_date", &self.air_date)
520            .field("poster_path", &self.poster_path)
521            .field("has_external_ids", &has_external_ids)
522            .field("images", &self.images)
523            .field("video_count", &self.videos.len())
524            .field("keyword_count", &self.keywords.len())
525            .field("translation_count", &self.translations.len())
526            .finish()
527    }
528}
529
530impl fmt::Debug for EpisodeDetails {
531    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532        let has_external_ids = self.external_ids != ExternalIds::default();
533        f.debug_struct("EpisodeDetails")
534            .field("id", &self.id)
535            .field("season_number", &self.season_number)
536            .field("episode_number", &self.episode_number)
537            .field("air_date", &self.air_date)
538            .field("runtime", &self.runtime)
539            .field("vote_average", &self.vote_average)
540            .field("vote_count", &self.vote_count)
541            .field("still_path", &self.still_path)
542            .field("has_external_ids", &has_external_ids)
543            .field("guest_star_count", &self.guest_stars.len())
544            .field("crew_count", &self.crew.len())
545            .field("keyword_count", &self.keywords.len())
546            .field("translation_count", &self.translations.len())
547            .field("content_rating_count", &self.content_ratings.len())
548            .field("images", &self.images)
549            .finish()
550    }
551}
552
553#[derive(Debug, Clone, PartialEq)]
554#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
555#[cfg_attr(
556    feature = "rkyv",
557    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
558)]
559#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
560pub struct CastMember {
561    pub id: u64,
562    pub person_id: Option<Uuid>,
563    pub credit_id: Option<String>,
564    pub cast_id: Option<u64>,
565    pub name: String,
566    pub original_name: Option<String>,
567    pub character: String,
568    pub profile_path: Option<String>,
569    pub order: u32,
570    pub gender: Option<u8>,
571    pub known_for_department: Option<String>,
572    pub adult: Option<bool>,
573    pub popularity: Option<f32>,
574    #[cfg_attr(feature = "serde", serde(default))]
575    pub also_known_as: Vec<String>,
576    #[cfg_attr(feature = "serde", serde(default))]
577    pub external_ids: PersonExternalIds,
578    #[cfg_attr(feature = "serde", serde(default))]
579    pub image_slot: u32,
580    /// Primary person profile image variant id (`tmdb_image_variants.id`).
581    ///
582    /// Optional because cast may not have an associated portrait.
583    #[cfg_attr(feature = "serde", serde(default))]
584    pub image_id: Option<Uuid>,
585}
586
587#[derive(Debug, Clone, PartialEq)]
588#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
589#[cfg_attr(
590    feature = "rkyv",
591    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
592)]
593#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq)))]
594pub struct CrewMember {
595    pub id: u64,
596    pub person_id: Option<Uuid>,
597    pub credit_id: Option<String>,
598    pub name: String,
599    pub job: String,
600    pub department: String,
601    pub profile_path: Option<String>,
602    pub gender: Option<u8>,
603    pub known_for_department: Option<String>,
604    pub adult: Option<bool>,
605    pub popularity: Option<f32>,
606    pub original_name: Option<String>,
607    #[cfg_attr(feature = "serde", serde(default))]
608    pub also_known_as: Vec<String>,
609    #[cfg_attr(feature = "serde", serde(default))]
610    pub external_ids: PersonExternalIds,
611    /// Primary person profile image variant id (`tmdb_image_variants.id`).
612    ///
613    /// Optional because crew may not have an associated portrait.
614    #[cfg_attr(feature = "serde", serde(default))]
615    pub profile_iid: Option<Uuid>,
616}
617
618#[derive(Debug, Clone, PartialEq)]
619#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
620#[cfg_attr(
621    feature = "rkyv",
622    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
623)]
624#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq, Hash)))]
625pub struct Video {
626    pub key: String,
627    pub name: Option<String>,
628    pub site: String,
629    pub video_type: Option<String>,
630    pub official: Option<bool>,
631    pub iso_639_1: Option<String>,
632    pub iso_3166_1: Option<String>,
633    pub published_at: Option<String>,
634    pub size: Option<u32>,
635}
636
637#[derive(Debug, Clone, Default, PartialEq)]
638#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
639#[cfg_attr(
640    feature = "rkyv",
641    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
642)]
643#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq, Hash)))]
644pub struct ExternalIds {
645    pub imdb_id: Option<String>,
646    pub tvdb_id: Option<u32>,
647    pub facebook_id: Option<String>,
648    pub instagram_id: Option<String>,
649    pub twitter_id: Option<String>,
650    pub wikidata_id: Option<String>,
651    pub tiktok_id: Option<String>,
652    pub youtube_id: Option<String>,
653    pub freebase_id: Option<String>,
654    pub freebase_mid: Option<String>,
655}
656
657// Library reference type - no media references
658#[derive(Debug, Clone)]
659#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
660#[cfg_attr(
661    feature = "rkyv",
662    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
663)]
664#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq, Hash)))]
665pub struct LibraryReference {
666    pub id: LibraryId,
667    pub name: String,
668    pub library_type: LibraryType,
669    #[cfg_attr(feature = "rkyv", rkyv(with = crate::rkyv_wrappers::VecPathBuf))]
670    pub paths: Vec<PathBuf>,
671}