Back to ES5 and Fix errors

This commit is contained in:
mrcanelas
2023-09-03 13:59:46 -03:00
parent 5da4621ab1
commit e97755d670
17 changed files with 1412 additions and 542 deletions
+1 -1
View File
@@ -222,7 +222,7 @@
/>
</div>
<h1 class="name">The Movie Database Addon</h1>
<h2 class="version">3.0.11</h2>
<h2 class="version">3.0.10</h2>
<h2 class="description">Metadata provided by TMDB.</h2>
<div class="separator"></div>
<h3 class="gives">This addon has more :</h3>
+42 -39
View File
@@ -1,19 +1,18 @@
import express from "express";
import urlExist from "url-exist";
import path, { dirname } from "path";
import { fileURLToPath } from 'url';
import getCatalog from "./lib/getCatalog.js"
import getSearch from "./lib/getSearch.js";
import { getManifest, DEFAULT_LANGUAGE } from "./lib/getManifest.js";
import getMeta from "./lib/getMeta.js";
import getTmdb from "./lib/getTmdb.js";
import getTrending from "./lib/getTrending.js";
import Utils from "./utils/parseProps.js";
const express = require("express");
const path = require("path")
const addon = express();
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const { getCatalog } = require("./lib/getCatalog");
const { getSearch } = require("./lib/getSearch");
const { getManifest, DEFAULT_LANGUAGE } = require("./lib/getManifest");
const { getMeta } = require("./lib/getMeta");
const { getTmdb } = require("./lib/getTmdb");
const { cacheWrapMeta } = require("./lib/getCache");
const { getTrending } = require("./lib/getTrending");
const { parseConfig, getRpdbPoster, checkIfExists } = require("./utils/parseProps");
const getCacheHeaders = function (opts) {
opts = opts || {};
const getCacheHeaders = (opts = {}) => {
if (!Object.keys(opts).length) return false;
let cacheHeaders = {
@@ -26,13 +25,13 @@ const getCacheHeaders = (opts = {}) => {
.map((prop) => {
const value = opts[prop];
if (!value) return false;
return `${cacheHeaders[prop]}=${value}`;
return cacheHeaders[prop] + "=" + value;
})
.filter((val) => !!val)
.join(", ");
};
const respond = (res, data, opts) => {
const respond = function (res, data, opts) {
const cacheControl = getCacheHeaders(opts);
if (cacheControl) res.setHeader("Cache-Control", `${cacheControl}, public`);
res.setHeader("Access-Control-Allow-Origin", "*");
@@ -41,16 +40,16 @@ const respond = (res, data, opts) => {
res.send(data);
};
addon.get("/", async (_, res) => {
addon.get("/", async function (_, res) {
res.redirect("/configure");
});
addon.get("/:catalogChoices?/configure", async (req, res) => {
res.sendFile(path.join(`${__dirname}/configure.html`));
addon.get("/:catalogChoices?/configure", async function (req, res) {
res.sendFile(path.join(__dirname + "/configure.html"));
});
addon.get("/:catalogChoices?/manifest.json", async ({ params }, res) => {
const config = Utils.parseConfig(params.catalogChoices);
addon.get("/:catalogChoices?/manifest.json", async function (req, res) {
const config = parseConfig(req.params.catalogChoices);
const language = config.language || DEFAULT_LANGUAGE;
const manifest = await getManifest(language);
const cacheOpts = {
@@ -61,15 +60,15 @@ addon.get("/:catalogChoices?/manifest.json", async ({ params }, res) => {
respond(res, manifest, cacheOpts);
});
addon.get("/:catalogChoices?/catalog/:type/:id/:extra?.json", async ({ params, url }, res) => {
const { catalogChoices, type, id } = params;
const config = Utils.parseConfig(catalogChoices)
addon.get("/:catalogChoices?/catalog/:type/:id/:extra?.json", async function (req, res) {
const { catalogChoices, type, id } = req.params;
const config = parseConfig(catalogChoices)
const language = config.language || DEFAULT_LANGUAGE;
const include_adult = config.include_adult || false
const rpdbkey = config.rpdbkey
const { genre, skip, search } = params.extra
const { genre, skip, search } = req.params.extra
? Object.fromEntries(
new URLSearchParams(url.split("/").pop().split("?")[0].slice(0, -5)).entries()
new URLSearchParams(req.url.split("/").pop().split("?")[0].slice(0, -5)).entries()
)
: {};
const page = Math.ceil(skip ? skip / 20 + 1 : undefined) || 1;
@@ -78,8 +77,8 @@ addon.get("/:catalogChoices?/catalog/:type/:id/:extra?.json", async ({ params, u
metas = search
? await getSearch(type, language, search, include_adult)
: id === "tmdb.trending"
? await getTrending(type, id, language, genre, page)
: await getCatalog(type, id, language, genre, page);
? await getTrending(type, id, language, genre, page, include_adult)
: await getCatalog(type, id, language, genre, page, include_adult);
} catch (e) {
res.status(404).send((e || {}).message || "Not found");
return;
@@ -97,8 +96,8 @@ addon.get("/:catalogChoices?/catalog/:type/:id/:extra?.json", async ({ params, u
try {
metas = JSON.parse(JSON.stringify(metas));
metas.metas = await Promise.all(metas.metas.map(async (el) => {
const rpdbPoster = Utils.getRpdbPoster(type, el.id.replace('tmdb:', ''), language, rpdbkey)
el.poster = (await urlExist(rpdbPoster)) ? rpdbPoster : el.poster;
const rpdbImage = getRpdbPoster(type, el.id.replace('tmdb:', ''), language, rpdbkey)
el.poster = await checkIfExists(rpdbImage) ? rpdbImage : el.poster;
return el;
}))
} catch (e) { }
@@ -106,15 +105,17 @@ addon.get("/:catalogChoices?/catalog/:type/:id/:extra?.json", async ({ params, u
respond(res, metas, cacheOpts);
});
addon.get("/:catalogChoices?/meta/:type/:id.json", async ({ params }, res) => {
const { catalogChoices, type, id } = params;
const config = Utils.parseConfig(catalogChoices);
addon.get("/:catalogChoices?/meta/:type/:id.json", async function (req, res) {
const { catalogChoices, type, id } = req.params;
const config = parseConfig(catalogChoices);
const tmdbId = id.split(":")[1];
const language = config.language || DEFAULT_LANGUAGE;
const imdbId = params.id.split(":")[0];
const imdbId = req.params.id.split(":")[0];
if (params.id.includes("tmdb:")) {
const resp = await getMeta(type, language, tmdbId);
if (req.params.id.includes("tmdb:")) {
const resp = await cacheWrapMeta(`${language}:${type}:${tmdbId}`, async () => {
return await getMeta(type, language, tmdbId)
});
const cacheOpts = {
staleRevalidate: 20 * 24 * 60 * 60, // 20 days
staleError: 30 * 24 * 60 * 60, // 30 days
@@ -129,10 +130,12 @@ addon.get("/:catalogChoices?/meta/:type/:id.json", async ({ params }, res) => {
}
respond(res, resp, cacheOpts);
}
if (params.id.includes("tt")) {
if (req.params.id.includes("tt")) {
const tmdbId = await getTmdb(type, imdbId);
if (tmdbId) {
const resp = await getMeta(type, language, tmdbId);
const resp = await cacheWrapMeta(`${language}:${type}:${tmdbId}`, async () => {
return await getMeta(type, language, tmdbId)
});
const cacheOpts = {
staleRevalidate: 20 * 24 * 60 * 60, // 20 days
staleError: 30 * 24 * 60 * 60, // 30 days
@@ -152,4 +155,4 @@ addon.get("/:catalogChoices?/meta/:type/:id.json", async ({ params }, res) => {
}
});
export default addon;
module.exports = addon;
+53
View File
@@ -0,0 +1,53 @@
const cacheManager = require('cache-manager');
const mangodbStore = require('cache-manager-mongodb');
const GLOBAL_KEY_PREFIX = 'tmdb-addon';
const META_KEY_PREFIX = `${GLOBAL_KEY_PREFIX}|meta`;
const CATALOG_KEY_PREFIX = `${GLOBAL_KEY_PREFIX}|catalog`;
const META_TTL = process.env.META_TTL || 7 * 24 * 60 * 60; // 7 day
const CATALOG_TTL = process.env.CATALOG_TTL || 15 * 24 * 60 * 60; // 15 day
const MONGO_URI = process.env.MONGODB_URI;
const NO_CACHE = process.env.NO_CACHE || false;
const cache = initiateCache();
function initiateCache() {
if (NO_CACHE) {
return null;
} else if (!NO_CACHE && MONGO_URI) {
return cacheManager.caching({
store: mangodbStore,
uri: MONGO_URI,
options: {
collection: 'tmdb_collection',
ttl: META_TTL
},
ttl: META_TTL,
ignoreCacheErrors: true
});
} else {
return cacheManager.caching({
store: 'memory',
ttl: META_TTL
});
}
}
function cacheWrap(key, method, options) {
if (NO_CACHE || !cache) {
return method();
}
return cache.wrap(key, method, options);
}
function cacheWrapCatalog(id, method) {
return cacheWrap(`${CATALOG_KEY_PREFIX}:${id}`, method, { ttl: CATALOG_TTL });
}
function cacheWrapMeta(id, method) {
return cacheWrap(`${META_KEY_PREFIX}:${id}`, method, { ttl: META_TTL });
}
module.exports = { cacheWrapCatalog, cacheWrapMeta };
+25 -20
View File
@@ -1,14 +1,15 @@
import "dotenv/config"
import { MovieDb } from "moviedb-promise";
const moviedb = new MovieDb(process.env.tmdb_api);
import getGenreList from "./getGenreList.js";
import getLanguages from "./getLanguages.js";
import getMeta from "./getMeta.js";
require("dotenv").config();
const { MovieDb } = require("moviedb-promise");
const moviedb = new MovieDb(process.env.TMDB_API);
const { getGenreList } = require("./getGenreList");
const { getLanguages } = require("./getLanguages");
const { cacheWrapMeta } = require("./getCache");
const { getMeta } = require("./getMeta")
async function getCatalog(type, id, language, genre, page, include_adult) {
const parameters = {
language,
page,
var parameters = {
language: language,
page: page,
include_adult,
};
const genre_id = await getGenreList(language, type);
@@ -18,7 +19,7 @@ async function getCatalog(type, id, language, genre, page, include_adult) {
let gen_name = false
if (genre) {
gen_name = genre
? (genre_id.find(({ name }) => name === genre) || {}).id || false
? (genre_id.find((x) => x.name === genre) || {}).id || false
: genre;
if (!gen_name) return Promise.reject(Error(`Could not find genre: ${genre}`))
}
@@ -27,15 +28,17 @@ async function getCatalog(type, id, language, genre, page, include_adult) {
parameters.primary_release_year = genre
} else if (id === "tmdb.language") {
parameters.with_original_language = languages
.find(({ name }) => name === genre)
.find((lang) => lang.name === genre)
.iso_639_1.split("-")[0]
}
return await moviedb
.discoverMovie(parameters)
.then(async ({ results }) => {
.then(async (res) => {
const metas = await Promise.all(
results.map(async (el) => {
const meta = await getMeta(type, language, el.id);
res.results.map(async (el) => {
const meta = await cacheWrapMeta(`${language}:${type}:${el.id}`, async () => {
return await getMeta(type, language, el.id);
});
return meta.meta;
})
);
@@ -49,7 +52,7 @@ async function getCatalog(type, id, language, genre, page, include_adult) {
let gen_name = false
if (genre) {
gen_name = genre
? (genre_id.find(({ name }) => name === genre) || {}).id || false
? (genre_id.find((x) => x.name === genre) || {}).id || false
: genre;
if (!gen_name) return Promise.reject(Error(`Could not find genre: ${genre}`))
}
@@ -58,15 +61,17 @@ async function getCatalog(type, id, language, genre, page, include_adult) {
parameters.first_air_date_year = genre
} else if (id === "tmdb.language") {
parameters.with_original_language = languages
.find(({ name }) => name === genre)
.find((lang) => lang.name === genre)
.iso_639_1.split("-")[0]
}
return await moviedb
.discoverTv(parameters)
.then(async ({ results }) => {
.then(async (res) => {
const metas = await Promise.all(
results.map(async (el) => {
const meta = await getMeta(type, language, el.id);
res.results.map(async (el) => {
const meta = await cacheWrapMeta(`${language}:${type}:${el.id}`, async () => {
return await getMeta(type, language, el.id);
});
return meta.meta;
})
);
@@ -76,4 +81,4 @@ async function getCatalog(type, id, language, genre, page, include_adult) {
}
}
export default getCatalog
module.exports = { getCatalog };
+34 -30
View File
@@ -1,19 +1,21 @@
import "dotenv/config"
import { MovieDb } from "moviedb-promise";
const moviedb = new MovieDb(process.env.tmdb_api);
import diferentOrder from "../static/diferentOrder.json" assert { type: "json" };
import diferentImdbId from "../static/diferentImdbId.json" assert { type: "json" };
require("dotenv").config();
const { MovieDb } = require("moviedb-promise");
const moviedb = new MovieDb(process.env.TMDB_API);
const diferentOrder = require("../static/diferentOrder.json");
const diferentImdbId = require("../static/diferentImdbId.json");
function genSeasonsString(seasons) {
if (seasons.length <= 20) {
return [
seasons.map(({ season_number }) => `season/${season_number}`).join(","),
seasons.map((season) => `season/${season.season_number}`).join(","),
];
} else {
const result = new Array(Math.ceil(seasons.length / 20))
.fill()
.map((_) => seasons.splice(0, 20));
return result.map(arr => arr.map(({ season_number }) => `season/${season_number}`).join(","));
return result.map((arr) => {
return arr.map((season) => `season/${season.season_number}`).join(",");
});
}
}
@@ -24,28 +26,30 @@ async function getEpisodes(language, tmdbId, imdb_id, seasons) {
imdb_id = !difImdbId ? imdb_id : difImdbId.imdbId;
if (difOrder != undefined) {
return await moviedb
.episodeGroup({ language, id: difOrder.episodeGroupId })
.then(({ groups }) => groups
.map(({ episodes, order }) => episodes.map((episode, index) => ({
id: difOrder.watchOrderOnly
? `${imdb_id}:${episode.season_number}:${episode.episode_number}`
: `${imdb_id}:${order}:${index + 1}`,
name: episode.name,
season: order,
episode: index + 1,
thumbnail: `https://image.tmdb.org/t/p/w500${episode.still_path}`,
overview: episode.overview,
description: episode.overview,
rating: episode.vote_average,
firstAired: difOrder.watchOrderOnly
? new Date(Date.parse(episodes[0].air_date) + index)
: new Date(Date.parse(episode.air_date) + index),
released: difOrder.watchOrderOnly
? new Date(Date.parse(episodes[0].air_date) + index)
: new Date(Date.parse(episode.air_date) + index),
}))
)
.reduce((a, b) => a.concat(b), [])
.episodeGroup({ language: language, id: difOrder.episodeGroupId })
.then((episodeGroups) =>
episodeGroups.groups
.map((group) =>
group.episodes.map((episode, index) => ({
id: difOrder.watchOrderOnly
? `${imdb_id}:${episode.season_number}:${episode.episode_number}`
: `${imdb_id}:${group.order}:${index + 1}`,
name: episode.name,
season: group.order,
episode: index + 1,
thumbnail: `https://image.tmdb.org/t/p/w500${episode.still_path}`,
overview: episode.overview,
description: episode.overview,
rating: episode.vote_average,
firstAired: difOrder.watchOrderOnly
? new Date(Date.parse(group.episodes[0].air_date) + index)
: new Date(Date.parse(episode.air_date) + index),
released: difOrder.watchOrderOnly
? new Date(Date.parse(group.episodes[0].air_date) + index)
: new Date(Date.parse(episode.air_date) + index),
}))
)
.reduce((a, b) => a.concat(b), [])
)
.catch(console.error);
} else {
@@ -89,4 +93,4 @@ async function getEpisodes(language, tmdbId, imdb_id, seasons) {
}
}
export default getEpisodes;
module.exports = { getEpisodes };
+14 -10
View File
@@ -1,21 +1,25 @@
import 'dotenv/config';
import { MovieDb } from 'moviedb-promise';
const moviedb = new MovieDb(process.env.tmdb_api)
require('dotenv').config()
const { MovieDb } = require('moviedb-promise')
const moviedb = new MovieDb(process.env.TMDB_API)
async function getGenreList(language, type) {
if (type === "movie") {
const genre = await moviedb
.genreMovieList({ language })
.then(({ genres }) => genres)
.genreMovieList({language})
.then((res) => {
return res.genres;
})
.catch(console.error);
return genre
return genre
} else {
const genre = await moviedb
.genreTvList({ language })
.then(({ genres }) => genres)
.catch(console.error);
.genreTvList({language})
.then((res) => {
return res.genres;
})
.catch(console.error);
return genre
}
}
export default getGenreList;
module.exports = { getGenreList };
+6 -6
View File
@@ -1,6 +1,6 @@
import "dotenv/config"
import { MovieDb } from "moviedb-promise";
const moviedb = new MovieDb(process.env.tmdb_api);
require("dotenv").config();
const { MovieDb } = require("moviedb-promise");
const moviedb = new MovieDb(process.env.TMDB_API);
async function getLanguages() {
const [primaryTranslations, languages] = await Promise.all([
@@ -9,9 +9,9 @@ async function getLanguages() {
]);
return primaryTranslations.map((element) => {
const [language, country] = element.split("-");
const findLanguage = languages.find(({ iso_639_1 }) => iso_639_1 === language);
return { iso_639_1: element, name: findLanguage.english_name };
const findLanguage = languages.find((obj) => obj.iso_639_1 === language);
return { iso_639_1: element, name: findLanguage.english_name};
});
}
export default getLanguages;
module.exports = { getLanguages };
+20 -16
View File
@@ -1,20 +1,20 @@
import 'dotenv/config';
import FanartTvApi from "fanart.tv-api";
const apiKey = process.env.fanart_api;
require('dotenv').config()
const FanartTvApi = require("fanart.tv-api");
const apiKey = process.env.FANART_API;
const baseUrl = "http://webservice.fanart.tv/v3/";
const fanart = new FanartTvApi({ apiKey, baseUrl });
function pickLogo(resp, language, original_language) {
if (
resp.find(({ lang }) => lang === language.split("-")[0]) != undefined
resp.find((data) => data.lang === language.split("-")[0]) != undefined
) {
return resp.find(({ lang }) => lang === language.split("-")[0]);
return resp.find((data) => data.lang === language.split("-")[0]);
} else if (
resp.find(({ lang }) => lang === original_language) != undefined
resp.find((data) => data.lang === original_language) != undefined
) {
return resp.find(({ lang }) => lang === original_language);
} else if (resp.find(({ lang }) => lang === "en") != undefined) {
return resp.find(({ lang }) => lang === "en");
return resp.find((data) => data.lang === original_language);
} else if (resp.find((data) => data.lang === "en") != undefined) {
return resp.find((data) => data.lang === "en");
} else {
return resp[0];
}
@@ -24,8 +24,8 @@ async function getLogo(tmdbId, language, original_language) {
if (!tmdbId) return Promise.reject(Error(`TMDB ID Not available for Fanart: ${tmdbId}`));
const meta = fanart
.getMovieImages(tmdbId)
.then(({ hdmovielogo }) => {
const resp = hdmovielogo
.then((res) => {
const resp = res.hdmovielogo
if (resp !== undefined) {
const { url } = pickLogo(resp, language, original_language);
return url
@@ -33,7 +33,9 @@ async function getLogo(tmdbId, language, original_language) {
return ''
}
})
.catch(err => "");
.catch((err) => {
return ""
});
return meta;
}
@@ -41,8 +43,8 @@ async function getTvLogo(tvdb_id, language, original_language) {
if (!tvdb_id) return Promise.reject(Error(`TVDB ID Not available for Fanart: ${tvdb_id}`));
const meta = fanart
.getShowImages(tvdb_id)
.then(({ hdtvlogo }) => {
const resp = hdtvlogo;
.then((res) => {
const resp = res.hdtvlogo;
if (resp !== undefined) {
const { url } = pickLogo(resp, language, original_language);
return url
@@ -50,8 +52,10 @@ async function getTvLogo(tvdb_id, language, original_language) {
return ''
}
})
.catch(err => "");
.catch((err) => {
return ""
});
return meta;
}
export { getLogo, getTvLogo };
module.exports = { getLogo, getTvLogo };
+8 -8
View File
@@ -1,7 +1,7 @@
import "dotenv/config"
import getGenreList from "./getGenreList.js";
import getLanguages from "./getLanguages.js";
import packageFile from "../package.json" assert { type: "json" };
require("dotenv").config();
const { getGenreList } = require("./getGenreList");
const { getLanguages } = require("./getLanguages");
const package = require("../package.json");
const DEFAULT_LANGUAGE = "en-US";
@@ -34,15 +34,15 @@ async function getManifest(language = DEFAULT_LANGUAGE) {
const descriptionSuffix = language && language !== DEFAULT_LANGUAGE ? ` with ${language} language.` : ".";
return {
id: packageFile.name,
version: packageFile.version,
id: package.name,
version: package.version,
favicon:
"https://github.com/mrcanelas/tmdb-addon/raw/main/images/favicon.png",
logo: "https://github.com/mrcanelas/tmdb-addon/raw/main/images/logo.png",
background:
"https://github.com/mrcanelas/tmdb-addon/raw/main/images/background.png",
name: "The Movie Database Addon",
description: packageFile.description + descriptionSuffix,
description: package.description + descriptionSuffix,
resources: ["catalog", "meta"],
types: ["movie", "series"],
idPrefixes: ["tmdb:"],
@@ -159,4 +159,4 @@ async function getManifest(language = DEFAULT_LANGUAGE) {
};
}
export { getManifest, DEFAULT_LANGUAGE };
module.exports = { getManifest, DEFAULT_LANGUAGE };
+14 -14
View File
@@ -1,9 +1,9 @@
import "dotenv/config"
import { MovieDb } from "moviedb-promise";
import Utils from "../utils/parseProps.js";
const moviedb = new MovieDb(process.env.tmdb_api);
import getEpisodes from "./getEpisodes.js";
import { getLogo, getTvLogo } from "./getLogo.js";
require("dotenv").config();
const { MovieDb } = require("moviedb-promise");
const Utils = require("../utils/parseProps");
const moviedb = new MovieDb(process.env.TMDB_API);
const { getEpisodes } = require("./getEpisodes");
const { getLogo, getTvLogo } = require("./getLogo");
const blacklistLogoUrls = [
@@ -14,7 +14,7 @@ const blacklistLogoUrls = [
async function getMeta(type, language, tmdbId) {
if (type === "movie") {
const meta = await moviedb
.movieInfo({ id: tmdbId, language, append_to_response: "videos,credits", })
.movieInfo({id: tmdbId, language, append_to_response: "videos,credits",})
.then(async (res) => {
const resp = {
imdb_id: res.imdb_id,
@@ -27,7 +27,7 @@ async function getMeta(type, language, tmdbId) {
name: res.title,
released: new Date(res.release_date),
slug: Utils.parseSlug(type, res.title, res.imdb_id),
type,
type: type,
writer: Utils.parseWriter(res.credits),
year: res.release_date ? res.release_date.substr(0, 4) : "",
trailers: Utils.parseTrailers(res.videos),
@@ -60,7 +60,7 @@ async function getMeta(type, language, tmdbId) {
};
try {
resp.logo = await getLogo(tmdbId, language, res.original_language);
} catch (e) {
} catch(e) {
console.log(`warning: logo could not be retrieved for ${tmdbId} - ${type}`);
console.log((e || {}).message || "unknown error");
}
@@ -73,7 +73,7 @@ async function getMeta(type, language, tmdbId) {
return Promise.resolve({ meta });
} else {
const meta = await moviedb
.tvInfo({ id: tmdbId, language, append_to_response: "videos,credits,external_ids", })
.tvInfo({id: tmdbId, language, append_to_response: "videos,credits,external_ids",})
.then(async (res) => {
const resp = {
cast: Utils.parseCast(res.credits),
@@ -87,7 +87,7 @@ async function getMeta(type, language, tmdbId) {
released: new Date(res.first_air_date),
runtime: Utils.parseRunTime(res.episode_run_time[0]),
status: res.status,
type,
type: type,
writer: Utils.parseCreatedBy(res.created_by),
year: Utils.parseYear(res.status, res.first_air_date, res.last_air_date),
background: `https://image.tmdb.org/t/p/original${res.backdrop_path}`,
@@ -111,7 +111,7 @@ async function getMeta(type, language, tmdbId) {
};
try {
resp.logo = await getTvLogo(res.external_ids.tvdb_id, language, res.original_language);
} catch (e) {
} catch(e) {
console.log(`warning: logo could not be retrieved for ${tmdbId} - ${type}`);
console.log((e || {}).message || "unknown error");
}
@@ -120,7 +120,7 @@ async function getMeta(type, language, tmdbId) {
}
try {
resp.videos = await getEpisodes(language, tmdbId, res.external_ids.imdb_id, res.seasons);
} catch (e) {
} catch(e) {
console.log(`warning: episodes could not be retrieved for ${tmdbId} - ${type}`);
console.log((e || {}).message || "unknown error");
}
@@ -132,4 +132,4 @@ async function getMeta(type, language, tmdbId) {
}
}
export default getMeta;
module.exports = { getMeta };
+28 -28
View File
@@ -1,14 +1,14 @@
import "dotenv/config"
import { MovieDb } from "moviedb-promise";
const moviedb = new MovieDb(process.env.tmdb_api);
require("dotenv").config();
const { MovieDb } = require("moviedb-promise");
const moviedb = new MovieDb(process.env.TMDB_API);
async function getSearch(type, language, query, include_adult) {
if (type === "movie") {
const searchMovie = []
const searchMovie = []
await moviedb
.searchMovie({ query, language, include_adult })
.then(({ results }) => {
results.map((el) => {
.then((res) => {
res.results.map((el) => {
searchMovie.push({
id: `tmdb:${el.id}`,
name: `${el.title}`,
@@ -20,13 +20,13 @@ async function getSearch(type, language, query, include_adult) {
});
})
.catch(console.error);
await moviedb.searchPerson({ query, language }).then(async ({ results }) => {
if (results[0]) {
await moviedb.searchPerson({ query, language }).then(async (res) => {
if (res.results[0]) {
await moviedb
.personMovieCredits({ id: results[0].id, language })
.then(({ cast, crew }) => {
cast.map((el) => {
if (!searchMovie.find(({ id }) => id === `tmdb:${el.id}`)) {
.personMovieCredits({ id: res.results[0].id, language })
.then((credits) => {
credits.cast.map((el) => {
if (!searchMovie.find((meta) => meta.id === `tmdb:${el.id}`)) {
searchMovie.push({
id: `tmdb:${el.id}`,
name: `${el.title}`,
@@ -37,9 +37,9 @@ async function getSearch(type, language, query, include_adult) {
});
}
});
crew.map((el) => {
credits.crew.map((el) => {
if (el.job === "Director" || "Writer") {
if (!searchMovie.find(({ id }) => id === `tmdb:${el.id}`)) {
if (!searchMovie.find((meta) => meta.id === `tmdb:${el.id}`)) {
searchMovie.push({
id: `tmdb:${el.id}`,
name: `${el.title}`,
@@ -56,13 +56,13 @@ async function getSearch(type, language, query, include_adult) {
});
const sortMetas = searchMovie.sort((a, b) => b.popularity - a.popularity);
return Promise.resolve({ query, metas: sortMetas });
return Promise.resolve({query, metas: sortMetas });
} else {
const searchTv = []
const searchTv = []
await moviedb
.searchTv({ query, language, include_adult })
.then(({ results }) => {
results.map((el) => {
.then((res) => {
res.results.map((el) => {
searchTv.push({
id: `tmdb:${el.id}`,
name: `${el.name}`,
@@ -74,14 +74,14 @@ async function getSearch(type, language, query, include_adult) {
});
})
.catch(console.error);
await moviedb.searchPerson({ query, language }).then(async ({ results }) => {
if (results[0]) {
await moviedb.searchPerson({ query, language }).then(async (res) => {
if (res.results[0]) {
await moviedb
.personTvCredits({ id: results[0].id, language })
.then(({ cast, crew }) => {
cast.map((el) => {
.personTvCredits({ id: res.results[0].id, language })
.then((credits) => {
credits.cast.map((el) => {
if (el.episode_count >= 5) {
if (!searchTv.find(({ id }) => id === `tmdb:${el.id}`)) {
if (!searchTv.find((meta) => meta.id === `tmdb:${el.id}`)) {
searchTv.push({
id: `tmdb:${el.id}`,
name: `${el.name}`,
@@ -93,9 +93,9 @@ async function getSearch(type, language, query, include_adult) {
}
}
});
crew.map((el) => {
credits.crew.map((el) => {
if (el.job === "Director" || "Writer") {
if (!searchTv.find(({ id }) => id === `tmdb:${el.id}`)) {
if (!searchTv.find((meta) => meta.id === `tmdb:${el.id}`)) {
searchTv.push({
id: `tmdb:${el.id}`,
name: `${el.name}`,
@@ -111,8 +111,8 @@ async function getSearch(type, language, query, include_adult) {
}
});
const sortMetas = searchTv.sort((a, b) => b.popularity - a.popularity);
return Promise.resolve({ query, metas: sortMetas });
return Promise.resolve({query, metas: sortMetas });
}
}
export default getSearch;
module.exports = { getSearch };
+20 -12
View File
@@ -1,21 +1,29 @@
import 'dotenv/config';
import { MovieDb } from 'moviedb-promise';
const moviedb = new MovieDb(process.env.tmdb_api)
require('dotenv').config()
const { MovieDb } = require('moviedb-promise')
const moviedb = new MovieDb(process.env.TMDB_API)
async function getTmdb(type, imdbId) {
if (type === "movie") {
const tmdbId = await moviedb
.find({ id: imdbId, external_source: 'imdb_id' })
.then(({ movie_results }) => movie_results[0] ? movie_results[0].id : null)
.catch(err => null);
return tmdbId;
.find({id: imdbId, external_source: 'imdb_id'})
.then((res) => {
return res.movie_results[0] ? res.movie_results[0].id : null;
})
.catch(err => {
return null
});
return tmdbId;
} else {
const tmdbId = await moviedb
.find({ id: imdbId, external_source: 'imdb_id' })
.then(({ tv_results }) => tv_results[0] ? tv_results[0].id : null)
.catch(err => null);
return tmdbId;
.find({id: imdbId, external_source: 'imdb_id'})
.then((res) => {
return res.tv_results[0] ? res.tv_results[0].id : null;
})
.catch(err => {
return null
});
return tmdbId;
}
}
export default getTmdb;
module.exports = { getTmdb };
+11 -8
View File
@@ -1,7 +1,8 @@
import "dotenv/config"
import { MovieDb } from "moviedb-promise";
const moviedb = new MovieDb(process.env.tmdb_api);
import getMeta from "./getMeta.js";
require("dotenv").config();
const { MovieDb } = require("moviedb-promise");
const moviedb = new MovieDb(process.env.TMDB_API);
const { cacheWrapMeta } = require("./getCache");
const { getMeta } = require("./getMeta");
async function getTrending(type, id, language, genre, page, include_adult) {
const parameters = {
@@ -13,10 +14,12 @@ async function getTrending(type, id, language, genre, page, include_adult) {
};
return await moviedb
.trending(parameters)
.then(async ({ results }) => {
.then(async (res) => {
const metas = await Promise.all(
results.map(async (el) => {
const meta = await getMeta(type, language, el.id);
res.results.map(async (el) => {
const meta = await cacheWrapMeta(`${language}:${type}:${el.id}`, async () => {
return await getMeta(type, language, el.id);
});
return meta.meta;
})
);
@@ -25,4 +28,4 @@ async function getTrending(type, id, language, genre, page, include_adult) {
.catch(console.error);
}
export default getTrending;
module.exports = { getTrending };
+1034 -280
View File
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -1,15 +1,16 @@
{
"name": "tmdb-addon",
"version": "3.0.11",
"version": "3.0.10",
"description": "Metadata provided by TMDB",
"main": "server.js",
"type": "module",
"dependencies": {
"cache-manager": "^3.6.3",
"cache-manager-mongodb": "^0.3.0",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"fanart.tv-api": "^2.0.1",
"moviedb-promise": "^4.0.0",
"url-exist": "^3.0.1"
"moviedb-promise": "^3.4.1",
"url-exists": "^1.0.3"
},
"scripts": {
"dev": "nodemon server.js",
+2 -3
View File
@@ -1,10 +1,9 @@
// require serverless version
import addon from './index.js';
const addon = require('./index.js')
const PORT = process.env.PORT || 7000
// create local server
addon.listen(PORT, () => {
addon.listen(PORT, function () {
console.log(`Addon active on port ${PORT}.`);
console.log(`http://127.0.0.1:${PORT}/`);
});
+95 -63
View File
@@ -1,23 +1,29 @@
function parseCertification({results}, language) {
return results.filter(
({iso_3166_1}) => iso_3166_1 == language.split("-")[1]
function parseCertification(release_dates, language) {
return release_dates.results.filter(
(releases) => releases.iso_3166_1 == language.split("-")[1]
)[0].release_dates[0].certification;
}
function parseCast({cast}) {
return cast.slice(0, 4).map(({name}) => name);
function parseCast(credits) {
return credits.cast.slice(0, 4).map((el) => {
return el.name;
});
}
function parseDirector({crew}) {
return crew
.filter(({job}) => job === "Director")
.map(({name}) => name);
function parseDirector(credits) {
return credits.crew
.filter((x) => x.job === "Director")
.map((el) => {
return el.name;
});
}
function parseWriter({crew}) {
return crew
.filter(({job}) => job === "Writer")
.map(({name}) => name);
function parseWriter(credits) {
return credits.crew
.filter((x) => x.job === "Writer")
.map((el) => {
return el.name;
});
}
function parseSlug(type, title, imdb_id) {
@@ -26,24 +32,28 @@ function parseSlug(type, title, imdb_id) {
}`;
}
function parseTrailers({results}) {
return results
.filter(({site}) => site === "YouTube")
.filter(({type}) => type === "Trailer")
.map(({key, type}) => ({
source: `${key}`,
type: `${type}`
}));
function parseTrailers(videos) {
return videos.results
.filter((el) => el.site === "YouTube")
.filter((el) => el.type === "Trailer")
.map((el) => {
return {
source: `${el.key}`,
type: `${el.type}`,
};
});
}
function parseTrailerStream({results}) {
return results
.filter(({site}) => site === "YouTube")
.filter(({type}) => type === "Trailer")
.map(({name, key}) => ({
title: `${name}`,
ytId: `${key}`
}));
function parseTrailerStream(videos) {
return videos.results
.filter((el) => el.site === "YouTube")
.filter((el) => el.type === "Trailer")
.map((el) => {
return {
title: `${el.name}`,
ytId: `${el.key}`,
};
});
}
function parseImdbLink(vote_average, imdb_id) {
@@ -63,43 +73,52 @@ function parseShareLink(title, imdb_id, type) {
}
function parseGenreLink(genres, type, language) {
return genres.map(({name}) => ({
name,
category: "Genres",
url: `stremio:///discover/${encodeURIComponent(
process.env.HOST_NAME
)}%2F${language}%2Fmanifest.json/${type}/tmdb.top?genre=${encodeURIComponent(
name
)}`
}));
return genres.map((genre) => {
return {
name: genre.name,
category: "Genres",
url: `stremio:///discover/${encodeURIComponent(
process.env.HOST_NAME
)}%2F${language}%2Fmanifest.json/${type}/tmdb.top?genre=${encodeURIComponent(
genre.name
)}`,
};
});
}
function parseCreditsLink(credits) {
const Cast = parseCast(credits).map(actor => ({
name: actor,
category: "Cast",
url: `stremio:///search?search=${encodeURIComponent(actor)}`
}));
const Director = parseDirector(credits).map(director => ({
name: director,
category: "Directors",
url: `stremio:///search?search=${encodeURIComponent(director)}`
}));
const Writer = parseWriter(credits).map(writer => ({
name: writer,
category: "Writers",
url: `stremio:///search?search=${encodeURIComponent(writer)}`
}));
const Cast = parseCast(credits).map((actor) => {
return {
name: actor,
category: "Cast",
url: `stremio:///search?search=${encodeURIComponent(actor)}`,
};
});
const Director = parseDirector(credits).map((director) => {
return {
name: director,
category: "Directors",
url: `stremio:///search?search=${encodeURIComponent(director)}`,
};
});
const Writer = parseWriter(credits).map((writer) => {
return {
name: writer,
category: "Writers",
url: `stremio:///search?search=${encodeURIComponent(writer)}`,
};
});
return new Array(...Cast, ...Director, ...Writer);
}
function parseCoutry(production_countries) {
return production_countries.map(({name}) => name).join(", ");
return production_countries.map((country) => country.name).join(", ");
}
function parseGenres(genres) {
return genres.map(({name}) => name);
return genres.map((el) => {
return el.name;
});
}
function parseYear(status, first_air_date, last_air_date) {
@@ -114,16 +133,16 @@ function parseYear(status, first_air_date, last_air_date) {
function parseRunTime(runtime) {
if (runtime) {
const hours = runtime / 60;
const rhours = Math.floor(hours);
const minutes = (hours - rhours) * 60;
const rminutes = Math.round(minutes);
return rhours > 0 ? `${rhours}h${rminutes}min` : `${rminutes}min`;
var hours = runtime / 60;
var rhours = Math.floor(hours);
var minutes = (hours - rhours) * 60;
var rminutes = Math.round(minutes);
return rhours > 0 ? rhours + "h" + rminutes + "min" : rminutes + "min";
}
}
function parseCreatedBy(created_by) {
return created_by.map(({name}) => name);
return created_by.map((el) => el.name);
}
function parseConfig(catalogChoices) {
@@ -149,7 +168,19 @@ function getRpdbPoster(type, id, language, rpdbkey) {
}
}
export default {
async function checkIfExists(rpdbImage) {
return new Promise((resolve) => {
urlExists(rpdbImage, (err, exists) => {
if (exists) {
resolve(true)
} else {
resolve(false);
}
})
});
}
module.exports = {
parseCertification,
parseCast,
parseDirector,
@@ -168,4 +199,5 @@ export default {
parseCreatedBy,
parseConfig,
getRpdbPoster,
checkIfExists
};