UNPKG

@tiktikimelbo7/extensions

Version:

Nodejs library that provides high-level APIs for obtaining information on various entertainment media such as books, movies, comic books, anime, manga, and so on.

297 lines 20.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const models_1 = require("../../models"); const utils_1 = require("../../utils"); const flixhq_1 = __importDefault(require("../movies/flixhq")); class TMDB extends models_1.MovieParser { constructor(apiKey = '5201b54eb0968700e693a30576d7d4dc', provider, proxyConfig, adapter) { super(proxyConfig, adapter); this.apiKey = apiKey; this.name = 'TMDB'; this.baseUrl = 'https://www.themoviedb.org'; this.apiUrl = 'https://api.themoviedb.org/3'; this.logo = 'https://pbs.twimg.com/profile_images/1243623122089041920/gVZIvphd_400x400.jpg'; this.classPath = 'META.TMDB'; this.supportedTypes = new Set([models_1.TvType.MOVIE, models_1.TvType.TVSERIES, models_1.TvType.ANIME]); /** * @param query search query * @param page page number */ this.search = async (query, page = 1) => { const searchUrl = `${this.apiUrl}/search/multi?api_key=${this.apiKey}&language=en-US&page=${page}&include_adult=false&query=${query}`; const search = { currentPage: page, hasNextPage: false, results: [], }; try { const { data } = await this.client.get(searchUrl); if (data.results.length < 1) return search; search.hasNextPage = page + 1 <= data.total_pages; search.currentPage = page; search.totalResults = data.total_results; search.totalPages = data.total_pages; data.results.forEach((result) => { const date = new Date((result === null || result === void 0 ? void 0 : result.release_date) || (result === null || result === void 0 ? void 0 : result.first_air_date)); const movie = { id: result.id, title: (result === null || result === void 0 ? void 0 : result.title) || (result === null || result === void 0 ? void 0 : result.name), image: `https://image.tmdb.org/t/p/original${result === null || result === void 0 ? void 0 : result.poster_path}`, type: result.media_type === 'movie' ? models_1.TvType.MOVIE : models_1.TvType.TVSERIES, rating: (result === null || result === void 0 ? void 0 : result.vote_average) || 0, releaseDate: `${date.getFullYear()}` || '0', }; return search.results.push(movie); }); return search; } catch (err) { throw new Error(err.message); } }; /** * @param id media id (anime or movie/tv) * @param type movie or tv */ this.fetchMediaInfo = async (mediaId, type) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2; type = type.toLowerCase() === 'movie' ? 'movie' : 'tv'; const infoUrl = `${this.apiUrl}/${type}/${mediaId}?api_key=${this.apiKey}&language=en-US&append_to_response=release_dates,watch/providers,alternative_titles,credits,external_ids,images,keywords,recommendations,reviews,similar,translations,videos&include_image_language=en`; const info = { id: mediaId, title: '', }; try { //request api to get media info from tmdb const { data } = await this.client.get(infoUrl); //get provider id from title and year (if available) to get the correct provider id for the movie/tv series (e.g. flixhq) const providerId = await this.findIdFromTitle((data === null || data === void 0 ? void 0 : data.title) || (data === null || data === void 0 ? void 0 : data.name), { type: type === 'movie' ? models_1.TvType.MOVIE : models_1.TvType.TVSERIES, totalSeasons: data === null || data === void 0 ? void 0 : data.number_of_seasons, totalEpisodes: data === null || data === void 0 ? void 0 : data.number_of_episodes, year: new Date((data === null || data === void 0 ? void 0 : data.release_year) || (data === null || data === void 0 ? void 0 : data.first_air_date)).getFullYear(), }); //fetch media info from provider const InfoFromProvider = await this.provider.fetchMediaInfo(providerId); info.id = providerId; //check if the movie so episode id does not show on tv shows if (type === 'movie') info.episodeId = (_a = InfoFromProvider === null || InfoFromProvider === void 0 ? void 0 : InfoFromProvider.episodes[0]) === null || _a === void 0 ? void 0 : _a.id; info.title = (data === null || data === void 0 ? void 0 : data.title) || (data === null || data === void 0 ? void 0 : data.name); info.translations = (_b = data === null || data === void 0 ? void 0 : data.translations) === null || _b === void 0 ? void 0 : _b.translations.map((translation) => { var _a, _b; return ({ title: ((_a = translation.data) === null || _a === void 0 ? void 0 : _a.title) || (data === null || data === void 0 ? void 0 : data.name) || undefined, description: ((_b = translation.data) === null || _b === void 0 ? void 0 : _b.overview) || undefined, language: (translation === null || translation === void 0 ? void 0 : translation.english_name) || undefined, }); }); //images info.image = `https://image.tmdb.org/t/p/original${data === null || data === void 0 ? void 0 : data.poster_path}`; info.cover = `https://image.tmdb.org/t/p/original${data === null || data === void 0 ? void 0 : data.backdrop_path}`; info.logos = (_c = data === null || data === void 0 ? void 0 : data.images) === null || _c === void 0 ? void 0 : _c.logos.map((logo) => ({ url: `https://image.tmdb.org/t/p/original${logo.file_path}`, aspectRatio: logo === null || logo === void 0 ? void 0 : logo.aspect_ratio, width: logo === null || logo === void 0 ? void 0 : logo.width, })); info.type = type === 'movie' ? models_1.TvType.MOVIE : models_1.TvType.TVSERIES; info.rating = (data === null || data === void 0 ? void 0 : data.vote_average) || 0; info.releaseDate = (data === null || data === void 0 ? void 0 : data.release_date) || (data === null || data === void 0 ? void 0 : data.first_air_date); info.description = data === null || data === void 0 ? void 0 : data.overview; info.genres = data === null || data === void 0 ? void 0 : data.genres.map((genre) => genre.name); info.duration = (data === null || data === void 0 ? void 0 : data.runtime) || (data === null || data === void 0 ? void 0 : data.episode_run_time[0]); info.totalEpisodes = data === null || data === void 0 ? void 0 : data.number_of_episodes; info.totalSeasons = data === null || data === void 0 ? void 0 : data.number_of_seasons; info.directors = (_d = data === null || data === void 0 ? void 0 : data.credits) === null || _d === void 0 ? void 0 : _d.crew.filter((crew) => crew.job === 'Director').map((crew) => crew.name); info.writers = (_e = data === null || data === void 0 ? void 0 : data.credits) === null || _e === void 0 ? void 0 : _e.crew.filter((crew) => crew.job === 'Screenplay').map((crew) => crew.name); info.actors = (_f = data === null || data === void 0 ? void 0 : data.credits) === null || _f === void 0 ? void 0 : _f.cast.map((cast) => cast.name); info.trailer = { id: (_h = (_g = data === null || data === void 0 ? void 0 : data.videos) === null || _g === void 0 ? void 0 : _g.results[0]) === null || _h === void 0 ? void 0 : _h.key, site: (_k = (_j = data === null || data === void 0 ? void 0 : data.videos) === null || _j === void 0 ? void 0 : _j.results[0]) === null || _k === void 0 ? void 0 : _k.site, url: `https://www.youtube.com/watch?v=${(_m = (_l = data === null || data === void 0 ? void 0 : data.videos) === null || _l === void 0 ? void 0 : _l.results[0]) === null || _m === void 0 ? void 0 : _m.key}`, }; info.mappings = { imdb: ((_o = data === null || data === void 0 ? void 0 : data.external_ids) === null || _o === void 0 ? void 0 : _o.imdb_id) || undefined, tmdb: (data === null || data === void 0 ? void 0 : data.id) || undefined, }; info.similar = ((_q = (_p = data === null || data === void 0 ? void 0 : data.similar) === null || _p === void 0 ? void 0 : _p.results) === null || _q === void 0 ? void 0 : _q.length) <= 0 ? undefined : (_r = data === null || data === void 0 ? void 0 : data.similar) === null || _r === void 0 ? void 0 : _r.results.map((result) => { return { id: result.id, title: result.title || result.name, image: `https://image.tmdb.org/t/p/original${result.poster_path}`, type: type === 'movie' ? models_1.TvType.MOVIE : models_1.TvType.TVSERIES, rating: result.vote_average || 0, releaseDate: result.release_date || result.first_air_date, }; }); info.recommendations = ((_t = (_s = data === null || data === void 0 ? void 0 : data.recommendations) === null || _s === void 0 ? void 0 : _s.results) === null || _t === void 0 ? void 0 : _t.length) <= 0 ? undefined : (_u = data === null || data === void 0 ? void 0 : data.recommendations) === null || _u === void 0 ? void 0 : _u.results.map((result) => { return { id: result.id, title: result.title || result.name, image: `https://image.tmdb.org/t/p/original${result.poster_path}`, type: type === 'movie' ? models_1.TvType.MOVIE : models_1.TvType.TVSERIES, rating: result.vote_average || 0, releaseDate: result.release_date || result.first_air_date, }; }); const totalSeasons = (info === null || info === void 0 ? void 0 : info.totalSeasons) || 0; if (type === 'tv' && totalSeasons > 0) { const seasonUrl = (season) => `${this.apiUrl}/tv/${mediaId}/season/${season}?api_key=${this.apiKey}`; info.seasons = []; const seasons = info.seasons; const providerEpisodes = InfoFromProvider === null || InfoFromProvider === void 0 ? void 0 : InfoFromProvider.episodes; if ((providerEpisodes === null || providerEpisodes === void 0 ? void 0 : providerEpisodes.length) < 1) return info; info.nextAiringEpisode = (data === null || data === void 0 ? void 0 : data.next_episode_to_air) ? { season: ((_v = data.next_episode_to_air) === null || _v === void 0 ? void 0 : _v.season_number) || undefined, episode: ((_w = data.next_episode_to_air) === null || _w === void 0 ? void 0 : _w.episode_number) || undefined, releaseDate: ((_x = data.next_episode_to_air) === null || _x === void 0 ? void 0 : _x.air_date) || undefined, title: ((_y = data.next_episode_to_air) === null || _y === void 0 ? void 0 : _y.name) || undefined, description: ((_z = data.next_episode_to_air) === null || _z === void 0 ? void 0 : _z.overview) || undefined, runtime: ((_0 = data.next_episode_to_air) === null || _0 === void 0 ? void 0 : _0.runtime) || undefined, } : undefined; for (let i = 1; i <= totalSeasons; i++) { const { data: seasonData } = await this.client.get(seasonUrl(i.toString())); //find season in each episode (providerEpisodes) const seasonEpisodes = providerEpisodes === null || providerEpisodes === void 0 ? void 0 : providerEpisodes.filter(episode => episode.season === i); const episodes = ((_1 = seasonData === null || seasonData === void 0 ? void 0 : seasonData.episodes) === null || _1 === void 0 ? void 0 : _1.length) <= 0 ? undefined : seasonData === null || seasonData === void 0 ? void 0 : seasonData.episodes.map((episode) => { //find episode in each season (seasonEpisodes) const episodeFromProvider = seasonEpisodes === null || seasonEpisodes === void 0 ? void 0 : seasonEpisodes.find(ep => ep.number === episode.episode_number); return { id: episodeFromProvider === null || episodeFromProvider === void 0 ? void 0 : episodeFromProvider.id, title: episode.name, episode: episode.episode_number, season: episode.season_number, releaseDate: episode.air_date, description: episode.overview, url: (episodeFromProvider === null || episodeFromProvider === void 0 ? void 0 : episodeFromProvider.url) || undefined, img: !(episode === null || episode === void 0 ? void 0 : episode.still_path) ? undefined : { mobile: `https://image.tmdb.org/t/p/w300${episode.still_path}`, hd: `https://image.tmdb.org/t/p/w780${episode.still_path}`, }, }; }); seasons.push({ season: i, image: !(seasonData === null || seasonData === void 0 ? void 0 : seasonData.poster_path) ? undefined : { mobile: `https://image.tmdb.org/t/p/w300${seasonData.poster_path}`, hd: `https://image.tmdb.org/t/p/w780${seasonData.poster_path}`, }, episodes, isReleased: ((_2 = seasonData === null || seasonData === void 0 ? void 0 : seasonData.episodes[0]) === null || _2 === void 0 ? void 0 : _2.air_date) > new Date().toISOString() ? false : true, }); } } } catch (err) { throw new Error(err.message); } return info; }; /** * Find the id of a media from its title. and extra data. (year, totalSeasons, totalEpisodes) * @param title * @param extraData * @returns id of the media */ this.findIdFromTitle = async (title, extraData) => { var _a; //clean title title = title.replace(/[^a-zA-Z0-9 ]/g, '').toLowerCase(); const findMedia = (await this.provider.search(title)); if (findMedia.results.length === 0) return ''; // console.log(findMedia.results); // console.log(extraData); // Sort the retrieved info for more accurate results. findMedia.results.sort((a, b) => { var _a, _b; const targetTitle = title; let firstTitle; let secondTitle; if (typeof a.title == 'string') firstTitle = a === null || a === void 0 ? void 0 : a.title; else firstTitle = (_a = a === null || a === void 0 ? void 0 : a.title) !== null && _a !== void 0 ? _a : ''; if (typeof b.title == 'string') secondTitle = b.title; else secondTitle = (_b = b === null || b === void 0 ? void 0 : b.title) !== null && _b !== void 0 ? _b : ''; const firstRating = (0, utils_1.compareTwoStrings)(targetTitle, firstTitle.toLowerCase()); const secondRating = (0, utils_1.compareTwoStrings)(targetTitle, secondTitle.toLowerCase()); // Sort in descending order return secondRating - firstRating; }); //remove results that dont match the type findMedia.results = findMedia.results.filter(result => { if (extraData.type === models_1.TvType.MOVIE) return result.type === models_1.TvType.MOVIE; else if (extraData.type === models_1.TvType.TVSERIES) return result.type === models_1.TvType.TVSERIES; else return result; }); // if extraData contains a year, filter out the results that don't match the year if (extraData && extraData.year && extraData.type === models_1.TvType.MOVIE) { findMedia.results = findMedia.results.filter(result => { var _a; return ((_a = result.releaseDate) === null || _a === void 0 ? void 0 : _a.split('-')[0]) === extraData.year; }); } // console.log({ test1: findMedia.results }); // check if the result contains the total number of seasons and compare it to the extraData by 1 up or down and make sure that its a number if (extraData && extraData.totalSeasons && extraData.type === models_1.TvType.TVSERIES) { findMedia.results = findMedia.results.filter(result => { const totalSeasons = result.seasons || 0; const extraDataSeasons = extraData.totalSeasons || 0; return (totalSeasons === extraDataSeasons || totalSeasons === extraDataSeasons + 1 || totalSeasons === extraDataSeasons - 1); }); } // console.log(findMedia.results); return ((_a = findMedia === null || findMedia === void 0 ? void 0 : findMedia.results[0]) === null || _a === void 0 ? void 0 : _a.id) || undefined; }; /** * @param id media id (anime or movie/tv) * @param args optional arguments */ this.fetchEpisodeSources = async (id, ...args) => { return this.provider.fetchEpisodeSources(id, ...args); }; /** * @param episodeId episode id * @param args optional arguments **/ this.fetchEpisodeServers = async (episodeId, ...args) => { return this.provider.fetchEpisodeServers(episodeId, ...args); }; this.provider = provider || new flixhq_1.default(); } } // (async () => { // const tmdb = new TMDB(); // const search = await tmdb.search('the flash'); // const info = await tmdb.fetchMediaInfo(search.results[0].id, search.results![0].type as string); // // console.log(info); // })(); exports.default = TMDB; //# sourceMappingURL=tmdb.js.map