From 0addc761261d24897ed2285dcc53f1e1a47a0f2c Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 9 Jan 2018 23:03:53 +0100 Subject: [PATCH 01/22] Changed the positioning of the type icon in the header and forgot the set the style of the movie info header to the correct css element, this is fixed now. --- client/app/components/admin/AdminRequestInfo.jsx | 2 +- client/app/components/styles/adminRequestInfo.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/app/components/admin/AdminRequestInfo.jsx b/client/app/components/admin/AdminRequestInfo.jsx index a67e7e1..4b10da4 100644 --- a/client/app/components/admin/AdminRequestInfo.jsx +++ b/client/app/components/admin/AdminRequestInfo.jsx @@ -195,7 +195,7 @@ class AdminRequestInfo extends Component {
-

Movie info

+

Movie info

{ this.generateSummary() }
diff --git a/client/app/components/styles/adminRequestInfo.jsx b/client/app/components/styles/adminRequestInfo.jsx index d3a525f..a03e83c 100644 --- a/client/app/components/styles/adminRequestInfo.jsx +++ b/client/app/components/styles/adminRequestInfo.jsx @@ -25,7 +25,7 @@ export default { }, type_icon: { - marginLeft: '-1.9em', + marginLeft: '-0.2em', marginRight: '0.7em', }, type_text: { -- 2.34.1 From 4f98f2fd235f4389f7f6dd15f583e7649082aa86 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 9 Jan 2018 23:08:59 +0100 Subject: [PATCH 02/22] Changed the distance between the search bar and the content to be a little less and added a shadow around the search bar to make it pop a bit more. --- client/app/components/styles/searchRequestStyle.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/app/components/styles/searchRequestStyle.jsx b/client/app/components/styles/searchRequestStyle.jsx index 0700a4e..0702afe 100644 --- a/client/app/components/styles/searchRequestStyle.jsx +++ b/client/app/components/styles/searchRequestStyle.jsx @@ -14,7 +14,7 @@ export default { backgroundColor: 'rgb(1, 28, 35)', // backgroundImage: 'radial-gradient(circle, #004c67 0, #005771 120%)', zIndex: 1, - marginBottom: '80px' + marginBottom: '70px' }, backgroundSmallHeader: { @@ -61,6 +61,7 @@ export default { width: '77%', paddingLeft: '23%', backgroundColor: 'white', + boxShadow: 'grey 0px 1px 2px', }, searchSmallContainer: { -- 2.34.1 From 0b42cf7f129d18d2a0b9393589337cb424919ebd Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 9 Jan 2018 23:12:27 +0100 Subject: [PATCH 03/22] Because the content on the landing page felt static I added a random function to pick between the four list types. --- client/app/components/SearchRequest.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/app/components/SearchRequest.jsx b/client/app/components/SearchRequest.jsx index bdb5098..50e93a4 100644 --- a/client/app/components/SearchRequest.jsx +++ b/client/app/components/SearchRequest.jsx @@ -47,7 +47,7 @@ class SearchRequest extends React.Component { // this.setState({responseMovieList: null}) this.resetPageNumber(); this.state.loadResults = true; - this.fetchTmdbList('discover'); + this.fetchTmdbList(this.allowedListTypes[Math.floor(Math.random()*this.allowedListTypes.length)]); } // Handles all errors of the response of a fetch call -- 2.34.1 From 3639105240bc51409a58d42c21fbd6a3bd2b2807 Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 9 Jan 2018 23:43:32 +0100 Subject: [PATCH 04/22] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0466557..9f50bc6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ [![Build Status](https://travis-ci.org/KevinMidboe/seasonedShows.svg?branch=master)](https://travis-ci.org/KevinMidboe/seasonedShows) [![DUB](https://img.shields.io/dub/l/vibe-d.svg)]() -Your customly *seasoned* movie and show requester, downloader and organizer. +Your customly *seasoned* movie and show requester, downloader and organizer. +Demo can be found [here](https://kevinmidboe.com/request) ## About The goal of this project is to create a full custom stack that can to everything surround downloading, organizing and notifiyng of new media. From the top down we have a website using [tmdb](https://www.themoviedb.com) api to search for from over 350k movies and 70k tv shows. Using [hjone72](https://github.com/hjone72/PlexAuth) great PHP reverse proxy we can have a secure way of allowing users to login with their plex credentials which limits request capabilites to only users that are authenticated to use your plex library. -- 2.34.1 From 6f6b38c23dc03c95d115d5f4745e18e76626e1ca Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 9 Jan 2018 23:43:44 +0100 Subject: [PATCH 05/22] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f50bc6..8a8d745 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/KevinMidboe/seasonedShows.svg?branch=master)](https://travis-ci.org/KevinMidboe/seasonedShows) [![DUB](https://img.shields.io/dub/l/vibe-d.svg)]() -Your customly *seasoned* movie and show requester, downloader and organizer. +Your customly *seasoned* movie and show requester, downloader and organizer. Demo can be found [here](https://kevinmidboe.com/request) ## About -- 2.34.1 From c0c958706673b37f9d0a8f8e85e9dc053c18a5f3 Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 9 Jan 2018 23:45:01 +0100 Subject: [PATCH 06/22] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 8a8d745..300c84b 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ [![Build Status](https://travis-ci.org/KevinMidboe/seasonedShows.svg?branch=master)](https://travis-ci.org/KevinMidboe/seasonedShows) [![DUB](https://img.shields.io/dub/l/vibe-d.svg)]() -Your customly *seasoned* movie and show requester, downloader and organizer. -Demo can be found [here](https://kevinmidboe.com/request) +Your customly *seasoned* movie and show requester, downloader and organizer. Demo page can be viewed [here](https://kevinmidboe.com/request) ## About The goal of this project is to create a full custom stack that can to everything surround downloading, organizing and notifiyng of new media. From the top down we have a website using [tmdb](https://www.themoviedb.com) api to search for from over 350k movies and 70k tv shows. Using [hjone72](https://github.com/hjone72/PlexAuth) great PHP reverse proxy we can have a secure way of allowing users to login with their plex credentials which limits request capabilites to only users that are authenticated to use your plex library. -- 2.34.1 From 444295d5d16d6d2e2e53d5b1cdfd725a5245af22 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:47:11 +0100 Subject: [PATCH 07/22] Updated our eslint config file. Still extends airbnb, but have changed indent rule and dropped some other rules. --- seasoned_api/.eslintrc.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/seasoned_api/.eslintrc.json b/seasoned_api/.eslintrc.json index 6f67564..d7e47e6 100644 --- a/seasoned_api/.eslintrc.json +++ b/seasoned_api/.eslintrc.json @@ -1,3 +1,12 @@ { - "extends": "airbnb-base" -} \ No newline at end of file + "extends": [ + "airbnb-base" + ], + "rules": { + "indent": ["error", 3], + "prefer-destructuring": 0, + "camelcase": 0, + "import/no-unresolved": 0, + "import/no-extraneous-dependencies": 0 + } +} -- 2.34.1 From fe1ad2b1adf698d9a17210cf9763ebb73600e2be Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:49:11 +0100 Subject: [PATCH 08/22] Linted all config files. --- seasoned_api/src/config/configuration.js | 56 +++++++------- .../src/config/environmentVariables.js | 19 +++-- seasoned_api/src/config/field.js | 73 +++++++++---------- seasoned_api/src/config/filters.js | 49 ++++++------- 4 files changed, 97 insertions(+), 100 deletions(-) diff --git a/seasoned_api/src/config/configuration.js b/seasoned_api/src/config/configuration.js index bd9d4c3..b9eede4 100644 --- a/seasoned_api/src/config/configuration.js +++ b/seasoned_api/src/config/configuration.js @@ -4,40 +4,40 @@ const Field = require('./field.js'); let instance = null; class Config { - constructor() { - this.location = Config.determineLocation(); - this.fields = require(`${this.location}`); - } + constructor() { + this.location = Config.determineLocation(); + this.fields = require(`${this.location}`); + } - static getInstance() { - if (instance == null) { - instance = new Config(); - } - return instance; - } + static getInstance() { + if (instance == null) { + instance = new Config(); + } + return instance; + } - static determineLocation() { - return path.join(__dirname, '..', '..', process.env.SEASONED_CONFIG); - } + static determineLocation() { + return path.join(__dirname, '..', '..', process.env.SEASONED_CONFIG); + } - get(section, option) { - if (this.fields[section] === undefined || this.fields[section][option] === undefined) { - throw new Error(`Filed "${section} => ${option}" does not exist.`); - } + get(section, option) { + if (this.fields[section] === undefined || this.fields[section][option] === undefined) { + throw new Error(`Filed "${section} => ${option}" does not exist.`); + } - const field = new Field(this.fields[section][option]) + const field = new Field(this.fields[section][option]); - if (field.value === '') { - const envField = process.env[[section.toUpperCase(), option.toUpperCase()].join('_')] - if (envField !== undefined && envField.length !== 0) { return envField } - } + if (field.value === '') { + const envField = process.env[[section.toUpperCase(), option.toUpperCase()].join('_')]; + if (envField !== undefined && envField.length !== 0) { return envField; } + } - if (field.value === undefined) { - throw new Error(`${section} => ${option} is empty.`); - } + if (field.value === undefined) { + throw new Error(`${section} => ${option} is empty.`); + } - return field.value; - } + return field.value; + } } -module.exports = Config; \ No newline at end of file +module.exports = Config; diff --git a/seasoned_api/src/config/environmentVariables.js b/seasoned_api/src/config/environmentVariables.js index d879fe7..b7fc3f2 100644 --- a/seasoned_api/src/config/environmentVariables.js +++ b/seasoned_api/src/config/environmentVariables.js @@ -1,16 +1,15 @@ class EnvironmentVariables { + constructor(variables) { + this.variables = variables || process.env; + } - constructor(variables) { - this.variables = variables || process.env; - } + get(variable) { + return this.variables[variable]; + } - get(variable) { - return this.variables[variable]; - } - - has(variable) { - return this.get(variable) !== undefined; - } + has(variable) { + return this.get(variable) !== undefined; + } } module.exports = EnvironmentVariables; diff --git a/seasoned_api/src/config/field.js b/seasoned_api/src/config/field.js index 1a8b79a..42eb8cd 100644 --- a/seasoned_api/src/config/field.js +++ b/seasoned_api/src/config/field.js @@ -2,49 +2,48 @@ const Filters = require('./filters.js'); const EnvironmentVariables = require('./environmentVariables.js'); class Field { + constructor(rawValue, environmentVariables) { + this.rawValue = rawValue; + this.filters = new Filters(rawValue); + this.valueWithoutFilters = this.filters.removeFiltersFromValue(); + this.environmentVariables = new EnvironmentVariables(environmentVariables); + } - constructor(rawValue, environmentVariables) { - this.rawValue = rawValue; - this.filters = new Filters(rawValue); - this.valueWithoutFilters = this.filters.removeFiltersFromValue(); - this.environmentVariables = new EnvironmentVariables(environmentVariables); - } + get value() { + if (this.filters.isEmpty()) { + return this.valueWithoutFilters; + } - get value() { - if (this.filters.isEmpty()) { - return this.valueWithoutFilters; - } + if (this.filters.has('base64') && !this.filters.has('env')) { + return Field.base64Decode(this.valueWithoutFilters); + } - if (this.filters.has('base64') && !this.filters.has('env')) { - return Field.base64Decode(this.valueWithoutFilters); - } + if (this.environmentVariables.has(this.valueWithoutFilters) && + this.environmentVariables.get(this.valueWithoutFilters) === '') { + return undefined; + } - if (this.environmentVariables.has(this.valueWithoutFilters) && - this.environmentVariables.get(this.valueWithoutFilters) === '') { - return undefined; - } + if (!this.filters.has('base64') && this.filters.has('env')) { + if (this.environmentVariables.has(this.valueWithoutFilters)) { + return this.environmentVariables.get(this.valueWithoutFilters); + } + return undefined; + } - if (!this.filters.has('base64') && this.filters.has('env')) { - if (this.environmentVariables.has(this.valueWithoutFilters)) { - return this.environmentVariables.get(this.valueWithoutFilters); - } - return undefined; - } + if (this.filters.has('env') && this.filters.has('base64')) { + if (this.environmentVariables.has(this.valueWithoutFilters)) { + const encodedEnvironmentVariable = this.environmentVariables.get(this.valueWithoutFilters); + return Field.base64Decode(encodedEnvironmentVariable); + } + return undefined; + } - if (this.filters.has('env') && this.filters.has('base64')) { - if (this.environmentVariables.has(this.valueWithoutFilters)) { - const encodedEnvironmentVariable = this.environmentVariables.get(this.valueWithoutFilters); - return Field.base64Decode(encodedEnvironmentVariable); - } - return undefined; - } + return this.valueWithoutFilters; + } - return this.valueWithoutFilters; - } - - static base64Decode(string) { - return new Buffer(string, 'base64').toString('utf-8'); - } + static base64Decode(string) { + return new Buffer(string, 'base64').toString('utf-8'); + } } -module.exports = Field; \ No newline at end of file +module.exports = Field; diff --git a/seasoned_api/src/config/filters.js b/seasoned_api/src/config/filters.js index fbeab07..b4ec359 100644 --- a/seasoned_api/src/config/filters.js +++ b/seasoned_api/src/config/filters.js @@ -1,35 +1,34 @@ class Filters { + constructor(value) { + this.value = value; + this.delimiter = '|'; + } - constructor(value) { - this.value = value; - this.delimiter = '|'; - } + get filters() { + return this.value.split(this.delimiter).slice(0, -1); + } - get filters() { - return this.value.split(this.delimiter).slice(0, -1); - } + isEmpty() { + return !this.hasValidType() || this.value.length === 0; + } - isEmpty() { - return !this.hasValidType() || this.value.length === 0; - } + has(filter) { + return this.filters.includes(filter); + } - has(filter) { - return this.filters.includes(filter); - } + hasValidType() { + return (typeof this.value === 'string'); + } - hasValidType() { - return (typeof this.value === 'string'); - } + removeFiltersFromValue() { + if (this.hasValidType() === false) { + return this.value; + } - removeFiltersFromValue() { - if (this.hasValidType() === false) { - return this.value; - } - - let filtersCombined = this.filters.join(this.delimiter); - filtersCombined += this.filters.length >= 1 ? this.delimiter : ''; - return this.value.replace(filtersCombined, ''); - } + let filtersCombined = this.filters.join(this.delimiter); + filtersCombined += this.filters.length >= 1 ? this.delimiter : ''; + return this.value.replace(filtersCombined, ''); + } } module.exports = Filters; -- 2.34.1 From 272300249e1e6a06663a595e22cf8162a4769916 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:49:22 +0100 Subject: [PATCH 09/22] Linted all database files. --- seasoned_api/src/database/database.js | 5 +++-- seasoned_api/src/database/sqliteDatabase.js | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/seasoned_api/src/database/database.js b/seasoned_api/src/database/database.js index 8e509df..b71c357 100644 --- a/seasoned_api/src/database/database.js +++ b/seasoned_api/src/database/database.js @@ -1,5 +1,6 @@ const configuration = require('src/config/configuration').getInstance(); const SqliteDatabase = require('src/database/sqliteDatabase'); + const database = new SqliteDatabase(configuration.get('database', 'host')); /** @@ -9,7 +10,7 @@ const database = new SqliteDatabase(configuration.get('database', 'host')); * If the tables already exists, it simply proceeds. */ Promise.resolve() -.then(() => database.connect()) -.then(() => database.setUp()); + .then(() => database.connect()) + .then(() => database.setUp()); module.exports = database; diff --git a/seasoned_api/src/database/sqliteDatabase.js b/seasoned_api/src/database/sqliteDatabase.js index a68e207..76b92f6 100644 --- a/seasoned_api/src/database/sqliteDatabase.js +++ b/seasoned_api/src/database/sqliteDatabase.js @@ -16,8 +16,8 @@ class SqliteDatabase { */ connect() { return Promise.resolve() - .then(() => sqlite.open(this.host)) - .then(() => sqlite.exec('pragma foreign_keys = on;')); + .then(() => sqlite.open(this.host)) + .then(() => sqlite.exec('pragma foreign_keys = on;')); } /** @@ -73,10 +73,10 @@ class SqliteDatabase { * Tears down the database by running tearDown.sql file in schemas/. * @returns {Promise} */ - tearDown() { - const tearDownSchema = this.readSqlFile('tearDown.sql'); - return this.execute(tearDownSchema); - } + tearDown() { + const tearDownSchema = this.readSqlFile('tearDown.sql'); + return this.execute(tearDownSchema); + } /** * Returns the file contents of a SQL file in schemas/. -- 2.34.1 From 97217a282640f791ae0ec1cfcb7b51eb98c30724 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:49:37 +0100 Subject: [PATCH 10/22] Linted all media_classes --- seasoned_api/src/media_classes/mediaInfo.js | 24 ++++++++++----------- seasoned_api/src/media_classes/player.js | 19 ++++++++-------- seasoned_api/src/media_classes/user.js | 10 ++++----- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/seasoned_api/src/media_classes/mediaInfo.js b/seasoned_api/src/media_classes/mediaInfo.js index 3019f25..3cbe69d 100644 --- a/seasoned_api/src/media_classes/mediaInfo.js +++ b/seasoned_api/src/media_classes/mediaInfo.js @@ -1,15 +1,15 @@ class MediaInfo { - constructor() { - this.duration = undefined; - this.height = undefined; - this.width = undefined; - this.bitrate = undefined; - this.resolution = undefined; - this.framerate = undefined; - this.protocol = undefined; - this.container = undefined; - this.audioCodec = undefined; - } + constructor() { + this.duration = undefined; + this.height = undefined; + this.width = undefined; + this.bitrate = undefined; + this.resolution = undefined; + this.framerate = undefined; + this.protocol = undefined; + this.container = undefined; + this.audioCodec = undefined; + } } -module.exports = MediaInfo; \ No newline at end of file +module.exports = MediaInfo; diff --git a/seasoned_api/src/media_classes/player.js b/seasoned_api/src/media_classes/player.js index cb430b2..e675f85 100644 --- a/seasoned_api/src/media_classes/player.js +++ b/seasoned_api/src/media_classes/player.js @@ -1,13 +1,12 @@ class Player { - constructor(device, address) { - this.device = device; - this.ip = address; - this.platform = undefined; - this.product = undefined; - this.title = undefined; - this.state = undefined; - - } + constructor(device, address) { + this.device = device; + this.ip = address; + this.platform = undefined; + this.product = undefined; + this.title = undefined; + this.state = undefined; + } } -module.exports = Player; \ No newline at end of file +module.exports = Player; diff --git a/seasoned_api/src/media_classes/user.js b/seasoned_api/src/media_classes/user.js index 73c4bec..fc09d7d 100644 --- a/seasoned_api/src/media_classes/user.js +++ b/seasoned_api/src/media_classes/user.js @@ -1,8 +1,8 @@ class User { - constructor(id, title) { - this.id = id; - this.title = title; - } + constructor(id, title) { + this.id = id; + this.title = title; + } } -module.exports = User; \ No newline at end of file +module.exports = User; -- 2.34.1 From dda1db6c5f63675bee3e4c2b1779c6586540e3e0 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:50:05 +0100 Subject: [PATCH 11/22] Linted all plex scripts. --- seasoned_api/src/plex/convertPlexToStream.js | 16 +- .../src/plex/convertStreamToMediaInfo.js | 30 +-- seasoned_api/src/plex/hookDump.js | 11 +- seasoned_api/src/plex/mailTemplate.js | 39 ++-- seasoned_api/src/plex/plexRepository.js | 137 ++++++------ seasoned_api/src/plex/requestRepository.js | 197 ++++++++---------- .../plex/stream/convertStreamToPlayback.js | 23 +- .../src/plex/stream/convertStreamToPlayer.js | 14 +- .../src/plex/stream/convertStreamToUser.js | 4 +- 9 files changed, 220 insertions(+), 251 deletions(-) diff --git a/seasoned_api/src/plex/convertPlexToStream.js b/seasoned_api/src/plex/convertPlexToStream.js index 1e82173..f6ba3ef 100644 --- a/seasoned_api/src/plex/convertPlexToStream.js +++ b/seasoned_api/src/plex/convertPlexToStream.js @@ -5,15 +5,15 @@ const convertStreamToUser = require('src/plex/stream/convertStreamToUser'); const ConvertStreamToPlayback = require('src/plex/stream/convertStreamToPlayback'); function convertPlexToStream(plexStream) { - const stream = convertPlexToSeasoned(plexStream) - const plexStreamMedia = plexStream.Media[0] - stream.mediaInfo = convertStreamToMediaInfo(plexStreamMedia); - stream.player = convertStreamToPlayer(plexStream.Player); + const stream = convertPlexToSeasoned(plexStream); + const plexStreamMedia = plexStream.Media[0]; + stream.mediaInfo = convertStreamToMediaInfo(plexStreamMedia); + stream.player = convertStreamToPlayer(plexStream.Player); - stream.user = convertStreamToUser(plexStream.User); - stream.playback = new ConvertStreamToPlayback(plexStreamMedia.Part[0]); + stream.user = convertStreamToUser(plexStream.User); + stream.playback = new ConvertStreamToPlayback(plexStreamMedia.Part[0]); - return stream; + return stream; } -module.exports = convertPlexToStream; \ No newline at end of file +module.exports = convertPlexToStream; diff --git a/seasoned_api/src/plex/convertStreamToMediaInfo.js b/seasoned_api/src/plex/convertStreamToMediaInfo.js index 60d6c1d..ca75776 100644 --- a/seasoned_api/src/plex/convertStreamToMediaInfo.js +++ b/seasoned_api/src/plex/convertStreamToMediaInfo.js @@ -1,22 +1,22 @@ const MediaInfo = require('src/media_classes/mediaInfo'); function convertStreamToMediaInfo(plexStream) { - const mediaInfo = new MediaInfo(); - - mediaInfo.duration = plexStream.duration; - mediaInfo.height = plexStream.height; - mediaInfo.width = plexStream.width; + const mediaInfo = new MediaInfo(); - if (plexStream.bitrate) { - mediaInfo.bitrate = plexStream.bitrate; - } - mediaInfo.resolution = plexStream.videoResolution; - mediaInfo.framerate = plexStream.videoFrameRate; - mediaInfo.protocol = plexStream.protocol; - mediaInfo.container = plexStream.container; - mediaInfo.audioCodec = plexStream.audioCodec; + mediaInfo.duration = plexStream.duration; + mediaInfo.height = plexStream.height; + mediaInfo.width = plexStream.width; - return mediaInfo; + if (plexStream.bitrate) { + mediaInfo.bitrate = plexStream.bitrate; + } + mediaInfo.resolution = plexStream.videoResolution; + mediaInfo.framerate = plexStream.videoFrameRate; + mediaInfo.protocol = plexStream.protocol; + mediaInfo.container = plexStream.container; + mediaInfo.audioCodec = plexStream.audioCodec; + + return mediaInfo; } -module.exports = convertStreamToMediaInfo; \ No newline at end of file +module.exports = convertStreamToMediaInfo; diff --git a/seasoned_api/src/plex/hookDump.js b/seasoned_api/src/plex/hookDump.js index 1761757..23cecf4 100644 --- a/seasoned_api/src/plex/hookDump.js +++ b/seasoned_api/src/plex/hookDump.js @@ -1,14 +1,7 @@ -/* -* @Author: KevinMidboe -* @Date: 2017-05-03 23:26:46 -* @Last Modified by: KevinMidboe -* @Last Modified time: 2017-05-03 23:27:59 -*/ - const configuration = require('src/config/configuration').getInstance(); function hookDumpController(req, res) { - console.log(req); + console.log(req); } -module.exports = hookDumpController; \ No newline at end of file +module.exports = hookDumpController; diff --git a/seasoned_api/src/plex/mailTemplate.js b/seasoned_api/src/plex/mailTemplate.js index c07e34f..64d38a9 100644 --- a/seasoned_api/src/plex/mailTemplate.js +++ b/seasoned_api/src/plex/mailTemplate.js @@ -1,26 +1,25 @@ class mailTemplate { - - constructor(mediaItem) { - this.mediaItem = mediaItem; - this.posterURL = 'https://image.tmdb.org/t/p/w600'; - } + constructor(mediaItem) { + this.mediaItem = mediaItem; + this.posterURL = 'https://image.tmdb.org/t/p/w600'; + } - toText() { - return this.mediaItem.title + ' (' + this.mediaItem.year + ')'; // plain text body - } + toText() { + return `${this.mediaItem.title} (${this.mediaItem.year})`; // plain text body + } - toHTML() { - const info = { - name: this.mediaItem.title, - year: '(' + this.mediaItem.year + ')', - poster: this.posterURL + this.mediaItem.poster - } + toHTML() { + const info = { + name: this.mediaItem.title, + year: `(${this.mediaItem.year})`, + poster: this.posterURL + this.mediaItem.poster, + }; - return ` -

${info.name} ${info.year}

- - ` - } + return ` +

${info.name} ${info.year}

+ + `; + } } -module.exports = mailTemplate; \ No newline at end of file +module.exports = mailTemplate; diff --git a/seasoned_api/src/plex/plexRepository.js b/seasoned_api/src/plex/plexRepository.js index 2a3b975..bde5c01 100644 --- a/seasoned_api/src/plex/plexRepository.js +++ b/seasoned_api/src/plex/plexRepository.js @@ -1,87 +1,80 @@ -const assert = require('assert'); const convertPlexToSeasoned = require('src/plex/convertPlexToSeasoned'); const convertPlexToStream = require('src/plex/convertPlexToStream'); -var rp = require('request-promise'); - -const PLEX_METHODS = ['lookup', 'playing'] +const rp = require('request-promise'); class PlexRepository { + inPlex(tmdbResult) { + return Promise.resolve() + .then(() => this.search(tmdbResult.title)) + .then(plexResult => this.compareTmdbToPlex(tmdbResult, plexResult)); + } - search(query, callback) { - var options = { - uri: 'http://10.0.0.44:32400/search?query=' + query, - headers: { - 'Accept': 'application/json' - }, - json: true - } + search(query) { + const options = { + uri: `http://10.0.0.44:32400/search?query=${query}`, + headers: { + Accept: 'application/json', + }, + json: true, + }; - return rp(options) - .then((result) => this.mapResults(result)) - .then(([mappedResults, resultCount]) => { - return { 'results': mappedResults, 'total_results': resultCount } - }) - } + return rp(options) + .then(result => this.mapResults(result)) + .then(([mappedResults, resultCount]) => ({ results: mappedResults, total_results: resultCount })); + } - compareTmdbToPlex(tmdb, plexResult) { - return Promise.resolve() - .then(() => { - plexResult.results.map((plexItem) => { - if (tmdb.title === plexItem.title && tmdb.year === plexItem.year) - tmdb.matchedInPlex = true; - }) - return tmdb - }) - } + static compareTmdbToPlex(tmdb, plexResult) { + return Promise.resolve() + .then(() => { + plexResult.results.map((plexItem) => { + if (tmdb.title === plexItem.title && tmdb.year === plexItem.year) { tmdb.matchedInPlex = true; } + return tmdb; + }); + return tmdb; + }); + } - inPlex(tmdbResult) { - return Promise.resolve() - .then(() => this.search(tmdbResult.title)) - .then((plexResult) => this.compareTmdbToPlex(tmdbResult, plexResult)) - } + static mapResults(response) { + return Promise.resolve() + .then(() => { + if (!response.MediaContainer.hasOwnProperty('Metadata')) return [[], 0]; - mapResults(response) { - return Promise.resolve() - .then(() => { - if (! response.MediaContainer.hasOwnProperty('Metadata')) return [[], 0] + const mappedResults = response.MediaContainer.Metadata.filter((element) => { + return (element.type === 'movie' || element.type === 'show'); + }).map((element) => convertPlexToSeasoned(element)); + return [mappedResults, mappedResults.length]; + }) + .catch((error) => { throw new Error(error); }); + } - const mappedResults = response.MediaContainer.Metadata.filter((element) => { - return (element.type === 'movie' || element.type === 'show') - }).map((element) => convertPlexToSeasoned(element)) - return [mappedResults, mappedResults.length] - }) - .catch((error) => {throw new Error(error)}) - } + nowPlaying() { + const options = { + uri: 'http://10.0.0.44:32400/status/sessions', + headers: { + Accept: 'application/json', + }, + json: true, + }; - nowPlaying() { - var options = { - uri: 'http://10.0.0.44:32400/status/sessions', - headers: { - 'Accept': 'application/json' - }, - json: true - } + return rp(options) + .then((result) => { + if (result.MediaContainer.size > 0) { + const playing = result.MediaContainer.Video.map(convertPlexToStream); + return { size: Object.keys(playing).length, video: playing }; + } + return { size: 0, video: [] }; + }) + .catch((err) => { + throw new Error(`Error handling plex playing. Error: ${err}`); + }); + } - return rp(options) - .then((result) => { - if (result.MediaContainer.size > 0) { - var playing = result.MediaContainer.Video.map(convertPlexToStream); - return {'size': Object.keys(playing).length, 'video': playing }; - } else { - return { 'size': 0, 'video': [] }; - } - }) - .catch((err) => { - throw new Error('Error handling plex playing. Error: ' + err); - }) - } - - // multipleInPlex(tmdbResults) { - // const results = tmdbResults.results.map(async (tmdb) => { - // return this.inPlex(tmdb) - // }) - // return Promise.all(results) - // } + // multipleInPlex(tmdbResults) { + // const results = tmdbResults.results.map(async (tmdb) => { + // return this.inPlex(tmdb) + // }) + // return Promise.all(results) + // } } module.exports = PlexRepository; diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index b24e7f8..3cfb60b 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -1,132 +1,117 @@ -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 configuration = require('src/config/configuration').getInstance(); const TMDB = require('src/tmdb/tmdb'); -const cache = new Cache(); -const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); -var Promise = require('bluebird'); -var rp = require('request-promise'); - const establishedDatabase = require('src/database/database'); -const MailTemplate = require('src/plex/mailTemplate') +const plexRepository = new PlexRepository(); +const cache = new Cache(); +const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); -var pythonShell = require('python-shell'); +const MailTemplate = require('src/plex/mailTemplate'); const nodemailer = require('nodemailer'); class RequestRepository { + constructor(cache, database) { + this.database = database || establishedDatabase; + this.queries = { + insertRequest: "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_DATE, 'requested', ?, ?)", + fetchRequstedItems: 'SELECT * FROM requests', + updateRequestedById: 'UPDATE requests SET status = ? WHERE id is ? AND type is ?', + checkIfIdRequested: 'SELECT * FROM requests WHERE id IS ? AND type IS ?', + }; + } - constructor(cache, database) { - this.database = database || establishedDatabase; - this.queries = { - 'insertRequest': "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_DATE, 'requested', ?, ?)", - 'fetchRequstedItems': "SELECT * FROM requests", - 'updateRequestedById': "UPDATE requests SET status = ? WHERE id is ? AND type is ?", - 'checkIfIdRequested': "SELECT * FROM requests WHERE id IS ? AND type IS ?", - } - } + search(query, type, page) { + return Promise.resolve() + .then(() => tmdb.search(query, type, page)) + // .then((tmdbResult) => plexRepository.multipleInPlex(tmdbResult)) + .then(result => result) + .catch(error => `error in the house${error}`); + } - search(query, type, page) { - return Promise.resolve() - .then(() => tmdb.search(query, type, page)) - // .then((tmdbResult) => plexRepository.multipleInPlex(tmdbResult)) - .then((result) => { - return result - }) - .catch((error) => {return 'error in the house' + error}) - } + lookup(identifier, type = 'movie') { + return Promise.resolve() + .then(() => tmdb.lookup(identifier, type)) + .then(tmdbMovie => this.checkID(tmdbMovie)) + .then(tmdbMovie => plexRepository.inPlex(tmdbMovie)) + .catch((error) => { + throw new Error(error); + }); + } - lookup(identifier, type = 'movie') { - return Promise.resolve() - .then(() => tmdb.lookup(identifier, type)) - .then((tmdbMovie) => this.checkID(tmdbMovie)) - .then((tmdbMovie) => plexRepository.inPlex(tmdbMovie)) - .catch((error) => { - console.log(error) - }) - } + checkID(tmdbMovie) { + return Promise.resolve() + .then(() => this.database.get(this.queries.checkIfIdRequested, [tmdbMovie.id, tmdbMovie.type])) + .then((result, error) => { + if (error) { throw new Error(error); } + let already_requested = false; + if (result) { already_requested = true; } - checkID(tmdbMovie) { - return Promise.resolve() - .then(() => this.database.get(this.queries.checkIfIdRequested, [tmdbMovie.id, tmdbMovie.type])) - .then((result, error) => { - let already_requested = false; - if (result) - already_requested = true + tmdbMovie.requested = already_requested; + return tmdbMovie; + }); + } - tmdbMovie.requested = already_requested; - return tmdbMovie; - }) - - } - - /** - * Send request for given media id. - * @param {identifier, type} the id of the media object and type of media must be defined - * @returns {Promise} If nothing has gone wrong. - */ - sendRequest(identifier, type, ip, user_agent, user) { - tmdb.lookup(identifier, type).then(movie => { - - if (user === 'false') - user = 'NULL'; - console.log(user) - // Add request to database - this.database.run(this.queries.insertRequest, [movie.id, movie.title, movie.year, movie.poster_path, movie.background_path, user, ip, user_agent, movie.type]) + /** + * Send request for given media id. + * @param {identifier, type} the id of the media object and type of media must be defined + * @returns {Promise} If nothing has gone wrong. + */ + sendRequest(identifier, type, ip, user_agent, user) { + tmdb.lookup(identifier, type).then((movie) => { + if (user === 'false') { user = 'NULL'; } + // Add request to database + this.database.run(this.queries.insertRequest, [movie.id, movie.title, movie.year, movie.poster_path, movie.background_path, user, ip, user_agent, movie.type]); - // create reusable transporter object using the default SMTP transport - let transporter = nodemailer.createTransport({ - service: 'gmail', - auth: { - user: configuration.get('mail', 'user_pi'), - pass: configuration.get('mail', 'password_pi') - } - // host: configuration.get('mail', 'host'), - // port: 26, - // ignoreTLS: true, - // tls :{rejectUnauthorized: false}, - // secure: false, // secure:true for port 465, secure:false for port 587 - }); + // create reusable transporter object using the default SMTP transport + const transporter = nodemailer.createTransport({ + service: 'gmail', + auth: { + user: configuration.get('mail', 'user_pi'), + pass: configuration.get('mail', 'password_pi'), + }, + // host: configuration.get('mail', 'host'), + // port: 26, + // ignoreTLS: true, + // tls :{rejectUnauthorized: false}, + // secure: false, // secure:true for port 465, secure:false for port 587 + }); - const mailTemplate = new MailTemplate(movie) + const mailTemplate = new MailTemplate(movie); - // setup email data with unicode symbols - let mailOptions = { - // TODO get the mail adr from global location (easy to add) - from: 'MovieRequester ', // sender address - to: 'kevin.midboe@gmail.com', // list of receivers - subject: 'Download request', // Subject line - text: mailTemplate.toText(), - html: mailTemplate.toHTML() - }; + // setup email data with unicode symbols + const mailOptions = { + // TODO get the mail adr from global location (easy to add) + from: 'MovieRequester ', // sender address + to: 'kevin.midboe@gmail.com', // list of receivers + subject: 'Download request', // Subject line + text: mailTemplate.toText(), + html: mailTemplate.toHTML(), + }; - // send mail with defined transport object - transporter.sendMail(mailOptions, (error, info) => { - if (error) { - return console.log(error); - } - console.log('Message %s sent: %s', info.messageId, info.response); - }); + // send mail with defined transport object + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + return console.log(error); + } + console.log('Message %s sent: %s', info.messageId, info.response); + }); + }); - }) + // TODO add better response when done. + return Promise.resolve(); + } - // TODO add better response when done. - return Promise.resolve(); - - } - - fetchRequested() { - return this.database.all(this.queries.fetchRequstedItems); - } - - updateRequestedById(id, type, status) { - return this.database.run(this.queries.updateRequestedById, [status, id, type]); - } + fetchRequested() { + return this.database.all(this.queries.fetchRequstedItems); + } + updateRequestedById(id, type, status) { + return this.database.run(this.queries.updateRequestedById, [status, id, type]); + } } module.exports = RequestRepository; diff --git a/seasoned_api/src/plex/stream/convertStreamToPlayback.js b/seasoned_api/src/plex/stream/convertStreamToPlayback.js index f4fae2d..cdabee4 100644 --- a/seasoned_api/src/plex/stream/convertStreamToPlayback.js +++ b/seasoned_api/src/plex/stream/convertStreamToPlayback.js @@ -1,15 +1,14 @@ class convertStreamToPlayback { - constructor(plexStream) { - this.bitrate = plexStream.bitrate; - this.width = plexStream.width; - this.height = plexStream.height; - this.decision = plexStream.decision; - this.audioProfile = plexStream.audioProfile; - this.videoProfile = plexStream.videoProfile; - this.duration = plexStream.duration; - this.container = plexStream.container; - - } + constructor(plexStream) { + this.bitrate = plexStream.bitrate; + this.width = plexStream.width; + this.height = plexStream.height; + this.decision = plexStream.decision; + this.audioProfile = plexStream.audioProfile; + this.videoProfile = plexStream.videoProfile; + this.duration = plexStream.duration; + this.container = plexStream.container; + } } -module.exports = convertStreamToPlayback; \ No newline at end of file +module.exports = convertStreamToPlayback; diff --git a/seasoned_api/src/plex/stream/convertStreamToPlayer.js b/seasoned_api/src/plex/stream/convertStreamToPlayer.js index bb64e2f..8d4abc5 100644 --- a/seasoned_api/src/plex/stream/convertStreamToPlayer.js +++ b/seasoned_api/src/plex/stream/convertStreamToPlayer.js @@ -1,13 +1,13 @@ const Player = require('src/media_classes/player'); function convertStreamToPlayer(plexStream) { - const player = new Player(plexStream.device, plexStream.address); - player.platform = plexStream.platform; - player.product = plexStream.product; - player.title = plexStream.title; - player.state = plexStream.state; + const player = new Player(plexStream.device, plexStream.address); + player.platform = plexStream.platform; + player.product = plexStream.product; + player.title = plexStream.title; + player.state = plexStream.state; - return player; + return player; } -module.exports = convertStreamToPlayer; \ No newline at end of file +module.exports = convertStreamToPlayer; diff --git a/seasoned_api/src/plex/stream/convertStreamToUser.js b/seasoned_api/src/plex/stream/convertStreamToUser.js index bce1c2a..6b356d2 100644 --- a/seasoned_api/src/plex/stream/convertStreamToUser.js +++ b/seasoned_api/src/plex/stream/convertStreamToUser.js @@ -1,7 +1,7 @@ const User = require('src/media_classes/user'); function convertStreamToUser(plexStream) { - return new User(plexStream.id, plexStream.title); + return new User(plexStream.id, plexStream.title); } -module.exports = convertStreamToUser; \ No newline at end of file +module.exports = convertStreamToUser; -- 2.34.1 From 74d143775b22a14c39beabb1c7f08db55626adc7 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:50:16 +0100 Subject: [PATCH 12/22] Linted all user files. --- seasoned_api/src/user/token.js | 45 +++++++------ seasoned_api/src/user/user.js | 10 +-- seasoned_api/src/user/userRepository.js | 70 ++++++++++---------- seasoned_api/src/user/userSecurity.js | 87 ++++++++++++------------- 4 files changed, 104 insertions(+), 108 deletions(-) diff --git a/seasoned_api/src/user/token.js b/seasoned_api/src/user/token.js index bce5c84..cd8c285 100644 --- a/seasoned_api/src/user/token.js +++ b/seasoned_api/src/user/token.js @@ -2,37 +2,36 @@ const User = require('src/user/user'); const jwt = require('jsonwebtoken'); class Token { + constructor(user) { + this.user = user; + } - constructor(user) { - this.user = user; - } + /** + * Generate a new token. + * @param {String} secret a cipher of the token + * @returns {String} + */ + toString(secret) { + return jwt.sign({ username: this.user.username }, secret); + } - /** - * Generate a new token. - * @param {String} secret a cipher of the token - * @returns {String} - */ - toString(secret) { - return jwt.sign({ username: this.user.username }, secret); - } - - /** + /** * Decode a token. * @param {Token} jwtToken an encrypted token * @param {String} secret a cipher of the token * @returns {Token} */ - static fromString(jwtToken, secret) { - let username = null; + static fromString(jwtToken, secret) { + let username = null; - try { - username = jwt.verify(jwtToken, secret).username; - } catch (error) { - throw new Error('The token is invalid.'); - } - const user = new User(username); - return new Token(user); - } + try { + username = jwt.verify(jwtToken, secret).username; + } catch (error) { + throw new Error('The token is invalid.'); + } + const user = new User(username); + return new Token(user); + } } module.exports = Token; diff --git a/seasoned_api/src/user/user.js b/seasoned_api/src/user/user.js index a4bb44c..d922fbb 100644 --- a/seasoned_api/src/user/user.js +++ b/seasoned_api/src/user/user.js @@ -1,8 +1,8 @@ class User { - constructor(username, email) { - this.username = username; - this.email = email; - } + constructor(username, email) { + this.username = username; + this.email = email; + } } -module.exports = User; \ No newline at end of file +module.exports = User; diff --git a/seasoned_api/src/user/userRepository.js b/seasoned_api/src/user/userRepository.js index b81ef30..b672a4d 100644 --- a/seasoned_api/src/user/userRepository.js +++ b/seasoned_api/src/user/userRepository.js @@ -2,58 +2,56 @@ const assert = require('assert'); const establishedDatabase = require('src/database/database'); class UserRepository { + constructor(database) { + this.database = database || establishedDatabase; + this.queries = { + read: 'select * from user where lower(user_name) = lower(?)', + create: 'insert into user (user_name, email) values(?, ?)', + change: 'update user set password = ? where user_name = ?', + retrieveHash: 'select * from user where user_name = ?', + }; + } - constructor(database) { - this.database = database || establishedDatabase; - this.queries = { - read: 'select * from user where lower(user_name) = lower(?)', - create: 'insert into user (user_name, email) values(?, ?)', - change: 'update user set password = ? where user_name = ?', - retrieveHash: 'select * from user where user_name = ?', - }; - } - - /** + /** * Create a user in a database. * @param {User} user the user you want to create * @returns {Promise} */ - create(user) { - return Promise.resolve() - .then(() => this.database.get(this.queries.read, user.username)) - .then(row => assert.equal(row, undefined)) - .then(() => this.database.run(this.queries.create, [user.username, user.email])) - .catch((error) => { - if (error.message.endsWith('email')) { - throw new Error('That email is already taken'); - } else if (error.name === 'AssertionError' || error.message.endsWith('user_name')) { - throw new Error('That username is already taken'); - } - }); - } + create(user) { + return Promise.resolve() + .then(() => this.database.get(this.queries.read, user.username)) + .then(row => assert.equal(row, undefined)) + .then(() => this.database.run(this.queries.create, [user.username, user.email])) + .catch((error) => { + if (error.message.endsWith('email')) { + throw new Error('That email is already taken'); + } else if (error.name === 'AssertionError' || error.message.endsWith('user_name')) { + throw new Error('That username is already taken'); + } + }); + } - /** + /** * Retrieve a password from a database. * @param {User} user the user you want to retrieve the password * @returns {Promise} */ - retrieveHash(user) { - return this.database.get(this.queries.retrieveHash, user.username).then((row) => { - assert(row, 'The user does not exist.'); - return row.password; - }); - } + retrieveHash(user) { + return this.database.get(this.queries.retrieveHash, user.username).then((row) => { + assert(row, 'The user does not exist.'); + return row.password; + }); + } - /** + /** * Change a user's password in a database. * @param {User} user the user you want to create * @param {String} password the new password you want to change * @returns {Promise} */ - changePassword(user, password) { - return this.database.run(this.queries.change, [password, user.username]); - } - + changePassword(user, password) { + return this.database.run(this.queries.change, [password, user.username]); + } } module.exports = UserRepository; diff --git a/seasoned_api/src/user/userSecurity.js b/seasoned_api/src/user/userSecurity.js index 185b1bd..71583db 100644 --- a/seasoned_api/src/user/userSecurity.js +++ b/seasoned_api/src/user/userSecurity.js @@ -2,75 +2,74 @@ const bcrypt = require('bcrypt-nodejs'); const UserRepository = require('src/user/userRepository'); class UserSecurity { + constructor(database) { + this.userRepository = new UserRepository(database); + } - constructor(database) { - this.userRepository = new UserRepository(database); - } - - /** + /** * Create a new user in PlanFlix. * @param {User} user the new user you want to create * @param {String} clearPassword a password of the user * @returns {Promise} */ - createNewUser(user, clearPassword) { - if (user.username.trim() === '') { - throw new Error('The username is empty.'); - } else if (user.email.trim() === '') { - throw new Error('The email is empty.'); - } else if (clearPassword.trim() === '') { - throw new Error('The password is empty.'); - } else { - return Promise.resolve() - .then(() => this.userRepository.create(user)) - .then(() => UserSecurity.hashPassword(clearPassword)) - .then(hash => this.userRepository.changePassword(user, hash)); - } - } + createNewUser(user, clearPassword) { + if (user.username.trim() === '') { + throw new Error('The username is empty.'); + } else if (user.email.trim() === '') { + throw new Error('The email is empty.'); + } else if (clearPassword.trim() === '') { + throw new Error('The password is empty.'); + } else { + return Promise.resolve() + .then(() => this.userRepository.create(user)) + .then(() => UserSecurity.hashPassword(clearPassword)) + .then(hash => this.userRepository.changePassword(user, hash)); + } + } - /** + /** * Login into PlanFlix. * @param {User} user the user you want to login * @param {String} clearPassword the user's password * @returns {Promise} */ - login(user, clearPassword) { - return Promise.resolve() - .then(() => this.userRepository.retrieveHash(user)) - .then(hash => UserSecurity.compareHashes(hash, clearPassword)) - .catch(() => { throw new Error('Wrong username or password.'); }); - } + login(user, clearPassword) { + return Promise.resolve() + .then(() => this.userRepository.retrieveHash(user)) + .then(hash => UserSecurity.compareHashes(hash, clearPassword)) + .catch(() => { throw new Error('Wrong username or password.'); }); + } - /** + /** * Compare between a password and a hash password from database. * @param {String} hash the hash password from database * @param {String} clearPassword the user's password * @returns {Promise} */ - static compareHashes(hash, clearPassword) { - return new Promise((resolve, reject) => { - bcrypt.compare(clearPassword, hash, (error, matches) => { - if (matches === true) { - resolve(); - } else { - reject(); - } + static compareHashes(hash, clearPassword) { + return new Promise((resolve, reject) => { + bcrypt.compare(clearPassword, hash, (error, matches) => { + if (matches === true) { + resolve(); + } else { + reject(); + } + }); }); - }); - } + } - /** + /** * Hashes a password. * @param {String} clearPassword the user's password * @returns {Promise} */ - static hashPassword(clearPassword) { - return new Promise((resolve) => { - bcrypt.hash(clearPassword, null, null, (error, hash) => { - resolve(hash); + static hashPassword(clearPassword) { + return new Promise((resolve) => { + bcrypt.hash(clearPassword, null, null, (error, hash) => { + resolve(hash); + }); }); - }); - } + } } module.exports = UserSecurity; -- 2.34.1 From a8ec7acff5d03489267a2ca6ad7929483c16dea5 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:51:02 +0100 Subject: [PATCH 13/22] Linted all seasoned scripts. --- seasoned_api/src/seasoned/stray.js | 8 +- seasoned_api/src/seasoned/strayRepository.js | 101 +++++++++---------- 2 files changed, 52 insertions(+), 57 deletions(-) diff --git a/seasoned_api/src/seasoned/stray.js b/seasoned_api/src/seasoned/stray.js index ce2218f..f33e2ac 100644 --- a/seasoned_api/src/seasoned/stray.js +++ b/seasoned_api/src/seasoned/stray.js @@ -1,7 +1,7 @@ class Stray { - constructor(id) { - this.id = id; - } + constructor(id) { + this.id = id; + } } -module.exports = Stray; \ No newline at end of file +module.exports = Stray; diff --git a/seasoned_api/src/seasoned/strayRepository.js b/seasoned_api/src/seasoned/strayRepository.js index 7d439b0..05ae66f 100644 --- a/seasoned_api/src/seasoned/strayRepository.js +++ b/seasoned_api/src/seasoned/strayRepository.js @@ -1,67 +1,62 @@ const assert = require('assert'); const Stray = require('src/seasoned/stray'); const establishedDatabase = require('src/database/database'); -var pythonShell = require('python-shell'); - -function foo(e) { - throw('Foooo'); -} +const pythonShell = require('python-shell'); class StrayRepository { + constructor(database) { + this.database = database || establishedDatabase; + this.queries = { + read: 'SELECT * FROM stray_eps WHERE id = ?', + readAll: 'SELECT id, name, season, episode, verified FROM stray_eps', + readAllFiltered: 'SELECT id, name, season, episode, verified FROM stray_eps WHERE verified = ', + checkVerified: 'SELECT id FROM stray_eps WHERE verified = 0 AND id = ?', + verify: 'UPDATE stray_eps SET verified = 1 WHERE id = ?', + }; + } - constructor(database) { - this.database = database || establishedDatabase; - this.queries = { - 'read': 'SELECT * FROM stray_eps WHERE id = ?', - 'readAll': 'SELECT id, name, season, episode, verified FROM stray_eps', - 'readAllFiltered': 'SELECT id, name, season, episode, verified FROM stray_eps WHERE verified = ', - 'checkVerified': 'SELECT id FROM stray_eps WHERE verified = 0 AND id = ?', - 'verify': 'UPDATE stray_eps SET verified = 1 WHERE id = ?', - }; - } + read(strayId) { + return this.database.get(this.queries.read, strayId).then((row) => { + assert.notEqual(row, undefined, `Could not find list with id ${strayId}.`); + return row; + }); + } - read(strayId) { - return this.database.get(this.queries.read, strayId).then((row) => { - assert.notEqual(row, undefined, `Could not find list with id ${strayId}.`); - return row; - }) - } + readAll(verified = null) { + let dbSearchQuery = this.queries.readAll; + if (verified != null) { + dbSearchQuery = this.queries.readAllFiltered + verified.toString(); + } + return this.database.all(dbSearchQuery).then(rows => + rows.map((row) => { + const stray = new Stray(row.id); + stray.name = row.name; + stray.season = row.season; + stray.episode = row.episode; + stray.verified = row.verified; + return stray; + })); + } - readAll(verified = null, page = 1) { - var dbSearchQuery = this.queries.readAll; - if (verified != null) { - dbSearchQuery = this.queries.readAllFiltered + verified.toString(); - } - return this.database.all(dbSearchQuery).then(rows => - rows.map((row) => { - const stray = new Stray(row.id); - stray.name = row.name; - stray.season = row.season; - stray.episode = row.episode; - stray.verified = row.verified; - return stray; - })) - } + verifyStray(strayId) { + return this.database.get(this.queries.checkVerified, strayId).then((row) => { + assert.notEqual(row, undefined, `Stray '${strayId}' already verified.`); - verifyStray(strayId) { - return this.database.get(this.queries.checkVerified, strayId).then((row) => { - assert.notEqual(row, undefined, `Stray '${strayId}' already verified.`); + const options = { + pythonPath: '/usr/bin/python3', + args: [strayId], + }; - var options = { - pythonPath: '/usr/bin/python3', - args: [strayId] - } + pythonShell.run('../app/moveSeasoned.py', options, (err, results) => { + if (err) throw err; + // TODO Add error handling!! StrayRepository.ERROR + // results is an array consisting of messages collected during execution + console.log('results: %j', results); + }); - pythonShell.run('../app/moveSeasoned.py', options, function (err, results) { - if (err) throw err; - // TODO Add error handling!! StrayRepository.ERROR - // results is an array consisting of messages collected during execution - console.log('results: %j', results); - }); - - return this.database.run(this.queries.verify, strayId); - }) - } + return this.database.run(this.queries.verify, strayId); + }); + } } module.exports = StrayRepository; -- 2.34.1 From 81aeed86efbcc30100ec920b5328aee5ffcea660 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:51:42 +0100 Subject: [PATCH 14/22] Linted all pirate, git, tmdb and searchHistory scripts. --- seasoned_api/src/git/gitRepository.js | 11 ++- seasoned_api/src/pirate/pirateRepository.js | 75 +++++++++---------- .../src/searchHistory/searchHistory.js | 43 ++++++----- seasoned_api/src/tmdb/cache.js | 70 ++++++++--------- 4 files changed, 98 insertions(+), 101 deletions(-) diff --git a/seasoned_api/src/git/gitRepository.js b/seasoned_api/src/git/gitRepository.js index 54d0891..703ce2c 100644 --- a/seasoned_api/src/git/gitRepository.js +++ b/seasoned_api/src/git/gitRepository.js @@ -1,10 +1,9 @@ -const assert = require('assert'); class GitRepository { - - dumpHook(body) { - console.log(body); - } + static dumpHook(body) { + /* eslint-disable no-console */ + console.log(body); + } } -module.exports = GitRepository; \ No newline at end of file +module.exports = GitRepository; diff --git a/seasoned_api/src/pirate/pirateRepository.js b/seasoned_api/src/pirate/pirateRepository.js index ca2a4fb..8dce82b 100644 --- a/seasoned_api/src/pirate/pirateRepository.js +++ b/seasoned_api/src/pirate/pirateRepository.js @@ -1,54 +1,53 @@ const assert = require('assert'); -var PythonShell = require('python-shell'); -var async = require('async'); +const PythonShell = require('python-shell'); async function find(searchterm, callback) { + const options = { + pythonPath: '/usr/bin/python3', + // pythonPath: '/Library/Frameworks/Python.framework/Versions/3.6/bin/python3', + args: [searchterm, '-s', 'piratebay', '--print'], + }; - var options = { - pythonPath: '/usr/bin/python3', - // pythonPath: '/Library/Frameworks/Python.framework/Versions/3.6/bin/python3', - args: [searchterm, '-s', 'piratebay', '--print'] - } - - PythonShell.run('../app/torrent_search/torrentSearch/search.py', options, callback); - // PythonShell does not support return -}; + PythonShell.run('../app/torrent_search/torrentSearch/search.py', options, callback); + // PythonShell does not support return +} async function callPythonAddMagnet(magnet, callback) { - var options = { - pythonPath: '/usr/bin/python', - // pythonPath: '/Library/Frameworks/Python.framework/Versions/3.6/bin/python3', - args: [magnet] - } + const options = { + pythonPath: '/usr/bin/python', + // pythonPath: '/Library/Frameworks/Python.framework/Versions/3.6/bin/python3', + args: [magnet], + }; - PythonShell.run('../app/magnet.py', options, callback); + PythonShell.run('../app/magnet.py', options, callback); } async function SearchPiratebay(query) { - return await new Promise((resolve, reject) => { - return find(query, function(err, results) { - if (err) { - console.log('THERE WAS A FUCKING ERROR!') - reject(Error('There was a error when searching for torrents')) - } - if (results) { - console.log('result', results); - resolve(JSON.parse(results, null, '\t')); - } - }) - }) + return await new Promise((resolve, reject) => find(query, (err, results) => { + if (err) { + /* eslint-disable no-console */ + console.log('THERE WAS A FUCKING ERROR!'); + reject(Error('There was a error when searching for torrents')); + } + if (results) { + /* eslint-disable no-console */ + console.log('result', results); + resolve(JSON.parse(results, null, '\t')); + } + })); } async function AddMagnet(magnet) { - return await new Promise((resolve) => { - return callPythonAddMagnet(magnet, function(err, results) { - if (err) { - console.log(err) - } - resolve({ success: true }) - }) - }) + return await new Promise(resolve => callPythonAddMagnet(magnet, (err, results) => { + if (err) { + /* eslint-disable no-console */ + console.log(err); + } + /* eslint-disable no-console */ + console.log(results); + resolve({ success: true }); + })); } -module.exports = { SearchPiratebay, AddMagnet } +module.exports = { SearchPiratebay, AddMagnet }; diff --git a/seasoned_api/src/searchHistory/searchHistory.js b/seasoned_api/src/searchHistory/searchHistory.js index 1fabb31..c51590e 100644 --- a/seasoned_api/src/searchHistory/searchHistory.js +++ b/seasoned_api/src/searchHistory/searchHistory.js @@ -1,39 +1,38 @@ const establishedDatabase = require('src/database/database'); class SearchHistory { + constructor(database) { + this.database = database || establishedDatabase; + this.queries = { + 'create': 'insert into search_history (search_query, user_name) values (?, ?)', + 'read': 'select search_query from search_history where user_name = ? order by id desc', + }; + } - constructor(database) { - this.database = database || establishedDatabase; - this.queries = { - 'create': 'insert into search_history (search_query, user_name) values (?, ?)', - 'read': 'select search_query from search_history where user_name = ? order by id desc', - }; - } - - /** + /** * Retrive a search queries for a user from the database. * @param {User} user existing user * @returns {Promise} */ - read(user) { - return this.database.all(this.queries.read, user) - .then(rows => rows.map(row => row.search_query)); - } + read(user) { + return this.database.all(this.queries.read, user) + .then(rows => rows.map(row => row.search_query)); + } - /** + /** * Creates a new search entry in the database. * @param {User} user a new user * @param {String} searchQuery the query the user searched for * @returns {Promise} */ - create(user, searchQuery) { - return this.database.run(this.queries.create, [searchQuery, user]).catch((error) => { - if (error.message.includes('FOREIGN')) { - throw new Error('Could not create search history.'); - } - }); - } - + create(user, searchQuery) { + return this.database.run(this.queries.create, [searchQuery, user]) + .catch((error) => { + if (error.message.includes('FOREIGN')) { + throw new Error('Could not create search history.'); + } + }); + } } module.exports = SearchHistory; diff --git a/seasoned_api/src/tmdb/cache.js b/seasoned_api/src/tmdb/cache.js index 4c8b62e..584df15 100644 --- a/seasoned_api/src/tmdb/cache.js +++ b/seasoned_api/src/tmdb/cache.js @@ -2,43 +2,43 @@ 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 (?, ?, ?)', - }; - } + 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); - }) - } + /** + * 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 = 172800) { - const json = JSON.stringify(value); - return Promise.resolve() - .then(() => this.database.run(this.queries.create, [key, json, timeToLive])) - .then(() => 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 = 172800) { + const json = JSON.stringify(value); + return Promise.resolve() + .then(() => this.database.run(this.queries.create, [key, json, timeToLive])) + .then(() => value); + } } module.exports = Cache; -- 2.34.1 From 34982c14fe7040f2427311b26bf1819d76699e91 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:51:57 +0100 Subject: [PATCH 15/22] Linted all controllers --- .../src/webserver/controllers/git/dumpHook.js | 14 ++++----- .../webserver/controllers/pirate/addMagnet.js | 16 +++++----- .../controllers/pirate/searchTheBay.js | 16 +++++----- .../controllers/plex/fetchRequested.js | 16 +++++----- .../webserver/controllers/plex/hookDump.js | 8 ++--- .../webserver/controllers/plex/plexPlaying.js | 17 ++++++----- .../webserver/controllers/plex/readRequest.js | 17 ++++++----- .../webserver/controllers/plex/searchMedia.js | 29 ++++++++++--------- .../controllers/plex/searchRequest.js | 25 ++++++++-------- .../controllers/plex/submitRequest.js | 29 ++++++++++--------- .../controllers/plex/updateRequested.js | 21 +++++++------- .../controllers/seasoned/readStrays.js | 19 ++++++------ .../controllers/seasoned/strayById.js | 18 ++++++------ .../controllers/seasoned/verifyStray.js | 16 +++++----- .../webserver/controllers/tmdb/listSearch.js | 19 ++++++------ .../webserver/controllers/tmdb/readMedia.js | 17 ++++++----- .../webserver/controllers/tmdb/searchMedia.js | 27 ++++++++--------- .../src/webserver/controllers/user/history.js | 17 ++++++----- .../src/webserver/controllers/user/login.js | 21 +++++++------- .../webserver/controllers/user/register.js | 19 ++++++------ 20 files changed, 195 insertions(+), 186 deletions(-) diff --git a/seasoned_api/src/webserver/controllers/git/dumpHook.js b/seasoned_api/src/webserver/controllers/git/dumpHook.js index c05ada6..cfc1637 100644 --- a/seasoned_api/src/webserver/controllers/git/dumpHook.js +++ b/seasoned_api/src/webserver/controllers/git/dumpHook.js @@ -3,13 +3,13 @@ const GitRepository = require('src/git/gitRepository'); const gitRepository = new GitRepository(); function dumpHookController(req, res) { - gitRepository.dumpHook(req.body) - .then(() => { - res.status(200); - }) - .catch((error) => { - res.status(500); - }); + gitRepository.dumpHook(req.body) + .then(() => { + res.status(200); + }) + .catch((error) => { + res.status(500); + }); } module.exports = dumpHookController; diff --git a/seasoned_api/src/webserver/controllers/pirate/addMagnet.js b/seasoned_api/src/webserver/controllers/pirate/addMagnet.js index 66d7e74..9899831 100644 --- a/seasoned_api/src/webserver/controllers/pirate/addMagnet.js +++ b/seasoned_api/src/webserver/controllers/pirate/addMagnet.js @@ -9,15 +9,15 @@ const PirateRepository = require('src/pirate/pirateRepository'); function updateRequested(req, res) { - const magnet = req.body.magnet; + const magnet = req.body.magnet; - PirateRepository.AddMagnet(magnet) - .then((result) => { - res.send(result); - }) - .catch((error) => { - res.status(401).send({ success: false, error: error.message }); - }); + PirateRepository.AddMagnet(magnet) + .then((result) => { + res.send(result); + }) + .catch((error) => { + res.status(401).send({ success: false, error: error.message }); + }); } module.exports = updateRequested; diff --git a/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js b/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js index 6ee8eee..4f85f69 100644 --- a/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js +++ b/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js @@ -15,15 +15,15 @@ const PirateRepository = require('src/pirate/pirateRepository'); * @returns {Callback} */ function updateRequested(req, res) { - const { query, page, type } = req.query; + const { query, page, type } = req.query; - PirateRepository.SearchPiratebay(query, page, type) - .then((result) => { - res.send({ success: true, torrents: result }); - }) - .catch((error) => { - res.status(401).send({ success: false, error: error.message }); - }); + PirateRepository.SearchPiratebay(query, page, type) + .then((result) => { + res.send({ success: true, torrents: result }); + }) + .catch((error) => { + res.status(401).send({ success: false, error: error.message }); + }); } module.exports = updateRequested; diff --git a/seasoned_api/src/webserver/controllers/plex/fetchRequested.js b/seasoned_api/src/webserver/controllers/plex/fetchRequested.js index 673e306..1602aba 100644 --- a/seasoned_api/src/webserver/controllers/plex/fetchRequested.js +++ b/seasoned_api/src/webserver/controllers/plex/fetchRequested.js @@ -9,15 +9,15 @@ const requestRepository = new RequestRepository(); * @returns {Callback} */ function historyController(req, res) { - const user = req.loggedInUser; + // const user = req.loggedInUser; - requestRepository.fetchRequested() - .then((requestedItems) => { - res.send({ success: true, results: requestedItems, total_results: requestedItems.length }); - }) - .catch((error) => { - res.status(401).send({ success: false, error: error.message }); - }); + requestRepository.fetchRequested() + .then((requestedItems) => { + res.send({ success: true, results: requestedItems, total_results: requestedItems.length }); + }) + .catch((error) => { + res.status(401).send({ success: false, error: error.message }); + }); } module.exports = historyController; diff --git a/seasoned_api/src/webserver/controllers/plex/hookDump.js b/seasoned_api/src/webserver/controllers/plex/hookDump.js index 1761757..82d4e69 100644 --- a/seasoned_api/src/webserver/controllers/plex/hookDump.js +++ b/seasoned_api/src/webserver/controllers/plex/hookDump.js @@ -2,13 +2,11 @@ * @Author: KevinMidboe * @Date: 2017-05-03 23:26:46 * @Last Modified by: KevinMidboe -* @Last Modified time: 2017-05-03 23:27:59 +* @Last Modified time: 2018-02-06 20:54:22 */ -const configuration = require('src/config/configuration').getInstance(); - function hookDumpController(req, res) { - console.log(req); + console.log(req); } -module.exports = hookDumpController; \ No newline at end of file +module.exports = hookDumpController; diff --git a/seasoned_api/src/webserver/controllers/plex/plexPlaying.js b/seasoned_api/src/webserver/controllers/plex/plexPlaying.js index 2670ea0..a14ec6a 100644 --- a/seasoned_api/src/webserver/controllers/plex/plexPlaying.js +++ b/seasoned_api/src/webserver/controllers/plex/plexPlaying.js @@ -1,14 +1,15 @@ const PlexRepository = require('src/plex/plexRepository'); + const plexRepository = new PlexRepository(); function playingController(req, res) { - plexRepository.nowPlaying() - .then((movies) => { - res.send(movies); - }) - .catch((error) => { - res.status(500).send({success: false, error: error.message }); - }) + plexRepository.nowPlaying() + .then((movies) => { + res.send(movies); + }) + .catch((error) => { + res.status(500).send({ success: false, error: error.message }); + }); } -module.exports = playingController; \ No newline at end of file +module.exports = playingController; diff --git a/seasoned_api/src/webserver/controllers/plex/readRequest.js b/seasoned_api/src/webserver/controllers/plex/readRequest.js index 0524a2f..351dae6 100644 --- a/seasoned_api/src/webserver/controllers/plex/readRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/readRequest.js @@ -1,4 +1,5 @@ const RequestRepository = require('src/plex/requestRepository'); + const requestRepository = new RequestRepository(); /** @@ -8,14 +9,14 @@ const requestRepository = new RequestRepository(); * @returns {Callback} */ function readRequestController(req, res) { - const mediaId = req.params.mediaId; - const { type } = req.query; - requestRepository.lookup(mediaId, type) - .then((movies) => { - res.send(movies); - }).catch((error) => { - res.status(404).send({ success: false, error: error.message }); - }); + const mediaId = req.params.mediaId; + const { type } = req.query; + requestRepository.lookup(mediaId, type) + .then((movies) => { + res.send(movies); + }).catch((error) => { + res.status(404).send({ success: false, error: error.message }); + }); } module.exports = readRequestController; diff --git a/seasoned_api/src/webserver/controllers/plex/searchMedia.js b/seasoned_api/src/webserver/controllers/plex/searchMedia.js index bef7f26..3351f6c 100644 --- a/seasoned_api/src/webserver/controllers/plex/searchMedia.js +++ b/seasoned_api/src/webserver/controllers/plex/searchMedia.js @@ -1,27 +1,28 @@ const PlexRepository = require('src/plex/plexRepository'); + const plexRepository = new PlexRepository(); /** - * Controller: Search for media and check existence + * 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; + const { query } = req.query; - plexRepository.searchMedia(query) - .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 }); - }) + plexRepository.search(query) + .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 }); + }); } -module.exports = searchMediaController; \ No newline at end of file +module.exports = searchMediaController; diff --git a/seasoned_api/src/webserver/controllers/plex/searchRequest.js b/seasoned_api/src/webserver/controllers/plex/searchRequest.js index 8be256a..e5b038c 100644 --- a/seasoned_api/src/webserver/controllers/plex/searchRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/searchRequest.js @@ -1,24 +1,25 @@ const SearchHistory = require('src/searchHistory/searchHistory'); const Cache = require('src/tmdb/cache'); const RequestRepository = require('src/plex/requestRepository.js'); + 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; + const user = req.headers.loggedinuser; + const { query, page, type } = req.query; - Promise.resolve() - .then(() => searchHistory.create(user, query)) - .then(() => requestRepository.search(query, page, type)) - .then((searchResult) => { - res.send(searchResult); - }) - .catch((error) => { - res.status(500).send({success: false, error: error.message }); - }) + Promise.resolve() + .then(() => searchHistory.create(user, query)) + .then(() => requestRepository.search(query, page, type)) + .then((searchResult) => { + res.send(searchResult); + }) + .catch((error) => { + res.status(500).send({ success: false, error: error.message }); + }); } -module.exports = searchRequestController; \ No newline at end of file +module.exports = searchRequestController; diff --git a/seasoned_api/src/webserver/controllers/plex/submitRequest.js b/seasoned_api/src/webserver/controllers/plex/submitRequest.js index 08f4ca3..6afb085 100644 --- a/seasoned_api/src/webserver/controllers/plex/submitRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/submitRequest.js @@ -1,4 +1,5 @@ const RequestRepository = require('src/plex/requestRepository.js'); + const requestRepository = new RequestRepository(); /** @@ -9,20 +10,20 @@ const requestRepository = new RequestRepository(); */ function submitRequestController(req, res) { - // This is the id that is the param of the url - const id = req.params.mediaId; - const type = req.query.type; - const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; - const user_agent = req.headers['user-agent'] - const user = req.headers.loggedinuser; + // This is the id that is the param of the url + const id = req.params.mediaId; + const type = req.query.type; + const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; + const user_agent = req.headers['user-agent']; + const user = req.headers.loggedinuser; - requestRepository.sendRequest(id, type, ip, user_agent, user) - .then(() => { - res.send({ success: true, message: 'Media item sucessfully requested!' }); - }) - .catch((error) => { - res.status(500).send({ success: false, error: error.message }); - }); + requestRepository.sendRequest(id, type, ip, user_agent, user) + .then(() => { + res.send({ success: true, message: 'Media item sucessfully requested!' }); + }) + .catch((error) => { + res.status(500).send({ success: false, error: error.message }); + }); } -module.exports = submitRequestController; \ No newline at end of file +module.exports = submitRequestController; diff --git a/seasoned_api/src/webserver/controllers/plex/updateRequested.js b/seasoned_api/src/webserver/controllers/plex/updateRequested.js index 57b2638..6057bf4 100644 --- a/seasoned_api/src/webserver/controllers/plex/updateRequested.js +++ b/seasoned_api/src/webserver/controllers/plex/updateRequested.js @@ -1,4 +1,5 @@ const RequestRepository = require('src/plex/requestRepository'); + const requestRepository = new RequestRepository(); /** @@ -8,17 +9,17 @@ const requestRepository = new RequestRepository(); * @returns {Callback} */ function updateRequested(req, res) { - const id = req.params.requestId; - const type = req.body.type; - const status = req.body.status; + const id = req.params.requestId; + const type = req.body.type; + const status = req.body.status; - requestRepository.updateRequestedById(id, type, status) - .then(() => { - res.send({ success: true }); - }) - .catch((error) => { - res.status(401).send({ success: false, error: error.message }); - }); + requestRepository.updateRequestedById(id, type, status) + .then(() => { + res.send({ success: true }); + }) + .catch((error) => { + res.status(401).send({ success: false, error: error.message }); + }); } module.exports = updateRequested; diff --git a/seasoned_api/src/webserver/controllers/seasoned/readStrays.js b/seasoned_api/src/webserver/controllers/seasoned/readStrays.js index 5e5193b..1f87b31 100644 --- a/seasoned_api/src/webserver/controllers/seasoned/readStrays.js +++ b/seasoned_api/src/webserver/controllers/seasoned/readStrays.js @@ -1,16 +1,17 @@ const StrayRepository = require('src/seasoned/strayRepository'); + const strayRepository = new StrayRepository(); function readStraysController(req, res) { - const { verified, page } = req.query; - strayRepository.readAll(verified, page) - .then((strays) => { - res.send(strays); - }) - .catch((error) => { - res.status(500).send({success: false, error: error.message }); - }); + const { verified, page } = req.query; + strayRepository.readAll(verified, page) + .then((strays) => { + res.send(strays); + }) + .catch((error) => { + res.status(500).send({ success: false, error: error.message }); + }); } -module.exports = readStraysController; \ No newline at end of file +module.exports = readStraysController; diff --git a/seasoned_api/src/webserver/controllers/seasoned/strayById.js b/seasoned_api/src/webserver/controllers/seasoned/strayById.js index e86e2ed..9cdd57c 100644 --- a/seasoned_api/src/webserver/controllers/seasoned/strayById.js +++ b/seasoned_api/src/webserver/controllers/seasoned/strayById.js @@ -1,17 +1,17 @@ -const configuration = require('src/config/configuration').getInstance(); const StrayRepository = require('src/seasoned/strayRepository'); + const strayRepository = new StrayRepository(); function strayByIdController(req, res) { - const id = req.params.strayId; + const id = req.params.strayId; - strayRepository.read(id) - .then((stray) => { - res.send(stray); - }) - .catch((error) => { - res.status(500).send({ success: false, error: error.message }); - }); + strayRepository.read(id) + .then((stray) => { + res.send(stray); + }) + .catch((error) => { + res.status(500).send({ success: false, error: error.message }); + }); } module.exports = strayByIdController; diff --git a/seasoned_api/src/webserver/controllers/seasoned/verifyStray.js b/seasoned_api/src/webserver/controllers/seasoned/verifyStray.js index 3f5bf92..79c807c 100644 --- a/seasoned_api/src/webserver/controllers/seasoned/verifyStray.js +++ b/seasoned_api/src/webserver/controllers/seasoned/verifyStray.js @@ -3,15 +3,15 @@ const StrayRepository = require('src/seasoned/strayRepository'); const strayRepository = new StrayRepository(); function verifyStrayController(req, res) { - const id = req.params.strayId; + const id = req.params.strayId; - strayRepository.verifyStray(id) - .then(() => { - res.send({ success: true, message: 'Episode verified' }); - }) - .catch((error) => { - res.status(500).send({ success: false, error: error.message }); - }); + strayRepository.verifyStray(id) + .then(() => { + res.send({ success: true, message: 'Episode verified' }); + }) + .catch((error) => { + res.status(500).send({ success: false, error: error.message }); + }); } module.exports = verifyStrayController; diff --git a/seasoned_api/src/webserver/controllers/tmdb/listSearch.js b/seasoned_api/src/webserver/controllers/tmdb/listSearch.js index 276fd12..103f94c 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/listSearch.js +++ b/seasoned_api/src/webserver/controllers/tmdb/listSearch.js @@ -1,10 +1,10 @@ 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')); - /** * Controller: Retrieve nowplaying movies / now airing shows * @param {Request} req http request variable @@ -12,15 +12,14 @@ const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); * @returns {Callback} */ function listSearchController(req, res) { - const listname = req.params.listname; - const { type, id, page } = req.query; - console.log(listname, type, id, page) - tmdb.listSearch(listname, type, id, page) - .then((results) => { - res.send(results); - }).catch((error) => { - res.status(404).send({ success: false, error: error.message }); - }); + const listname = req.params.listname; + const { type, id, page } = req.query; + tmdb.listSearch(listname, type, id, page) + .then((results) => { + res.send(results); + }).catch((error) => { + res.status(404).send({ success: false, error: error.message }); + }); } module.exports = listSearchController; diff --git a/seasoned_api/src/webserver/controllers/tmdb/readMedia.js b/seasoned_api/src/webserver/controllers/tmdb/readMedia.js index d9d86a4..d2c7294 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/readMedia.js +++ b/seasoned_api/src/webserver/controllers/tmdb/readMedia.js @@ -1,6 +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')); @@ -11,14 +12,14 @@ const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); * @returns {Callback} */ function readMediaController(req, res) { - const mediaId = req.params.mediaId; - const { type } = req.query; - tmdb.lookup(mediaId, type) - .then((movies) => { - res.send(movies); - }).catch((error) => { - res.status(404).send({ success: false, error: error.message }); - }); + const mediaId = req.params.mediaId; + const { type } = req.query; + tmdb.lookup(mediaId, type) + .then((movies) => { + res.send(movies); + }).catch((error) => { + res.status(404).send({ success: false, error: error.message }); + }); } module.exports = readMediaController; diff --git a/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js b/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js index 4443bde..5d5910e 100644 --- a/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js +++ b/seasoned_api/src/webserver/controllers/tmdb/searchMedia.js @@ -1,6 +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')); @@ -11,20 +12,20 @@ const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey')); * @returns {Callback} */ function searchMediaController(req, res) { - const { query, page, type } = req.query; + const { query, page, type } = req.query; - Promise.resolve() - .then(() => tmdb.search(query, page, type)) - .then((movies) => { - if (movies !== undefined || movies.length > 0) { - res.send(movies); - } 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 }); - }); + Promise.resolve() + .then(() => tmdb.search(query, page, type)) + .then((movies) => { + if (movies !== undefined || movies.length > 0) { + res.send(movies); + } 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 }); + }); } module.exports = searchMediaController; diff --git a/seasoned_api/src/webserver/controllers/user/history.js b/seasoned_api/src/webserver/controllers/user/history.js index e619d19..a396c1d 100644 --- a/seasoned_api/src/webserver/controllers/user/history.js +++ b/seasoned_api/src/webserver/controllers/user/history.js @@ -1,4 +1,5 @@ const SearchHistory = require('src/searchHistory/searchHistory'); + const searchHistory = new SearchHistory(); /** @@ -8,15 +9,15 @@ const searchHistory = new SearchHistory(); * @returns {Callback} */ function historyController(req, res) { - const user = req.loggedInUser; + const user = req.loggedInUser; - searchHistory.read(user) - .then((searchQueries) => { - res.send({ success: true, searchQueries }); - }) - .catch((error) => { - res.status(401).send({ success: false, error: error.message }); - }); + searchHistory.read(user) + .then((searchQueries) => { + res.send({ success: true, searchQueries }); + }) + .catch((error) => { + res.status(401).send({ success: false, error: error.message }); + }); } module.exports = historyController; diff --git a/seasoned_api/src/webserver/controllers/user/login.js b/seasoned_api/src/webserver/controllers/user/login.js index 4fe7755..e839276 100644 --- a/seasoned_api/src/webserver/controllers/user/login.js +++ b/seasoned_api/src/webserver/controllers/user/login.js @@ -2,6 +2,7 @@ const User = require('src/user/user'); const Token = require('src/user/token'); const UserSecurity = require('src/user/userSecurity'); const configuration = require('src/config/configuration').getInstance(); + const secret = configuration.get('authentication', 'secret'); const userSecurity = new UserSecurity(); @@ -12,17 +13,17 @@ const userSecurity = new UserSecurity(); * @returns {Callback} */ function loginController(req, res) { - const user = new User(req.body.username); - const password = req.body.password; + const user = new User(req.body.username); + const password = req.body.password; - userSecurity.login(user, password) - .then(() => { - const token = new Token(user).toString(secret); - res.send({ success: true, token }); - }) - .catch((error) => { - res.status(401).send({ success: false, error: error.message }); - }); + userSecurity.login(user, password) + .then(() => { + const token = new Token(user).toString(secret); + res.send({ success: true, token }); + }) + .catch((error) => { + res.status(401).send({ success: false, error: error.message }); + }); } module.exports = loginController; diff --git a/seasoned_api/src/webserver/controllers/user/register.js b/seasoned_api/src/webserver/controllers/user/register.js index b7e081a..6ca3663 100644 --- a/seasoned_api/src/webserver/controllers/user/register.js +++ b/seasoned_api/src/webserver/controllers/user/register.js @@ -1,5 +1,6 @@ const User = require('src/user/user'); const UserSecurity = require('src/user/userSecurity'); + const userSecurity = new UserSecurity(); /** @@ -9,16 +10,16 @@ const userSecurity = new UserSecurity(); * @returns {Callback} */ function registerController(req, res) { - const user = new User(req.body.username, req.body.email); - const password = req.body.password; + const user = new User(req.body.username, req.body.email); + const password = req.body.password; - userSecurity.createNewUser(user, password) - .then(() => { - res.send({ success: true, message: 'Welcome to Seasoned!' }); - }) - .catch((error) => { - res.status(401).send({ success: false, error: error.message }); - }); + userSecurity.createNewUser(user, password) + .then(() => { + res.send({ success: true, message: 'Welcome to Seasoned!' }); + }) + .catch((error) => { + res.status(401).send({ success: false, error: error.message }); + }); } module.exports = registerController; -- 2.34.1 From 58449fc75329d71dfccbfeed301bb8330a78d7ad Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:52:08 +0100 Subject: [PATCH 16/22] Linted all middleware. --- .../middleware/mustBeAuthenticated.js | 14 ++++++------- .../src/webserver/middleware/tokenToUser.js | 21 ++++++++++--------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/seasoned_api/src/webserver/middleware/mustBeAuthenticated.js b/seasoned_api/src/webserver/middleware/mustBeAuthenticated.js index 7613179..17a8973 100644 --- a/seasoned_api/src/webserver/middleware/mustBeAuthenticated.js +++ b/seasoned_api/src/webserver/middleware/mustBeAuthenticated.js @@ -1,11 +1,11 @@ const mustBeAuthenticated = (req, res, next) => { - - if (req.loggedInUser === undefined) { - return res.status(401).send({ - success: false, - error: 'You must be logged in.', - }); } - return next(); + if (req.loggedInUser === undefined) { + return res.status(401).send({ + success: false, + error: 'You must be logged in.', + }); + } + return next(); }; module.exports = mustBeAuthenticated; diff --git a/seasoned_api/src/webserver/middleware/tokenToUser.js b/seasoned_api/src/webserver/middleware/tokenToUser.js index 08e8f2a..462d077 100644 --- a/seasoned_api/src/webserver/middleware/tokenToUser.js +++ b/seasoned_api/src/webserver/middleware/tokenToUser.js @@ -1,5 +1,6 @@ /* eslint-disable no-param-reassign */ const configuration = require('src/config/configuration').getInstance(); + const secret = configuration.get('authentication', 'secret'); const Token = require('src/user/token'); @@ -7,16 +8,16 @@ const Token = require('src/user/token'); // curl -i -H "Authorization:[token]" localhost:31459/api/v1/user/history const tokenToUser = (req, res, next) => { - const rawToken = req.headers.authorization; - if (rawToken) { - try { - const token = Token.fromString(rawToken, secret); - req.loggedInUser = token.user; - } catch (error) { - req.loggedInUser = undefined; - } - } - next(); + const rawToken = req.headers.authorization; + if (rawToken) { + try { + const token = Token.fromString(rawToken, secret); + req.loggedInUser = token.user; + } catch (error) { + req.loggedInUser = undefined; + } + } + next(); }; module.exports = tokenToUser; -- 2.34.1 From 93e1ef6d99f0755d7246740269257853ee32a146 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:52:39 +0100 Subject: [PATCH 17/22] Linted app and server.js files. --- seasoned_api/src/webserver/app.js | 29 ++++++++++++++-------------- seasoned_api/src/webserver/server.js | 11 +++++++---- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/seasoned_api/src/webserver/app.js b/seasoned_api/src/webserver/app.js index df3dfe2..cf5aabc 100644 --- a/seasoned_api/src/webserver/app.js +++ b/seasoned_api/src/webserver/app.js @@ -5,10 +5,9 @@ const tokenToUser = require('./middleware/tokenToUser'); const mustBeAuthenticated = require('./middleware/mustBeAuthenticated'); const configuration = require('src/config/configuration').getInstance(); -// TODO: Have our raven router check if there is a value, if not don't enable raven. +// TODO: Have our raven router check if there is a value, if not don't enable raven. Raven.config(configuration.get('raven', 'DSN')).install(); - const app = express(); // define our app using express app.use(Raven.requestHandler()); // this will let us get the data from a POST @@ -34,27 +33,27 @@ router.use(tokenToUser); // TODO: Should have a separate middleware/router for handling headers. router.use((req, res, next) => { - // TODO add logging of all incoming - console.log('Request: ', req.originalUrl); - const origin = req.headers.origin; - if (allowedOrigins.indexOf(origin) > -1) { - console.log('allowed'); - res.setHeader('Access-Control-Allow-Origin', origin); - } - res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, loggedinuser'); - res.header('Access-Control-Allow-Methods', 'POST, GET, PUT'); + // TODO add logging of all incoming + console.log('Request: ', req.originalUrl); + const origin = req.headers.origin; + if (allowedOrigins.indexOf(origin) > -1) { + console.log('allowed'); + res.setHeader('Access-Control-Allow-Origin', origin); + } + res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, loggedinuser'); + res.header('Access-Control-Allow-Methods', 'POST, GET, PUT'); - next(); + next(); }); router.get('/', function mainHandler(req, res) { - throw new Error('Broke!'); + throw new Error('Broke!'); }); app.use(Raven.errorHandler()); app.use(function onError(err, req, res, next) { - res.statusCode = 500; - res.end(res.sentry + '\n'); + res.statusCode = 500; + res.end(res.sentry + '\n'); }); /** diff --git a/seasoned_api/src/webserver/server.js b/seasoned_api/src/webserver/server.js index b045332..a3f91b4 100644 --- a/seasoned_api/src/webserver/server.js +++ b/seasoned_api/src/webserver/server.js @@ -2,7 +2,10 @@ const config = require('src/config/configuration').getInstance(); const app = require('./app'); module.exports = app.listen(config.get('webserver', 'port'), () => { - console.log('seasonedAPI'); - console.log(`Database is located at ${config.get('database', 'host')}`); - console.log(`Webserver is listening on ${config.get('webserver', 'port')}`); -}) \ No newline at end of file + /* eslint-disable no-console */ + console.log('seasonedAPI'); + /* eslint-disable no-console */ + console.log(`Database is located at ${config.get('database', 'host')}`); + /* eslint-disable no-console */ + console.log(`Webserver is listening on ${config.get('webserver', 'port')}`); +}); -- 2.34.1 From f6c504223a31224bdeee611253dab84a7fb2eec8 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 13:53:15 +0100 Subject: [PATCH 18/22] Now yarn lint lints all files in src not only webserver. --- seasoned_api/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/package.json b/seasoned_api/package.json index 7814f28..7ef0308 100644 --- a/seasoned_api/package.json +++ b/seasoned_api/package.json @@ -5,7 +5,7 @@ "start": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. node src/webserver/server.js", "test": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. mocha --recursive test/system", "coverage": "cross-env PLANFLIX_CONFIG=conf/test.json NODE_PATH=. istanbul cover -x script/autogenerate-documentation.js --include-all-sources --dir test/.coverage node_modules/mocha/bin/_mocha --recursive test/**/* -- --report lcovonly && cat test/.coverage/lcov.info | coveralls && rm -rf test/.coverage", - "lint": "./node_modules/.bin/eslint src/webserver/" + "lint": "./node_modules/.bin/eslint src/" }, "dependencies": { "bcrypt-nodejs": "^0.0.3", -- 2.34.1 From 3ca3c068248c88c8800d71db9823773c2e7360bd Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 14:13:50 +0100 Subject: [PATCH 19/22] Removed static tag in tmdb functions. --- seasoned_api/src/tmdb/tmdb.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seasoned_api/src/tmdb/tmdb.js b/seasoned_api/src/tmdb/tmdb.js index 79b1e40..84ff91b 100644 --- a/seasoned_api/src/tmdb/tmdb.js +++ b/seasoned_api/src/tmdb/tmdb.js @@ -92,7 +92,7 @@ class TMDB { })); } - static tmdbMethod(apiMethod, type) { + tmdbMethod(apiMethod, type) { const method = TMDB_METHODS[apiMethod][type]; if (method !== undefined) return method; throw new Error('Could not find tmdb api method.'); @@ -104,7 +104,7 @@ class TMDB { * @param {type} The type declared in listSearch. * @returns {Promise} dict with tmdb results, mapped as movie/show objects. */ - static mapResults(response, type) { + mapResults(response, type) { return Promise.resolve() .then(() => { const mappedResults = response.results.map(result => convertTmdbToSeasoned(result, type)); -- 2.34.1 From 98b10aa6935eaf08f7ea5184e893ce71a01ac9e7 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 14:15:10 +0100 Subject: [PATCH 20/22] Changed the api endpoint to one that requires to be logged in. --- .../system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/test/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js b/seasoned_api/test/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js index 73811b2..df637bd 100644 --- a/seasoned_api/test/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js +++ b/seasoned_api/test/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js @@ -8,7 +8,7 @@ describe('As a user I want a forbidden error if the token is malformed', () => { it('should return 401', () => request(app) - .get('/api/v1/plex/requests/all') + .get('/api/v1/pirate/search?query=test') .set('Authorization', 'maLfOrMed TOKEN') .expect(401) .then(response => assert.equal(response.body.error, 'You must be logged in.')) -- 2.34.1 From b037cb23a2f64964e9ee2dd70faeb20ef74be045 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 14:16:45 +0100 Subject: [PATCH 21/22] Updated test to reflect new tmdb response. --- .../popular-movies-success-response.json | 376 +----------------- 1 file changed, 1 insertion(+), 375 deletions(-) diff --git a/seasoned_api/test/fixtures/popular-movies-success-response.json b/seasoned_api/test/fixtures/popular-movies-success-response.json index 3a906d4..30b8e5c 100644 --- a/seasoned_api/test/fixtures/popular-movies-success-response.json +++ b/seasoned_api/test/fixtures/popular-movies-success-response.json @@ -1,375 +1 @@ -{ - "page": 1, - "results": [ - { - "background": "/tcheoA2nPATCm2vvXw2hVQoaEFD.jpg", - "genre": [ - 18, - 14, - 27, - 53 - ], - "id": 346364, - "matchedInPlex": false, - "popularity": 847.49142, - "poster": "/9E2y5Q7WlCVNEhP5GiVTjhEhx1o.jpg", - "rating": 7.2, - "summary": "In a small town in Maine, seven children known as The Losers Club come face to face with life problems, bullies and a monster that takes the shape of a clown called Pennywise.", - "title": "It", - "type": "movie", - "vote_count": 4647, - "year": 2017 - }, - { - "background": "/askg3SMvhqEl4OL52YuvdtY40Yb.jpg", - "genre": [ - 12, - 16, - 10751 - ], - "id": 354912, - "matchedInPlex": false, - "popularity": 545.354595, - "poster": "/eKi8dIrr8voobbaGzDpe8w0PVbC.jpg", - "rating": 7.5, - "summary": "Despite his family’s baffling generations-old ban on music, Miguel dreams of becoming an accomplished musician like his idol, Ernesto de la Cruz. Desperate to prove his talent, Miguel finds himself in the stunning and colorful Land of the Dead following a mysterious chain of events. Along the way, he meets charming trickster Hector, and together, they set off on an extraordinary journey to unlock the real story behind Miguel's family history.", - "title": "Coco", - "type": "movie", - "vote_count": 532, - "year": 2017 - }, - { - "background": "/5Iw7zQTHVRBOYpA0V6z0yypOPZh.jpg", - "genre": [ - 28, - 12, - 14, - 878 - ], - "id": 181808, - "matchedInPlex": false, - "popularity": 510.708216, - "poster": "/xGWVjewoXnJhvxKW619cMzppJDQ.jpg", - "rating": 7.5, - "summary": "Rey develops her newly discovered abilities with the guidance of Luke Skywalker, who is unsettled by the strength of her powers. Meanwhile, the Resistance prepares to do battle with the First Order.", - "title": "Star Wars: The Last Jedi", - "type": "movie", - "vote_count": 1054, - "year": 2017 - }, - { - "background": "/o5T8rZxoWSBMYwjsUFUqTt6uMQB.jpg", - "genre": [ - 28, - 12, - 14, - 878 - ], - "id": 141052, - "matchedInPlex": false, - "popularity": 423.487801, - "poster": "/9rtrRGeRnL0JKtu9IMBWsmlmmZz.jpg", - "rating": 6.6, - "summary": "Fueled by his restored faith in humanity and inspired by Superman's selfless act, Bruce Wayne and Diana Prince assemble a team of metahumans consisting of Barry Allen, Arthur Curry, and Victor Stone to face the catastrophic threat of Steppenwolf and the Parademons who are on the hunt for three Mother Boxes on Earth.", - "title": "Justice League", - "type": "movie", - "vote_count": 1805, - "year": 2017 - }, - { - "background": "/52lVqTDhIeNTjT7EiJuovXgw6iE.jpg", - "genre": [ - 12, - 14, - 10751 - ], - "id": 8844, - "matchedInPlex": false, - "popularity": 372.129434, - "poster": "/8wBKXZNod4frLZjAKSDuAcQ2dEU.jpg", - "rating": 6.9, - "summary": "When siblings Judy and Peter discover an enchanted board game that opens the door to a magical world, they unwittingly invite Alan -- an adult who's been trapped inside the game for 26 years -- into their living room. Alan's only hope for freedom is to finish the game, which proves risky as all three find themselves running from giant rhinoceroses, evil monkeys and other terrifying creatures.", - "title": "Jumanji", - "type": "movie", - "vote_count": 2907, - "year": 1995 - }, - { - "background": "/qLmdjn2fv0FV2Mh4NBzMArdA0Uu.jpg", - "genre": [ - 10751, - 16, - 12, - 35 - ], - "id": 211672, - "matchedInPlex": false, - "popularity": 345.173187, - "poster": "/q0R4crx2SehcEEQEkYObktdeFy.jpg", - "rating": 6.4, - "summary": "Minions Stuart, Kevin and Bob are recruited by Scarlet Overkill, a super-villain who, alongside her inventor husband Herb, hatches a plot to take over the world.", - "title": "Minions", - "type": "movie", - "vote_count": 5237, - "year": 2015 - }, - { - "background": "/6aUWe0GSl69wMTSWWexsorMIvwU.jpg", - "genre": [ - 10751, - 14, - 10749 - ], - "id": 321612, - "matchedInPlex": false, - "popularity": 297.124109, - "poster": "/tWqifoYuwLETmmasnGHO7xBjEtt.jpg", - "rating": 6.8, - "summary": "A live-action adaptation of Disney's version of the classic tale of a cursed prince and a beautiful young woman who helps him break the spell.", - "title": "Beauty and the Beast", - "type": "movie", - "vote_count": 6318, - "year": 2017 - }, - { - "background": "/lMDyuHzBhx3zNAv48vYzmgcJCCD.jpg", - "genre": [ - 18, - 35 - ], - "id": 419680, - "matchedInPlex": false, - "popularity": 278.025258, - "poster": "/rF2IoKL0IFmumEXQFUuB8LajTYP.jpg", - "rating": 5.7, - "summary": "Brad and Dusty must deal with their intrusive fathers during the holidays.", - "title": "Daddy's Home 2", - "type": "movie", - "vote_count": 408, - "year": 2017 - }, - { - "background": "/tvKcA4OFUiZkNeTJmmTkNqKHMMg.jpg", - "genre": [ - 80, - 18, - 9648 - ], - "id": 392044, - "matchedInPlex": false, - "popularity": 259.276687, - "poster": "/iBlfxlw8qwtUS0R8YjIU7JtM6LM.jpg", - "rating": 6.8, - "summary": "Genius Belgian detective Hercule Poirot investigates the murder of an American tycoon aboard the Orient Express train.", - "title": "Murder on the Orient Express", - "type": "movie", - "vote_count": 878, - "year": 2017 - }, - { - "background": "/ulMscezy9YX0bhknvJbZoUgQxO5.jpg", - "genre": [ - 18, - 878, - 10752 - ], - "id": 281338, - "matchedInPlex": false, - "popularity": 252.304349, - "poster": "/3vYhLLxrTtZLysXtIWktmd57Snv.jpg", - "rating": 6.7, - "summary": "Caesar and his apes are forced into a deadly conflict with an army of humans led by a ruthless Colonel. After the apes suffer unimaginable losses, Caesar wrestles with his darker instincts and begins his own mythic quest to avenge his kind. As the journey finally brings them face to face, Caesar and the Colonel are pitted against each other in an epic battle that will determine the fate of both their species and the future of the planet.", - "title": "War for the Planet of the Apes", - "type": "movie", - "vote_count": 2692, - "year": 2017 - }, - { - "background": "/rz3TAyd5kmiJmozp3GUbYeB5Kep.jpg", - "genre": [ - 28, - 12, - 35, - 10751 - ], - "id": 353486, - "matchedInPlex": false, - "popularity": 250.35028, - "poster": "/bXrZ5iHBEjH7WMidbUDQ0U2xbmr.jpg", - "rating": 5.6, - "summary": "The tables are turned as four teenagers are sucked into Jumanji's world - pitted against rhinos, black mambas and an endless variety of jungle traps and puzzles. To survive, they'll play as characters from the game.", - "title": "Jumanji: Welcome to the Jungle", - "type": "movie", - "vote_count": 128, - "year": 2017 - }, - { - "background": "/iJ5dkwIHQnq8dfmwSLh7dpETNhi.jpg", - "genre": [ - 35, - 16, - 12 - ], - "id": 355547, - "matchedInPlex": false, - "popularity": 250.28269, - "poster": "/zms2RpkqjAtCsbjndTG9gAGWvnx.jpg", - "rating": 4.6, - "summary": "A small but brave donkey and his animal friends become the unsung heroes of the greatest story ever told, the first Christmas.", - "title": "The Star", - "type": "movie", - "vote_count": 78, - "year": 2017 - }, - { - "background": "/2SEgJ0mHJ7TSdVDbkGU061tR33K.jpg", - "genre": [ - 18, - 53, - 28, - 878 - ], - "id": 347882, - "matchedInPlex": false, - "popularity": 210.896389, - "poster": "/wridRvGxDqGldhzAIh3IcZhHT5F.jpg", - "rating": 5.4, - "summary": "A young street magician is left to take care of his little sister after his mother's passing and turns to drug dealing in the Los Angeles party scene to keep a roof over their heads. When he gets into trouble with his supplier, his sister is kidnapped and he is forced to rely on both his sleight of hand and brilliant mind to save her.", - "title": "Sleight", - "type": "movie", - "vote_count": 156, - "year": 2017 - }, - { - "background": "/5wNUJs23rT5rTBacNyf5h83AynM.jpg", - "genre": [ - 28, - 12, - 35, - 14, - 878 - ], - "id": 284053, - "matchedInPlex": false, - "popularity": 210.575092, - "poster": "/oSLd5GYGsiGgzDPKTwQh7wamO8t.jpg", - "rating": 7.5, - "summary": "Thor is imprisoned on the other side of the universe and finds himself in a race against time to get back to Asgard to stop Ragnarok, the prophecy of destruction to his homeworld and the end of Asgardian civilization, at the hands of an all-powerful new threat, the ruthless Hela.", - "title": "Thor: Ragnarok", - "type": "movie", - "vote_count": 2598, - "year": 2017 - }, - { - "background": "/uExPmkOHJySrbJyJDJylHDqaT58.jpg", - "genre": [ - 28, - 12, - 35 - ], - "id": 343668, - "matchedInPlex": false, - "popularity": 190.179283, - "poster": "/34xBL6BXNYFqtHO9zhcgoakS4aP.jpg", - "rating": 7.1, - "summary": "When an attack on the Kingsman headquarters takes place and a new villain rises, Eggsy and Merlin are forced to work together with the American agency known as the Statesman to save the world.", - "title": "Kingsman: The Golden Circle", - "type": "movie", - "vote_count": 1714, - "year": 2017 - }, - { - "background": "/bAI7aPHQcvSZXvt7L11kMJdS0Gm.jpg", - "genre": [ - 18, - 35, - 36 - ], - "id": 371638, - "matchedInPlex": false, - "popularity": 187.757689, - "poster": "/uCH6FOFsDW6pfvbbmIIswuvuNtM.jpg", - "rating": 7.2, - "summary": "An aspiring actor in Hollywood meets an enigmatic stranger by the name of Tommy Wiseau, the meeting leads the actor down a path nobody could have predicted; creating the worst movie ever made.", - "title": "The Disaster Artist", - "type": "movie", - "vote_count": 87, - "year": 2017 - }, - { - "background": "/2BXd0t9JdVqCp9sKf6kzMkr7QjB.jpg", - "genre": [ - 12, - 10751, - 16, - 28, - 35 - ], - "id": 177572, - "matchedInPlex": false, - "popularity": 180.209866, - "poster": "/9gLu47Zw5ertuFTZaxXOvNfy78T.jpg", - "rating": 7.7, - "summary": "The special bond that develops between plus-sized inflatable robot Baymax, and prodigy Hiro Hamada, who team up with a group of friends to form a band of high-tech heroes.", - "title": "Big Hero 6", - "type": "movie", - "vote_count": 6872, - "year": 2014 - }, - { - "background": "/6iUNJZymJBMXXriQyFZfLAKnjO6.jpg", - "genre": [ - 28, - 12, - 14 - ], - "id": 297762, - "matchedInPlex": false, - "popularity": 176.828995, - "poster": "/imekS7f1OuHyUP2LAiTEM0zBzUz.jpg", - "rating": 7.2, - "summary": "An Amazon princess comes to the world of Man to become the greatest of the female superheroes.", - "title": "Wonder Woman", - "type": "movie", - "vote_count": 6535, - "year": 2017 - }, - { - "background": "/umC04Cozevu8nn3JTDJ1pc7PVTn.jpg", - "genre": [ - 28, - 53 - ], - "id": 245891, - "matchedInPlex": false, - "popularity": 171.364116, - "poster": "/5vHssUeVe25bMrof1HyaPyWgaP.jpg", - "rating": 7, - "summary": "Ex-hitman John Wick comes out of retirement to track down the gangsters that took everything from him.", - "title": "John Wick", - "type": "movie", - "vote_count": 6117, - "year": 2014 - }, - { - "background": "/vc8bCGjdVp0UbMNLzHnHSLRbBWQ.jpg", - "genre": [ - 28, - 12, - 35, - 878 - ], - "id": 315635, - "matchedInPlex": false, - "popularity": 157.789584, - "poster": "/ApYhuwBWzl29Oxe9JJsgL7qILbD.jpg", - "rating": 7.3, - "summary": "Following the events of Captain America: Civil War, Peter Parker, with the help of his mentor Tony Stark, tries to balance his life as an ordinary high school student in Queens, New York City, with fighting crime as his superhero alter ego Spider-Man as a new threat, the Vulture, emerges.", - "title": "Spider-Man: Homecoming", - "type": "movie", - "vote_count": 5218, - "year": 2017 - } - ], - "total_pages": 992 -} \ No newline at end of file +{"results":[{"title":"The Maze Runner","year":2014,"type":"movie","id":198663,"summary":"Set in a post-apocalyptic world, young Thomas is deposited in a community of boys after his memory is erased, soon learning they're all trapped in a maze that will require him to join forces with fellow “runners” for a shot at escape.","poster_path":"/coss7RgL0NH6g4fC2s5atvf3dFO.jpg","background_path":"/lkOZcsXcOLZYeJ2YxJd3vSldvU4.jpg","popularity":435.990884,"score":7},{"title":"Blade Runner 2049","year":2017,"type":"movie","id":335984,"summary":"Thirty years after the events of the first film, a new blade runner, LAPD Officer K, unearths a long-buried secret that has the potential to plunge what's left of society into chaos. K's discovery leads him on a quest to find Rick Deckard, a former LAPD blade runner who has been missing for 30 years.","poster_path":"/gajva2L0rPYkEWjzgFlBXCAVBE5.jpg","background_path":"/mVr0UiqyltcfqxbAUcLl9zWL8ah.jpg","popularity":375.70732,"score":7.4},{"title":"Coco","year":2017,"type":"movie","id":354912,"summary":"Despite his family’s baffling generations-old ban on music, Miguel dreams of becoming an accomplished musician like his idol, Ernesto de la Cruz. Desperate to prove his talent, Miguel finds himself in the stunning and colorful Land of the Dead following a mysterious chain of events. Along the way, he meets charming trickster Hector, and together, they set off on an extraordinary journey to unlock the real story behind Miguel's family history.","poster_path":"/eKi8dIrr8voobbaGzDpe8w0PVbC.jpg","background_path":"/askg3SMvhqEl4OL52YuvdtY40Yb.jpg","popularity":373.720653,"score":7.7},{"title":"It","year":2017,"type":"movie","id":346364,"summary":"In a small town in Maine, seven children known as The Losers Club come face to face with life problems, bullies and a monster that takes the shape of a clown called Pennywise.","poster_path":"/9E2y5Q7WlCVNEhP5GiVTjhEhx1o.jpg","background_path":"/tcheoA2nPATCm2vvXw2hVQoaEFD.jpg","popularity":372.536196,"score":7.1},{"title":"Jumanji","year":1995,"type":"movie","id":8844,"summary":"When siblings Judy and Peter discover an enchanted board game that opens the door to a magical world, they unwittingly invite Alan -- an adult who's been trapped inside the game for 26 years -- into their living room. Alan's only hope for freedom is to finish the game, which proves risky as all three find themselves running from giant rhinoceroses, evil monkeys and other terrifying creatures.","poster_path":"/8wBKXZNod4frLZjAKSDuAcQ2dEU.jpg","background_path":"/7k4zEgUZbzMHawDaMc9yIkmY1qR.jpg","popularity":328.104005,"score":7},{"title":"Sleight","year":2017,"type":"movie","id":347882,"summary":"A young street magician is left to take care of his little sister after his mother's passing and turns to drug dealing in the Los Angeles party scene to keep a roof over their heads. When he gets into trouble with his supplier, his sister is kidnapped and he is forced to rely on both his sleight of hand and brilliant mind to save her.","poster_path":"/wridRvGxDqGldhzAIh3IcZhHT5F.jpg","background_path":"/2SEgJ0mHJ7TSdVDbkGU061tR33K.jpg","popularity":313.194105,"score":5.2},{"title":"Thor: Ragnarok","year":2017,"type":"movie","id":284053,"summary":"Thor is imprisoned on the other side of the universe and finds himself in a race against time to get back to Asgard to stop Ragnarok, the prophecy of destruction to his homeworld and the end of Asgardian civilization, at the hands of an all-powerful new threat, the ruthless Hela.","poster_path":"/oSLd5GYGsiGgzDPKTwQh7wamO8t.jpg","background_path":"/kaIfm5ryEOwYg8mLbq8HkPuM1Fo.jpg","popularity":275.821051,"score":7.5},{"title":"War for the Planet of the Apes","year":2017,"type":"movie","id":281338,"summary":"Caesar and his apes are forced into a deadly conflict with an army of humans led by a ruthless Colonel. After the apes suffer unimaginable losses, Caesar wrestles with his darker instincts and begins his own mythic quest to avenge his kind. As the journey finally brings them face to face, Caesar and the Colonel are pitted against each other in an epic battle that will determine the fate of both their species and the future of the planet.","poster_path":"/3vYhLLxrTtZLysXtIWktmd57Snv.jpg","background_path":"/ulMscezy9YX0bhknvJbZoUgQxO5.jpg","popularity":256.86709,"score":6.8},{"title":"Olaf's Frozen Adventure","year":2017,"type":"movie","id":460793,"summary":"Olaf is on a mission to harness the best holiday traditions for Anna, Elsa, and Kristoff.","poster_path":"/47pLZ1gr63WaciDfHCpmoiXJlVr.jpg","background_path":"/9K4QqQZg4TVXcxBGDiVY4Aey3Rn.jpg","popularity":255.47965,"score":5.9},{"title":"Minions","year":2015,"type":"movie","id":211672,"summary":"Minions Stuart, Kevin and Bob are recruited by Scarlet Overkill, a super-villain who, alongside her inventor husband Herb, hatches a plot to take over the world.","poster_path":"/q0R4crx2SehcEEQEkYObktdeFy.jpg","background_path":"/qLmdjn2fv0FV2Mh4NBzMArdA0Uu.jpg","popularity":211.499685,"score":6.4},{"title":"Baby Driver","year":2017,"type":"movie","id":339403,"summary":"After being coerced into working for a crime boss, a young getaway driver finds himself taking part in a heist doomed to fail.","poster_path":"/dN9LbVNNZFITwfaRjl4tmwGWkRg.jpg","background_path":"/goCvLSUFz0p7k8R10Hv4CVh3EQv.jpg","popularity":208.126298,"score":7.3},{"title":"Batman v Superman: Dawn of Justice","year":2016,"type":"movie","id":209112,"summary":"Fearing the actions of a god-like Super Hero left unchecked, Gotham City’s own formidable, forceful vigilante takes on Metropolis’s most revered, modern-day savior, while the world wrestles with what sort of hero it really needs. And with Batman and Superman at war with one another, a new threat quickly arises, putting mankind in greater danger than it’s ever known before.","poster_path":"/cGOPbv9wA5gEejkUN892JrveARt.jpg","background_path":"/vsjBeMPZtyB7yNsYY56XYxifaQZ.jpg","popularity":186.4518,"score":5.7},{"title":"Pirates of the Caribbean: Dead Men Tell No Tales","year":2017,"type":"movie","id":166426,"summary":"Thrust into an all-new adventure, a down-on-his-luck Capt. Jack Sparrow feels the winds of ill-fortune blowing even more strongly when deadly ghost sailors led by his old nemesis, the evil Capt. Salazar, escape from the Devil's Triangle. Jack's only hope of survival lies in seeking out the legendary Trident of Poseidon, but to find it, he must forge an uneasy alliance with a brilliant and beautiful astronomer and a headstrong young man in the British navy.","poster_path":"/xbpSDU3p7YUGlu9Mr6Egg2Vweto.jpg","background_path":"/7C921eWK06n12c1miRXnYoEu5Yv.jpg","popularity":177.161496,"score":6.5},{"title":"Valerian and the City of a Thousand Planets","year":2017,"type":"movie","id":339964,"summary":"In the 28th century, Valerian and Laureline are special operatives charged with keeping order throughout the human territories. On assignment from the Minister of Defense, the two undertake a mission to Alpha, an ever-expanding metropolis where species from across the universe have converged over centuries to share knowledge, intelligence, and cultures. At the center of Alpha is a mysterious dark force which threatens the peaceful existence of the City of a Thousand Planets, and Valerian and Laureline must race to identify the menace and safeguard not just Alpha, but the future of the universe.","poster_path":"/jfIpMh79fGRqYJ6PwZLCntzgxlF.jpg","background_path":"/7WjMTRF6LDa4latRUIDM25xnDO0.jpg","popularity":175.858459,"score":6.6},{"title":"John Wick","year":2014,"type":"movie","id":245891,"summary":"Ex-hitman John Wick comes out of retirement to track down the gangsters that took everything from him.","poster_path":"/5vHssUeVe25bMrof1HyaPyWgaP.jpg","background_path":"/umC04Cozevu8nn3JTDJ1pc7PVTn.jpg","popularity":171.559878,"score":7},{"title":"Geostorm","year":2017,"type":"movie","id":274855,"summary":"After an unprecedented series of natural disasters threatened the planet, the world's leaders came together to create an intricate network of satellites to control the global climate and keep everyone safe. But now, something has gone wrong: the system built to protect Earth is attacking it, and it becomes a race against the clock to uncover the real threat before a worldwide geostorm wipes out everything and everyone along with it.","poster_path":"/nrsx0jEaBgXq4PWo7SooSnYJTv.jpg","background_path":"/6jrMdMe4sMygTcJPpQTjKPmP4l0.jpg","popularity":159.899247,"score":5.7},{"title":"Beauty and the Beast","year":2017,"type":"movie","id":321612,"summary":"A live-action adaptation of Disney's version of the classic tale of a cursed prince and a beautiful young woman who helps him break the spell.","poster_path":"/tWqifoYuwLETmmasnGHO7xBjEtt.jpg","background_path":"/6aUWe0GSl69wMTSWWexsorMIvwU.jpg","popularity":156.774587,"score":6.8},{"title":"The Hunger Games: Mockingjay - Part 1","year":2014,"type":"movie","id":131631,"summary":"Katniss Everdeen reluctantly becomes the symbol of a mass rebellion against the autocratic Capitol.","poster_path":"/gj282Pniaa78ZJfbaixyLXnXEDI.jpg","background_path":"/4PwyB0ErucIANzW24Kori71J6gU.jpg","popularity":148.551513,"score":6.7},{"title":"Star Wars: The Last Jedi","year":2017,"type":"movie","id":181808,"summary":"Rey develops her newly discovered abilities with the guidance of Luke Skywalker, who is unsettled by the strength of her powers. Meanwhile, the Resistance prepares to do battle with the First Order.","poster_path":"/kOVEVeg59E0wsnXmF9nrh6OmWII.jpg","background_path":"/5Iw7zQTHVRBOYpA0V6z0yypOPZh.jpg","popularity":144.320581,"score":7.2},{"title":"John Wick: Chapter 2","year":2017,"type":"movie","id":324552,"summary":"John Wick is forced out of retirement by a former associate looking to seize control of a shadowy international assassins’ guild. Bound by a blood oath to aid him, Wick travels to Rome and does battle against some of the world’s most dangerous killers.","poster_path":"/zkXnKIwX5pYorKJp2fjFSfNyKT0.jpg","background_path":"/dQ6s3Ud2KoOs3LKw6xgZr1cw7Yq.jpg","popularity":137.808961,"score":6.8}],"page":1,"total_pages":988,"total_results":19757} \ No newline at end of file -- 2.34.1 From 30b494e3565cb480dd1e27224def19d0d2972075 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Feb 2018 14:20:34 +0100 Subject: [PATCH 22/22] The id used for searching was somehow not a movies id and returned false. --- seasoned_api/test/system/asAUserIWantToRequestAMovie.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/test/system/asAUserIWantToRequestAMovie.js b/seasoned_api/test/system/asAUserIWantToRequestAMovie.js index fda5f0a..f51c085 100644 --- a/seasoned_api/test/system/asAUserIWantToRequestAMovie.js +++ b/seasoned_api/test/system/asAUserIWantToRequestAMovie.js @@ -10,7 +10,7 @@ describe('As a user I want to request a movie', () => { it('should return 200 when item is requested', () => request(app) - .post('/api/v1/plex/request/31749') + .post('/api/v1/plex/request/329865') .set('Authorization', createToken('test_user', 'secret')) .expect(200) ); -- 2.34.1