From bc6fe3ed488cf9f083a56d3f2fd4b290a91060c2 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Thu, 16 Jan 2020 21:25:13 +0100 Subject: [PATCH 01/14] Encode search query before searching plex. --- seasoned_api/src/plex/plex.js | 1 + 1 file changed, 1 insertion(+) diff --git a/seasoned_api/src/plex/plex.js b/seasoned_api/src/plex/plex.js index 37207fa..cae536a 100644 --- a/seasoned_api/src/plex/plex.js +++ b/seasoned_api/src/plex/plex.js @@ -67,6 +67,7 @@ class Plex { } search(query) { + query = encodeURIComponent(query) const url = `http://${this.plexIP}:${this.plexPort}/hubs/search?query=${query}` const options = { timeout: 2000, From a4d3123910fd5990c8315a7431b946c7653e8af3 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Thu, 16 Jan 2020 21:25:45 +0100 Subject: [PATCH 02/14] Stricter check for plex search results. --- seasoned_api/src/plex/plex.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seasoned_api/src/plex/plex.js b/seasoned_api/src/plex/plex.js index cae536a..6fe692b 100644 --- a/seasoned_api/src/plex/plex.js +++ b/seasoned_api/src/plex/plex.js @@ -87,8 +87,8 @@ class Plex { } mapResults(response) { - if (response === undefined || response.MediaContainer === undefined) { - console.log('response was not valid to map', response) + if (response == null || response.MediaContainer == null || response.MediaContainer.Hub == null) { + console.log('No results to map in:', response) return [] } From 91f64e5cfbfe511e38e3543a095bbc2b9b6c55ca Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Fri, 21 Feb 2020 18:09:04 +0100 Subject: [PATCH 03/14] Redis new dependency --- seasoned_api/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/seasoned_api/package.json b/seasoned_api/package.json index f313702..8f73d4b 100644 --- a/seasoned_api/package.json +++ b/seasoned_api/package.json @@ -29,6 +29,7 @@ "node-fetch": "^2.6.0", "python-shell": "^0.5.0", "raven": "^2.4.2", + "redis": "^3.0.2", "request": "^2.87.0", "request-promise": "^4.2", "sqlite3": "^4.0.0" From f37786aa764ea29686b21ce1361059500a8681bd Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Fri, 21 Feb 2020 18:11:39 +0100 Subject: [PATCH 04/14] Redis cache script with get and set functions. This replaces old way of caching to sqlite. Still have same functionality, so users of old cache functions just need to rename their import. --- seasoned_api/src/cache/redis.js | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 seasoned_api/src/cache/redis.js diff --git a/seasoned_api/src/cache/redis.js b/seasoned_api/src/cache/redis.js new file mode 100644 index 0000000..c7b1266 --- /dev/null +++ b/seasoned_api/src/cache/redis.js @@ -0,0 +1,46 @@ +const redis = require("redis") +const client = redis.createClient() + +class Cache { + /** + * Retrieve an unexpired cache entry by key. + * @param {String} key of the cache entry + * @returns {Promise} + */ + get(key) { + return new Promise((resolve, reject) => { + client.get(key, (error, reply) => { + if (reply == null) { + reject() + } + + resolve(JSON.parse(reply)) + }) + }) + } + + /** + * Insert cache entry with key and value. + * @param {String} key of the cache entry + * @param {String} value of the cache entry + * @param {Number} timeToLive the number of seconds before entry expires + * @returns {Object} + */ + set(key, value, timeToLive = 10800) { + const json = JSON.stringify(value); + client.set(key, json, (error, reply) => { + if (reply == 'OK') { + + // successfully set value with key, now set TTL for key + client.expire(key, timeToLive, (e) => { + if (e) + console.error('Unexpected error while setting expiration for key:', key, '. Error:', error) + }) + } + }) + + return value + } +} + +module.exports = Cache; From 2672266908b98c3ea4ad0f200092f6fcfc282709 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Fri, 21 Feb 2020 21:47:00 +0100 Subject: [PATCH 05/14] Simplified every function towards tmdb by having the shared functionality separated into a function. --- seasoned_api/src/plex/plex.js | 15 +++- seasoned_api/src/tmdb/tmdb.js | 152 ++++++++++++++++------------------ 2 files changed, 83 insertions(+), 84 deletions(-) diff --git a/seasoned_api/src/plex/plex.js b/seasoned_api/src/plex/plex.js index 6fe692b..01814bd 100644 --- a/seasoned_api/src/plex/plex.js +++ b/seasoned_api/src/plex/plex.js @@ -3,8 +3,10 @@ const convertPlexToMovie = require('src/plex/convertPlexToMovie') const convertPlexToShow = require('src/plex/convertPlexToShow') const convertPlexToEpisode = require('src/plex/convertPlexToEpisode') +const { Movie, Show, Person } = require('src/tmdb/types') -const { Movie, Show, Person } = require('src/tmdb/types'); +const RedisCache = require('src/cache/redis') +const redisCache = new RedisCache() // const { Movie, } // TODO? import class definitions to compare types ? @@ -24,9 +26,14 @@ const matchingYear = (plex, tmdb) => { const sanitize = (string) => string.toLowerCase() class Plex { - constructor(ip, port=32400) { + constructor(ip, port=32400, cache=null) { this.plexIP = ip this.plexPort = port + + this.cache = cache || redisCache; + this.cacheTags = { + search: 's' + } } matchTmdbAndPlexMedia(plex, tmdb) { @@ -37,12 +44,12 @@ class Plex { let yearMatches; if (plex instanceof Array) { - console.log('Plex object to compare is a list.') const plexList = plex - console.log('List of plex objects:', plexList) titleMatches = plexList.map(plexItem => matchingTitleOrName(plexItem, tmdb)) yearMatches = plexList.map(plexItem => matchingYear(plexItem, tmdb)) + titleMatches = titleMatches.includes(true) + yearMatches = yearMatches.includes(true) } else { titleMatches = matchingTitleOrName(plex, tmdb) yearMatches = matchingYear(plex, tmdb) diff --git a/seasoned_api/src/tmdb/tmdb.js b/seasoned_api/src/tmdb/tmdb.js index 3cd68ec..19a8bea 100644 --- a/seasoned_api/src/tmdb/tmdb.js +++ b/seasoned_api/src/tmdb/tmdb.js @@ -1,11 +1,34 @@ const moviedb = require('km-moviedb'); +const RedisCache = require('src/cache/redis') +const redisCache = new RedisCache() const { Movie, Show, Person, Credits, ReleaseDates } = require('src/tmdb/types'); // const { tmdbInfo } = require('src/tmdb/types') +const tmdbErrorResponse = (error, typeString=undefined) => { + if (error.status === 404) { + let message = error.response.body.status_message; + + throw { + status: 404, + message: message.slice(0, -1) + " in tmdb." + } + } else if (error.status === 401) { + throw { + status: 401, + message: error.response.body.status_message + } + } + + throw { + status: 500, + message: `An unexpected error occured while fetching ${typeString} from tmdb` + } +} + class TMDB { constructor(cache, apiKey, tmdbLibrary) { - this.cache = cache; + this.cache = cache || redisCache; this.tmdbLibrary = tmdbLibrary || moviedb(apiKey); this.cacheTags = { multiSearch: 'mus', @@ -26,6 +49,16 @@ class TMDB { miscPopularTvs: 'pt', miscTopRatedTvs: 'trt', }; + this.defaultTTL = 86400 + } + + getFromCacheOrFetchFromTmdb(cacheKey, tmdbMethod, query) { + return new Promise((resolve, reject) => this.cache.get(cacheKey) + .then(resolve) + .catch(() => this.tmdb(tmdbMethod, query)) + .then(resolve) + .catch(error => reject(tmdbErrorResponse(error, tmdbMethod))) + ) } /** @@ -37,12 +70,10 @@ class TMDB { */ movieInfo(identifier) { const query = { id: identifier }; - const cacheKey = `${this.cacheTags.movieInfo}:${identifier}`; + const cacheKey = `tmdb/${this.cacheTags.movieInfo}:${identifier}`; - return this.cache.get(cacheKey) - .catch(() => this.tmdb('movieInfo', query)) - .catch(tmdbError => tmdbErrorResponse(tmdbError, 'movie info')) - .then(movie => this.cache.set(cacheKey, movie, 1)) + return this.getFromCacheOrFetchFromTmdb(cacheKey, 'movieInfo', query) + .then(movie => this.cache.set(cacheKey, movie, this.defaultTTL)) .then(movie => Movie.convertFromTmdbResponse(movie)) } @@ -53,12 +84,10 @@ class TMDB { */ movieCredits(identifier) { const query = { id: identifier } - const cacheKey = `${this.cacheTags.movieCredits}:${identifier}` + const cacheKey = `tmdb/${this.cacheTags.movieCredits}:${identifier}` - return this.cache.get(cacheKey) - .catch(() => this.tmdb('movieCredits', query)) - .catch(tmdbError => tmdbErrorResponse(tmdbError, 'movie credits')) - .then(credits => this.cache.set(cacheKey, credits, 1)) + return this.getFromCacheOrFetchFromTmdb(cacheKey, 'movieCredits', query) + .then(credits => this.cache.set(cacheKey, credits, this.defaultTTL)) .then(credits => Credits.convertFromTmdbResponse(credits)) } @@ -69,12 +98,10 @@ class TMDB { */ movieReleaseDates(identifier) { const query = { id: identifier } - const cacheKey = `${this.cacheTags.movieReleaseDates}:${identifier}` + const cacheKey = `tmdb/${this.cacheTags.movieReleaseDates}:${identifier}` - return this.cache.get(cacheKey) - .catch(() => this.tmdb('movieReleaseDates', query)) - .catch(tmdbError => tmdbErrorResponse(tmdbError, 'movie release dates')) - .then(releaseDates => this.cache.set(cacheKey, releaseDates, 1)) + return this.getFromCacheOrFetchFromTmdb(cacheKey, 'movieReleaseDates', query) + .then(releaseDates => this.cache.set(cacheKey, releaseDates, this.defaultTTL)) .then(releaseDates => ReleaseDates.convertFromTmdbResponse(releaseDates)) } @@ -86,23 +113,19 @@ class TMDB { */ showInfo(identifier) { const query = { id: identifier }; - const cacheKey = `${this.cacheTags.showInfo}:${identifier}`; + const cacheKey = `tmdb/${this.cacheTags.showInfo}:${identifier}`; - return this.cache.get(cacheKey) - .catch(() => this.tmdb('tvInfo', query)) - .catch(tmdbError => tmdbErrorResponse(tmdbError, 'tv info')) - .then(show => this.cache.set(cacheKey, show, 1)) + return this.getFromCacheOrFetchFromTmdb(cacheKey, 'tvInfo', query) + .then(show => this.cache.set(cacheKey, show, this.defaultTTL)) .then(show => Show.convertFromTmdbResponse(show)) } showCredits(identifier) { const query = { id: identifier } - const cacheKey = `${this.cacheTags.showCredits}:${identifier}` + const cacheKey = `tmdb/${this.cacheTags.showCredits}:${identifier}` - return this.cache.get(cacheKey) - .catch(() => this.tmdb('tvCredits', query)) - .catch(tmdbError => tmdbErrorResponse(tmdbError, 'show credits')) - .then(credits => this.cache.set(cacheKey, credits, 1)) + return this.getFromCacheOrFetchFromTmdb(cacheKey, 'tvCredits', query) + .then(credits => this.cache.set(cacheKey, credits, this.defaultTTL)) .then(credits => Credits.convertFromTmdbResponse(credits)) } @@ -114,22 +137,19 @@ class TMDB { */ personInfo(identifier) { const query = { id: identifier }; - const cacheKey = `${this.cacheTags.personInfo}:${identifier}`; + const cacheKey = `tmdb/${this.cacheTags.personInfo}:${identifier}`; - return this.cache.get(cacheKey) - .catch(() => this.tmdb('personInfo', query)) - .catch(tmdbError => tmdbErrorResponse(tmdbError, 'person info')) - .then(person => this.cache.set(cacheKey, person, 1)) + return this.getFromCacheOrFetchFromTmdb(cacheKey, 'personInfo', query) + .then(person => this.cache.set(cacheKey, person, this.defaultTTL)) .then(person => Person.convertFromTmdbResponse(person)) } multiSearch(search_query, page=1) { const query = { query: search_query, page: page }; - const cacheKey = `${this.cacheTags.multiSearch}:${page}:${search_query}`; - return this.cache.get(cacheKey) - .catch(() => this.tmdb('searchMulti', query)) - .catch(tmdbError => tmdbErrorResponse(tmdbError, 'search results')) - .then(response => this.cache.set(cacheKey, response, 1)) + const cacheKey = `tmdb/${this.cacheTags.multiSearch}:${page}:${search_query}`; + + return this.getFromCacheOrFetchFromTmdb(cacheKey, 'searchMulti', query) + .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) .then(response => this.mapResults(response)); } @@ -141,12 +161,10 @@ class TMDB { */ movieSearch(query, page=1) { const tmdbquery = { query: query, page: page }; - const cacheKey = `${this.cacheTags.movieSearch}:${page}:${query}`; + const cacheKey = `tmdb/${this.cacheTags.movieSearch}:${page}:${query}`; - return this.cache.get(cacheKey) - .catch(() => this.tmdb('searchMovie', tmdbquery)) - .catch(tmdbError => tmdbErrorResponse(tmdbError, 'movie search results')) - .then(response => this.cache.set(cacheKey, response, 1)) + return this.getFromCacheOrFetchFromTmdb(cacheKey, 'searchMovie', query) + .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) .then(response => this.mapResults(response, 'movie')) } @@ -158,12 +176,10 @@ class TMDB { */ showSearch(query, page=1) { const tmdbquery = { query: query, page: page }; - const cacheKey = `${this.cacheTags.showSearch}:${page}:${query}`; + const cacheKey = `tmdb/${this.cacheTags.showSearch}:${page}:${query}`; - return this.cache.get(cacheKey) - .catch(() => this.tmdb('searchTv', tmdbquery)) - .catch(tmdbError => tmdbErrorResponse(tmdbError, 'tv search results')) - .then(response => this.cache.set(cacheKey, response, 1)) + return this.getFromCacheOrFetchFromTmdb(cacheKey, 'searchTv', query) + .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) .then(response => this.mapResults(response, 'show')) } @@ -176,33 +192,28 @@ class TMDB { personSearch(query, page=1) { const tmdbquery = { query: query, page: page, include_adult: true }; - const cacheKey = `${this.cacheTags.personSearch}:${page}:${query}`; + const cacheKey = `tmdb/${this.cacheTags.personSearch}:${page}:${query}`; - return this.cache.get(cacheKey) - .catch(() => this.tmdb('searchPerson', tmdbquery)) - .catch(tmdbError => tmdbErrorResponse(tmdbError, 'person search results')) - .then(response => this.cache.set(cacheKey, response, 1)) + return this.getFromCacheOrFetchFromTmdb(cacheKey, 'searchPerson', query) + .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) .then(response => this.mapResults(response, 'person')) } movieList(listname, page = 1) { const query = { page: page }; - const cacheKey = `${this.cacheTags[listname]}:${page}`; - return this.cache.get(cacheKey) - .catch(() => this.tmdb(listname, query)) - .catch(tmdbError => this.tmdbErrorResponse(tmdbError, 'movie list ' + listname)) - .then(response => this.cache.set(cacheKey, response, 1)) + const cacheKey = `tmdb/${this.cacheTags[listname]}:${page}`; + + return this.getFromCacheOrFetchFromTmdb(cacheKey, listname, query) + .then(response => this.cache.set(cacheKey, response, 10800)) .then(response => this.mapResults(response, 'movie')) } showList(listname, page = 1) { const query = { page: page }; - const cacheKey = `${this.cacheTags[listname]}:${page}`; + const cacheKey = `tmdb/${this.cacheTags[listname]}:${page}`; - return this.cache.get(cacheKey) - .catch(() => this.tmdb(listname, query)) - .catch(tmdbError => this.tmdbErrorResponse(tmdbError, 'show list ' + listname)) - .then(response => this.cache.set(cacheKey, response, 1)) + return this.getFromCacheOrFetchFromTmdb(cacheKey, listName, query) + .then(response => this.cache.set(cacheKey, response, 10800)) .then(response => this.mapResults(response, 'show')) } @@ -262,25 +273,6 @@ class TMDB { } -function tmdbErrorResponse(error, typeString=undefined) { - if (error.status === 404) { - let message = error.response.body.status_message; - throw { - status: 404, - message: message.slice(0, -1) + " in tmdb." - } - } else if (error.status === 401) { - throw { - status: 401, - message: error.response.body.status_message - } - } - - throw { - status: 500, - message: `An unexpected error occured while fetching ${typeString} from tmdb` - } -} module.exports = TMDB; From 74340afd16f5689be29cf38031d80598811faa89 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Fri, 21 Feb 2020 21:48:34 +0100 Subject: [PATCH 06/14] Full re-write. Refactored, cache and watchlink. - Now the api calls to plex are cached. - Search function has been refactored. - Exists in plex has been re-written to use findPlexItemByTitleAndYear if anything is found we return true. findPlexItemByTitleAndYear is then also used for our new endpoint to get direct watch link for plex item. Function parameters are title and year. Title is used when querying plex and year is used with title to match correct plex search result. The direct link includes the machine identifier so a function was added to get system information from plex (read: 'PLEX_URL/' e.g. base path). --- seasoned_api/src/plex/plex.js | 184 ++++++++++++++++++++++------------ 1 file changed, 121 insertions(+), 63 deletions(-) diff --git a/seasoned_api/src/plex/plex.js b/seasoned_api/src/plex/plex.js index 01814bd..403d15a 100644 --- a/seasoned_api/src/plex/plex.js +++ b/seasoned_api/src/plex/plex.js @@ -12,19 +12,35 @@ const redisCache = new RedisCache() // TODO? import class definitions to compare types ? // what would typescript do? -const matchingTitleOrName = (plex, tmdb) => { - if (plex['title'] !== undefined && tmdb['title'] !== undefined) - return sanitize(plex.title) === sanitize(tmdb.title) - - return false -} - -const matchingYear = (plex, tmdb) => { - return plex.year === tmdb.year -} - const sanitize = (string) => string.toLowerCase() +const matchingTitleAndYear = (plex, tmdb) => { + let matchingTitle, matchingYear; + + if (plex['title'] != null && tmdb['title'] != null) + matchingTitle = sanitize(plex.title) == sanitize(tmdb.title); + else + matchingTitle = false; + + if (plex['year'] != null && tmdb['year'] != null) + matchingYear = plex.year == tmdb.year; + else + matchingYear = false; + + return matchingTitle && matchingYear +} + +const successfullResponse = (response) => { + const { status, statusText } = response + + if (status === 200) { + return response.json() + } else { + throw { message: statusText, status: status } + } +} + + class Plex { constructor(ip, port=32400, cache=null) { this.plexIP = ip @@ -32,65 +48,110 @@ class Plex { this.cache = cache || redisCache; this.cacheTags = { + machineInfo: 'mi', search: 's' } } - matchTmdbAndPlexMedia(plex, tmdb) { - if (plex === undefined || tmdb === undefined) - return false - - let titleMatches; - let yearMatches; - - if (plex instanceof Array) { - const plexList = plex - - titleMatches = plexList.map(plexItem => matchingTitleOrName(plexItem, tmdb)) - yearMatches = plexList.map(plexItem => matchingYear(plexItem, tmdb)) - titleMatches = titleMatches.includes(true) - yearMatches = yearMatches.includes(true) - } else { - titleMatches = matchingTitleOrName(plex, tmdb) - yearMatches = matchingYear(plex, tmdb) - } - - return titleMatches && yearMatches - } - - existsInPlex(tmdbMovie) { - return this.search(tmdbMovie.title) - .then(plexMovies => plexMovies.some(plex => this.matchTmdbAndPlexMedia(plex, tmdbMovie))) - } - - successfullResponse(response) { - const { status, statusText } = response - - if (status === 200) { - return response.json() - } else { - throw { message: statusText, status: status } - } - } - - search(query) { - query = encodeURIComponent(query) - const url = `http://${this.plexIP}:${this.plexPort}/hubs/search?query=${query}` + fetchMachineIdentifier() { + const cacheKey = `plex/${this.cacheTags.machineInfo}` + const url = `http://${this.plexIP}:${this.plexPort}/` const options = { - timeout: 2000, + timeout: 20000, headers: { 'Accept': 'application/json' } } - return fetch(url, options) - .then(this.successfullResponse) - .then(this.mapResults) + return new Promise((resolve, reject) => this.cache.get(cacheKey) + .then(machineInfo => resolve(machineInfo['machineIdentifier'])) + .catch(() => fetch(url, options)) + .then(response => response.json()) + .then(machineInfo => this.cache.set(cacheKey, machineInfo['MediaContainer'], 2628000)) + .then(machineInfo => resolve(machineInfo['machineIdentifier'])) .catch(error => { - if (error.type === 'request-timeout') { - throw { message: 'Plex did not respond', status: 408, success: false } + if (error != undefined && error.type === 'request-timeout') { + reject({ message: 'Plex did not respond', status: 408, success: false }) } - throw error + reject(error) }) + ) + } + + matchTmdbAndPlexMedia(plex, tmdb) { + let match; + + if (plex == null || tmdb == null) + return false + + if (plex instanceof Array) { + let possibleMatches = plex.map(plexItem => matchingTitleAndYear(plexItem, tmdb)) + match = possibleMatches.includes(true) + } else { + match = matchingTitleAndYear(plex, tmdb) + } + + return match + } + + existsInPlex(tmdb) { + const plexMatch = this.findPlexItemByTitleAndYear(tmdb.title, tmdb.year) + return plexMatch ? true : false + } + + + findPlexItemByTitleAndYear(title, year) { + const query = { title, year } + + return this.search(query.title) + .then(plexSearchResults => { + const matchesInPlex = plexSearchResults.map(plex => this.matchTmdbAndPlexMedia(plex, query)) + + if (matchesInPlex.includes(true) === false) + return false; + + const firstMatchIndex = matchesInPlex.indexOf(true) + return plexSearchResults[firstMatchIndex][0] + }) + } + + getDirectLinkByTitleAndYear(title, year) { + const machineIdentifierPromise = this.fetchMachineIdentifier() + const matchingObjectInPlexPromise = this.findPlexItemByTitleAndYear(title, year) + + return Promise.all([machineIdentifierPromise, matchingObjectInPlexPromise]) + .then(([machineIdentifier, matchingObjectInPlex]) => { + if (matchingObjectInPlex == false || matchingObjectInPlex == null || + matchingObjectInPlex['key'] == null || machineIdentifier == null) + return false + + const keyUriComponent = encodeURIComponent(matchingObjectInPlex.key) + return `https://app.plex.tv/desktop#!/server/${machineIdentifier}/details?key=${keyUriComponent}` + }) + } + + search(query) { + const cacheKey = `plex/${this.cacheTags.search}:${query}` + const url = `http://${this.plexIP}:${this.plexPort}/hubs/search?query=${query}` + const options = { + timeout: 20000, + headers: { 'Accept': 'application/json' } + } + + return new Promise((resolve, reject) => this.cache.get(cacheKey) + .then(resolve) // if found in cache resolve + .catch(() => fetch(url, options)) // else fetch fresh data + .then(successfullResponse) + .then(this.mapResults) + .then(results => this.cache.set(cacheKey, results, 600)) + .then(resolve) + .catch(error => { + if (error != undefined && error.type === 'request-timeout') { + reject({ message: 'Plex did not respond', status: 408, success: false }) + } + + reject(error) + }) + ) } mapResults(response) { @@ -103,10 +164,7 @@ class Plex { .filter(category => category.size > 0) .map(category => { if (category.type === 'movie') { - return category.Metadata.map(movie => { - const ovie = Movie.convertFromPlexResponse(movie) - return ovie.createJsonResponse() - }) + return category.Metadata } else if (category.type === 'show') { return category.Metadata.map(convertPlexToShow) } else if (category.type === 'episode') { @@ -114,7 +172,7 @@ class Plex { } }) .filter(result => result !== undefined) - .flat() +// .flat() } } From aa4a1c2a576e4e4fff38b6faec882db1716d1a31 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Fri, 21 Feb 2020 21:53:51 +0100 Subject: [PATCH 07/14] Registed route watch-link, by title & year Fetch watch link for plex item matching query parameters title and year. --- seasoned_api/src/webserver/app.js | 2 ++ .../controllers/plex/watchDirectLink.js | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 seasoned_api/src/webserver/controllers/plex/watchDirectLink.js diff --git a/seasoned_api/src/webserver/app.js b/seasoned_api/src/webserver/app.js index bbe61c1..2eee898 100644 --- a/seasoned_api/src/webserver/app.js +++ b/seasoned_api/src/webserver/app.js @@ -113,6 +113,8 @@ router.get('/v1/plex/request/:mediaId', require('./controllers/plex/readRequest. router.post('/v1/plex/request/:mediaId', require('./controllers/plex/submitRequest.js')); router.post('/v1/plex/hook', require('./controllers/plex/hookDump.js')); +router.get('/v1/plex/watch-link', mustBeAuthenticated, require('./controllers/plex/watchDirectLink.js')); + /** * Requests */ diff --git a/seasoned_api/src/webserver/controllers/plex/watchDirectLink.js b/seasoned_api/src/webserver/controllers/plex/watchDirectLink.js new file mode 100644 index 0000000..0020ba7 --- /dev/null +++ b/seasoned_api/src/webserver/controllers/plex/watchDirectLink.js @@ -0,0 +1,27 @@ +const configuration = require('src/config/configuration').getInstance(); +const Plex = require('src/plex/plex'); +const plex = new Plex(configuration.get('plex', 'ip')); + +/** + * Controller: Search plex for movies, shows and episodes by query + * @param {Request} req http request variable + * @param {Response} res + * @returns {Callback} + */ + +function watchDirectLink (req, res) { + const { title, year } = req.query; + + plex.getDirectLinkByTitleAndYear(title, year) + .then(plexDirectLink => { + if (plexDirectLink == false) + res.status(404).send({ success: true, link: null }) + else + res.status(200).send({ success: true, link: plexDirectLink }) + }) + .catch(error => { + res.status(500).send({ success: false, message: error.message }); + }); +} + +module.exports = watchDirectLink; From 085fb76e11edbd3a0b61c99d6a52b6d57fb657ce Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Fri, 21 Feb 2020 22:09:42 +0100 Subject: [PATCH 08/14] Cache pirate respons for 3 hours in redis. --- seasoned_api/src/pirate/pirateRepository.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/seasoned_api/src/pirate/pirateRepository.js b/seasoned_api/src/pirate/pirateRepository.js index 031f780..9373e01 100644 --- a/seasoned_api/src/pirate/pirateRepository.js +++ b/seasoned_api/src/pirate/pirateRepository.js @@ -5,6 +5,9 @@ const PythonShell = require('python-shell'); const establishedDatabase = require('src/database/database'); +const RedisCache = require('src/cache/redis') +const cache = new RedisCache() + function getMagnetFromURL(url) { return new Promise((resolve, reject) => { const options = new URL(url); @@ -49,15 +52,23 @@ async function callPythonAddMagnet(url, callback) { } async function SearchPiratebay(query) { - return await new Promise((resolve, reject) => find(query, (err, results) => { + const cacheKey = `pirate/${query}` + + return new Promise((resolve, reject) => cache.get(cacheKey) + .then(resolve) + .catch(() => find(query, (err, results) => { if (err) { - console.log('THERE WAS A FUCKING ERROR!\n', err); - reject(Error('There was a error when searching for torrents')); + console.log('THERE WAS A FUCKING ERROR!\n', err); + reject(Error('There was a error when searching for torrents')); } + if (results) { - resolve(JSON.parse(results, null, '\t')); + const jsonData = JSON.parse(results, null, '\t') + cache.set(cacheKey, jsonData) + resolve(jsonData); } - })); + })) + ); } async function AddMagnet(magnet, name, tmdb_id) { From f89db46bf29033a9628d8b6be0d50002c325432b Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Fri, 21 Feb 2020 23:09:42 +0100 Subject: [PATCH 09/14] findPlexItemByTitleAndYear returns a promise so we await its response. --- seasoned_api/src/plex/plex.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seasoned_api/src/plex/plex.js b/seasoned_api/src/plex/plex.js index 403d15a..4b5ef09 100644 --- a/seasoned_api/src/plex/plex.js +++ b/seasoned_api/src/plex/plex.js @@ -93,8 +93,8 @@ class Plex { return match } - existsInPlex(tmdb) { - const plexMatch = this.findPlexItemByTitleAndYear(tmdb.title, tmdb.year) + async existsInPlex(tmdb) { + const plexMatch = await this.findPlexItemByTitleAndYear(tmdb.title, tmdb.year) return plexMatch ? true : false } From 943cbe5cb8e1ca0d2fc10dd04d6c300d60e34da3 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 8 Apr 2020 21:57:49 +0200 Subject: [PATCH 10/14] Return rejected promise and don't set cache if key or value is null. --- seasoned_api/src/cache/redis.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/seasoned_api/src/cache/redis.js b/seasoned_api/src/cache/redis.js index c7b1266..df206bb 100644 --- a/seasoned_api/src/cache/redis.js +++ b/seasoned_api/src/cache/redis.js @@ -11,7 +11,7 @@ class Cache { return new Promise((resolve, reject) => { client.get(key, (error, reply) => { if (reply == null) { - reject() + return reject() } resolve(JSON.parse(reply)) @@ -27,6 +27,9 @@ class Cache { * @returns {Object} */ set(key, value, timeToLive = 10800) { + if (value == null || key == null) + return null + const json = JSON.stringify(value); client.set(key, json, (error, reply) => { if (reply == 'OK') { From 578eff30fb84deab63657e6039a5352987e4bf95 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 8 Apr 2020 21:58:37 +0200 Subject: [PATCH 11/14] Id of request has been incorrectly saved as string, this has dictated the returntype to the frontend. Now set from string to int. --- seasoned_api/src/database/schemas/setup.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/database/schemas/setup.sql b/seasoned_api/src/database/schemas/setup.sql index 015d356..0dfc9c6 100644 --- a/seasoned_api/src/database/schemas/setup.sql +++ b/seasoned_api/src/database/schemas/setup.sql @@ -31,7 +31,7 @@ CREATE TABLE IF NOT EXISTS search_history ( ); CREATE TABLE IF NOT EXISTS requests( - id TEXT, + id NUMBER, title TEXT, year NUMBER, poster_path TEXT DEFAULT NULL, From 815aaedffb8deac773b0c2f23daeab1c37c49dca Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 8 Apr 2020 22:54:19 +0200 Subject: [PATCH 12/14] Changed tmdb constructor to have apiKey as first parameter. If cache is not defined we use redis. --- seasoned_api/src/tmdb/tmdb.js | 5 +++-- .../src/webserver/controllers/list/listController.js | 4 +--- seasoned_api/src/webserver/controllers/movie/credits.js | 6 ++---- seasoned_api/src/webserver/controllers/movie/info.js | 4 +--- .../src/webserver/controllers/movie/releaseDates.js | 6 ++---- seasoned_api/src/webserver/controllers/person/info.js | 4 +--- .../src/webserver/controllers/search/movieSearch.js | 4 +--- .../src/webserver/controllers/search/multiSearch.js | 4 +--- .../src/webserver/controllers/search/personSearch.js | 4 +--- .../src/webserver/controllers/search/showSearch.js | 4 +--- seasoned_api/src/webserver/controllers/show/credits.js | 7 ++----- seasoned_api/src/webserver/controllers/show/info.js | 4 +--- 12 files changed, 17 insertions(+), 39 deletions(-) diff --git a/seasoned_api/src/tmdb/tmdb.js b/seasoned_api/src/tmdb/tmdb.js index 19a8bea..1e6a8cc 100644 --- a/seasoned_api/src/tmdb/tmdb.js +++ b/seasoned_api/src/tmdb/tmdb.js @@ -27,9 +27,10 @@ const tmdbErrorResponse = (error, typeString=undefined) => { } class TMDB { - constructor(cache, apiKey, tmdbLibrary) { - this.cache = cache || redisCache; + constructor(apiKey, cache, tmdbLibrary) { this.tmdbLibrary = tmdbLibrary || moviedb(apiKey); + + this.cache = cache || redisCache; this.cacheTags = { multiSearch: 'mus', movieSearch: 'mos', diff --git a/seasoned_api/src/webserver/controllers/list/listController.js b/seasoned_api/src/webserver/controllers/list/listController.js index 4e7806f..db71722 100644 --- a/seasoned_api/src/webserver/controllers/list/listController.js +++ b/seasoned_api/src/webserver/controllers/list/listController.js @@ -1,8 +1,6 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); // there should be a translate function from query params to // tmdb list that is valid. Should it be a helper function or does it diff --git a/seasoned_api/src/webserver/controllers/movie/credits.js b/seasoned_api/src/webserver/controllers/movie/credits.js index 542adfc..dbf5ff2 100644 --- a/seasoned_api/src/webserver/controllers/movie/credits.js +++ b/seasoned_api/src/webserver/controllers/movie/credits.js @@ -1,9 +1,7 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const movieCreditsController = (req, res) => { const movieId = req.params.id; @@ -23,4 +21,4 @@ const movieCreditsController = (req, res) => { }) } -module.exports = movieCreditsController; \ No newline at end of file +module.exports = movieCreditsController; diff --git a/seasoned_api/src/webserver/controllers/movie/info.js b/seasoned_api/src/webserver/controllers/movie/info.js index 91d8391..76cbe21 100644 --- a/seasoned_api/src/webserver/controllers/movie/info.js +++ b/seasoned_api/src/webserver/controllers/movie/info.js @@ -1,9 +1,7 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); const Plex = require('src/plex/plex'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const plex = new Plex(configuration.get('plex', 'ip')); function handleError(error, res) { diff --git a/seasoned_api/src/webserver/controllers/movie/releaseDates.js b/seasoned_api/src/webserver/controllers/movie/releaseDates.js index c9797de..4a87c6a 100644 --- a/seasoned_api/src/webserver/controllers/movie/releaseDates.js +++ b/seasoned_api/src/webserver/controllers/movie/releaseDates.js @@ -1,9 +1,7 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const movieReleaseDatesController = (req, res) => { const movieId = req.params.id; @@ -23,4 +21,4 @@ const movieReleaseDatesController = (req, res) => { }) } -module.exports = movieReleaseDatesController; \ No newline at end of file +module.exports = movieReleaseDatesController; diff --git a/seasoned_api/src/webserver/controllers/person/info.js b/seasoned_api/src/webserver/controllers/person/info.js index ea24d7a..1af2654 100644 --- a/seasoned_api/src/webserver/controllers/person/info.js +++ b/seasoned_api/src/webserver/controllers/person/info.js @@ -1,8 +1,6 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); /** * Controller: Retrieve information for a person diff --git a/seasoned_api/src/webserver/controllers/search/movieSearch.js b/seasoned_api/src/webserver/controllers/search/movieSearch.js index e9b7ffa..22b5740 100644 --- a/seasoned_api/src/webserver/controllers/search/movieSearch.js +++ b/seasoned_api/src/webserver/controllers/search/movieSearch.js @@ -1,9 +1,7 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); const SearchHistory = require('src/searchHistory/searchHistory'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const searchHistory = new SearchHistory(); /** diff --git a/seasoned_api/src/webserver/controllers/search/multiSearch.js b/seasoned_api/src/webserver/controllers/search/multiSearch.js index f0a3810..a9cc40a 100644 --- a/seasoned_api/src/webserver/controllers/search/multiSearch.js +++ b/seasoned_api/src/webserver/controllers/search/multiSearch.js @@ -1,9 +1,7 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); const SearchHistory = require('src/searchHistory/searchHistory'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const searchHistory = new SearchHistory(); function checkAndCreateJsonResponse(result) { diff --git a/seasoned_api/src/webserver/controllers/search/personSearch.js b/seasoned_api/src/webserver/controllers/search/personSearch.js index dcb7b2a..88d7989 100644 --- a/seasoned_api/src/webserver/controllers/search/personSearch.js +++ b/seasoned_api/src/webserver/controllers/search/personSearch.js @@ -1,9 +1,7 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); const SearchHistory = require('src/searchHistory/searchHistory'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const searchHistory = new SearchHistory(); /** diff --git a/seasoned_api/src/webserver/controllers/search/showSearch.js b/seasoned_api/src/webserver/controllers/search/showSearch.js index fc77cae..b2d81b6 100644 --- a/seasoned_api/src/webserver/controllers/search/showSearch.js +++ b/seasoned_api/src/webserver/controllers/search/showSearch.js @@ -1,9 +1,7 @@ const SearchHistory = require('src/searchHistory/searchHistory'); const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const searchHistory = new SearchHistory(); /** diff --git a/seasoned_api/src/webserver/controllers/show/credits.js b/seasoned_api/src/webserver/controllers/show/credits.js index 7974f1f..f146391 100644 --- a/seasoned_api/src/webserver/controllers/show/credits.js +++ b/seasoned_api/src/webserver/controllers/show/credits.js @@ -1,9 +1,6 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); - -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const showCreditsController = (req, res) => { const showId = req.params.id; @@ -23,4 +20,4 @@ const showCreditsController = (req, res) => { }) } -module.exports = showCreditsController; \ No newline at end of file +module.exports = showCreditsController; diff --git a/seasoned_api/src/webserver/controllers/show/info.js b/seasoned_api/src/webserver/controllers/show/info.js index e335b15..340dc8b 100644 --- a/seasoned_api/src/webserver/controllers/show/info.js +++ b/seasoned_api/src/webserver/controllers/show/info.js @@ -1,9 +1,7 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); const Plex = require('src/plex/plex'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const plex = new Plex(configuration.get('plex', 'ip')); function handleError(error, res) { From 776f83553ac7455b254e9c05a860c1eaa32644f8 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 8 Apr 2020 22:59:23 +0200 Subject: [PATCH 13/14] Changed more instances of tmdb to new TMDB constructor not needing cache instance anymore. --- seasoned_api/src/plex/requestRepository.js | 4 +--- seasoned_api/src/request/request.js | 4 +--- seasoned_api/src/webserver/controllers/plex/submitRequest.js | 5 +---- .../src/webserver/controllers/request/requestTmdbId.js | 4 +--- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index 28e4d9a..01f2558 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -1,12 +1,10 @@ const PlexRepository = require('src/plex/plexRepository'); -const Cache = require('src/tmdb/cache'); const configuration = require('src/config/configuration').getInstance(); const TMDB = require('src/tmdb/tmdb'); const establishedDatabase = require('src/database/database'); const plexRepository = new PlexRepository(configuration.get('plex', 'ip')); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); class RequestRepository { constructor(database) { diff --git a/seasoned_api/src/request/request.js b/seasoned_api/src/request/request.js index 43fe112..79a15ba 100644 --- a/seasoned_api/src/request/request.js +++ b/seasoned_api/src/request/request.js @@ -1,9 +1,7 @@ const assert = require('assert') const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const establishedDatabase = require('src/database/database'); const utils = require('./utils'); diff --git a/seasoned_api/src/webserver/controllers/plex/submitRequest.js b/seasoned_api/src/webserver/controllers/plex/submitRequest.js index a86aaa2..febaf1a 100644 --- a/seasoned_api/src/webserver/controllers/plex/submitRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/submitRequest.js @@ -1,10 +1,7 @@ const configuration = require('src/config/configuration').getInstance() const RequestRepository = require('src/request/request'); -const Cache = require('src/tmdb/cache') const TMDB = require('src/tmdb/tmdb') - -const cache = new Cache() -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')) +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')) const request = new RequestRepository() const tmdbMovieInfo = (id) => { diff --git a/seasoned_api/src/webserver/controllers/request/requestTmdbId.js b/seasoned_api/src/webserver/controllers/request/requestTmdbId.js index 016accb..09d55f4 100644 --- a/seasoned_api/src/webserver/controllers/request/requestTmdbId.js +++ b/seasoned_api/src/webserver/controllers/request/requestTmdbId.js @@ -1,9 +1,7 @@ const configuration = require('src/config/configuration').getInstance(); -const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); const RequestRepository = require('src/request/request'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); const request = new RequestRepository(); const tmdbMovieInfo = (id) => { From 2b2539725395ce9fbf0d497087b366e7b6c482a4 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 8 Apr 2020 23:01:33 +0200 Subject: [PATCH 14/14] Misc updates to caching from plex and tmdb. --- seasoned_api/src/plex/plex.js | 13 +++++++------ seasoned_api/src/tmdb/tmdb.js | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/seasoned_api/src/plex/plex.js b/seasoned_api/src/plex/plex.js index 4b5ef09..3659de3 100644 --- a/seasoned_api/src/plex/plex.js +++ b/seasoned_api/src/plex/plex.js @@ -48,13 +48,13 @@ class Plex { this.cache = cache || redisCache; this.cacheTags = { - machineInfo: 'mi', - search: 's' + machineInfo: 'plex/mi', + search: 'plex/s' } } fetchMachineIdentifier() { - const cacheKey = `plex/${this.cacheTags.machineInfo}` + const cacheKey = `${this.cacheTags.machineInfo}` const url = `http://${this.plexIP}:${this.plexPort}/` const options = { timeout: 20000, @@ -130,8 +130,9 @@ class Plex { } search(query) { - const cacheKey = `plex/${this.cacheTags.search}:${query}` - const url = `http://${this.plexIP}:${this.plexPort}/hubs/search?query=${query}` + const cacheKey = `${this.cacheTags.search}:${query}` + + const url = `http://${this.plexIP}:${this.plexPort}/hubs/search?query=${encodeURIComponent(query)}` const options = { timeout: 20000, headers: { 'Accept': 'application/json' } @@ -141,8 +142,8 @@ class Plex { .then(resolve) // if found in cache resolve .catch(() => fetch(url, options)) // else fetch fresh data .then(successfullResponse) + .then(results => this.cache.set(cacheKey, results, 21600)) .then(this.mapResults) - .then(results => this.cache.set(cacheKey, results, 600)) .then(resolve) .catch(error => { if (error != undefined && error.type === 'request-timeout') { diff --git a/seasoned_api/src/tmdb/tmdb.js b/seasoned_api/src/tmdb/tmdb.js index 1e6a8cc..4f03dcc 100644 --- a/seasoned_api/src/tmdb/tmdb.js +++ b/seasoned_api/src/tmdb/tmdb.js @@ -205,7 +205,7 @@ class TMDB { const cacheKey = `tmdb/${this.cacheTags[listname]}:${page}`; return this.getFromCacheOrFetchFromTmdb(cacheKey, listname, query) - .then(response => this.cache.set(cacheKey, response, 10800)) + .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) .then(response => this.mapResults(response, 'movie')) } @@ -214,7 +214,7 @@ class TMDB { const cacheKey = `tmdb/${this.cacheTags[listname]}:${page}`; return this.getFromCacheOrFetchFromTmdb(cacheKey, listName, query) - .then(response => this.cache.set(cacheKey, response, 10800)) + .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) .then(response => this.mapResults(response, 'show')) }