342 lines
13 KiB
JavaScript
342 lines
13 KiB
JavaScript
const moviedb = require('km-moviedb');
|
|
const convertTmdbToMovie = require('src/tmdb/convertTmdbToMovie');
|
|
const convertTmdbToShow = require('src/tmdb/convertTmdbToShow');
|
|
const convertTmdbToPerson = require('src/tmdb/convertTmdbToPerson');
|
|
// const { tmdbInfo } = require('src/tmdb/types')
|
|
|
|
class TMDB {
|
|
constructor(cache, apiKey, tmdbLibrary) {
|
|
this.cache = cache;
|
|
this.tmdbLibrary = tmdbLibrary || moviedb(apiKey);
|
|
this.cacheTags = {
|
|
multiSearch: 'mus',
|
|
movieSearch: 'mos',
|
|
showSearch: 'ss',
|
|
personSearch: 'ps',
|
|
movieInfo: 'mi',
|
|
showInfo: 'si',
|
|
personInfo: 'pi',
|
|
miscNowPlayingMovies: 'npm',
|
|
miscPopularMovies: 'pm',
|
|
miscTopRatedMovies: 'tpm',
|
|
miscUpcomingMovies: 'um',
|
|
tvOnTheAir: 'toa',
|
|
miscPopularTvs: 'pt',
|
|
miscTopRatedTvs: 'trt',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Retrieve a specific movie by id from TMDB.
|
|
* @param {Number} identifier of the movie you want to retrieve
|
|
* @param {String} type filter results by type (default movie).
|
|
* @returns {Promise} succeeds if movie was found
|
|
*/
|
|
lookup(identifier, type = 'movie') {
|
|
const query = { id: identifier };
|
|
const cacheKey = `${this.cacheTags.info}:${type}:${identifier}`;
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => this.tmdb(TMDB_METHODS['info'][type], query))
|
|
.catch(() => { throw new Error('Could not find a movie with that id.'); })
|
|
.then(response => this.cache.set(cacheKey, response))
|
|
.then(response => {
|
|
try {
|
|
return convertTmdbToSeasoned(response, type);
|
|
} catch (parseError) {
|
|
console.error(parseError);
|
|
throw new Error('Could not parse movie.');
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Retrive search results from TMDB.
|
|
* @param {String} text query you want to search for
|
|
* @param {Number} page representing pagination of results
|
|
* @param {String} type filter results by type (default multi)
|
|
* @returns {Promise} dict with query results, current page and total_pages
|
|
*/
|
|
search(text, page = 1, type = 'multi') {
|
|
const query = { query: text, page: page };
|
|
const cacheKey = `${this.cacheTags.search}:${page}:${type}:${text}`;
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => this.tmdb(TMDB_METHODS['search'][type], query))
|
|
.catch(() => { throw new Error('Could not search for movies/shows at tmdb.'); })
|
|
.then(response => this.cache.set(cacheKey, response))
|
|
.then(response => this.mapResults(response));
|
|
}
|
|
|
|
/**
|
|
* Retrieve a specific movie by id from TMDB.
|
|
* @param {Number} identifier of the movie you want to retrieve
|
|
* @param {String} type filter results by type (default movie).
|
|
* @returns {Promise} succeeds if movie was found
|
|
*/
|
|
movieInfo(identifier, credits=false, releaseDates=false) {
|
|
const query = { id: identifier };
|
|
const cacheKey = `${this.cacheTags.movieInfo}:${identifier}:${credits}`;
|
|
|
|
const requests = [this.tmdb('movieInfo', query)]
|
|
|
|
if (credits) {
|
|
requests.push(this.tmdb('movieCredits', query))
|
|
} else {
|
|
// This is because we expect ordered parameters below
|
|
requests.push(Promise.resolve([]))
|
|
}
|
|
|
|
if (releaseDates) {
|
|
requests.push(this.tmdb('movieReleaseDates', query))
|
|
}
|
|
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => Promise.all(requests))
|
|
.catch(error => {
|
|
if (error.status === 401) {
|
|
throw new Error('Unathorized tmdb request, please check api key.')
|
|
} else if (error.status === 404) {
|
|
throw new Error(`Could not find a movie with id: ${identifier}`)
|
|
}
|
|
|
|
throw new Error('Unexpected error has occured:', error.message)
|
|
})
|
|
.then(([movies, credits, releaseDates]) => this.cache.set(cacheKey, [movies, credits, releaseDates]))
|
|
.then(([movies, credits, releaseDates]) => convertTmdbToMovie(movies, credits, releaseDates))
|
|
}
|
|
|
|
/**
|
|
* Retrieve a specific show by id from TMDB.
|
|
* @param {Number} identifier of the show you want to retrieve
|
|
* @param {String} type filter results by type (default show).
|
|
* @returns {Promise} succeeds if show was found
|
|
*/
|
|
showInfo(identifier, credits=false) {
|
|
const query = { id: identifier };
|
|
const cacheKey = `${this.cacheTags.showInfo}:${identifier}:${credits}`;
|
|
|
|
const requests = [this.tmdb('tvInfo', query)]
|
|
|
|
if (credits) {
|
|
requests.push(this.tmdb('tvCredits', query))
|
|
}
|
|
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => Promise.all(requests))
|
|
.catch(error => {
|
|
if (error.status === 401) {
|
|
throw new Error('Unathorized tmdb request, please check api key.')
|
|
} else if (error.status === 404) {
|
|
throw new Error(`Could not find a show with id: ${identifier}`)
|
|
}
|
|
|
|
throw new Error('Unexpected error has occured:', error.message)
|
|
})
|
|
.then(([shows, credits]) => this.cache.set(cacheKey, [shows, credits]))
|
|
.then(([shows, credits]) => convertTmdbToShow(shows, credits))
|
|
}
|
|
|
|
/**
|
|
* Retrieve a specific person id from TMDB.
|
|
* @param {Number} identifier of the person you want to retrieve
|
|
* @param {String} type filter results by type (default person).
|
|
* @returns {Promise} succeeds if person was found
|
|
*/
|
|
personInfo(identifier) {
|
|
const query = { id: identifier };
|
|
const cacheKey = `${this.cacheTags.personInfo}:${identifier}`;
|
|
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => Promise.all([this.tmdb('personInfo', query), this.tmdb('personCombinedCredits', query)]))
|
|
.catch(() => { throw new Error('Could not find a person with that id.'); })
|
|
.then(([person, cast]) => this.cache.set(cacheKey, [person, cast]))
|
|
.then(([person, cast]) => convertTmdbToPerson(person, cast))
|
|
.catch(err => new Error('Unable to convert result to person', err))
|
|
}
|
|
|
|
|
|
|
|
multiSearch(search_query, page=1) {
|
|
const query = { query: search_query, page: page };
|
|
const cacheKey = `${this.cacheTags.multiSearch}:${page}:${search_query}`;
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => this.tmdb('searchMulti', query))
|
|
.catch(() => { throw new Error('Could not complete search to tmdb'); })
|
|
.then(response => this.cache.set(cacheKey, response))
|
|
.then(response => this.mapResults(response));
|
|
}
|
|
|
|
/**
|
|
* Retrive movie search results from TMDB.
|
|
* @param {String} text query you want to search for
|
|
* @param {Number} page representing pagination of results
|
|
* @returns {Promise} dict with query results, current page and total_pages
|
|
*/
|
|
movieSearch(query, page=1) {
|
|
const tmdbquery = { query: query, page: page };
|
|
const cacheKey = `${this.cacheTags.movieSearch}:${page}:${query}`;
|
|
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => this.tmdb('searchMovie', tmdbquery))
|
|
.catch(() => { throw new Error('Could not complete movie search to tmdb'); })
|
|
.then(response => this.cache.set(cacheKey, response))
|
|
.then(response => this.mapAndCreateResponse(response, convertTmdbToMovie))
|
|
.catch((error) => { console.log(error); throw new Error('Could not parse movie search result') })
|
|
}
|
|
|
|
/**
|
|
* Retrive show search results from TMDB.
|
|
* @param {String} text query you want to search for
|
|
* @param {Number} page representing pagination of results
|
|
* @returns {Promise} dict with query results, current page and total_pages
|
|
*/
|
|
showSearch(query, page=1) {
|
|
const tmdbquery = { query: query, page: page };
|
|
const cacheKey = `${this.cacheTags.showSearch}:${page}:${query}`;
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => this.tmdb('searchTv', tmdbquery))
|
|
.catch(() => { throw new Error('Could not complete show search to tmdb'); })
|
|
.then(response => this.cache.set(cacheKey, response))
|
|
.then(response => this.mapAndCreateResponse(response, convertTmdbToShow))
|
|
.catch((error) => { console.log(error); throw new Error('Could not parse show search result') })
|
|
}
|
|
|
|
/**
|
|
* Retrive person search results from TMDB.
|
|
* @param {String} text query you want to search for
|
|
* @param {Number} page representing pagination of results
|
|
* @returns {Promise} dict with query results, current page and total_pages
|
|
*/
|
|
personSearch(query, page=1) {
|
|
const tmdbquery = { query: query, page: page };
|
|
const cacheKey = `${this.cacheTags.personSearch}:${page}:${query}`;
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => this.tmdb('searchPerson', tmdbquery))
|
|
.catch(() => { throw new Error('Could not complete person search to tmdb'); })
|
|
.then(response => this.cache.set(cacheKey, response))
|
|
.then(response => this.mapAndCreateResponse(response, convertTmdbToPerson))
|
|
.catch((error) => { console.log(error); throw new Error('Could not parse person search result') })
|
|
}
|
|
|
|
mapAndCreateResponse(response, resultConvertFunction) {
|
|
// console.log(response)
|
|
return {
|
|
results: response.results.map(resultConvertFunction),
|
|
page: response.page,
|
|
total_results: response.total_results,
|
|
total_pages: response.total_pages
|
|
}
|
|
}
|
|
|
|
|
|
movieList(listname, page = 1) {
|
|
const query = { page: page };
|
|
const cacheKey = `${this.cacheTags[listname]}:${page}`;
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => this.tmdb(listname, query))
|
|
.catch(() => { throw new Error('Unable to get movie list from tmdb')})
|
|
.then(response => this.cache.set(cacheKey, response))
|
|
.then(response => this.mapAndCreateResponse(response, convertTmdbToMovie));
|
|
}
|
|
|
|
showList(listname, page = 1) {
|
|
const query = { page: page };
|
|
const cacheKey = `${this.cacheTags[listname]}:${page}`;
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => this.tmdb(listname, query))
|
|
.catch(() => { throw new Error('Unable to get show list from tmdb')})
|
|
.then(response => this.cache.set(cacheKey, response))
|
|
.then(response => this.mapAndCreateResponse(response, convertTmdbToShow));
|
|
}
|
|
|
|
/**
|
|
* Fetches a given list from tmdb.
|
|
* @param {String} listName Name of list
|
|
* @param {String} type filter results by type (default movie)
|
|
* @param {Number} page representing pagination of results
|
|
* @returns {Promise} dict with query results, current page and total_pages
|
|
*/
|
|
listSearch(listName, type = 'movie', page = '1') {
|
|
const query = { page: page };
|
|
console.log(query);
|
|
const cacheKey = `${this.cacheTags[listName]}:${type}:${page}`;
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => this.tmdb(TMDB_METHODS[listName][type], query))
|
|
.catch(() => { throw new Error('Error fetching list from tmdb.'); })
|
|
.then(response => this.cache.set(cacheKey, response))
|
|
.then(response => this.mapResults(response, type));
|
|
}
|
|
|
|
popular(type='movie', page=1) {
|
|
const query = { type: type, page: page };
|
|
const cacheKey = `${this.cacheTags.popular}:${type}:${page}`;
|
|
return Promise.resolve()
|
|
.then(() => this.cache.get(cacheKey))
|
|
.catch(() => this.tmdb('miscPopularMovies', query))
|
|
.catch((e) => { throw new Error(`Error fetching popular list of type ${type} : ${e}`) })
|
|
.then(response => this.cache.set(cacheKey, response))
|
|
.then(response => this.mapResults(response, type));
|
|
}
|
|
|
|
/**
|
|
* Maps our response from tmdb api to a movie/show object.
|
|
* @param {String} response from tmdb.
|
|
* @param {String} The type declared in listSearch.
|
|
* @returns {Promise} dict with tmdb results, mapped as movie/show objects.
|
|
*/
|
|
mapResults(response, _) {
|
|
let results = response.results.map((result) => {
|
|
if (result.media_type === 'movie') {
|
|
return convertTmdbToMovie(result);
|
|
} else if (result.media_type === 'tv') {
|
|
return convertTmdbToShow(result);
|
|
} else if (result.media_type === 'person') {
|
|
return convertTmdbToPerson(result);
|
|
}
|
|
})
|
|
|
|
return {
|
|
results: results,
|
|
page: response.page,
|
|
total_results: response.total_results,
|
|
total_pages: response.total_pages
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wraps moviedb library to support Promises.
|
|
* @param {String} method function name in the library
|
|
* @param {Object} argument argument to function being called
|
|
* @returns {Promise} succeeds if callback succeeds
|
|
*/
|
|
tmdb(method, argument) {
|
|
return new Promise((resolve, reject) => {
|
|
const callback = (error, reponse) => {
|
|
if (error) {
|
|
return reject(error);
|
|
}
|
|
resolve(reponse);
|
|
};
|
|
|
|
if (!argument) {
|
|
this.tmdbLibrary[method](callback);
|
|
} else {
|
|
this.tmdbLibrary[method](argument, callback);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = TMDB;
|