From 9457dce115fda8688b93bc7b8a6e773bbb52fe6a Mon Sep 17 00:00:00 2001 From: DerPenz Date: Sat, 6 May 2023 18:57:20 +0200 Subject: [PATCH 1/4] base tv-episode integration --- src/endpoints/index.ts | 2 + src/endpoints/tv-episode.ts | 83 +++++++++++++++++++++++++++++++++++++ src/tmdb.ts | 5 +++ src/types/index.ts | 1 + src/types/options.ts | 5 +++ src/types/tv-episode.ts | 74 +++++++++++++++++++++++++++++++++ src/types/tv-shows.ts | 33 +-------------- 7 files changed, 171 insertions(+), 32 deletions(-) create mode 100644 src/endpoints/tv-episode.ts create mode 100644 src/types/tv-episode.ts diff --git a/src/endpoints/index.ts b/src/endpoints/index.ts index 6c2fa6a..e08baa8 100644 --- a/src/endpoints/index.ts +++ b/src/endpoints/index.ts @@ -14,3 +14,5 @@ export * from './trending'; export * from './find'; export * from './keywords'; export * from './collections'; +export * from './tv-episode'; + diff --git a/src/endpoints/tv-episode.ts b/src/endpoints/tv-episode.ts new file mode 100644 index 0000000..5988f1b --- /dev/null +++ b/src/endpoints/tv-episode.ts @@ -0,0 +1,83 @@ +import { + Episode, + EpisodeSelection, + LanguageOption, + PageOption, + ChangeOption, + TvEpisodeChanges, + TvEpisodeCredit, + ExternalIds, + Images, + TvEpisodeTranslations, + Videos, + AppendToResponseMovieKey, + AppendToResponse, + } from '..'; + import { BaseEndpoint } from './base'; + + const BASE_EPISODE = (episodeSelection: EpisodeSelection): string => { + return `/tv/${episodeSelection.tvShowID}/season/${episodeSelection.seasonNumber}/episode/${episodeSelection.episodeNumber}`; + }; + + export class TvEpisodesEndpoint extends BaseEndpoint { + constructor(accessToken: string) { + super(accessToken); + } + + async details( + episodeSelection: EpisodeSelection, + appendToResponse?: T, + options?: LanguageOption + ) { + const combinedOptions = { + append_to_response: appendToResponse + ? appendToResponse.join(',') + : undefined, + ...options, + }; + + return await this.api.get< + AppendToResponse, T, 'movie'> + >(`${BASE_EPISODE(episodeSelection)}`, combinedOptions); + } + + async changes(episodeID: number, options?: PageOption & ChangeOption) { + return await this.api.get( + `/tv/episode/${episodeID}/changes`, + options + ); + } + + async credits(episodeSelection: EpisodeSelection, options?: LanguageOption) { + return await this.api.get( + `${BASE_EPISODE(episodeSelection)}/credits`, + options + ); + } + + async externalIds(episodeSelection: EpisodeSelection) { + return await this.api.get( + `${BASE_EPISODE(episodeSelection)}/external_ids` + ); + } + + async images(episodeSelection: EpisodeSelection) { + return await this.api.get( + `${BASE_EPISODE(episodeSelection)}/images` + ); + } + + async translations(episodeSelection: EpisodeSelection) { + return await this.api.get( + `${BASE_EPISODE(episodeSelection)}/translations` + ); + } + + async videos(episodeSelection: EpisodeSelection, options?: LanguageOption) { + return await this.api.get( + `${BASE_EPISODE(episodeSelection)}/videos`, + options + ); + } + } + \ No newline at end of file diff --git a/src/tmdb.ts b/src/tmdb.ts index b0a5416..3e72afa 100644 --- a/src/tmdb.ts +++ b/src/tmdb.ts @@ -15,6 +15,7 @@ import { FindEndpoint, KeywordsEndpoint, CollectionsEndpoint, + TvEpisodesEndpoint, } from './endpoints'; export class TMDB { @@ -60,6 +61,10 @@ export class TMDB { return new TvShowsEndpoint(this.accessToken); } + get tvEpisode(): TvEpisodesEndpoint { + return new TvEpisodesEndpoint(this.accessToken); + } + get discover(): DiscoverEndpoint { return new DiscoverEndpoint(this.accessToken); } diff --git a/src/types/index.ts b/src/types/index.ts index a6f0c0b..0e04011 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -14,6 +14,7 @@ export * from './trending'; export * from './find'; export * from './keywords'; export * from './collections'; +export * from './tv-episode'; export type MediaType = 'movie' | 'tv' | 'person'; diff --git a/src/types/options.ts b/src/types/options.ts index af8f924..11556bc 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -38,6 +38,11 @@ export interface PageOption { page?: number; } +export interface ChangeOption extends PageOption { + start_date?: Date; + end_date?: Date; +} + export type AppendToResponseMovieKey = | 'images' | 'videos' diff --git a/src/types/tv-episode.ts b/src/types/tv-episode.ts new file mode 100644 index 0000000..fc7819e --- /dev/null +++ b/src/types/tv-episode.ts @@ -0,0 +1,74 @@ +import { Credits, Crew } from '.'; + +export interface EpisodeSelection { + tvShowID: number; + seasonNumber: number; + episodeNumber: number; +} + +export interface Episode { + air_date: string; + episode_number: number; + crew: Crew[]; + guest_stars: GuestStar[]; + id: number; + name: string; + overview: string; + production_code: string; + season_number: number; + still_path: string; + vote_average: number; + vote_count: number; + runtime: number; + show_id: number; +} + +export interface GuestStar { + credit_id: string; + order: number; + character: string; + adult: boolean; + gender: number | null; + id: number; + known_for_department: string; + name: string; + original_name: string; + popularity: number; + profile_path: string | null; +} + +export interface TvEpisodeChangeItem { + id: string; + action: string; + time: string; + iso_639_1: string; + iso_3166_1: string; + value: string; +} + +export interface TvEpisodeChange { + key: string; + items: TvEpisodeChangeItem[]; +} + +export interface TvEpisodeChanges { + changes: TvEpisodeChange[]; +} + +export interface TvEpisodeCredit extends Credits { + guest_stars: GuestStar[]; +} + +export interface TvEpisodeTranslations { + id: number; + translations: { + iso_3166_1: string; + iso_639_1: string; + name: string; + english_name: string; + data: { + name: string; + overview: string; + }; + }; +} diff --git a/src/types/tv-shows.ts b/src/types/tv-shows.ts index a38f533..6fa34a2 100644 --- a/src/types/tv-shows.ts +++ b/src/types/tv-shows.ts @@ -3,7 +3,7 @@ import { ProductionCompany, ProductionCountry, SpokenLanguage, - Crew, + Episode, } from './'; export interface CreatedBy { @@ -93,37 +93,6 @@ export interface TvShowDetails { vote_count: number; } -export interface GuestStar { - credit_id: string; - order: number; - character: string; - adult: boolean; - gender: number | null; - id: number; - known_for_department: string; - name: string; - original_name: string; - popularity: number; - profile_path: string | null; -} - -export interface Episode { - air_date: string; - episode_number: number; - crew: Crew[]; - guest_stars: GuestStar[]; - id: number; - name: string; - overview: string; - production_code: string; - season_number: number; - still_path: string; - vote_average: number; - vote_count: number; - show_id: number; - runtime: number; -} - export interface SeasonDetails { air_date: string; episodes: Episode[]; From 33830afe92896ad7f7568dd663f085b9d71a5c25 Mon Sep 17 00:00:00 2001 From: DerPenz Date: Sat, 6 May 2023 19:22:40 +0200 Subject: [PATCH 2/4] refactored change type --- src/endpoints/changes.ts | 8 +- src/endpoints/movies.ts | 7 +- src/endpoints/people.ts | 12 ++- src/endpoints/tv-episode.ts | 161 ++++++++++++++++++------------------ src/endpoints/tv-shows.ts | 7 +- src/types/changes.ts | 20 ++--- src/types/movies.ts | 11 +++ src/types/options.ts | 23 ++++-- src/types/people.ts | 23 ++---- src/types/tv-episode.ts | 20 +---- src/types/tv-shows.ts | 5 ++ 11 files changed, 150 insertions(+), 147 deletions(-) diff --git a/src/endpoints/changes.ts b/src/endpoints/changes.ts index b7521de..be3d2dd 100644 --- a/src/endpoints/changes.ts +++ b/src/endpoints/changes.ts @@ -1,20 +1,20 @@ +import { ChangeOption, MediaChanges } from '../types'; import { BaseEndpoint } from './base'; -import { ChangeOptions, MediaChanges } from '../types/changes'; export class ChangeEndpoint extends BaseEndpoint { constructor(protected readonly accessToken: string) { super(accessToken); } - async movies(options?: ChangeOptions): Promise { + async movies(options?: ChangeOption): Promise { return await this.api.get(`/movie/changes`, options); } - async tvShows(options?: ChangeOptions): Promise { + async tvShows(options?: ChangeOption): Promise { return await this.api.get(`/tv/changes`, options); } - async person(options?: ChangeOptions): Promise { + async person(options?: ChangeOption): Promise { return await this.api.get(`/person/change`, options); } } diff --git a/src/endpoints/movies.ts b/src/endpoints/movies.ts index 70d0734..e81064e 100644 --- a/src/endpoints/movies.ts +++ b/src/endpoints/movies.ts @@ -3,7 +3,7 @@ import { AlternativeTitles, AppendToResponse, AppendToResponseMovieKey, - ChangeOptions, + ChangeOption, Changes, Credits, ExternalIds, @@ -11,6 +11,7 @@ import { Keywords, LanguageOption, LatestMovie, + MovieChangeValue, MovieDetails, MovieLists, MoviesPlayingNow, @@ -57,8 +58,8 @@ export class MoviesEndpoint extends BaseEndpoint { ); } - async changes(id: number, options?: ChangeOptions): Promise { - return await this.api.get(`${BASE_MOVIE}/${id}/changes`, options); + async changes(id: number, options?: ChangeOption): Promise> { + return await this.api.get>(`${BASE_MOVIE}/${id}/changes`, options); } async credits(id: number): Promise { diff --git a/src/endpoints/people.ts b/src/endpoints/people.ts index 0d4aa70..48ae5b7 100644 --- a/src/endpoints/people.ts +++ b/src/endpoints/people.ts @@ -1,18 +1,19 @@ import { AppendToResponse, AppendToResponsePersonKey, - ChangeOptions, + ChangeOption, ExternalIds, PageOption, PeopleImages, PersonTranslations, - PersonChanges, PersonCombinedCredits, PersonDetails, PersonMovieCredit, PersonTvShowCredit, PopularPersons, TaggedImages, + Changes, + PersonChangeValue, } from '../types'; import { BaseEndpoint } from './base'; @@ -38,8 +39,11 @@ export class PeopleEndpoint extends BaseEndpoint { ); } - async changes(id: number, options?: ChangeOptions): Promise { - return await this.api.get( + async changes( + id: number, + options?: ChangeOption + ): Promise> { + return await this.api.get>( `${BASE_PERSON}/${id}/changes`, options ); diff --git a/src/endpoints/tv-episode.ts b/src/endpoints/tv-episode.ts index 5988f1b..f7e9e7d 100644 --- a/src/endpoints/tv-episode.ts +++ b/src/endpoints/tv-episode.ts @@ -1,83 +1,82 @@ import { - Episode, - EpisodeSelection, - LanguageOption, - PageOption, - ChangeOption, - TvEpisodeChanges, - TvEpisodeCredit, - ExternalIds, - Images, - TvEpisodeTranslations, - Videos, - AppendToResponseMovieKey, - AppendToResponse, - } from '..'; - import { BaseEndpoint } from './base'; - - const BASE_EPISODE = (episodeSelection: EpisodeSelection): string => { - return `/tv/${episodeSelection.tvShowID}/season/${episodeSelection.seasonNumber}/episode/${episodeSelection.episodeNumber}`; - }; - - export class TvEpisodesEndpoint extends BaseEndpoint { - constructor(accessToken: string) { - super(accessToken); - } - - async details( - episodeSelection: EpisodeSelection, - appendToResponse?: T, - options?: LanguageOption - ) { - const combinedOptions = { - append_to_response: appendToResponse - ? appendToResponse.join(',') - : undefined, - ...options, - }; - - return await this.api.get< - AppendToResponse, T, 'movie'> - >(`${BASE_EPISODE(episodeSelection)}`, combinedOptions); - } - - async changes(episodeID: number, options?: PageOption & ChangeOption) { - return await this.api.get( - `/tv/episode/${episodeID}/changes`, - options - ); - } - - async credits(episodeSelection: EpisodeSelection, options?: LanguageOption) { - return await this.api.get( - `${BASE_EPISODE(episodeSelection)}/credits`, - options - ); - } - - async externalIds(episodeSelection: EpisodeSelection) { - return await this.api.get( - `${BASE_EPISODE(episodeSelection)}/external_ids` - ); - } - - async images(episodeSelection: EpisodeSelection) { - return await this.api.get( - `${BASE_EPISODE(episodeSelection)}/images` - ); - } - - async translations(episodeSelection: EpisodeSelection) { - return await this.api.get( - `${BASE_EPISODE(episodeSelection)}/translations` - ); - } - - async videos(episodeSelection: EpisodeSelection, options?: LanguageOption) { - return await this.api.get( - `${BASE_EPISODE(episodeSelection)}/videos`, - options - ); - } + Episode, + EpisodeSelection, + LanguageOption, + ChangeOption, + TvEpisodeCredit, + ExternalIds, + Images, + TvEpisodeTranslations, + Videos, + AppendToResponseMovieKey, + AppendToResponse, + Changes, + TvEpisodeChangeValue, +} from '..'; +import { BaseEndpoint } from './base'; + +const BASE_EPISODE = (episodeSelection: EpisodeSelection): string => { + return `/tv/${episodeSelection.tvShowID}/season/${episodeSelection.seasonNumber}/episode/${episodeSelection.episodeNumber}`; +}; + +export class TvEpisodesEndpoint extends BaseEndpoint { + constructor(accessToken: string) { + super(accessToken); } - \ No newline at end of file + + async details( + episodeSelection: EpisodeSelection, + appendToResponse?: T, + options?: LanguageOption + ) { + const combinedOptions = { + append_to_response: appendToResponse + ? appendToResponse.join(',') + : undefined, + ...options, + }; + + return await this.api.get< + AppendToResponse, T, 'movie'> + >(`${BASE_EPISODE(episodeSelection)}`, combinedOptions); + } + + async changes(episodeID: number, options?: ChangeOption) { + return await this.api.get>( + `/tv/episode/${episodeID}/changes`, + options + ); + } + + async credits(episodeSelection: EpisodeSelection, options?: LanguageOption) { + return await this.api.get( + `${BASE_EPISODE(episodeSelection)}/credits`, + options + ); + } + + async externalIds(episodeSelection: EpisodeSelection) { + return await this.api.get( + `${BASE_EPISODE(episodeSelection)}/external_ids` + ); + } + + async images(episodeSelection: EpisodeSelection) { + return await this.api.get( + `${BASE_EPISODE(episodeSelection)}/images` + ); + } + + async translations(episodeSelection: EpisodeSelection) { + return await this.api.get( + `${BASE_EPISODE(episodeSelection)}/translations` + ); + } + + async videos(episodeSelection: EpisodeSelection, options?: LanguageOption) { + return await this.api.get( + `${BASE_EPISODE(episodeSelection)}/videos`, + options + ); + } +} diff --git a/src/endpoints/tv-shows.ts b/src/endpoints/tv-shows.ts index 738d4e2..4073dc8 100644 --- a/src/endpoints/tv-shows.ts +++ b/src/endpoints/tv-shows.ts @@ -3,7 +3,7 @@ import { AlternativeTitles, AppendToResponse, AppendToResponseTvKey, - ChangeOptions, + ChangeOption, Changes, ContentRatings, Credits, @@ -24,6 +24,7 @@ import { SimilarTvShows, TopRatedTvShows, Translations, + TvShowChangeValue, TvShowDetails, TvShowsAiringToday, Videos, @@ -58,8 +59,8 @@ export class TvShowsEndpoint extends BaseEndpoint { ); } - async changes(id: number, options?: ChangeOptions): Promise { - return await this.api.get(`${BASE_TV}/${id}/changes`, options); + async changes(id: number, options?: ChangeOption): Promise> { + return await this.api.get>(`${BASE_TV}/${id}/changes`, options); } async contentRatings(id: number): Promise { diff --git a/src/types/changes.ts b/src/types/changes.ts index 3c5f786..62151e9 100644 --- a/src/types/changes.ts +++ b/src/types/changes.ts @@ -10,26 +10,20 @@ export interface MediaChanges { total_results: number; } -export interface ChangeOptions { - end_date?: string; - start_date?: string; - page?: number; +export interface Changes { + changes: Change[]; } -export interface Changes { - changes: Change[]; -} - -export interface Change { +export interface Change { key: string; - items: ChangeItem[]; + items: ChangeItem[]; } -export interface ChangeItem { +export interface ChangeItem { id: string; action: string; time: string; - value: Array; + value: T; iso_639_1: string; - original_value: Array; + original_value: T; } diff --git a/src/types/movies.ts b/src/types/movies.ts index 77789b9..15fce6e 100644 --- a/src/types/movies.ts +++ b/src/types/movies.ts @@ -155,3 +155,14 @@ export interface UpcomingMovies { total_results: number; total_pages: number; } + +export type MovieChangeValue = + | string + | { + person_id: number; + character: string; + order: number; + cast_id: number; + credit_id: string; + } + | unknown; diff --git a/src/types/options.ts b/src/types/options.ts index 11556bc..bdff84d 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -10,7 +10,6 @@ import { MovieLists, PeopleImages, PersonTranslations, - PersonChanges, PersonCombinedCredits, PersonMovieCredit, PersonTvShowCredit, @@ -24,6 +23,10 @@ import { Translations, Videos, WatchProviders, + PersonChangeValue, + MovieChangeValue, + TvShowChangeValue, + TvEpisodeChangeValue, } from '.'; export interface LanguageOption { @@ -125,9 +128,14 @@ export type AppendToResponse< : object) & ('changes' extends T[number] ? { - changes: Omit< - Media extends 'person' ? PersonChanges : Changes, - 'id' + changes: Changes< + Media extends 'person' + ? PersonChangeValue + : Media extends 'movie' + ? MovieChangeValue + : Media extends 'tvShow' + ? TvShowChangeValue + : TvEpisodeChangeValue >; } : object) & @@ -147,7 +155,12 @@ export type AppendToResponse< ? { external_ids: Omit } : object) & ('translations' extends T[number] - ? { translations: Omit } + ? { + translations: Omit< + Media extends 'person' ? PersonTranslations : Translations, + 'id' + >; + } : object) & ('watch/providers' extends T[number] ? { 'watch/providers': Omit } diff --git a/src/types/people.ts b/src/types/people.ts index 333c1ba..cb34952 100644 --- a/src/types/people.ts +++ b/src/types/people.ts @@ -96,22 +96,13 @@ export interface PersonDetails { homepage: string; } -export interface PersonChange { - id: string; - action: string; - time: string; - iso_639_1: string; - iso_3166_1: string; - value: string | { profile: { file_path: string } }; - original_value: string | { profile: { file_path: string } }; -} - -export interface PersonChanges { - changes: { - key: string; - items: PersonChange[]; - }[]; -} +export type PersonChangeValue = + | string + | { + profile: { + file_path: string; + }; + }; export interface PopularPersons { page: number; diff --git a/src/types/tv-episode.ts b/src/types/tv-episode.ts index fc7819e..8212d2e 100644 --- a/src/types/tv-episode.ts +++ b/src/types/tv-episode.ts @@ -37,24 +37,6 @@ export interface GuestStar { profile_path: string | null; } -export interface TvEpisodeChangeItem { - id: string; - action: string; - time: string; - iso_639_1: string; - iso_3166_1: string; - value: string; -} - -export interface TvEpisodeChange { - key: string; - items: TvEpisodeChangeItem[]; -} - -export interface TvEpisodeChanges { - changes: TvEpisodeChange[]; -} - export interface TvEpisodeCredit extends Credits { guest_stars: GuestStar[]; } @@ -72,3 +54,5 @@ export interface TvEpisodeTranslations { }; }; } + +export type TvEpisodeChangeValue = string | unknown; \ No newline at end of file diff --git a/src/types/tv-shows.ts b/src/types/tv-shows.ts index 6fa34a2..eba1193 100644 --- a/src/types/tv-shows.ts +++ b/src/types/tv-shows.ts @@ -279,3 +279,8 @@ export interface TopRatedTvShows { total_results: number; total_pages: number; } + +export interface TvShowChangeValue { + season_id: number; + season_number: number; +} From e46f140890e417538770177db0a6a5ed14cd1ee1 Mon Sep 17 00:00:00 2001 From: DerPenz Date: Sat, 6 May 2023 19:29:36 +0200 Subject: [PATCH 3/4] append to response support --- src/endpoints/tv-episode.ts | 5 +++-- src/types/options.ts | 28 +++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/endpoints/tv-episode.ts b/src/endpoints/tv-episode.ts index f7e9e7d..88ee28e 100644 --- a/src/endpoints/tv-episode.ts +++ b/src/endpoints/tv-episode.ts @@ -12,6 +12,7 @@ import { AppendToResponse, Changes, TvEpisodeChangeValue, + AppendToResponseTvEpisodeKey, } from '..'; import { BaseEndpoint } from './base'; @@ -24,7 +25,7 @@ export class TvEpisodesEndpoint extends BaseEndpoint { super(accessToken); } - async details( + async details( episodeSelection: EpisodeSelection, appendToResponse?: T, options?: LanguageOption @@ -37,7 +38,7 @@ export class TvEpisodesEndpoint extends BaseEndpoint { }; return await this.api.get< - AppendToResponse, T, 'movie'> + AppendToResponse, T, 'tvEpisode'> >(`${BASE_EPISODE(episodeSelection)}`, combinedOptions); } diff --git a/src/types/options.ts b/src/types/options.ts index bdff84d..b2ceb61 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -27,6 +27,8 @@ import { MovieChangeValue, TvShowChangeValue, TvEpisodeChangeValue, + TvEpisodeCredit, + TvEpisodeTranslations, } from '.'; export interface LanguageOption { @@ -90,12 +92,24 @@ export type AppendToResponsePersonKey = | 'tagged_images' | 'translations'; +export type AppendToResponseTvEpisodeKey = + | 'images' + | 'credits' + | 'external_ids' + | 'videos' + | 'translations'; + type AppendToResponseAllKeys = | AppendToResponseTvKey | AppendToResponseMovieKey + | AppendToResponseTvEpisodeKey | AppendToResponsePersonKey; -export type AppendToResponseMediaType = 'movie' | 'tvShow' | 'person'; +export type AppendToResponseMediaType = + | 'movie' + | 'tvShow' + | 'person' + | 'tvEpisode'; export type AppendToResponse< K, @@ -106,7 +120,11 @@ export type AppendToResponse< ? object : T extends Array ? ('credits' extends T[number] - ? { credits: Omit } + ? { + credits: Media extends 'tvEpisode' + ? TvEpisodeCredit + : Omit; + } : object) & ('videos' extends T[number] ? { videos: Omit } : object) & ('images' extends T[number] @@ -157,7 +175,11 @@ export type AppendToResponse< ('translations' extends T[number] ? { translations: Omit< - Media extends 'person' ? PersonTranslations : Translations, + Media extends 'person' + ? PersonTranslations + : Media extends 'tvEpisode' + ? TvEpisodeTranslations + : Translations, 'id' >; } From 54cb13c23ea5cfb4f8c46bae8796bd3f478b63a0 Mon Sep 17 00:00:00 2001 From: DerPenz <99838921+Der-Penz@users.noreply.github.com> Date: Sat, 6 May 2023 19:32:14 +0200 Subject: [PATCH 4/4] bumbed version : 1.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bbfe876..9773a3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tmdb-ts", - "version": "1.2.0", + "version": "1.3.0", "description": "TMDB v3 library wrapper", "main": "dist/index.js", "types": "dist/index.d.ts",