From b82efddeba714816ba072f1cd62f8cb3e01754fd Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 14:08:36 +0200 Subject: [PATCH 01/18] Now tmdb searches also check cache for a matching query request, if so returns it. --- seasoned_api/src/tmdb/tmdb.js | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/seasoned_api/src/tmdb/tmdb.js b/seasoned_api/src/tmdb/tmdb.js index d876287..872880b 100644 --- a/seasoned_api/src/tmdb/tmdb.js +++ b/seasoned_api/src/tmdb/tmdb.js @@ -7,8 +7,19 @@ var methodTypes = { 'movie': 'searchMovie', 'show': 'searchTv', 'multi': 'search 'showSimilar': 'tvSimilar' }; class TMDB { - constructor(apiKey, tmdbLibrary) { + constructor(cache, apiKey, tmdbLibrary) { + this.cache = cache this.tmdbLibrary = tmdbLibrary || moviedb(apiKey); + this.cacheTags = { + 'search': 'se', + 'discover': 'd', + 'popular': 'p', + 'nowplaying': 'n', + 'upcoming': 'u', + 'similar': 'si', + 'lookup': 'l' + + } } /** @@ -16,22 +27,21 @@ class TMDB { * @param {queryText, page, type} the page number to specify in the request for discover, * @returns {Promise} dict with query results, current page and total_pages */ - search(queryText, page = 1, type = 'multi') { - // Setup query object for tmdb api search - const query = { 'query': queryText, 'page': page }; + search(text, page = 1, type = 'multi') { + const query = { 'query': text, 'page': page }; + const cacheKey = `${this.cacheTags.search}${page}:${type}:${text}`; return Promise.resolve() - .then(() => this.tmdb(type, query)) // Search the tmdb api - .catch(() => { throw new Error('Could not search for movies.'); }) // If any error at all when fetching + .then(() => this.cache.get(cacheKey)) + .catch(() => this.tmdb(type, query)) + .catch(() => { throw new Error('Could not search for movies/shows at tmdb.'); }) + .then((response) => this.cache.set(cacheKey, response)) .then((response) => { try { - // We want to filter because there are movies really low rated that are not interesting to us. let filteredTmdbItems = response.results.filter(function(tmdbResultItem) { return ((tmdbResultItem.vote_count >= 40 || tmdbResultItem.popularity > 8) && (tmdbResultItem.release_date !== undefined || tmdbResultItem.first_air_date !== undefined)) }) - // Here we convert the filtered result from the tmdb api to seaonsed objects let seasonedItems = filteredTmdbItems.map((tmdbItem) => { - if (type === 'movie') return convertTmdbToSeasoned(tmdbItem, 'movie'); else if (type === 'show') @@ -45,7 +55,6 @@ class TMDB { 'page': 1, 'total_pages': 1 }; } catch (parseError) { - console.log(parseError) throw new Error('Could not parse result.'); } }); From f57878813d9a458bf89b2349d36cf9c71bd774c9 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 14:09:57 +0200 Subject: [PATCH 02/18] Added Cache file for tmdb queries and controller check the cache and returns it if hit. This is to limit our request to a third party library. --- seasoned_api/src/tmdb/cache.js | 44 +++++++++++++++++++ .../webserver/controllers/tmdb/searchMedia.js | 18 ++++++-- 2 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 seasoned_api/src/tmdb/cache.js diff --git a/seasoned_api/src/tmdb/cache.js b/seasoned_api/src/tmdb/cache.js new file mode 100644 index 0000000..ab980d5 --- /dev/null +++ b/seasoned_api/src/tmdb/cache.js @@ -0,0 +1,44 @@ +const assert = require('assert'); +const establishedDatabase = require('src/database/database'); + +class Cache { + constructor(database) { + this.database = database || establishedDatabase + this.queries = { + 'read': 'SELECT value, time_to_live, created_at, DATETIME("now", "localtime") as now, ' + + 'DATETIME(created_at, "+" || time_to_live || " seconds") as expires ' + + 'FROM cache WHERE key = ? AND now < expires', + 'create': 'INSERT OR REPLACE INTO cache (key, value, time_to_live) VALUES (?, ?, ?)', + }; + } + + /** + * Retrieve an unexpired cache entry by key. + * @param {String} key of the cache entry + * @returns {Object} + */ + get(key) { + return Promise.resolve() + .then(() => this.database.get(this.queries.read, [key])) + .then((row) => { + assert(row, 'Could not find cache enrty with that key.'); + return JSON.parse(row.value); + }) + } + + /** + * 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 = 60) { + const json = JSON.stringify(value); + return Promise.resolve() + .then(() => this.database.run(this.queries.create, [key, json, timeToLive])) + .then(() => value); + } +} + +module.exports = Cache; \ No newline at end of file diff --git a/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js b/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js index 90f5cda..e67f0a8 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js +++ b/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js @@ -1,6 +1,10 @@ +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 tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); +const cache = new Cache(); +const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); +const searchHistory = new SearchHistory(); /** * Controller: Search for movies by query, page and optionally adult @@ -8,10 +12,17 @@ const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); * @param {Response} res * @returns {Callback} */ -function searchMoviesController(req, res) { +function searchMediaController(req, res) { + const user = req.loggedInUser; const { query, page, type } = req.query; Promise.resolve() + .then(() => { + if (user) { + return searchHistory.create(user, query); + } + return null; + } .then(() => tmdb.search(query, page, type)) .then((movies) => { if (movies !== undefined || movies.length > 0) { @@ -19,11 +30,10 @@ function searchMoviesController(req, res) { } else { res.status(404).send({ success: false, error: 'Search query did not return any results.'}) } - res.send(movies); }) .catch((error) => { res.status(500).send({ success: false, error: error.message }); }); } -module.exports = searchMoviesController; +module.exports = searchMediaController; From 1b29a08ce8d016472900e172b4c65312160c6579 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 14:10:25 +0200 Subject: [PATCH 03/18] Removed a unused comment --- seasoned_api/src/webserver/controllers/user/login.js | 1 - 1 file changed, 1 deletion(-) diff --git a/seasoned_api/src/webserver/controllers/user/login.js b/seasoned_api/src/webserver/controllers/user/login.js index 49be74a..4fe7755 100644 --- a/seasoned_api/src/webserver/controllers/user/login.js +++ b/seasoned_api/src/webserver/controllers/user/login.js @@ -14,7 +14,6 @@ const userSecurity = new UserSecurity(); function loginController(req, res) { const user = new User(req.body.username); const password = req.body.password; - // console.log('login: ', req.body) userSecurity.login(user, password) .then(() => { From f89d81681a439fd8e3e0b5fdb9143c2fa438ab10 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 14:14:29 +0200 Subject: [PATCH 04/18] Added import for cache to initiate our tmdb class in the correct way, but still not implemented the actual cache lookup. --- seasoned_api/src/webserver/controllers/tmdb/discoverMedia.js | 4 +++- seasoned_api/src/webserver/controllers/tmdb/getUpcoming.js | 4 +++- .../src/webserver/controllers/tmdb/nowPlayingMedia.js | 4 +++- seasoned_api/src/webserver/controllers/tmdb/popularMedia.js | 4 +++- seasoned_api/src/webserver/controllers/tmdb/readMedia.js | 4 +++- seasoned_api/src/webserver/controllers/tmdb/searchSimilar.js | 4 +++- 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/seasoned_api/src/webserver/controllers/tmdb/discoverMedia.js b/seasoned_api/src/webserver/controllers/tmdb/discoverMedia.js index 3669035..235d7c2 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/discoverMedia.js +++ b/seasoned_api/src/webserver/controllers/tmdb/discoverMedia.js @@ -1,6 +1,8 @@ const configuration = require('src/config/configuration').getInstance(); +const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); +const cache = new Cache(); +const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); /** * Controller: Retrieve a list of movies or shows in discover section in TMDB diff --git a/seasoned_api/src/webserver/controllers/tmdb/getUpcoming.js b/seasoned_api/src/webserver/controllers/tmdb/getUpcoming.js index 9c9e049..7c3d476 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/getUpcoming.js +++ b/seasoned_api/src/webserver/controllers/tmdb/getUpcoming.js @@ -1,6 +1,8 @@ const configuration = require('src/config/configuration').getInstance(); +const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); +const cache = new Cache(); +const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); /** * Controller: Retrieve upcoming movies diff --git a/seasoned_api/src/webserver/controllers/tmdb/nowPlayingMedia.js b/seasoned_api/src/webserver/controllers/tmdb/nowPlayingMedia.js index 5e67db8..adebeb0 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/nowPlayingMedia.js +++ b/seasoned_api/src/webserver/controllers/tmdb/nowPlayingMedia.js @@ -1,6 +1,8 @@ const configuration = require('src/config/configuration').getInstance(); +const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); +const cache = new Cache(); +const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); /** * Controller: Retrieve nowplaying movies / now airing shows diff --git a/seasoned_api/src/webserver/controllers/tmdb/popularMedia.js b/seasoned_api/src/webserver/controllers/tmdb/popularMedia.js index 963d553..b4addc9 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/popularMedia.js +++ b/seasoned_api/src/webserver/controllers/tmdb/popularMedia.js @@ -1,6 +1,8 @@ const configuration = require('src/config/configuration').getInstance(); +const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); +const cache = new Cache(); +const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); /** * Controller: Retrieve information for a movie diff --git a/seasoned_api/src/webserver/controllers/tmdb/readMedia.js b/seasoned_api/src/webserver/controllers/tmdb/readMedia.js index 6ac9d54..d9d86a4 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/readMedia.js +++ b/seasoned_api/src/webserver/controllers/tmdb/readMedia.js @@ -1,6 +1,8 @@ const configuration = require('src/config/configuration').getInstance(); +const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); +const cache = new Cache(); +const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); /** * Controller: Retrieve information for a movie diff --git a/seasoned_api/src/webserver/controllers/tmdb/searchSimilar.js b/seasoned_api/src/webserver/controllers/tmdb/searchSimilar.js index bc2383f..a8556b4 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/searchSimilar.js +++ b/seasoned_api/src/webserver/controllers/tmdb/searchSimilar.js @@ -1,6 +1,8 @@ const configuration = require('src/config/configuration').getInstance(); +const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); +const cache = new Cache(); +const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); /** * Controller: Retrieve similar movies or shows From 8f4e3a24f466a628c6d5145c1db58c6fa35d6dbe Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 14:16:43 +0200 Subject: [PATCH 05/18] And the last that imports tmdb class. --- seasoned_api/src/plex/requestRepository.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index 97e5c37..ef8b020 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -2,8 +2,10 @@ const assert = require('assert'); const PlexRepository = require('src/plex/plexRepository'); const plexRepository = new PlexRepository(); const configuration = require('src/config/configuration').getInstance(); +const Cache = require('src/tmdb/cache'); const TMDB = require('src/tmdb/tmdb'); -const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); +const cache = new Cache(); +const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); var Promise = require('bluebird'); var rp = require('request-promise'); From d20ac6470f131d926dcc358be20ef556fcc24ea6 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 14:18:38 +0200 Subject: [PATCH 06/18] Was a missing ) --- seasoned_api/src/webserver/controllers/tmdb/searchMedia.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js b/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js index e67f0a8..2eb66f5 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js +++ b/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js @@ -22,7 +22,7 @@ function searchMediaController(req, res) { return searchHistory.create(user, query); } return null; - } + }) .then(() => tmdb.search(query, page, type)) .then((movies) => { if (movies !== undefined || movies.length > 0) { From d90197b8b47d8e8f0ea67a6890cf89afe15a508a Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 14:58:38 +0200 Subject: [PATCH 07/18] Added a cookie variable loggedInUser, to see search history of a user. --- client/app/components/redux/reducer.jsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/app/components/redux/reducer.jsx b/client/app/components/redux/reducer.jsx index 18317d7..e12d427 100644 --- a/client/app/components/redux/reducer.jsx +++ b/client/app/components/redux/reducer.jsx @@ -44,7 +44,7 @@ function setLoginError(loginError) { } -function callLoginApi(email, password, callback) { +function callLoginApi(username, password, callback) { Promise.resolve() fetch('https://apollo.kevinmidboe.com/api/v1/user/login', { @@ -53,7 +53,7 @@ function callLoginApi(email, password, callback) { 'Content-type': 'application/json' }, body: JSON.stringify({ - username: email, + username: username, password: password, }) }) @@ -66,6 +66,7 @@ function callLoginApi(email, password, callback) { let token = data.token; setCookie('token', token, 10); setCookie('logged_in', true, 10); + setCookie('loggedInUser', username, 10); window.location.reload(); } @@ -77,7 +78,7 @@ function callLoginApi(email, password, callback) { } }) .catch(error => { - return callback(new Error('Invalid email and password')); + return callback(new Error('Invalid username and password')); }); } From 6574c087bc35263490ac3dd15ba8c5c3310b5648 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 17:01:26 +0200 Subject: [PATCH 08/18] Added user history saving and that tmdb now gets to use cache. --- seasoned_api/src/plex/requestRepository.js | 56 +++++++++---------- .../controllers/plex/searchRequest.js | 19 +++++-- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index ef8b020..5ec3379 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -19,7 +19,7 @@ const nodemailer = require('nodemailer'); class RequestRepository { - constructor(database) { + constructor(cache, database) { this.database = database || establishedDatabase; this.queries = { 'insertRequest': "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, CURRENT_DATE, 'requested', ?, ?)", @@ -28,13 +28,12 @@ class RequestRepository { } } - searchRequest(query, page, type) { - // TODO get from cache + searchRequest(text, page, type) { // STRIP METADATA THAT IS NOT ALLOWED // Do a search in the tmdb api and return the results of the object let getTmdbResults = function() { - return tmdb.search(query, page, type) + return tmdb.search(text, page, type) .then((tmdbSearch) => { return tmdbSearch.results; }) @@ -54,35 +53,34 @@ class RequestRepository { } return Promise.resolve() - .then(() => plexRepository.searchMedia(query) - // Get the list of plexItems matching the query passed. - .then((plexItem) => { - let tmdbSearchResult = getTmdbResults(); + .catch(() => plexRepository.searchMedia(text)) + // Get the list of plexItems matching the query passed. + .then((plexItem) => { + let tmdbSearchResult = getTmdbResults(); - // When we get the result from tmdbSearchResult we pass it along and iterate over each - // element, and updates the matchedInPlex status of a item. - return tmdbSearchResult.then((tmdbResult) => { - for (var i = 0; i < tmdbResult.length; i++) { - let foundMatchInPlex = checkIfMatchesPlexObjects(tmdbResult[i].title, tmdbResult[i].year, plexItem); - tmdbResult[i].matchedInPlex = foundMatchInPlex; - } - return { 'results': tmdbResult, 'page': 1 }; - }) - // TODO log error - .catch((error) => { - console.log(error); - throw new Error('Search query did not give any results.'); - }) + // When we get the result from tmdbSearchResult we pass it along and iterate over each + // element, and updates the matchedInPlex status of a item. + return tmdbSearchResult.then((tmdbResult) => { + for (var i = 0; i < tmdbResult.length; i++) { + let foundMatchInPlex = checkIfMatchesPlexObjects(tmdbResult[i].title, tmdbResult[i].year, plexItem); + tmdbResult[i].matchedInPlex = foundMatchInPlex; + } + return { 'results': tmdbResult, 'page': 1 }; }) - .catch(() => { - let tmdbSearchResult = getTmdbResults(); + // TODO log error + .catch((error) => { + console.log(error); + throw new Error('Search query did not give any results.'); + }) + }) + .catch(() => { + let tmdbSearchResult = getTmdbResults(); - // Catch if empty, then 404 - return tmdbSearchResult.then((tmdbResult) => { - return {'results': tmdbResult, 'page': 1 }; - }) + // Catch if empty, then 404 + return tmdbSearchResult.then((tmdbResult) => { + return {'results': tmdbResult, 'page': 1 }; }) - ) + }) } lookup(identifier, type = 'movie') { diff --git a/seasoned_api/src/webserver/controllers/plex/searchRequest.js b/seasoned_api/src/webserver/controllers/plex/searchRequest.js index 4bf8a3c..44bcd74 100644 --- a/seasoned_api/src/webserver/controllers/plex/searchRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/searchRequest.js @@ -1,17 +1,28 @@ +const SearchHistory = require('src/searchHistory/searchHistory'); +const Cache = require('src/tmdb/cache'); const RequestRepository = require('src/plex/requestRepository.js'); -const requestRepository = new RequestRepository(); +const cache = new Cache(); +const requestRepository = new RequestRepository(cache); +const searchHistory = new SearchHistory(); + function searchRequestController(req, res) { + const user = req.headers.loggedinuser; const { query, page, type } = req.query; console.log('searchReq: ' + query, page, type); - requestRepository.searchRequest(query, page, type) + Promise.resolve() + .then(() => { + if (user) { + return searchHistory.create(user, query); + } + return null; + }) + .then(() => requestRepository.searchRequest(query, page, type)) .then((searchResult) => { - // Verify that respond has content, if so send the content back if (searchResult.results.length > 0) { res.send(searchResult); } - // If no content was found, send 404 status and error message else { res.status(404).send({success: false, error: 'Search query did not return any results.'}) } From 8d248135e06a3f4263da7f9d6e0e6ffda7e57a25 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 17:01:58 +0200 Subject: [PATCH 09/18] Chagned from using user.username, to just the variable user. --- seasoned_api/src/searchHistory/searchHistory.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seasoned_api/src/searchHistory/searchHistory.js b/seasoned_api/src/searchHistory/searchHistory.js index fbe2f35..1fabb31 100644 --- a/seasoned_api/src/searchHistory/searchHistory.js +++ b/seasoned_api/src/searchHistory/searchHistory.js @@ -16,7 +16,7 @@ class SearchHistory { * @returns {Promise} */ read(user) { - return this.database.all(this.queries.read, user.username) + return this.database.all(this.queries.read, user) .then(rows => rows.map(row => row.search_query)); } @@ -27,7 +27,7 @@ class SearchHistory { * @returns {Promise} */ create(user, searchQuery) { - return this.database.run(this.queries.create, [searchQuery, user.username]).catch((error) => { + return this.database.run(this.queries.create, [searchQuery, user]).catch((error) => { if (error.message.includes('FOREIGN')) { throw new Error('Could not create search history.'); } From cc8d9f0c504732c734420e33092dec1a2179343a Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 17:03:16 +0200 Subject: [PATCH 10/18] Added docstring, removed a unused console.log and added better error handling for empty return statement.s --- .../webserver/controllers/plex/searchMedia.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/seasoned_api/src/webserver/controllers/plex/searchMedia.js b/seasoned_api/src/webserver/controllers/plex/searchMedia.js index 0199254..bef7f26 100644 --- a/seasoned_api/src/webserver/controllers/plex/searchMedia.js +++ b/seasoned_api/src/webserver/controllers/plex/searchMedia.js @@ -1,13 +1,23 @@ const PlexRepository = require('src/plex/plexRepository'); const plexRepository = new PlexRepository(); +/** + * Controller: Search for media and check existence + * in plex by query and page + * @param {Request} req http request variable + * @param {Response} res + * @returns {Callback} + */ function searchMediaController(req, res) { const { query, page } = req.query; - console.log(query); plexRepository.searchMedia(query) - .then((movies) => { - res.send(movies); + .then((media) => { + if (media !== undefined || media.length > 0) { + res.send(media); + } else { + res.status(404).send({ success: false, error: 'Search query did not return any results.'}) + } }) .catch((error) => { res.status(500).send({success: false, error: error.message }); From 354e06a963e6831d413064c4ef2acc95a7224415 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 17:03:40 +0200 Subject: [PATCH 11/18] Removed searchHistory from tmdb class. --- .../src/webserver/controllers/tmdb/searchMedia.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js b/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js index 2eb66f5..4443bde 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js +++ b/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js @@ -1,28 +1,19 @@ -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 searchHistory = new SearchHistory(); /** - * Controller: Search for movies by query, page and optionally adult + * Controller: Search for movies by query, page and optional type * @param {Request} req http request variable * @param {Response} res * @returns {Callback} */ function searchMediaController(req, res) { - const user = req.loggedInUser; const { query, page, type } = req.query; Promise.resolve() - .then(() => { - if (user) { - return searchHistory.create(user, query); - } - return null; - }) .then(() => tmdb.search(query, page, type)) .then((movies) => { if (movies !== undefined || movies.length > 0) { From 592528dec27512dd049b7d0df97393ab093bdc6b Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 17:30:49 +0200 Subject: [PATCH 12/18] Forgot to change this to point at our new server --- seasoned_api/src/plex/plexRepository.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/plex/plexRepository.js b/seasoned_api/src/plex/plexRepository.js index 4bfcff7..aebaf9a 100644 --- a/seasoned_api/src/plex/plexRepository.js +++ b/seasoned_api/src/plex/plexRepository.js @@ -31,7 +31,7 @@ class PlexRepository { nowPlaying() { var options = { - uri: 'http://10.0.0.41:32400/status/sessions', + uri: 'http://10.0.0.42:32400/status/sessions', headers: { 'Accept': 'application/json' }, From 0e70a10cc2434f13836f57eaddca8a7b55664b11 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 17:31:14 +0200 Subject: [PATCH 13/18] Opps, start with then. --- seasoned_api/src/plex/requestRepository.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index 5ec3379..c1f5a37 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -53,7 +53,7 @@ class RequestRepository { } return Promise.resolve() - .catch(() => plexRepository.searchMedia(text)) + .then(() => plexRepository.searchMedia(text)) // Get the list of plexItems matching the query passed. .then((plexItem) => { let tmdbSearchResult = getTmdbResults(); From d2d791f5b27e518d8682276e596b4b0ef1120daf Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 17:31:37 +0200 Subject: [PATCH 14/18] added loggedinuser as acceptable header. --- seasoned_api/src/webserver/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/webserver/app.js b/seasoned_api/src/webserver/app.js index cf3b93a..0dd0e0e 100644 --- a/seasoned_api/src/webserver/app.js +++ b/seasoned_api/src/webserver/app.js @@ -33,7 +33,7 @@ router.use(function(req, res, next) { console.log('allowed'); res.setHeader('Access-Control-Allow-Origin', origin); } - res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); + res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, loggedinuser'); res.header('Access-Control-Allow-Methods', 'POST, GET, PUT'); next(); From 6e95d48f11e7a058a6fbf914477d7b9c24ec1134 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 17:34:16 +0200 Subject: [PATCH 15/18] Now when searching a loggedinuser header element is passed also. --- client/app/components/SearchRequest.jsx | 28 ++++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/client/app/components/SearchRequest.jsx b/client/app/components/SearchRequest.jsx index d3d0056..3bf9afc 100644 --- a/client/app/components/SearchRequest.jsx +++ b/client/app/components/SearchRequest.jsx @@ -10,6 +10,7 @@ import URI from 'urijs'; import InfiniteScroll from 'react-infinite-scroller'; import { fetchJSON } from './http.jsx'; +import { getCookie } from './Cookie.jsx'; var MediaQuery = require('react-responsive'); @@ -105,11 +106,18 @@ class SearchRequest extends React.Component { // Test this by calling missing endpoint or 404 query and see what code // and filter the error message based on the code. // Calls a uri and returns the response as json - callURI(uri) { - return fetch(uri) + callURI(uri, method, data={}) { + return fetch(uri, { + method: method, + headers: new Headers({ + 'Content-Type': 'application/json', + 'authorization': getCookie('token'), + 'loggedinuser': getCookie('loggedInUser'), + }) + }) .then(response => { return response }) - .catch(error => { - throw Error('Something went wrong while fetching URI.'); + .catch((error) => { + throw Error(error); }); } @@ -128,7 +136,7 @@ class SearchRequest extends React.Component { // this.writeLoading(); Promise.resolve() - .then(() => this.callURI(uri)) + .then(() => this.callURI(uri, 'GET')) .then(response => { // If we get a error code for the request if (!response.ok) { @@ -174,8 +182,8 @@ class SearchRequest extends React.Component { console.log('CallSearchFillMovieList: ', error) }) }) - .catch(() => { - throw Error('Something went wrong when fetching query.') + .catch((error) => { + console.log('Something went wrong when fetching query.', error) }) } @@ -184,7 +192,7 @@ class SearchRequest extends React.Component { // this.writeLoading(); Promise.resolve() - .then(() => this.callURI(uri)) + .then(() => this.callURI(uri, 'GET', undefined)) .then(response => { // If we get a error code for the request if (!response.ok) { @@ -217,8 +225,8 @@ class SearchRequest extends React.Component { } }) }) - .catch(() => { - throw Error('Something went wrong when fetching query.') + .catch((error) => { + console.log('Something went wrong when fetching query.', error) }) } From 7952e6015a5d83ee65b223eaf4230f3031b5d891 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 17:41:12 +0200 Subject: [PATCH 16/18] Added caching for all tmdb requests. --- seasoned_api/src/tmdb/tmdb.js | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/seasoned_api/src/tmdb/tmdb.js b/seasoned_api/src/tmdb/tmdb.js index 872880b..140691f 100644 --- a/seasoned_api/src/tmdb/tmdb.js +++ b/seasoned_api/src/tmdb/tmdb.js @@ -18,7 +18,6 @@ class TMDB { 'upcoming': 'u', 'similar': 'si', 'lookup': 'l' - } } @@ -29,7 +28,7 @@ class TMDB { */ search(text, page = 1, type = 'multi') { const query = { 'query': text, 'page': page }; - const cacheKey = `${this.cacheTags.search}${page}:${type}:${text}`; + const cacheKey = `${this.cacheTags.search}:${page}:${type}:${text}`; return Promise.resolve() .then(() => this.cache.get(cacheKey)) .catch(() => this.tmdb(type, query)) @@ -84,9 +83,12 @@ class TMDB { // Build a query for tmdb with pagenumber const query = { 'page': page } + const cacheKey = `${this.cacheTags.discover}:${page}:${type}`; return Promise.resolve() - .then(() => this.tmdb(tmdbType, query)) + .then(() => this.cache.get(cacheKey)) + .catch(() => this.tmdb(tmdbType, query)) .catch(() => { throw new Error('Could not fetch discover.'); }) + .then((response) => this.cache.set(cacheKey, response)) .then((response) => { try { // Return a object that has the results and a variable for page, total_pages @@ -128,9 +130,12 @@ class TMDB { // Build a query for tmdb with pagenumber const query = { 'page': page } + const cacheKey = `${this.cacheTags.popular}:${page}:${type}`; return Promise.resolve() - .then(() => this.tmdb(tmdbType, query)) + .then(() => this.cache.get(cacheKey)) + .catch(() => this.tmdb(tmdbType, query)) .catch(() => { throw new Error('Could not fetch popular.'); }) + .then((response) => this.cache.set(cacheKey, response)) .then((response) => { try { var seasonedResponse = response.results.map((result) => { @@ -173,9 +178,12 @@ class TMDB { // Build a query for tmdb with pagenumber const query = { 'page': page } + const cacheKey = `${this.cacheTags.nowplaying}:${page}:${type}`; return Promise.resolve() - .then(() => this.tmdb(tmdbType, query)) + .then(() => this.cache.get(cacheKey)) + .catch(() => this.tmdb(tmdbType, query)) .catch(() => { throw new Error('Could not fetch popular.'); }) + .then((response) => this.cache.set(cacheKey, response)) .then((response) => { try { var seasonedResponse = response.results.map((result) => { @@ -200,9 +208,12 @@ class TMDB { // TODO add filter for language upcoming(page) { const query = { 'page': page } + const cacheKey = `${this.cacheTags.upcoming}:${page}`; return Promise.resolve() - .then(() => this.tmdb('upcomingMovies', query)) + .then(() => this.cache.get(cacheKey)) + .catch(() => this.tmdb('upcomingMovies', query)) .catch(() => { throw new Error('Could not fetch upcoming movies.'); }) + .then((response) => this.cache.set(cacheKey, response)) .then((response) => { try { var seasonedResponse = response.results.map((result) => { @@ -240,9 +251,12 @@ class TMDB { } const query = { id: identifier } + const cacheKey = `${this.cacheTags.similar}:${type}:${identifier}`; return Promise.resolve() - .then(() => this.tmdb(tmdbType, query)) + .then(() => this.cache.get(cacheKey)) + .catch(() => this.tmdb(tmdbType, query)) .catch(() => { throw new Error('Could not fetch upcoming movies.'); }) + .then((response) => this.cache.set(cacheKey, response)) .then((response) => { try { var seasonedResponse = response.results.map((result) => { @@ -275,9 +289,12 @@ class TMDB { }) } const query = { id: identifier }; + const cacheKey = `${this.cacheTags.lookup}:${type}:${identifier}`; return Promise.resolve() - .then(() => this.tmdb(type, query)) + .then(() => this.cache.get(cacheKey)) + .catch(() => this.tmdb(type, query)) .catch(() => { throw new Error('Could not find a movie with that id.'); }) + .then((response) => this.cache.set(cacheKey, response)) .then((response) => { try { var car = convertTmdbToSeasoned(response, queryType); From 1925c2a5e35bad7de02eb39e5ff412f6aaa28d03 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 18:04:20 +0200 Subject: [PATCH 17/18] Changed the variable for saving to searchHistory to be set when user is not false. --- seasoned_api/src/webserver/controllers/plex/searchRequest.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/seasoned_api/src/webserver/controllers/plex/searchRequest.js b/seasoned_api/src/webserver/controllers/plex/searchRequest.js index 44bcd74..020bb5e 100644 --- a/seasoned_api/src/webserver/controllers/plex/searchRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/searchRequest.js @@ -13,10 +13,9 @@ function searchRequestController(req, res) { Promise.resolve() .then(() => { - if (user) { - return searchHistory.create(user, query); + if (user !== 'false') { + searchHistory.create(user, query); } - return null; }) .then(() => requestRepository.searchRequest(query, page, type)) .then((searchResult) => { From 0e3189ff11cf0455d6cac067d89fbd907d351d0c Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Sun, 22 Oct 2017 18:16:39 +0200 Subject: [PATCH 18/18] Added default cache time to be 1 day --- seasoned_api/src/tmdb/cache.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/tmdb/cache.js b/seasoned_api/src/tmdb/cache.js index ab980d5..1a55117 100644 --- a/seasoned_api/src/tmdb/cache.js +++ b/seasoned_api/src/tmdb/cache.js @@ -33,7 +33,7 @@ class Cache { * @param {Number} timeToLive the number of seconds before entry expires * @returnsĀ {Object} */ - set(key, value, timeToLive = 60) { + set(key, value, timeToLive = 86400) { const json = JSON.stringify(value); return Promise.resolve() .then(() => this.database.run(this.queries.create, [key, json, timeToLive]))