import axios , { AxiosInstance } from 'axios' ;
export const ANIME_KEYWORD_ID = 210024 ;
interface SearchOptions {
query : string ;
page? : number ;
includeAdult? : boolean ;
language? : string ;
}
interface DiscoverMovieOptions {
page? : number ;
includeAdult? : boolean ;
language? : string ;
sortBy ? :
| 'popularity.asc'
| 'popularity.desc'
| 'release_date.asc'
| 'release_date.desc'
| 'revenue.asc'
| 'revenue.desc'
| 'primary_release_date.asc'
| 'primary_release_date.desc'
| 'original_title.asc'
| 'original_title.desc'
| 'vote_average.asc'
| 'vote_average.desc'
| 'vote_count.asc'
| 'vote_count.desc' ;
}
interface DiscoverTvOptions {
page? : number ;
language? : string ;
sortBy ? :
| 'popularity.asc'
| 'popularity.desc'
| 'vote_average.asc'
| 'vote_average.desc'
| 'vote_count.asc'
| 'vote_count.desc'
| 'first_air_date.asc'
| 'first_air_date.desc' ;
}
interface TmdbMediaResult {
id : number ;
media_type : string ;
popularity : number ;
poster_path? : string ;
backdrop_path? : string ;
vote_count : number ;
vote_average : number ;
genre_ids : number [ ] ;
overview : string ;
original_language : string ;
}
export interface TmdbMovieResult extends TmdbMediaResult {
media_type : 'movie' ;
title : string ;
original_title : string ;
release_date : string ;
adult : boolean ;
video : boolean ;
}
export interface TmdbTvResult extends TmdbMediaResult {
media_type : 'tv' ;
name : string ;
original_name : string ;
origin_country : string [ ] ;
first_air_date : string ;
}
export interface TmdbPersonResult {
id : number ;
name : string ;
popularity : number ;
profile_path? : string ;
adult : boolean ;
media_type : 'person' ;
known_for : ( TmdbMovieResult | TmdbTvResult ) [ ] ;
}
interface TmdbPaginatedResponse {
page : number ;
total_results : number ;
total_pages : number ;
}
interface TmdbSearchMultiResponse extends TmdbPaginatedResponse {
results : ( TmdbMovieResult | TmdbTvResult | TmdbPersonResult ) [ ] ;
}
interface TmdbSearchMovieResponse extends TmdbPaginatedResponse {
results : TmdbMovieResult [ ] ;
}
interface TmdbSearchTvResponse extends TmdbPaginatedResponse {
results : TmdbTvResult [ ] ;
}
interface TmdbUpcomingMoviesResponse extends TmdbPaginatedResponse {
dates : {
maximum : string ;
minimum : string ;
} ;
results : TmdbMovieResult [ ] ;
}
interface TmdbExternalIdResponse {
movie_results : TmdbMovieResult [ ] ;
tv_results : TmdbTvResult [ ] ;
}
export interface TmdbCreditCast {
cast_id : number ;
character : string ;
credit_id : string ;
gender? : number ;
id : number ;
name : string ;
order : number ;
profile_path? : string ;
}
export interface TmdbCreditCrew {
credit_id : string ;
gender? : number ;
id : number ;
name : string ;
profile_path? : string ;
job : string ;
department : string ;
}
export interface TmdbExternalIds {
imdb_id? : string ;
freebase_mid? : string ;
freebase_id? : string ;
tvdb_id? : number ;
tvrage_id? : string ;
facebook_id? : string ;
instagram_id? : string ;
twitter_id? : string ;
}
export interface TmdbMovieDetails {
id : number ;
imdb_id? : string ;
adult : boolean ;
backdrop_path? : string ;
poster_path? : string ;
budget : number ;
genres : {
id : number ;
name : string ;
} [ ] ;
homepage? : string ;
original_language : string ;
original_title : string ;
overview? : string ;
popularity : number ;
production_companies : {
id : number ;
name : string ;
logo_path? : string ;
origin_country : string ;
} [ ] ;
production_countries : {
iso_3166_1 : string ;
name : string ;
} [ ] ;
release_date : string ;
revenue : number ;
runtime? : number ;
spoken_languages : {
iso_639_1 : string ;
name : string ;
} [ ] ;
status : string ;
tagline? : string ;
title : string ;
video : boolean ;
vote_average : number ;
vote_count : number ;
credits : {
cast : TmdbCreditCast [ ] ;
crew : TmdbCreditCrew [ ] ;
} ;
belongs_to_collection ? : {
id : number ;
name : string ;
poster_path? : string ;
backdrop_path? : string ;
} ;
external_ids : TmdbExternalIds ;
videos : TmdbVideoResult ;
}
export interface TmdbVideo {
id : string ;
key : string ;
name : string ;
site : 'YouTube' ;
size : number ;
type :
| 'Clip'
| 'Teaser'
| 'Trailer'
| 'Featurette'
| 'Opening Credits'
| 'Behind the Scenes'
| 'Bloopers' ;
}
export interface TmdbTvEpisodeResult {
id : number ;
air_date : string ;
episode_number : number ;
name : string ;
overview : string ;
production_code : string ;
season_number : number ;
show_id : number ;
still_path : string ;
vote_average : number ;
vote_cuont : number ;
}
export interface TmdbTvSeasonResult {
id : number ;
air_date : string ;
episode_count : number ;
name : string ;
overview : string ;
poster_path? : string ;
season_number : number ;
}
export interface TmdbTvDetails {
id : number ;
backdrop_path? : string ;
created_by : {
id : number ;
credit_id : string ;
name : string ;
gender : number ;
profile_path? : string ;
} [ ] ;
episode_run_time : number [ ] ;
first_air_date : string ;
genres : {
id : number ;
name : string ;
} [ ] ;
homepage : string ;
in_production : boolean ;
languages : string [ ] ;
last_air_date : string ;
last_episode_to_air? : TmdbTvEpisodeResult ;
name : string ;
next_episode_to_air? : TmdbTvEpisodeResult ;
networks : {
id : number ;
name : string ;
logo_path : string ;
origin_country : string ;
} [ ] ;
number_of_episodes : number ;
number_of_seasons : number ;
origin_country : string [ ] ;
original_language : string ;
original_name : string ;
overview : string ;
popularity : number ;
poster_path? : string ;
production_companies : {
id : number ;
logo_path? : string ;
name : string ;
origin_country : string ;
} [ ] ;
spoken_languages : {
english_name : string ;
iso_639_1 : string ;
name : string ;
} [ ] ;
seasons : TmdbTvSeasonResult [ ] ;
status : string ;
type : string ;
vote_average : number ;
vote_count : number ;
credits : {
cast : TmdbCreditCast [ ] ;
crew : TmdbCreditCrew [ ] ;
} ;
external_ids : TmdbExternalIds ;
keywords : {
results : TmdbKeyword [ ] ;
} ;
videos : TmdbVideoResult ;
}
export interface TmdbVideoResult {
results : TmdbVideo [ ] ;
}
export interface TmdbKeyword {
id : number ;
name : string ;
}
export interface TmdbPersonDetail {
id : number ;
name : string ;
deathday : string ;
known_for_department : string ;
also_known_as? : string [ ] ;
gender : number ;
biography : string ;
popularity : string ;
place_of_birth? : string ;
profile_path? : string ;
adult : boolean ;
imdb_id? : string ;
homepage? : string ;
}
export interface TmdbPersonCredit {
id : number ;
original_language : string ;
episode_count : number ;
overview : string ;
origin_country : string [ ] ;
original_name : string ;
vote_count : number ;
name : string ;
media_type? : string ;
popularity : number ;
credit_id : string ;
backdrop_path? : string ;
first_air_date : string ;
vote_average : number ;
genre_ids? : number [ ] ;
poster_path? : string ;
original_title : string ;
video? : boolean ;
title : string ;
adult : boolean ;
release_date : string ;
}
export interface TmdbPersonCreditCast extends TmdbPersonCredit {
character : string ;
}
export interface TmdbPersonCreditCrew extends TmdbPersonCredit {
department : string ;
job : string ;
}
export interface TmdbPersonCombinedCredits {
id : number ;
cast : TmdbPersonCreditCast [ ] ;
crew : TmdbPersonCreditCrew [ ] ;
}
export interface TmdbSeasonWithEpisodes extends TmdbTvSeasonResult {
episodes : TmdbTvEpisodeResult [ ] ;
external_ids : TmdbExternalIds ;
}
export interface TmdbCollection {
id : number ;
name : string ;
overview? : string ;
poster_path? : string ;
backdrop_path? : string ;
parts : TmdbMovieResult [ ] ;
}
class TheMovieDb {
private apiKey = 'db55323b8d3e4154498498a75642b381' ;
private axios : AxiosInstance ;
constructor ( ) {
this . axios = axios . create ( {
baseURL : 'https://api.themoviedb.org/3' ,
params : {
api_key : this.apiKey ,
} ,
headers : {
'Content-Type' : 'application/json' ,
Accept : 'application/json' ,
} ,
} ) ;
}
public searchMulti = async ( {
query ,
page = 1 ,
includeAdult = false ,
language = 'en-US' ,
} : SearchOptions ) : Promise < TmdbSearchMultiResponse > = > {
try {
const response = await this . axios . get ( '/search/multi' , {
params : { query , page , include_adult : includeAdult , language } ,
} ) ;
return response . data ;
} catch ( e ) {
return {
page : 1 ,
results : [ ] ,
total_pages : 1 ,
total_results : 0 ,
} ;
}
} ;
public getPerson = async ( {
personId ,
language = 'en-US' ,
} : {
personId : number ;
language? : string ;
} ) : Promise < TmdbPersonDetail > = > {
try {
const response = await this . axios . get < TmdbPersonDetail > (
` /person/ ${ personId } ` ,
{
params : { language } ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch person details: ${ e . message } ` ) ;
}
} ;
public getPersonCombinedCredits = async ( {
personId ,
language = 'en-US' ,
} : {
personId : number ;
language? : string ;
} ) : Promise < TmdbPersonCombinedCredits > = > {
try {
const response = await this . axios . get < TmdbPersonCombinedCredits > (
` /person/ ${ personId } /combined_credits ` ,
{
params : { language } ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error (
` [TMDB] Failed to fetch person combined credits: ${ e . message } `
) ;
}
} ;
public getMovie = async ( {
movieId ,
language = 'en-US' ,
} : {
movieId : number ;
language? : string ;
} ) : Promise < TmdbMovieDetails > = > {
try {
const response = await this . axios . get < TmdbMovieDetails > (
` /movie/ ${ movieId } ` ,
{
params : {
language ,
append_to_response : 'credits,external_ids,videos' ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch movie details: ${ e . message } ` ) ;
}
} ;
public getTvShow = async ( {
tvId ,
language = 'en-US' ,
} : {
tvId : number ;
language? : string ;
} ) : Promise < TmdbTvDetails > = > {
try {
const response = await this . axios . get < TmdbTvDetails > ( ` /tv/ ${ tvId } ` , {
params : {
language ,
append_to_response : 'credits,external_ids,keywords,videos' ,
} ,
} ) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch tv show details: ${ e . message } ` ) ;
}
} ;
public getTvSeason = async ( {
tvId ,
seasonNumber ,
language ,
} : {
tvId : number ;
seasonNumber : number ;
language? : string ;
} ) : Promise < TmdbSeasonWithEpisodes > = > {
try {
const response = await this . axios . get < TmdbSeasonWithEpisodes > (
` /tv/ ${ tvId } /season/ ${ seasonNumber } ` ,
{
params : {
language ,
append_to_response : 'external_ids' ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch tv show details: ${ e . message } ` ) ;
}
} ;
public async getMovieRecommendations ( {
movieId ,
page = 1 ,
language = 'en-US' ,
} : {
movieId : number ;
page? : number ;
language? : string ;
} ) : Promise < TmdbSearchMovieResponse > {
try {
const response = await this . axios . get < TmdbSearchMovieResponse > (
` /movie/ ${ movieId } /recommendations ` ,
{
params : {
page ,
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch discover movies: ${ e . message } ` ) ;
}
}
public async getMovieSimilar ( {
movieId ,
page = 1 ,
language = 'en-US' ,
} : {
movieId : number ;
page? : number ;
language? : string ;
} ) : Promise < TmdbSearchMovieResponse > {
try {
const response = await this . axios . get < TmdbSearchMovieResponse > (
` /movie/ ${ movieId } /similar ` ,
{
params : {
page ,
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch discover movies: ${ e . message } ` ) ;
}
}
public async getMoviesByKeyword ( {
keywordId ,
page = 1 ,
language = 'en-US' ,
} : {
keywordId : number ;
page? : number ;
language? : string ;
} ) : Promise < TmdbSearchMovieResponse > {
try {
const response = await this . axios . get < TmdbSearchMovieResponse > (
` /keyword/ ${ keywordId } /movies ` ,
{
params : {
page ,
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch movies by keyword: ${ e . message } ` ) ;
}
}
public async getTvRecommendations ( {
tvId ,
page = 1 ,
language = 'en-US' ,
} : {
tvId : number ;
page? : number ;
language? : string ;
} ) : Promise < TmdbSearchTvResponse > {
try {
const response = await this . axios . get < TmdbSearchTvResponse > (
` /tv/ ${ tvId } /recommendations ` ,
{
params : {
page ,
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error (
` [TMDB] Failed to fetch tv recommendations: ${ e . message } `
) ;
}
}
public async getTvSimilar ( {
tvId ,
page = 1 ,
language = 'en-US' ,
} : {
tvId : number ;
page? : number ;
language? : string ;
} ) : Promise < TmdbSearchTvResponse > {
try {
const response = await this . axios . get < TmdbSearchTvResponse > (
` /tv/ ${ tvId } /similar ` ,
{
params : {
page ,
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch tv similar: ${ e . message } ` ) ;
}
}
public getDiscoverMovies = async ( {
sortBy = 'popularity.desc' ,
page = 1 ,
includeAdult = false ,
language = 'en-US' ,
} : DiscoverMovieOptions = { } ) : Promise < TmdbSearchMovieResponse > = > {
try {
const response = await this . axios . get < TmdbSearchMovieResponse > (
'/discover/movie' ,
{
params : {
sort_by : sortBy ,
page ,
include_adult : includeAdult ,
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch discover movies: ${ e . message } ` ) ;
}
} ;
public getDiscoverTv = async ( {
sortBy = 'popularity.desc' ,
page = 1 ,
language = 'en-US' ,
} : DiscoverTvOptions = { } ) : Promise < TmdbSearchTvResponse > = > {
try {
const response = await this . axios . get < TmdbSearchTvResponse > (
'/discover/tv' ,
{
params : {
sort_by : sortBy ,
page ,
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch discover tv: ${ e . message } ` ) ;
}
} ;
public getUpcomingMovies = async ( {
page = 1 ,
language = 'en-US' ,
} : {
page : number ;
language : string ;
} ) : Promise < TmdbUpcomingMoviesResponse > = > {
try {
const response = await this . axios . get < TmdbUpcomingMoviesResponse > (
'/movie/upcoming' ,
{
params : {
page ,
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch upcoming movies: ${ e . message } ` ) ;
}
} ;
public getAllTrending = async ( {
page = 1 ,
timeWindow = 'day' ,
language = 'en-US' ,
} : {
page? : number ;
timeWindow ? : 'day' | 'week' ;
language? : string ;
} = { } ) : Promise < TmdbSearchMultiResponse > = > {
try {
const response = await this . axios . get < TmdbSearchMultiResponse > (
` /trending/all/ ${ timeWindow } ` ,
{
params : {
page ,
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch all trending: ${ e . message } ` ) ;
}
} ;
public getMovieTrending = async ( {
page = 1 ,
timeWindow = 'day' ,
} : {
page? : number ;
timeWindow ? : 'day' | 'week' ;
} = { } ) : Promise < TmdbSearchMovieResponse > = > {
try {
const response = await this . axios . get < TmdbSearchMovieResponse > (
` /trending/movie/ ${ timeWindow } ` ,
{
params : {
page ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch all trending: ${ e . message } ` ) ;
}
} ;
public getTvTrending = async ( {
page = 1 ,
timeWindow = 'day' ,
} : {
page? : number ;
timeWindow ? : 'day' | 'week' ;
} = { } ) : Promise < TmdbSearchTvResponse > = > {
try {
const response = await this . axios . get < TmdbSearchTvResponse > (
` /trending/tv/ ${ timeWindow } ` ,
{
params : {
page ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch all trending: ${ e . message } ` ) ;
}
} ;
public async getByExternalId ( {
externalId ,
type ,
language = 'en-US' ,
} :
| {
externalId : string ;
type : 'imdb' ;
language? : string ;
}
| {
externalId : number ;
type : 'tvdb' ;
language? : string ;
} ) : Promise < TmdbExternalIdResponse > {
try {
const response = await this . axios . get < TmdbExternalIdResponse > (
` /find/ ${ externalId } ` ,
{
params : {
external_source : type === 'imdb' ? 'imdb_id' : 'tvdb_id' ,
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to find by external ID: ${ e . message } ` ) ;
}
}
public async getMovieByImdbId ( {
imdbId ,
language = 'en-US' ,
} : {
imdbId : string ;
language? : string ;
} ) : Promise < TmdbMovieDetails > {
try {
const extResponse = await this . getByExternalId ( {
externalId : imdbId ,
type : 'imdb' ,
} ) ;
if ( extResponse . movie_results [ 0 ] ) {
const movie = await this . getMovie ( {
movieId : extResponse.movie_results [ 0 ] . id ,
language ,
} ) ;
return movie ;
}
throw new Error (
'[TMDB] Failed to find a title with the provided IMDB id'
) ;
} catch ( e ) {
throw new Error (
` [TMDB] Failed to get movie by external imdb ID: ${ e . message } `
) ;
}
}
public async getShowByTvdbId ( {
tvdbId ,
language = 'en-US' ,
} : {
tvdbId : number ;
language? : string ;
} ) : Promise < TmdbTvDetails > {
try {
const extResponse = await this . getByExternalId ( {
externalId : tvdbId ,
type : 'tvdb' ,
} ) ;
if ( extResponse . tv_results [ 0 ] ) {
const tvshow = await this . getTvShow ( {
tvId : extResponse.tv_results [ 0 ] . id ,
language ,
} ) ;
return tvshow ;
}
throw new Error (
` [TMDB] Failed to find a tv show with the provided TVDB id: ${ tvdbId } `
) ;
} catch ( e ) {
throw new Error (
` [TMDB] Failed to get tv show by external tvdb ID: ${ e . message } `
) ;
}
}
public async getCollection ( {
collectionId ,
language = 'en-US' ,
} : {
collectionId : number ;
language? : string ;
} ) : Promise < TmdbCollection > {
try {
const response = await this . axios . get < TmdbCollection > (
` /collection/ ${ collectionId } ` ,
{
params : {
language ,
} ,
}
) ;
return response . data ;
} catch ( e ) {
throw new Error ( ` [TMDB] Failed to fetch collection: ${ e . message } ` ) ;
}
}
}
export default TheMovieDb ;