tmdb_async/
model.rs

1use compact_str::CompactString;
2use gset::Getset;
3use isocountry::CountryCode;
4use isolanguage_1::LanguageCode;
5use serde::{Deserialize, Deserializer};
6use serde_with::serde_as;
7use time::Date;
8
9time::serde::format_description!(date, Date, "[year]-[month]-[day]");
10
11#[inline]
12fn country_code<'de, D: Deserializer<'de>>(de: D) -> Result<Option<CountryCode>, D::Error> {
13	use serde::de::{Error, Unexpected};
14	match Option::<&str>::deserialize(de)? {
15		None => Ok(None),
16		Some("") => Ok(None),
17		Some(s) if s.len() == 2 => match CountryCode::for_alpha2_caseless(s) {
18			Ok(v) => Ok(Some(v)),
19			Err(_) => Err(D::Error::invalid_value(Unexpected::Str(s), &"any 2-letter ISO 3166-1 country code"))
20		},
21		Some(s) => Err(D::Error::invalid_value(Unexpected::Str(s), &"any 2-letter ISO 3166-1 country code"))
22	}
23}
24
25mod imdb_id {
26	use serde::{Deserialize, Deserializer};
27	use serde::de::{Error, Unexpected};
28
29	#[inline]
30	fn from_str<'de, D: Deserializer<'de>>(s: &str) -> Result<u32, D::Error> {
31		if(s.len() < 3 || &s[..2] != "tt") {
32			return Err(D::Error::invalid_value(Unexpected::Str(s), &"a signed integer prefixed by \"tt\""));
33		}
34		match s[2..].parse() {
35			Ok(v) => Ok(v),
36			Err(_) => Err(D::Error::invalid_value(Unexpected::Str(s), &"a signed integer prefixed by \"tt\""))
37		}
38	}
39
40	#[inline]
41	pub(crate) fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<u32, D::Error> {
42		let s = <&str>::deserialize(de)?;
43		from_str::<D>(s)
44	}
45
46	pub(super) mod option {
47		use super::*;
48		#[inline]
49		pub(crate) fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<Option<u32>, D::Error> {
50			match Option::<&str>::deserialize(de)? {
51				Some(s) => Ok(Some(from_str::<D>(s)?)),
52				None => Ok(None)
53			}
54		}
55	}
56}
57
58#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
59pub struct Genre {
60	#[getset(get_copy, vis = "pub")]
61	id: u16,
62	#[getset(get_deref, vis = "pub")]
63	name: CompactString,
64}
65
66#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
67pub struct Results<T> {
68	#[getset(get_deref, vis = "pub")]
69	results: Vec<T>,
70}
71
72#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
73pub struct Video {
74	#[getset(get_deref, vis = "pub")]
75	id: CompactString,
76	#[getset(get_copy, vis = "pub")]
77	iso_639_1: LanguageCode,
78	#[getset(get_deref, vis = "pub")]
79	key: CompactString,
80	#[getset(get_deref, vis = "pub")]
81	name: CompactString,
82	#[getset(get_deref, vis = "pub")]
83	site: CompactString,
84	#[getset(get_copy, vis = "pub")]
85	size: u16,
86	#[getset(get_deref, vis = "pub")]
87	#[serde(rename = "type")]
88	video_type: CompactString,
89}
90
91#[serde_as]
92#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
93pub struct Cast {
94	#[getset(get_copy, vis = "pub")]
95	id: u32,
96	#[getset(get_copy, vis = "pub")]
97	cast_id: u32,
98	#[serde_as(as = "serde_with::hex::Hex")]
99	#[getset(get_copy, vis = "pub")]
100	credit_id: [u8; 12],
101	#[getset(get_deref, vis = "pub")]
102	character: CompactString,
103	#[getset(get_copy, vis = "pub")]
104	gender: Option<u8>,
105	#[getset(get_deref, vis = "pub")]
106	name: CompactString,
107	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
108	profile_path: Option<String>,
109	#[getset(get_copy, vis = "pub")]
110	order: u8,
111}
112
113#[serde_as]
114#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
115pub struct TVCast {
116	#[getset(get_copy, vis = "pub")]
117	id: u32,
118	#[serde_as(as = "serde_with::hex::Hex")]
119	#[getset(get_copy, vis = "pub")]
120	credit_id: [u8; 12],
121	#[getset(get_deref, vis = "pub")]
122	character: CompactString,
123	#[getset(get_copy, vis = "pub")]
124	gender: Option<u8>,
125	#[getset(get_deref, vis = "pub")]
126	name: CompactString,
127	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
128	profile_path: Option<String>,
129	#[getset(get_copy, vis = "pub")]
130	order: u32,
131}
132
133#[serde_as]
134#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
135pub struct TVCreator {
136	#[getset(get_copy, vis = "pub")]
137	id: u32,
138	#[serde_as(as = "serde_with::hex::Hex")]
139	#[getset(get_copy, vis = "pub")]
140	credit_id: [u8; 12],
141	#[getset(get_deref, vis = "pub")]
142	name: CompactString,
143	#[getset(get_copy, vis = "pub")]
144	gender: Option<u8>,
145	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
146	profile_path: Option<String>,
147}
148
149#[serde_as]
150#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
151pub struct Crew {
152	#[serde_as(as = "serde_with::hex::Hex")]
153	#[getset(get_copy, vis = "pub")]
154	credit_id: [u8; 12],
155	#[getset(get_deref, vis = "pub")]
156	department: CompactString,
157	#[getset(get_copy, vis = "pub")]
158	gender: Option<u8>,
159	#[getset(get_copy, vis = "pub")]
160	id: u32,
161	#[getset(get_deref, vis = "pub")]
162	job: CompactString,
163	#[getset(get_deref, vis = "pub")]
164	name: CompactString,
165	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
166	profile_path: Option<String>,
167}
168
169#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
170pub struct Credits {
171	#[getset(get_deref, vis = "pub")]
172	cast: Vec<Cast>,
173	#[getset(get_deref, vis = "pub")]
174	crew: Vec<Crew>,
175}
176
177#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
178pub struct TVCredits {
179	#[getset(get_deref, vis = "pub")]
180	cast: Vec<TVCast>,
181	#[getset(get_deref, vis = "pub")]
182	crew: Vec<Crew>,
183}
184
185#[derive(Debug, PartialEq, Deserialize, Getset)]
186pub struct LastEpisode {
187	#[serde(with = "date")]
188	#[getset(get_copy, vis = "pub")]
189	air_date: Date,
190	#[getset(get_copy, vis = "pub")]
191	episode_number: u32,
192	#[getset(get_copy, vis = "pub")]
193	id: u32,
194	#[getset(get_deref, vis = "pub")]
195	name: CompactString,
196	#[getset(get_deref, vis = "pub")]
197	overview: String,
198	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
199	production_code: Option<String>,
200	#[getset(get_copy, vis = "pub")]
201	season_number: u32,
202	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
203	still_path: Option<String>,
204	#[getset(get_copy, vis = "pub")]
205	vote_average: f64,
206	#[getset(get_copy, vis = "pub")]
207	vote_count: u64,
208}
209
210#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
211pub struct ProductionCompany {
212	#[getset(get_copy, vis = "pub")]
213	id: u32,
214	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
215	logo_path: Option<String>,
216	#[getset(get_deref, vis = "pub")]
217	name: CompactString,
218	#[serde(deserialize_with = "country_code")]
219	#[getset(get_copy, vis = "pub")]
220	origin_country: Option<CountryCode>,
221}
222
223#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
224pub struct Network {
225	#[getset(get_copy, vis = "pub")]
226	id: u32,
227	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
228	logo_path: Option<String>,
229	#[getset(get_deref, vis = "pub")]
230	name: CompactString,
231	#[serde(deserialize_with = "country_code")]
232	#[getset(get_copy, vis = "pub")]
233	origin_country: Option<CountryCode>,
234}
235
236#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
237pub struct Season {
238	#[serde(with = "date::option")]
239	#[getset(get_copy, vis = "pub")]
240	air_date: Option<Date>,
241	#[getset(get_copy, vis = "pub")]
242	episode_count: u32,
243	#[getset(get_copy, vis = "pub")]
244	id: u32,
245	#[getset(get_deref, vis = "pub")]
246	name: CompactString,
247	#[getset(get_deref, vis = "pub")]
248	overview: String,
249	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
250	poster_path: Option<String>,
251	#[getset(get_copy, vis = "pub")]
252	season_number: u32,
253}
254
255#[derive(Debug, PartialEq, Deserialize, Getset)]
256pub struct Movie {
257	#[getset(get_copy, vis = "pub")]
258	id: u32,
259	#[serde(with = "imdb_id")]
260	#[getset(get_copy, vis = "pub")]
261	imdb_id: u32,
262	#[getset(get_deref, vis = "pub")]
263	title: CompactString,
264	#[getset(get_deref, vis = "pub")]
265	tagline: String,
266	#[getset(get_deref, vis = "pub")]
267	original_title: CompactString,
268	#[getset(get_copy, vis = "pub")]
269	original_language: LanguageCode,
270	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
271	overview: Option<String>,
272	#[serde(with = "date")]
273	#[getset(get_copy, vis = "pub")]
274	release_date: Date,
275	#[getset(get_copy, vis = "pub")]
276	runtime: u32,
277	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
278	homepage: Option<String>,
279	#[getset(get_deref, vis = "pub")]
280	genres: Vec<Genre>,
281	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
282	poster_path: Option<String>,
283	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
284	backdrop_path: Option<String>,
285	#[getset(get_copy, vis = "pub")]
286	popularity: f64,
287	#[getset(get_copy, vis = "pub")]
288	budget: u64,
289	#[getset(get_copy, vis = "pub")]
290	adult: bool,
291	#[getset(get_as_ref, vis = "pub", ty = "Option<&Results<Video>>")]
292	videos: Option<Results<Video>>,
293	#[getset(get_as_ref, vis = "pub", ty = "Option<&Credits>")]
294	credits: Option<Credits>,
295}
296
297#[derive(Debug, PartialEq, Deserialize, Getset)]
298pub struct TV {
299	#[getset(get_copy, vis = "pub")]
300	id: u32,
301	backdrop_path: Option<String>,
302	#[getset(get_deref, vis = "pub")]
303	created_by: Vec<TVCreator>,
304	#[getset(get_deref, vis = "pub")]
305	episode_run_time: Vec<u16>,
306	#[serde(with = "date")]
307	#[getset(get_copy, vis = "pub")]
308	first_air_date: Date,
309	#[getset(get_deref, vis = "pub")]
310	genres: Vec<Genre>,
311	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
312	homepage: Option<String>,
313	#[getset(get_copy, vis = "pub")]
314	in_production: bool,
315	#[getset(get_deref, vis = "pub")]
316	languages: Vec<LanguageCode>,
317	#[serde(with = "date")]
318	#[getset(get_copy, vis = "pub")]
319	last_air_date: Date,
320	#[getset(get_as_ref, vis = "pub", ty = "Option<&LastEpisode>")]
321	last_episode_to_air: Option<LastEpisode>,
322	#[getset(get_deref, vis = "pub")]
323	name: CompactString,
324	#[getset(get_deref, vis = "pub")]
325	networks: Vec<Network>,
326	#[getset(get_copy, vis = "pub")]
327	number_of_episodes: u32,
328	#[getset(get_copy, vis = "pub")]
329	number_of_seasons: u32,
330	#[getset(get_deref, vis = "pub")]
331	origin_country: Vec<CountryCode>,
332	#[getset(get_copy, vis = "pub")]
333	original_language: LanguageCode,
334	#[getset(get_deref, vis = "pub")]
335	original_name: CompactString,
336	#[getset(get_deref, vis = "pub")]
337	overview: String,
338	#[getset(get_copy, vis = "pub")]
339	popularity: f64,
340	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
341	poster_path: Option<CompactString>,
342	#[getset(get_deref, vis = "pub")]
343	production_companies: Vec<ProductionCompany>,
344	#[getset(get_deref, vis = "pub")]
345	seasons: Vec<Season>,
346	#[getset(get_deref, vis = "pub")]
347	status: CompactString,
348	#[getset(get_deref, vis = "pub")]
349	r#type: CompactString,
350	#[getset(get_copy, vis = "pub")]
351	vote_average: f64,
352	#[getset(get_copy, vis = "pub")]
353	vote_count: u64,
354	#[getset(get_as_ref, vis = "pub", ty = "Option<&Results<Video>>")]
355	videos: Option<Results<Video>>,
356	#[getset(get_as_ref, vis = "pub", ty = "Option<&TVCredits>")]
357	credits: Option<TVCredits>,
358}
359
360#[derive(Debug, PartialEq, Deserialize, Getset)]
361pub struct SearchMovie {
362	#[getset(get_copy, vis = "pub")]
363	id: u32,
364	#[getset(get_deref, vis = "pub")]
365	title: CompactString,
366	#[getset(get_deref, vis = "pub")]
367	original_title: CompactString,
368	#[getset(get_copy, vis = "pub")]
369	original_language: LanguageCode,
370	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
371	overview: Option<String>,
372	#[serde(with = "date")]
373	#[getset(get_copy, vis = "pub")]
374	release_date: Date,
375	#[getset(get_deref, vis = "pub")]
376	genre_ids: Vec<u16>,
377	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
378	poster_path: Option<String>,
379	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
380	backdrop_path: Option<String>,
381	#[getset(get_copy, vis = "pub")]
382	popularity: f64,
383	#[getset(get_copy, vis = "pub")]
384	adult: bool,
385}
386
387#[derive(Debug, PartialEq, Deserialize, Getset)]
388pub struct SearchTV {
389	#[getset(get_copy, vis = "pub")]
390	id: u32,
391	#[getset(get_deref, vis = "pub")]
392	name: CompactString,
393	#[getset(get_deref, vis = "pub")]
394	original_name: CompactString,
395	#[getset(get_copy, vis = "pub")]
396	original_language: LanguageCode,
397	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
398	overview: Option<String>,
399	#[serde(with = "date")]
400	#[getset(get_copy, vis = "pub")]
401	first_air_date: Date,
402	#[getset(get_deref, vis = "pub")]
403	genre_ids: Vec<u16>,
404	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
405	poster_path: Option<String>,
406	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
407	backdrop_path: Option<String>,
408	#[getset(get_copy, vis = "pub")]
409	popularity: f64,
410	#[getset(get_copy, vis = "pub")]
411	vote_average: f32,
412	#[getset(get_copy, vis = "pub")]
413	vote_count: u32,
414}
415
416#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
417pub struct FindMovie {
418	#[getset(get_copy, vis = "pub")]
419	id: u32,
420	#[getset(get_deref, vis = "pub")]
421	title: CompactString,
422	#[getset(get_deref, vis = "pub")]
423	original_title: CompactString,
424	#[getset(get_copy, vis = "pub")]
425	original_language: LanguageCode,
426	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
427	overview: Option<String>,
428	#[serde(with = "date")]
429	#[getset(get_copy, vis = "pub")]
430	release_date: Date,
431	#[getset(get_deref, vis = "pub")]
432	genre_ids: Vec<u16>,
433	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
434	poster_path: Option<String>,
435	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
436	backdrop_path: Option<String>,
437	#[getset(get_copy, vis = "pub")]
438	adult: bool,
439}
440
441#[derive(Debug, PartialEq, Deserialize, Getset)]
442pub struct FindTV {
443	#[getset(get_copy, vis = "pub")]
444	id: u32,
445	#[getset(get_deref, vis = "pub")]
446	name: CompactString,
447	#[getset(get_deref, vis = "pub")]
448	original_name: CompactString,
449	#[getset(get_copy, vis = "pub")]
450	original_language: LanguageCode,
451	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
452	overview: Option<String>,
453	#[serde(with = "date")]
454	#[getset(get_copy, vis = "pub")]
455	first_air_date: Date,
456	#[getset(get_deref, vis = "pub")]
457	genre_ids: Vec<u16>,
458	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
459	poster_path: Option<String>,
460	#[getset(get_as_deref, vis = "pub", ty = "Option<&str>")]
461	backdrop_path: Option<String>,
462	#[getset(get_copy, vis = "pub")]
463	popularity: f64,
464	#[getset(get_copy, vis = "pub")]
465	vote_average: f32,
466	#[getset(get_copy, vis = "pub")]
467	vote_count: u32,
468}
469
470#[derive(Debug, PartialEq, Deserialize, Getset)]
471pub struct MovieSearchResult {
472	#[getset(get_copy, vis = "pub")]
473	page: u8,
474	#[getset(get_copy, vis = "pub")]
475	total_results: u8,
476	#[getset(get_copy, vis = "pub")]
477	total_pages: u8,
478	#[getset(get_deref, vis = "pub")]
479	results: Vec<SearchMovie>,
480}
481
482#[derive(Debug, PartialEq, Deserialize, Getset)]
483pub struct TVSearchResult {
484	#[getset(get_copy, vis = "pub")]
485	page: u8,
486	#[getset(get_copy, vis = "pub")]
487	total_results: u8,
488	#[getset(get_copy, vis = "pub")]
489	total_pages: u8,
490	#[getset(get_deref, vis = "pub")]
491	results: Vec<SearchTV>,
492}
493
494#[derive(Debug, PartialEq, Deserialize, Getset)]
495pub struct FindResult {
496	#[getset(get_deref, vis = "pub")]
497	movie_results: Vec<FindMovie>,
498	#[getset(get_deref, vis = "pub")]
499	tv_results: Vec<FindTV>
500}
501
502#[derive(Debug, Eq, PartialEq, Deserialize, Getset)]
503pub struct TVExternalIds {
504	#[getset(get_copy, vis = "pub")]
505	id: u32,
506	#[serde(with = "imdb_id::option")]
507	#[getset(get_copy, vis = "pub")]
508	imdb_id: Option<u32>,
509	freebase_mid: Option<CompactString>,
510	freebase_id: Option<CompactString>,
511	#[getset(get_copy, vis = "pub")]
512	tvdb_id: Option<u32>,
513	#[getset(get_copy, vis = "pub")]
514	tvrage_id: Option<u32>,
515	facebook_id: Option<CompactString>,
516	instagram_id: Option<CompactString>,
517	twitter_id: Option<CompactString>
518}
519
520impl TVExternalIds {
521	#[inline]
522	pub fn freebase_mid(&self) -> Option<&str> {
523		self.freebase_mid.as_deref()
524	}
525
526	#[inline]
527	pub fn freebase_id(&self) -> Option<&str> {
528		self.freebase_id.as_deref()
529	}
530
531	#[inline]
532	pub fn facebook_id(&self) -> Option<&str> {
533		self.facebook_id.as_deref()
534	}
535
536	#[inline]
537	pub fn instagram_id(&self) -> Option<&str> {
538		self.instagram_id.as_deref()
539	}
540
541	#[inline]
542	pub fn twitter_id(&self) -> Option<&str> {
543		self.twitter_id.as_deref()
544	}
545}
546