Skip to main content

tmdb_rs/endpoints/
tv.rs

1use serde::Deserialize;
2use time::Date;
3
4use crate::common::{
5    AccountStates, AlternativeTitles, Changes, ExternalIds, Images, Rated, StatusResponse,
6    Translations, Videos, WatchProviders,
7};
8use crate::endpoints::credit::Credits;
9use crate::endpoints::genre::Genre;
10use crate::endpoints::keyword::{Keyword, TvKeywords};
11use crate::endpoints::list::ListShort;
12use crate::endpoints::review::Review;
13use crate::{
14    Backdrop, CountryCode, GuestSessionId, Language, Logo, Page, Poster, Profile, SessionId, Still,
15};
16
17#[derive(Debug, Clone, Deserialize)]
18pub struct ContentRating {
19    #[serde(rename = "iso_3166_1")]
20    pub country: CountryCode,
21    pub rating: String,
22}
23
24#[derive(Debug, Clone, Deserialize)]
25pub struct ContentRatings {
26    pub results: Vec<ContentRating>,
27}
28
29/// one season inside a series' details
30#[derive(Debug, Clone, Deserialize)]
31pub struct SeasonShort {
32    pub season_number: u32,
33    pub name: String,
34    pub episode_count: u32,
35    pub overview: Option<String>,
36    #[serde(rename = "poster_path")]
37    pub poster: Option<Poster>,
38    #[serde(default, deserialize_with = "crate::common::opt_date")]
39    pub air_date: Option<Date>,
40}
41
42use crate::append::appendable;
43
44/// one series in a list or search response
45#[derive(Debug, Clone, Deserialize)]
46pub struct TvShort {
47    pub id: u64,
48    pub name: String,
49    pub original_name: String,
50    pub overview: String,
51    #[serde(
52        rename = "first_air_date",
53        default,
54        deserialize_with = "crate::common::opt_date"
55    )]
56    pub release_date: Option<Date>,
57    #[serde(rename = "poster_path")]
58    pub poster: Option<Poster>,
59    #[serde(rename = "backdrop_path")]
60    pub backdrop: Option<Backdrop>,
61    pub vote_average: f64,
62    pub vote_count: u32,
63    pub popularity: f64,
64    #[serde(default)]
65    pub genre_ids: Vec<u64>,
66    #[serde(default, deserialize_with = "crate::common::opt_language")]
67    pub original_language: Option<Language>,
68    #[serde(default)]
69    pub origin_country: Vec<String>,
70    pub adult: bool,
71}
72
73/// a series' next aired episode
74#[derive(Debug, Clone, Deserialize)]
75pub struct NextEpisode {
76    pub id: u64,
77    pub name: String,
78    pub episode_number: u32,
79    pub season_number: u32,
80    #[serde(default, deserialize_with = "crate::common::opt_date")]
81    pub air_date: Option<Date>,
82}
83
84/// one episode inside a season
85#[derive(Debug, Clone, Deserialize)]
86pub struct Episode {
87    pub id: u64,
88    pub name: String,
89    pub overview: String,
90    pub episode_number: u32,
91    pub season_number: u32,
92    pub runtime: Option<u32>,
93    #[serde(rename = "still_path")]
94    pub still: Option<Still>,
95    #[serde(default, deserialize_with = "crate::common::opt_date")]
96    pub air_date: Option<Date>,
97    pub vote_average: f64,
98    pub vote_count: u32,
99}
100
101/// one role in an aggregate credits entry
102#[derive(Debug, Clone, Deserialize)]
103pub struct Role {
104    pub credit_id: String,
105    pub character: String,
106    pub episode_count: u32,
107}
108
109#[derive(Debug, Clone, Deserialize)]
110pub struct AggregateCastMember {
111    pub id: u64,
112    pub name: String,
113    #[serde(rename = "profile_path")]
114    pub profile: Option<Profile>,
115    pub roles: Vec<Role>,
116    pub total_episode_count: u32,
117    pub order: Option<u32>,
118}
119
120/// one job in an aggregate credits entry
121#[derive(Debug, Clone, Deserialize)]
122pub struct Job {
123    pub credit_id: String,
124    pub job: String,
125    pub episode_count: u32,
126}
127
128#[derive(Debug, Clone, Deserialize)]
129pub struct AggregateCrewMember {
130    pub id: u64,
131    pub name: String,
132    #[serde(rename = "profile_path")]
133    pub profile: Option<Profile>,
134    pub jobs: Vec<Job>,
135    pub total_episode_count: u32,
136    pub department: String,
137}
138
139/// credits rolled up across all episodes of a series
140#[derive(Debug, Clone, Deserialize)]
141pub struct AggregateCredits {
142    pub cast: Vec<AggregateCastMember>,
143    pub crew: Vec<AggregateCrewMember>,
144}
145
146/// one network on an episode group
147#[derive(Debug, Clone, Deserialize)]
148pub struct NetworkShort {
149    pub id: u64,
150    pub name: String,
151    #[serde(rename = "logo_path")]
152    pub logo: Option<Logo>,
153    pub origin_country: Option<String>,
154}
155
156#[derive(Debug, Clone, Deserialize)]
157pub struct EpisodeGroupShort {
158    pub id: String,
159    pub name: String,
160    pub description: String,
161    pub episode_count: u32,
162    pub group_count: u32,
163    #[serde(rename = "type")]
164    pub kind: u32,
165    pub network: Option<NetworkShort>,
166}
167
168#[derive(Debug, Clone, Deserialize)]
169pub struct EpisodeGroups {
170    pub results: Vec<EpisodeGroupShort>,
171}
172
173/// one group inside an episode group
174#[derive(Debug, Clone, Deserialize)]
175pub struct EpisodeGroupEntry {
176    pub id: String,
177    pub name: String,
178    pub order: u32,
179    #[serde(default)]
180    pub episodes: Vec<Episode>,
181}
182
183#[derive(Debug, Clone, Deserialize)]
184pub struct EpisodeGroup {
185    pub id: String,
186    pub name: String,
187    pub description: String,
188    pub episode_count: u32,
189    pub group_count: u32,
190    #[serde(rename = "type")]
191    pub kind: u32,
192    pub network: Option<NetworkShort>,
193    pub groups: Vec<EpisodeGroupEntry>,
194}
195
196/// one episode screened in theatres
197#[derive(Debug, Clone, Deserialize)]
198pub struct ScreenedEntry {
199    pub id: u64,
200    pub episode_number: u32,
201    pub season_number: u32,
202}
203
204#[derive(Debug, Clone, Deserialize)]
205pub struct ScreenedTheatrically {
206    pub results: Vec<ScreenedEntry>,
207}
208
209appendable! {
210    AggregateCredits,
211    ContentRatings,
212    EpisodeGroups,
213    ScreenedTheatrically,
214}
215
216endpoint! {
217    /// the primary details of a series
218    tv(id: u64): GET "/tv/{id}" => TvDetails {
219        params { language: Language }
220        base {
221            pub id: u64,
222            pub name: String,
223            pub original_name: String,
224            pub overview: String,
225            pub tagline: String,
226            #[serde(
227                rename = "first_air_date",
228                default,
229                deserialize_with = "crate::common::opt_date"
230            )]
231            pub release_date: Option<Date>,
232            #[serde(default, deserialize_with = "crate::common::opt_date")]
233            pub last_air_date: Option<Date>,
234            pub vote_average: f64,
235            pub vote_count: u32,
236            pub popularity: f64,
237            pub number_of_seasons: u32,
238            pub number_of_episodes: u32,
239            pub episode_run_time: Vec<u32>,
240            #[serde(default, deserialize_with = "crate::common::opt_language")]
241            pub original_language: Option<Language>,
242            #[serde(rename = "poster_path")]
243            pub poster: Option<Poster>,
244            #[serde(rename = "backdrop_path")]
245            pub backdrop: Option<Backdrop>,
246            pub genres: Vec<Genre>,
247            #[serde(rename = "homepage")]
248            pub website: String,
249            pub status: String,
250            pub in_production: bool,
251            #[serde(default, deserialize_with = "crate::common::language_list")]
252            pub languages: Vec<Language>,
253            #[serde(default)]
254            pub origin_country: Vec<String>,
255            #[serde(default)]
256            pub seasons: Vec<SeasonShort>,
257            pub next_episode_to_air: Option<NextEpisode>,
258            pub adult: bool,
259        }
260        appends {
261            account_states: AccountStates,
262            aggregate_credits: AggregateCredits,
263            alternative_titles: AlternativeTitles,
264            changes: Changes,
265            content_ratings: ContentRatings,
266            credits: Credits,
267            episode_groups: EpisodeGroups,
268            external_ids: ExternalIds,
269            images: Images,
270            keywords: TvKeywords,
271            lists: Page<ListShort>,
272            recommendations: Page<TvShort>,
273            reviews: Page<Review>,
274            similar: Page<TvShort>,
275            translations: Translations,
276            videos: Videos,
277            watch_providers: WatchProviders as "watch/providers",
278        }
279    }
280}
281
282endpoint! {
283    /// one season of a series, episodes included
284    tv_season(id: u64, season: u32): GET "/tv/{id}/season/{season}" => SeasonDetails {
285        params { language: Language }
286        base {
287            pub id: u64,
288            pub season_number: u32,
289            pub name: String,
290            pub overview: String,
291            #[serde(default, deserialize_with = "crate::common::opt_date")]
292            pub air_date: Option<Date>,
293            #[serde(rename = "poster_path")]
294    pub poster: Option<Poster>,
295            #[serde(default)]
296            pub episodes: Vec<Episode>,
297        }
298        appends {
299            account_states: AccountStates,
300            aggregate_credits: AggregateCredits,
301            changes: Changes,
302            credits: Credits,
303            external_ids: ExternalIds,
304            images: Images,
305            translations: Translations,
306            videos: Videos,
307            watch_providers: WatchProviders as "watch/providers",
308        }
309    }
310}
311
312endpoint! {
313    /// one episode of a series
314    tv_episode(id: u64, season: u32, episode: u32): GET "/tv/{id}/season/{season}/episode/{episode}" => EpisodeDetails {
315        params { language: Language }
316        base {
317            pub id: u64,
318            pub name: String,
319            pub overview: String,
320            pub episode_number: u32,
321            pub season_number: u32,
322            pub runtime: Option<u32>,
323            #[serde(rename = "still_path")]
324    pub still: Option<Still>,
325            #[serde(default, deserialize_with = "crate::common::opt_date")]
326            pub air_date: Option<Date>,
327            pub vote_average: f64,
328            pub vote_count: u32,
329        }
330        appends {
331            account_states: AccountStates,
332            changes: Changes,
333            credits: Credits,
334            external_ids: ExternalIds,
335            images: Images,
336            translations: Translations,
337            videos: Videos,
338        }
339    }
340}
341
342endpoint! {
343    /// the newest series
344    tv_latest(): GET "/tv/latest" => TvDetails {
345        params { language: Language }
346    }
347}
348
349endpoint! {
350    /// series ordered by popularity
351    tv_popular(): GET "/tv/popular" => Page<TvShort> {
352        params { language: Language, page: u32 }
353    }
354}
355
356endpoint! {
357    /// series ordered by rating
358    tv_top_rated(): GET "/tv/top_rated" => Page<TvShort> {
359        params { language: Language, page: u32 }
360    }
361}
362
363endpoint! {
364    /// series with an episode airing in the next week
365    tv_on_the_air(): GET "/tv/on_the_air" => Page<TvShort> {
366        params { language: Language, page: u32 }
367    }
368}
369
370endpoint! {
371    /// series with an episode airing today
372    tv_airing_today(): GET "/tv/airing_today" => Page<TvShort> {
373        params { language: Language, page: u32 }
374    }
375}
376
377endpoint! {
378    /// a series' keywords, without the details round-trip
379    tv_keywords(id: u64): GET "/tv/{id}/keywords" => Vec<Keyword> [results]
380}
381
382endpoint! {
383    /// a series' ids on other databases
384    tv_external_ids(id: u64): GET "/tv/{id}/external_ids" => ExternalIds
385}
386
387endpoint! {
388    /// a series' account states (favorite, rated, watchlist)
389    tv_account_states(id: u64): GET "/tv/{id}/account_states" => AccountStates {
390        params { session_id: SessionId, guest_session_id: GuestSessionId }
391    }
392}
393
394endpoint! {
395    /// a series' aggregate credits
396    tv_aggregate_credits(id: u64): GET "/tv/{id}/aggregate_credits" => AggregateCredits {
397        params { language: Language }
398    }
399}
400
401endpoint! {
402    /// a series' alternative titles
403    tv_alternative_titles(id: u64): GET "/tv/{id}/alternative_titles" => AlternativeTitles
404}
405
406endpoint! {
407    /// a series' recent changes
408    tv_changes_by_id(id: u64): GET "/tv/{id}/changes" => Changes {
409        params { start_date: Date, end_date: Date, page: u32 }
410    }
411}
412
413endpoint! {
414    /// a series' content ratings by country
415    tv_content_ratings(id: u64): GET "/tv/{id}/content_ratings" => ContentRatings
416}
417
418endpoint! {
419    /// a series' credits
420    tv_credits(id: u64): GET "/tv/{id}/credits" => Credits {
421        params { language: Language }
422    }
423}
424
425endpoint! {
426    /// a series' episode groups
427    tv_episode_groups(id: u64): GET "/tv/{id}/episode_groups" => EpisodeGroups
428}
429
430endpoint! {
431    /// a series' images
432    tv_images(id: u64): GET "/tv/{id}/images" => Images {
433        params { language: Language, include_image_language: Vec<Language> }
434    }
435}
436
437endpoint! {
438    /// the lists a series appears in
439    tv_lists(id: u64): GET "/tv/{id}/lists" => Page<ListShort> {
440        params { language: Language, page: u32 }
441    }
442}
443
444endpoint! {
445    /// series similar to a series
446    tv_similar(id: u64): GET "/tv/{id}/similar" => Page<TvShort> {
447        params { language: Language, page: u32 }
448    }
449}
450
451endpoint! {
452    /// a series' recommendations
453    tv_recommendations(id: u64): GET "/tv/{id}/recommendations" => Page<TvShort> {
454        params { language: Language, page: u32 }
455    }
456}
457
458endpoint! {
459    /// a series' reviews
460    tv_reviews(id: u64): GET "/tv/{id}/reviews" => Page<Review> {
461        params { language: Language, page: u32 }
462    }
463}
464
465endpoint! {
466    /// the episodes of a series that were screened in theatres
467    tv_screened_theatrically(id: u64): GET "/tv/{id}/screened_theatrically" => ScreenedTheatrically
468}
469
470endpoint! {
471    /// a series' translations
472    tv_translations(id: u64): GET "/tv/{id}/translations" => Translations
473}
474
475endpoint! {
476    /// a series' videos (trailers, teasers, ...)
477    tv_videos(id: u64): GET "/tv/{id}/videos" => Videos {
478        params { language: Language, include_image_language: Vec<Language> }
479    }
480}
481
482endpoint! {
483    /// where a series can be streamed, rented or bought, by country
484    tv_watch_providers(id: u64): GET "/tv/{id}/watch/providers" => WatchProviders
485}
486
487endpoint! {
488    /// rate a series; pass a session or guest session
489    rate_tv(id: u64): POST "/tv/{id}/rating" => StatusResponse {
490        params { session_id: SessionId, guest_session_id: GuestSessionId }
491        body { value: f64 }
492    }
493}
494
495endpoint! {
496    /// delete a series rating
497    unrate_tv(id: u64): DELETE "/tv/{id}/rating" => StatusResponse {
498        params { session_id: SessionId, guest_session_id: GuestSessionId }
499    }
500}
501
502endpoint! {
503    /// a season's account states (per-episode ratings)
504    tv_season_account_states(id: u64, season: u32): GET "/tv/{id}/season/{season}/account_states" => Vec<EpisodeAccountState> [results] {
505        params { session_id: SessionId, guest_session_id: GuestSessionId }
506    }
507}
508
509#[derive(Debug, Clone, Deserialize)]
510pub struct EpisodeAccountState {
511    pub id: u64,
512    pub episode_number: u32,
513    pub rated: Rated,
514}
515
516endpoint! {
517    /// a season's aggregate credits
518    tv_season_aggregate_credits(id: u64, season: u32): GET "/tv/{id}/season/{season}/aggregate_credits" => AggregateCredits {
519        params { language: Language }
520    }
521}
522
523endpoint! {
524    /// a season's changes
525    tv_season_changes(id: u64): GET "/tv/season/{id}/changes" => Changes {
526        params { start_date: Date, end_date: Date, page: u32 }
527    }
528}
529
530endpoint! {
531    /// a season's credits
532    tv_season_credits(id: u64, season: u32): GET "/tv/{id}/season/{season}/credits" => Credits {
533        params { language: Language }
534    }
535}
536
537endpoint! {
538    /// a season's ids on other databases
539    tv_season_external_ids(id: u64, season: u32): GET "/tv/{id}/season/{season}/external_ids" => ExternalIds
540}
541
542endpoint! {
543    /// a season's images
544    tv_season_images(id: u64, season: u32): GET "/tv/{id}/season/{season}/images" => Images {
545        params { language: Language, include_image_language: Vec<Language> }
546    }
547}
548
549endpoint! {
550    /// a season's translations
551    tv_season_translations(id: u64, season: u32): GET "/tv/{id}/season/{season}/translations" => Translations
552}
553
554endpoint! {
555    /// a season's videos
556    tv_season_videos(id: u64, season: u32): GET "/tv/{id}/season/{season}/videos" => Videos {
557        params { language: Language, include_image_language: Vec<Language> }
558    }
559}
560
561endpoint! {
562    /// where a season can be watched, by country
563    tv_season_watch_providers(id: u64, season: u32): GET "/tv/{id}/season/{season}/watch/providers" => WatchProviders
564}
565
566endpoint! {
567    /// an episode's account states
568    tv_episode_account_states(id: u64, season: u32, episode: u32): GET "/tv/{id}/season/{season}/episode/{episode}/account_states" => EpisodeAccountStates {
569        params { session_id: SessionId, guest_session_id: GuestSessionId }
570    }
571}
572
573/// an episode's own account state
574#[derive(Debug, Clone, Deserialize)]
575pub struct EpisodeAccountStates {
576    pub id: u64,
577    pub rated: Rated,
578}
579
580endpoint! {
581    /// an episode's changes
582    tv_episode_changes(id: u64): GET "/tv/episode/{id}/changes" => Changes {
583        params { start_date: Date, end_date: Date, page: u32 }
584    }
585}
586
587endpoint! {
588    /// an episode's credits
589    tv_episode_credits(id: u64, season: u32, episode: u32): GET "/tv/{id}/season/{season}/episode/{episode}/credits" => Credits {
590        params { language: Language }
591    }
592}
593
594endpoint! {
595    /// an episode's ids on other databases
596    tv_episode_external_ids(id: u64, season: u32, episode: u32): GET "/tv/{id}/season/{season}/episode/{episode}/external_ids" => ExternalIds
597}
598
599endpoint! {
600    /// an episode's images
601    tv_episode_images(id: u64, season: u32, episode: u32): GET "/tv/{id}/season/{season}/episode/{episode}/images" => Images {
602        params { language: Language, include_image_language: Vec<Language> }
603    }
604}
605
606endpoint! {
607    /// an episode's translations
608    tv_episode_translations(id: u64, season: u32, episode: u32): GET "/tv/{id}/season/{season}/episode/{episode}/translations" => Translations
609}
610
611endpoint! {
612    /// an episode's videos
613    tv_episode_videos(id: u64, season: u32, episode: u32): GET "/tv/{id}/season/{season}/episode/{episode}/videos" => Videos {
614        params { language: Language, include_image_language: Vec<Language> }
615    }
616}
617
618endpoint! {
619    /// rate an episode; pass a session or guest session
620    rate_tv_episode(id: u64, season: u32, episode: u32): POST "/tv/{id}/season/{season}/episode/{episode}/rating" => StatusResponse {
621        params { session_id: SessionId, guest_session_id: GuestSessionId }
622        body { value: f64 }
623    }
624}
625
626endpoint! {
627    /// delete an episode rating
628    unrate_tv_episode(id: u64, season: u32, episode: u32): DELETE "/tv/{id}/season/{season}/episode/{episode}/rating" => StatusResponse {
629        params { session_id: SessionId, guest_session_id: GuestSessionId }
630    }
631}
632
633endpoint! {
634    /// an episode group
635    tv_episode_group(id: &str): GET "/tv/episode_group/{id}" => EpisodeGroup {
636        params { language: Language }
637    }
638}