From 4bc94ae3b7f881a7c96bb28a7dcd5862f12f71c6 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 26 Feb 2018 16:59:56 +0100 Subject: [PATCH 01/37] When a element is not found in plex it now still gets a matchedInPlex value, now False when not found. --- seasoned_api/.gitignore | 4 +++- seasoned_api/src/plex/plexRepository.js | 13 +++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/seasoned_api/.gitignore b/seasoned_api/.gitignore index 436d607..b275448 100644 --- a/seasoned_api/.gitignore +++ b/seasoned_api/.gitignore @@ -61,4 +61,6 @@ typings/ # - - - - - # My own gitignore files and folders shows.db -conf/ +conf/development.json + +# conf/development-prod.json diff --git a/seasoned_api/src/plex/plexRepository.js b/seasoned_api/src/plex/plexRepository.js index a51f331..c02a65a 100644 --- a/seasoned_api/src/plex/plexRepository.js +++ b/seasoned_api/src/plex/plexRepository.js @@ -26,10 +26,15 @@ class PlexRepository { 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; - }); + if (plexResult.results.length === 0) { + tmdb.matchedInPlex = false + } + else { + plexResult.results.map((plexItem) => { + if (tmdb.title === plexItem.title && tmdb.year === plexItem.year) { tmdb.matchedInPlex = true; } + return tmdb; + }); + } return tmdb; }); } From ec0923f1c0e943acc8580c9a7333c09c31e22c55 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 26 Feb 2018 17:17:37 +0100 Subject: [PATCH 02/37] Can now filter the response by status. --- seasoned_api/src/plex/requestRepository.js | 10 +++++++--- .../src/webserver/controllers/plex/fetchRequested.js | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index 3cfb60b..2c4b58e 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -17,7 +17,8 @@ class RequestRepository { this.database = database || establishedDatabase; this.queries = { insertRequest: "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_DATE, 'requested', ?, ?)", - fetchRequstedItems: 'SELECT * FROM requests', + fetchRequestedItems: 'SELECT * FROM requests', + fetchRequestedItemsByStatus: 'SELECT * FROM requests WHERE status is ?', updateRequestedById: 'UPDATE requests SET status = ? WHERE id is ? AND type is ?', checkIfIdRequested: 'SELECT * FROM requests WHERE id IS ? AND type IS ?', }; @@ -105,8 +106,11 @@ class RequestRepository { return Promise.resolve(); } - fetchRequested() { - return this.database.all(this.queries.fetchRequstedItems); + fetchRequested(status) { + if (status === 'requested' || status === 'downloading' || status === 'downloaded') + return this.database.all(this.queries.fetchRequestedItemsByStatus, status); + else + return this.database.all(this.queries.fetchRequestedItems); } updateRequestedById(id, type, status) { diff --git a/seasoned_api/src/webserver/controllers/plex/fetchRequested.js b/seasoned_api/src/webserver/controllers/plex/fetchRequested.js index 1602aba..3f5f4d0 100644 --- a/seasoned_api/src/webserver/controllers/plex/fetchRequested.js +++ b/seasoned_api/src/webserver/controllers/plex/fetchRequested.js @@ -10,8 +10,9 @@ const requestRepository = new RequestRepository(); */ function historyController(req, res) { // const user = req.loggedInUser; + const { status } = req.query; - requestRepository.fetchRequested() + requestRepository.fetchRequested(status) .then((requestedItems) => { res.send({ success: true, results: requestedItems, total_results: requestedItems.length }); }) From 08b373cba039e1df8ef2071ef05460d86d40a72c Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 26 Feb 2018 19:58:54 +0100 Subject: [PATCH 03/37] Response results are now saved in the object results instead of torrents --- seasoned_api/src/webserver/controllers/pirate/searchTheBay.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js b/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js index 4f85f69..fcba93a 100644 --- a/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js +++ b/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js @@ -2,7 +2,7 @@ * @Author: KevinMidboe * @Date: 2017-10-21 09:54:31 * @Last Modified by: KevinMidboe -* @Last Modified time: 2017-10-21 12:12:26 +* @Last Modified time: 2018-02-26 19:56:32 */ const PirateRepository = require('src/pirate/pirateRepository'); @@ -19,7 +19,7 @@ function updateRequested(req, res) { PirateRepository.SearchPiratebay(query, page, type) .then((result) => { - res.send({ success: true, torrents: result }); + res.send({ success: true, results: result }); }) .catch((error) => { res.status(401).send({ success: false, error: error.message }); From e6a851543210e4b46e2fa047cb9e84cc992054b2 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:12:21 +0100 Subject: [PATCH 04/37] Now we can check if user is admin. This has to be set manually and now only is used for fetching torrents. --- seasoned_api/src/database/schemas/setup.sql | 1 + .../src/webserver/middleware/mustBeAdmin.js | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 seasoned_api/src/webserver/middleware/mustBeAdmin.js diff --git a/seasoned_api/src/database/schemas/setup.sql b/seasoned_api/src/database/schemas/setup.sql index 9b54acd..83b11d7 100644 --- a/seasoned_api/src/database/schemas/setup.sql +++ b/seasoned_api/src/database/schemas/setup.sql @@ -2,6 +2,7 @@ CREATE TABLE IF NOT EXISTS user ( user_name varchar(127) UNIQUE, password varchar(127), email varchar(127) UNIQUE, + admin boolean DEFAULT 0, primary key (user_name) ); diff --git a/seasoned_api/src/webserver/middleware/mustBeAdmin.js b/seasoned_api/src/webserver/middleware/mustBeAdmin.js new file mode 100644 index 0000000..9d35d53 --- /dev/null +++ b/seasoned_api/src/webserver/middleware/mustBeAdmin.js @@ -0,0 +1,26 @@ +const establishedDatabase = require('src/database/database'); + +const mustBeAdmin = (req, res, next) => { + let database = establishedDatabase; + + if (req.loggedInUser === undefined) { + return res.status(401).send({ + success: false, + error: 'You must be logged in.', + }); + } else { + database.get(`SELECT admin FROM user WHERE user_name IS ?`, req.loggedInUser.username) + .then((isAdmin) => { + if (isAdmin.admin == 0) { + return res.status(401).send({ + success: false, + error: 'You must be logged in as a admin.' + }) + } + }) + } + + return next(); +}; + +module.exports = mustBeAdmin; From 34a97c069b76af1332848ab552dd3e4989ed2e74 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:16:10 +0100 Subject: [PATCH 05/37] Updated from sqlite to sqlite3 now all functions are async so we wait for response. --- seasoned_api/src/database/sqliteDatabase.js | 49 ++++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/seasoned_api/src/database/sqliteDatabase.js b/seasoned_api/src/database/sqliteDatabase.js index 76b92f6..7b346a6 100644 --- a/seasoned_api/src/database/sqliteDatabase.js +++ b/seasoned_api/src/database/sqliteDatabase.js @@ -1,12 +1,12 @@ const fs = require('fs'); const path = require('path'); -const sqlite = require('sqlite'); +const sqlite3 = require('sqlite3').verbose(); class SqliteDatabase { constructor(host) { this.host = host; - this.connection = sqlite; + this.connection = this.connect() this.schemaDirectory = path.join(__dirname, 'schemas'); } @@ -14,10 +14,12 @@ class SqliteDatabase { * Connect to the database. * @returns {Promise} succeeds if connection was established */ - connect() { + async connect() { return Promise.resolve() - .then(() => sqlite.open(this.host)) - .then(() => sqlite.exec('pragma foreign_keys = on;')); + .then(() => { + this.connection = new sqlite3.Database(this.host); + this.connection.run('PRAGMA foreign_keys=on') + }); } /** @@ -27,7 +29,13 @@ class SqliteDatabase { * @returns {Promise} */ run(sql, parameters) { - return this.connection.run(sql, parameters); + return new Promise((resolve, reject) => { + this.connection.run(sql, parameters, (error, result) => { + if (error) + reject(error); + resolve(result) + }); + }); } /** @@ -36,8 +44,15 @@ class SqliteDatabase { * @param {Array} parameters in the SQL query * @returns {Promise} */ - all(sql, parameters) { - return this.connection.all(sql, parameters); + async all(sql, parameters) { + return new Promise((resolve, reject) => { + this.connection.all(sql, parameters, (err, rows) => { + if (err) { + reject(err); + } + resolve(rows); + }) + }) } /** @@ -46,8 +61,16 @@ class SqliteDatabase { * @param {Array} parameters in the SQL query * @returns {Promise} */ - get(sql, parameters) { - return this.connection.get(sql, parameters); + async get(sql, parameters) { + return new Promise((resolve, reject) => { + this.connection.get(sql, parameters, (err, rows) => { + if (err) { + reject(err); + } + console.log('rows', rows) + resolve(rows); + }) + }) } /** @@ -56,8 +79,10 @@ class SqliteDatabase { * @param {Array} parameters in the SQL query * @returns {Promise} */ - execute(sql) { - return this.connection.exec(sql); + async execute(sql) { + return new Promise(resolve => { + resolve(this.connection.exec(sql)); + }) } /** From 6619184a45c3405d19c53df1bf220fd3537c410a Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:18:51 +0100 Subject: [PATCH 06/37] When creating a account the email field is now optional. --- seasoned_api/src/user/user.js | 2 +- seasoned_api/src/user/userRepository.js | 11 ++++------- seasoned_api/src/user/userSecurity.js | 2 -- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/seasoned_api/src/user/user.js b/seasoned_api/src/user/user.js index d922fbb..bdf326a 100644 --- a/seasoned_api/src/user/user.js +++ b/seasoned_api/src/user/user.js @@ -1,5 +1,5 @@ class User { - constructor(username, email) { + constructor(username, email=undefined) { this.username = username; this.email = email; } diff --git a/seasoned_api/src/user/userRepository.js b/seasoned_api/src/user/userRepository.js index b672a4d..5a0e9b1 100644 --- a/seasoned_api/src/user/userRepository.js +++ b/seasoned_api/src/user/userRepository.js @@ -6,7 +6,7 @@ class UserRepository { this.database = database || establishedDatabase; this.queries = { read: 'select * from user where lower(user_name) = lower(?)', - create: 'insert into user (user_name, email) values(?, ?)', + create: 'insert into user (user_name) values (?)', change: 'update user set password = ? where user_name = ?', retrieveHash: 'select * from user where user_name = ?', }; @@ -20,13 +20,10 @@ class UserRepository { 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])) + .then(() => this.database.run(this.queries.create, user.username)) .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'); + if (error.name === 'AssertionError' || error.message.endsWith('user_name')) { + throw new Error('That username is already registered'); } }); } diff --git a/seasoned_api/src/user/userSecurity.js b/seasoned_api/src/user/userSecurity.js index 71583db..9cf4ba4 100644 --- a/seasoned_api/src/user/userSecurity.js +++ b/seasoned_api/src/user/userSecurity.js @@ -15,8 +15,6 @@ class UserSecurity { 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 { From 2df734bb32f50e2401b1e2e972490274661519c3 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:20:32 +0100 Subject: [PATCH 07/37] ADded endpoints for checking search history and the items a user has requested, both require authentication. Changed that searching for torrents now require being admin not just signed in. --- seasoned_api/src/webserver/app.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/seasoned_api/src/webserver/app.js b/seasoned_api/src/webserver/app.js index cf5aabc..67adcd6 100644 --- a/seasoned_api/src/webserver/app.js +++ b/seasoned_api/src/webserver/app.js @@ -3,6 +3,7 @@ const Raven = require('raven'); const bodyParser = require('body-parser'); const tokenToUser = require('./middleware/tokenToUser'); const mustBeAuthenticated = require('./middleware/mustBeAuthenticated'); +const mustBeAdmin = require('./middleware/mustBeAdmin'); const configuration = require('src/config/configuration').getInstance(); // TODO: Have our raven router check if there is a value, if not don't enable raven. @@ -61,7 +62,8 @@ app.use(function onError(err, req, res, next) { */ router.post('/v1/user', require('./controllers/user/register.js')); router.post('/v1/user/login', require('./controllers/user/login.js')); -router.get('/v1/user/history', require('./controllers/user/history.js')); +router.get('/v1/user/history', mustBeAuthenticated, require('./controllers/user/history.js')); +router.get('/v1/user/requests', mustBeAuthenticated, require('./controllers/user/requests.js')); /** * Seasoned @@ -89,7 +91,7 @@ router.put('/v1/plex/request/:requestId', mustBeAuthenticated, require('./contro /** * Pirate */ -router.get('/v1/pirate/search', mustBeAuthenticated, require('./controllers/pirate/searchTheBay.js')); +router.get('/v1/pirate/search', mustBeAdmin, require('./controllers/pirate/searchTheBay.js')); router.post('/v1/pirate/add', mustBeAuthenticated, require('./controllers/pirate/addMagnet.js')); /** From 1a693ef92f4f30958af824586a6cd63a6ba85cad Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:21:55 +0100 Subject: [PATCH 08/37] Our new controller for getting a users requested items. --- .../webserver/controllers/user/requests.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 seasoned_api/src/webserver/controllers/user/requests.js diff --git a/seasoned_api/src/webserver/controllers/user/requests.js b/seasoned_api/src/webserver/controllers/user/requests.js new file mode 100644 index 0000000..2b0b2d4 --- /dev/null +++ b/seasoned_api/src/webserver/controllers/user/requests.js @@ -0,0 +1,25 @@ +const RequestRepository = require('src/plex/requestRepository.js'); + +const requestRepository = new RequestRepository(); + +/** + * Controller: Retrieves search history of a logged in user + * @param {Request} req http request variable + * @param {Response} res + * @returns {Callback} + */ +function requestsController(req, res) { + const user = req.loggedInUser; + console.log('user: ', user) + + requestRepository.userRequests(user) + .then((requests) => { + res.send({ success: true, results: requests, total_results: requests.length }); + }) + .catch((error) => { + console.log(error) + res.status(500).send({ success: false, error: error }); + }); +} + +module.exports = requestsController; From e11dfc7712548231691d369c0552e6be3ebecb1f Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:23:11 +0100 Subject: [PATCH 09/37] Renamed class name. --- seasoned_api/src/webserver/controllers/plex/fetchRequested.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seasoned_api/src/webserver/controllers/plex/fetchRequested.js b/seasoned_api/src/webserver/controllers/plex/fetchRequested.js index 3f5f4d0..f216396 100644 --- a/seasoned_api/src/webserver/controllers/plex/fetchRequested.js +++ b/seasoned_api/src/webserver/controllers/plex/fetchRequested.js @@ -8,7 +8,7 @@ const requestRepository = new RequestRepository(); * @param {Response} res * @returns {Callback} */ -function historyController(req, res) { +function fetchRequestedController(req, res) { // const user = req.loggedInUser; const { status } = req.query; @@ -21,4 +21,4 @@ function historyController(req, res) { }); } -module.exports = historyController; +module.exports = fetchRequestedController; From cede376349b62bc6376ff1e5f7d2ea650fec6f7b Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:24:58 +0100 Subject: [PATCH 10/37] Was not using the registered loggedInUser variable, but one passed by client --- seasoned_api/src/webserver/controllers/plex/searchRequest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/webserver/controllers/plex/searchRequest.js b/seasoned_api/src/webserver/controllers/plex/searchRequest.js index e5b038c..74873d4 100644 --- a/seasoned_api/src/webserver/controllers/plex/searchRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/searchRequest.js @@ -8,7 +8,7 @@ const searchHistory = new SearchHistory(); function searchRequestController(req, res) { - const user = req.headers.loggedinuser; + const user = req.loggedInUser; const { query, page, type } = req.query; Promise.resolve() From ca146d77bc3c09b1b81fd882c9001043a62e63c8 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:25:33 +0100 Subject: [PATCH 11/37] Fixed error message --- seasoned_api/src/webserver/controllers/user/history.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/webserver/controllers/user/history.js b/seasoned_api/src/webserver/controllers/user/history.js index a396c1d..54b2ff0 100644 --- a/seasoned_api/src/webserver/controllers/user/history.js +++ b/seasoned_api/src/webserver/controllers/user/history.js @@ -16,7 +16,7 @@ function historyController(req, res) { res.send({ success: true, searchQueries }); }) .catch((error) => { - res.status(401).send({ success: false, error: error.message }); + res.status(404).send({ success: false, error: error }); }); } From 7c4aeb48abb8a709b5db3608d2b9fac5b3d259a9 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:26:28 +0100 Subject: [PATCH 12/37] When registering a token is also returned so we dont need to sign in after registration. --- seasoned_api/src/webserver/controllers/user/register.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/seasoned_api/src/webserver/controllers/user/register.js b/seasoned_api/src/webserver/controllers/user/register.js index 6ca3663..96322a5 100644 --- a/seasoned_api/src/webserver/controllers/user/register.js +++ b/seasoned_api/src/webserver/controllers/user/register.js @@ -1,6 +1,9 @@ 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(); /** @@ -15,7 +18,8 @@ function registerController(req, res) { userSecurity.createNewUser(user, password) .then(() => { - res.send({ success: true, message: 'Welcome to Seasoned!' }); + const token = new Token(user).toString(secret); + res.send({ success: true, message: 'Welcome to Seasoned!', token}); }) .catch((error) => { res.status(401).send({ success: false, error: error.message }); From aa0094762b8fa02df081cd67c7aab6891362a55e Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:27:18 +0100 Subject: [PATCH 13/37] Now save only the username of the user in search history. --- seasoned_api/src/searchHistory/searchHistory.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seasoned_api/src/searchHistory/searchHistory.js b/seasoned_api/src/searchHistory/searchHistory.js index c51590e..2be86e7 100644 --- a/seasoned_api/src/searchHistory/searchHistory.js +++ b/seasoned_api/src/searchHistory/searchHistory.js @@ -15,7 +15,7 @@ class SearchHistory { * @returns {Promise} */ read(user) { - return this.database.all(this.queries.read, user) + return this.database.all(this.queries.read, user.username) .then(rows => rows.map(row => row.search_query)); } @@ -26,7 +26,7 @@ class SearchHistory { * @returns {Promise} */ create(user, searchQuery) { - return this.database.run(this.queries.create, [searchQuery, user]) + return this.database.run(this.queries.create, [searchQuery, user.username]) .catch((error) => { if (error.message.includes('FOREIGN')) { throw new Error('Could not create search history.'); From 404c20047491827991b89508b0e20bc90b786450 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:29:21 +0100 Subject: [PATCH 14/37] Removed unused mail conf and added a function for getting all requested elements by loggedInUser. --- seasoned_api/src/plex/requestRepository.js | 68 +++++++--------------- 1 file changed, 22 insertions(+), 46 deletions(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index 2c4b58e..cbd3f20 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -17,17 +17,21 @@ class RequestRepository { this.database = database || establishedDatabase; this.queries = { insertRequest: "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_DATE, 'requested', ?, ?)", - fetchRequestedItems: 'SELECT * FROM requests', - fetchRequestedItemsByStatus: 'SELECT * FROM requests WHERE status is ?', + fetchRequestedItems: 'SELECT * FROM requests ORDER BY name ASC', + fetchRequestedItemsByStatus: 'SELECT * FROM requests WHERE status IS ? AND type LIKE ?', updateRequestedById: 'UPDATE requests SET status = ? WHERE id is ? AND type is ?', checkIfIdRequested: 'SELECT * FROM requests WHERE id IS ? AND type IS ?', + userRequests: 'SELECT * FROM requests WHERE requested_by IS ?' + }; + this.cacheTags = { + search: 'se', + lookup: 'i', }; } 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}`); } @@ -65,52 +69,24 @@ class RequestRepository { 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 - 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); - - // 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); - }); }); - - // TODO add better response when done. - return Promise.resolve(); } - fetchRequested(status) { - if (status === 'requested' || status === 'downloading' || status === 'downloaded') - return this.database.all(this.queries.fetchRequestedItemsByStatus, status); - else - return this.database.all(this.queries.fetchRequestedItems); + fetchRequested(status, type = '%') { + return Promise.resolve() + .then(() => { + return this.database.all(this.queries.fetchRequestedItems); + }) + } + + userRequests(user) { + return Promise.resolve() + .then(() => this.database.all(this.queries.userRequests, user.username)) + .catch((error) => { + if (String(error).includes('no such column')) { throw new Error('Username not found'); } + else { throw new Error('Unable to fetch your requests')} + }) + .then((result) => { return result }) } updateRequestedById(id, type, status) { From 02c36d041a95ec241540e81d92e399f8d6b13d25 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:30:11 +0100 Subject: [PATCH 15/37] Removed console.log and fixed docstring comment. --- seasoned_api/src/webserver/controllers/user/requests.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/seasoned_api/src/webserver/controllers/user/requests.js b/seasoned_api/src/webserver/controllers/user/requests.js index 2b0b2d4..98bb219 100644 --- a/seasoned_api/src/webserver/controllers/user/requests.js +++ b/seasoned_api/src/webserver/controllers/user/requests.js @@ -3,14 +3,13 @@ const RequestRepository = require('src/plex/requestRepository.js'); const requestRepository = new RequestRepository(); /** - * Controller: Retrieves search history of a logged in user + * Controller: Retrieves requested items of a logged in user * @param {Request} req http request variable * @param {Response} res * @returns {Callback} */ function requestsController(req, res) { const user = req.loggedInUser; - console.log('user: ', user) requestRepository.userRequests(user) .then((requests) => { From 164191f89d340be9a28b760debf10edd2c2dc001 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:32:21 +0100 Subject: [PATCH 16/37] =?UTF-8?q?Fixed=20indentation=20and=20updated=20sql?= =?UTF-8?q?ite=20to=20sqlite3!=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seasoned_api/package.json | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/seasoned_api/package.json b/seasoned_api/package.json index 7ef0308..a7a3720 100644 --- a/seasoned_api/package.json +++ b/seasoned_api/package.json @@ -4,7 +4,7 @@ "scripts": { "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", + "coverage": "cross-env SEASONED_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/" }, "dependencies": { @@ -12,7 +12,7 @@ "body-parser": "~1.0.1", "cross-env": "^3.1.3", "express": "~4.11.0", - "jsonwebtoken": "^8.0.1", + "jsonwebtoken": "^8.0.1", "mongoose": "^3.6.13", "moviedb": "^0.2.10", "node-cache": "^4.1.1", @@ -21,17 +21,15 @@ "raven": "^2.2.1", "request": "^2.81.0", "request-promise": "^4.2", - "sqlite": "^2.9.0" + "sqlite3": "3.1.13" }, "devDependencies": { - "eslint": "^4.9.0", + "eslint": "^4.9.0", "eslint-config-airbnb-base": "^12.1.0", "eslint-plugin-import": "^2.8.0", - "eslint": "^4.9.0", "istanbul": "^0.4.5", "mocha": "^3.1.0", "supertest": "^2.0.1", "supertest-as-promised": "^4.0.1" - } } From d3b4a342981146adb9223e3c0c88bb812fe14c74 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:32:51 +0100 Subject: [PATCH 17/37] Re-added filter options for later use. --- seasoned_api/src/plex/requestRepository.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index cbd3f20..ecc8e3b 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -75,7 +75,10 @@ class RequestRepository { fetchRequested(status, type = '%') { return Promise.resolve() .then(() => { - return this.database.all(this.queries.fetchRequestedItems); + if (status === 'requested' || status === 'downloading' || status === 'downloaded') + return this.database.all(this.queries.fetchRequestedItemsByStatus, [status, type]); + else + return this.database.all(this.queries.fetchRequestedItems); }) } From cffba202b0f7e0cab0445290f988d62cdbd1dfff Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 19:33:22 +0100 Subject: [PATCH 18/37] Now the server does not crash when unable to search plex. --- seasoned_api/src/plex/plexRepository.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/seasoned_api/src/plex/plexRepository.js b/seasoned_api/src/plex/plexRepository.js index c02a65a..0a506c6 100644 --- a/seasoned_api/src/plex/plexRepository.js +++ b/seasoned_api/src/plex/plexRepository.js @@ -6,7 +6,12 @@ class PlexRepository { inPlex(tmdbResult) { return Promise.resolve() .then(() => this.search(tmdbResult.title)) - .then(plexResult => this.compareTmdbToPlex(tmdbResult, plexResult)); + .then(plexResult => this.compareTmdbToPlex(tmdbResult, plexResult)) + .catch((error) => { + console.log(error) + tmdbResult.matchedInPlex = false; + return tmdbResult; + }); } search(query) { @@ -19,6 +24,9 @@ class PlexRepository { }; return rp(options) + .catch((error) => { + throw new Error('Unable to search plex.') + }) .then(result => this.mapResults(result)) .then(([mappedResults, resultCount]) => ({ results: mappedResults, total_results: resultCount })); } From 354b8333751b8fcca7c06e23839311c3976bcf56 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 21:24:18 +0100 Subject: [PATCH 19/37] Removed console log of table data. --- seasoned_api/src/database/sqliteDatabase.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/seasoned_api/src/database/sqliteDatabase.js b/seasoned_api/src/database/sqliteDatabase.js index 7b346a6..10c2262 100644 --- a/seasoned_api/src/database/sqliteDatabase.js +++ b/seasoned_api/src/database/sqliteDatabase.js @@ -14,12 +14,10 @@ class SqliteDatabase { * Connect to the database. * @returns {Promise} succeeds if connection was established */ - async connect() { - return Promise.resolve() - .then(() => { - this.connection = new sqlite3.Database(this.host); - this.connection.run('PRAGMA foreign_keys=on') - }); + connect() { + let database = new sqlite3.Database(this.host); + this.connection = database; + return database; } /** @@ -67,7 +65,6 @@ class SqliteDatabase { if (err) { reject(err); } - console.log('rows', rows) resolve(rows); }) }) From e65d4125b9f4cb8445b0f9d45acd690de082424a Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 21:27:31 +0100 Subject: [PATCH 20/37] Trying to sort on the wrong column name. --- seasoned_api/src/plex/requestRepository.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index ecc8e3b..1958bb9 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -17,7 +17,7 @@ class RequestRepository { this.database = database || establishedDatabase; this.queries = { insertRequest: "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_DATE, 'requested', ?, ?)", - fetchRequestedItems: 'SELECT * FROM requests ORDER BY name ASC', + fetchRequestedItems: 'SELECT * FROM requests ORDER BY requested_by ASC', fetchRequestedItemsByStatus: 'SELECT * FROM requests WHERE status IS ? AND type LIKE ?', updateRequestedById: 'UPDATE requests SET status = ? WHERE id is ? AND type is ?', checkIfIdRequested: 'SELECT * FROM requests WHERE id IS ? AND type IS ?', From fac9e0e425dc6ed504e44a62795ebd131730c3f8 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 22:02:32 +0100 Subject: [PATCH 21/37] Added a endpoint to fetch a random emoji. --- seasoned_api/src/webserver/app.js | 4 ++++ .../src/webserver/controllers/misc/emoji.js | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 seasoned_api/src/webserver/controllers/misc/emoji.js diff --git a/seasoned_api/src/webserver/app.js b/seasoned_api/src/webserver/app.js index 67adcd6..58dc4fa 100644 --- a/seasoned_api/src/webserver/app.js +++ b/seasoned_api/src/webserver/app.js @@ -106,6 +106,10 @@ router.get('/v1/tmdb/:mediaId', require('./controllers/tmdb/readMedia.js')); */ router.post('/v1/git/dump', require('./controllers/git/dumpHook.js')); +/** + * misc + */ + router.get('v1/emoji', require('./controllers/misc/emoji.js')); // REGISTER OUR ROUTES ------------------------------- // all of our routes will be prefixed with /api diff --git a/seasoned_api/src/webserver/controllers/misc/emoji.js b/seasoned_api/src/webserver/controllers/misc/emoji.js new file mode 100644 index 0000000..546d93b --- /dev/null +++ b/seasoned_api/src/webserver/controllers/misc/emoji.js @@ -0,0 +1,23 @@ +const RequestRepository = require('src/plex/requestRepository.js'); + +const requestRepository = new RequestRepository(); + +/** + * Controller: Returns a random emoji โœจ + * @param {Request} req http request variable + * @param {Response} res + * @returns {Callback} + */ +function emojiController(req, res) { + var emojis = [ + '๐Ÿ˜„','๐Ÿ˜ƒ','๐Ÿ˜€','๐Ÿ˜Š','โ˜บ','๐Ÿ˜‰','๐Ÿ˜','๐Ÿ˜˜','๐Ÿ˜š','๐Ÿ˜—','๐Ÿ˜™','๐Ÿ˜œ','๐Ÿ˜','๐Ÿ˜›','๐Ÿ˜ณ','๐Ÿ˜','๐Ÿ˜”','๐Ÿ˜Œ','๐Ÿ˜’','๐Ÿ˜ž','๐Ÿ˜ฃ','๐Ÿ˜ข','๐Ÿ˜‚','๐Ÿ˜ญ','๐Ÿ˜ช','๐Ÿ˜ฅ','๐Ÿ˜ฐ','๐Ÿ˜…','๐Ÿ˜“','๐Ÿ˜ฉ','๐Ÿ˜ซ','๐Ÿ˜จ','๐Ÿ˜ฑ','๐Ÿ˜ ','๐Ÿ˜ก','๐Ÿ˜ค','๐Ÿ˜–','๐Ÿ˜†','๐Ÿ˜‹','๐Ÿ˜ท','๐Ÿ˜Ž','๐Ÿ˜ด','๐Ÿ˜ต','๐Ÿ˜ฒ','๐Ÿ˜Ÿ','๐Ÿ˜ฆ','๐Ÿ˜ง','๐Ÿ˜ˆ','๐Ÿ‘ฟ','๐Ÿ˜ฎ','๐Ÿ˜ฌ','๐Ÿ˜','๐Ÿ˜•','๐Ÿ˜ฏ','๐Ÿ˜ถ','๐Ÿ˜‡','๐Ÿ˜','๐Ÿ˜‘','๐Ÿ‘ฒ','๐Ÿ‘ณ','๐Ÿ‘ฎ','๐Ÿ‘ท','๐Ÿ’‚','๐Ÿ‘ถ','๐Ÿ‘ฆ','๐Ÿ‘ง','๐Ÿ‘จ','๐Ÿ‘ฉ','๐Ÿ‘ด','๐Ÿ‘ต','๐Ÿ‘ฑ','๐Ÿ‘ผ','๐Ÿ‘ธ','๐Ÿ˜บ','๐Ÿ˜ธ','๐Ÿ˜ป','๐Ÿ˜ฝ','๐Ÿ˜ผ','๐Ÿ™€','๐Ÿ˜ฟ','๐Ÿ˜น','๐Ÿ˜พ','๐Ÿ‘น','๐Ÿ‘บ','๐Ÿ™ˆ','๐Ÿ™‰','๐Ÿ™Š','๐Ÿ’€','๐Ÿ‘ฝ','๐Ÿ’ฉ','๐Ÿ”ฅ','โœจ','๐ŸŒŸ','๐Ÿ’ซ','๐Ÿ’ฅ','๐Ÿ’ข','๐Ÿ’ฆ','๐Ÿ’ง','๐Ÿ’ค','๐Ÿ’จ','๐Ÿ‘‚','๐Ÿ‘€','๐Ÿ‘ƒ','๐Ÿ‘…','๐Ÿ‘„','๐Ÿ‘','๐Ÿ‘Ž','๐Ÿ‘Œ','๐Ÿ‘Š','โœŠ','โœŒ','๐Ÿ‘‹','โœ‹','๐Ÿ‘','๐Ÿ‘†','๐Ÿ‘‡','๐Ÿ‘‰','๐Ÿ‘ˆ','๐Ÿ™Œ','๐Ÿ™','โ˜','๐Ÿ‘','๐Ÿ’ช','๐Ÿšถ','๐Ÿƒ','๐Ÿ’ƒ','๐Ÿ‘ซ','๐Ÿ‘ช','๐Ÿ‘ฌ','๐Ÿ‘ญ','๐Ÿ’','๐Ÿ’‘','๐Ÿ‘ฏ','๐Ÿ™†','๐Ÿ™…','๐Ÿ’','๐Ÿ™‹','๐Ÿ’†','๐Ÿ’‡','๐Ÿ’…','๐Ÿ‘ฐ','๐Ÿ™Ž','๐Ÿ™','๐Ÿ™‡','๐ŸŽฉ','๐Ÿ‘‘','๐Ÿ‘’','๐Ÿ‘Ÿ','๐Ÿ‘ž','๐Ÿ‘ก','๐Ÿ‘ ','๐Ÿ‘ข','๐Ÿ‘•','๐Ÿ‘”','๐Ÿ‘š','๐Ÿ‘—','๐ŸŽฝ','๐Ÿ‘–','๐Ÿ‘˜','๐Ÿ‘™','๐Ÿ’ผ','๐Ÿ‘œ','๐Ÿ‘','๐Ÿ‘›','๐Ÿ‘“','๐ŸŽ€','๐ŸŒ‚','๐Ÿ’„','๐Ÿ’›','๐Ÿ’™','๐Ÿ’œ','๐Ÿ’š','โค','๐Ÿ’”','๐Ÿ’—','๐Ÿ’“','๐Ÿ’•','๐Ÿ’–','๐Ÿ’ž','๐Ÿ’˜','๐Ÿ’Œ','๐Ÿ’‹','๐Ÿ’','๐Ÿ’Ž','๐Ÿ‘ค','๐Ÿ‘ฅ','๐Ÿ’ฌ','๐Ÿ‘ฃ','๐Ÿ’ญ','๐Ÿถ','๐Ÿบ','๐Ÿฑ','๐Ÿญ','๐Ÿน','๐Ÿฐ','๐Ÿธ','๐Ÿฏ','๐Ÿจ','๐Ÿป','๐Ÿท','๐Ÿฝ','๐Ÿฎ','๐Ÿ—','๐Ÿต','๐Ÿ’','๐Ÿด','๐Ÿ‘','๐Ÿ˜','๐Ÿผ','๐Ÿง','๐Ÿฆ','๐Ÿค','๐Ÿฅ','๐Ÿฃ','๐Ÿ”','๐Ÿ','๐Ÿข','๐Ÿ›','๐Ÿ','๐Ÿœ','๐Ÿž','๐ŸŒ','๐Ÿ™','๐Ÿš','๐Ÿ ','๐ŸŸ','๐Ÿฌ','๐Ÿณ','๐Ÿ‹','๐Ÿ„','๐Ÿ','๐Ÿ€','๐Ÿƒ','๐Ÿ…','๐Ÿ‡','๐Ÿ‰','๐ŸŽ','๐Ÿ','๐Ÿ“','๐Ÿ•','๐Ÿ–','๐Ÿ','๐Ÿ‚','๐Ÿฒ','๐Ÿก','๐ŸŠ','๐Ÿซ','๐Ÿช','๐Ÿ†','๐Ÿˆ','๐Ÿฉ','๐Ÿพ','๐Ÿ’','๐ŸŒธ','๐ŸŒท','๐Ÿ€','๐ŸŒน','๐ŸŒป','๐ŸŒบ','๐Ÿ','๐Ÿƒ','๐Ÿ‚','๐ŸŒฟ','๐ŸŒพ','๐Ÿ„','๐ŸŒต','๐ŸŒด','๐ŸŒฒ','๐ŸŒณ','๐ŸŒฐ','๐ŸŒฑ','๐ŸŒผ','๐ŸŒ','๐ŸŒž','๐ŸŒ','๐ŸŒš','๐ŸŒ‘','๐ŸŒ’','๐ŸŒ“','๐ŸŒ”','๐ŸŒ•','๐ŸŒ–','๐ŸŒ—','๐ŸŒ˜','๐ŸŒœ','๐ŸŒ›','๐ŸŒ™','๐ŸŒ','๐ŸŒŽ','๐ŸŒ','๐ŸŒ‹','๐ŸŒŒ','๐ŸŒ ','โญ','โ˜€','โ›…','โ˜','โšก','โ˜”','โ„','โ›„','๐ŸŒ€','๐ŸŒ','๐ŸŒˆ','๐ŸŒŠ','๐ŸŽ','๐Ÿ’','๐ŸŽŽ','๐ŸŽ’','๐ŸŽ“','๐ŸŽ','๐ŸŽ†','๐ŸŽ‡','๐ŸŽ','๐ŸŽ‘','๐ŸŽƒ','๐Ÿ‘ป','๐ŸŽ…','๐ŸŽ„','๐ŸŽ','๐ŸŽ‹','๐ŸŽ‰','๐ŸŽŠ','๐ŸŽˆ','๐ŸŽŒ','๐Ÿ”ฎ','๐ŸŽฅ','๐Ÿ“ท','๐Ÿ“น','๐Ÿ“ผ','๐Ÿ’ฟ','๐Ÿ“€','๐Ÿ’ฝ','๐Ÿ’พ','๐Ÿ’ป','๐Ÿ“ฑ','โ˜Ž','๐Ÿ“ž','๐Ÿ“Ÿ','๐Ÿ“ ','๐Ÿ“ก','๐Ÿ“บ','๐Ÿ“ป','๐Ÿ”Š','๐Ÿ”‰','๐Ÿ”ˆ','๐Ÿ”‡','๐Ÿ””','๐Ÿ”•','๐Ÿ“ข','๐Ÿ“ฃ','โณ','โŒ›','โฐ','โŒš','๐Ÿ”“','๐Ÿ”’','๐Ÿ”','๐Ÿ”','๐Ÿ”‘','๐Ÿ”Ž','๐Ÿ’ก','๐Ÿ”ฆ','๐Ÿ”†','๐Ÿ”…','๐Ÿ”Œ','๐Ÿ”‹','๐Ÿ”','๐Ÿ›','๐Ÿ›€','๐Ÿšฟ','๐Ÿšฝ','๐Ÿ”ง','๐Ÿ”ฉ','๐Ÿ”จ','๐Ÿšช','๐Ÿšฌ','๐Ÿ’ฃ','๐Ÿ”ซ','๐Ÿ”ช','๐Ÿ’Š','๐Ÿ’‰','๐Ÿ’ฐ','๐Ÿ’ด','๐Ÿ’ต','๐Ÿ’ท','๐Ÿ’ถ','๐Ÿ’ณ','๐Ÿ’ธ','๐Ÿ“ฒ','๐Ÿ“ง','๐Ÿ“ฅ','๐Ÿ“ค','โœ‰','๐Ÿ“ฉ','๐Ÿ“จ','๐Ÿ“ฏ','๐Ÿ“ซ','๐Ÿ“ช','๐Ÿ“ฌ','๐Ÿ“ญ','๐Ÿ“ฎ','๐Ÿ“ฆ','๐Ÿ“','๐Ÿ“„','๐Ÿ“ƒ','๐Ÿ“‘','๐Ÿ“Š','๐Ÿ“ˆ','๐Ÿ“‰','๐Ÿ“œ','๐Ÿ“‹','๐Ÿ“…','๐Ÿ“†','๐Ÿ“‡','๐Ÿ“','๐Ÿ“‚','โœ‚','๐Ÿ“Œ','๐Ÿ“Ž','โœ’','โœ','๐Ÿ“','๐Ÿ“','๐Ÿ“•','๐Ÿ“—','๐Ÿ“˜','๐Ÿ“™','๐Ÿ““','๐Ÿ“”','๐Ÿ“’','๐Ÿ“š','๐Ÿ“–','๐Ÿ”–','๐Ÿ“›','๐Ÿ”ฌ','๐Ÿ”ญ','๐Ÿ“ฐ','๐ŸŽจ','๐ŸŽฌ','๐ŸŽค','๐ŸŽง','๐ŸŽผ','๐ŸŽต','๐ŸŽถ','๐ŸŽน','๐ŸŽป','๐ŸŽบ','๐ŸŽท','๐ŸŽธ','๐Ÿ‘พ','๐ŸŽฎ','๐Ÿƒ','๐ŸŽด','๐Ÿ€„','๐ŸŽฒ','๐ŸŽฏ','๐Ÿˆ','๐Ÿ€','โšฝ','โšพ','๐ŸŽพ','๐ŸŽฑ','๐Ÿ‰','๐ŸŽณ','โ›ณ','๐Ÿšต','๐Ÿšด','๐Ÿ','๐Ÿ‡','๐Ÿ†','๐ŸŽฟ','๐Ÿ‚','๐ŸŠ','๐Ÿ„','๐ŸŽฃ','โ˜•','๐Ÿต','๐Ÿถ','๐Ÿผ','๐Ÿบ','๐Ÿป','๐Ÿธ','๐Ÿน','๐Ÿท','๐Ÿด','๐Ÿ•','๐Ÿ”','๐ŸŸ','๐Ÿ—','๐Ÿ–','๐Ÿ','๐Ÿ›','๐Ÿค','๐Ÿฑ','๐Ÿฃ','๐Ÿฅ','๐Ÿ™','๐Ÿ˜','๐Ÿš','๐Ÿœ','๐Ÿฒ','๐Ÿข','๐Ÿก','๐Ÿณ','๐Ÿž','๐Ÿฉ','๐Ÿฎ','๐Ÿฆ','๐Ÿจ','๐Ÿง','๐ŸŽ‚','๐Ÿฐ','๐Ÿช','๐Ÿซ','๐Ÿฌ','๐Ÿญ','๐Ÿฏ','๐ŸŽ','๐Ÿ','๐ŸŠ','๐Ÿ‹','๐Ÿ’','๐Ÿ‡','๐Ÿ‰','๐Ÿ“','๐Ÿ‘','๐Ÿˆ','๐ŸŒ','๐Ÿ','๐Ÿ','๐Ÿ ','๐Ÿ†','๐Ÿ…','๐ŸŒฝ','๐Ÿ ','๐Ÿก','๐Ÿซ','๐Ÿข','๐Ÿฃ','๐Ÿฅ','๐Ÿฆ','๐Ÿช','๐Ÿฉ','๐Ÿจ','๐Ÿ’’','โ›ช','๐Ÿฌ','๐Ÿค','๐ŸŒ‡','๐ŸŒ†','๐Ÿฏ','๐Ÿฐ','โ›บ','๐Ÿญ','๐Ÿ—ผ','๐Ÿ—พ','๐Ÿ—ป','๐ŸŒ„','๐ŸŒ…','๐ŸŒƒ','๐Ÿ—ฝ','๐ŸŒ‰','๐ŸŽ ','๐ŸŽก','โ›ฒ','๐ŸŽข','๐Ÿšข','โ›ต','๐Ÿšค','๐Ÿšฃ','โš“','๐Ÿš€','โœˆ','๐Ÿ’บ','๐Ÿš','๐Ÿš‚','๐ŸšŠ','๐Ÿš‰','๐Ÿšž','๐Ÿš†','๐Ÿš„','๐Ÿš…','๐Ÿšˆ','๐Ÿš‡','๐Ÿš','๐Ÿš‹','๐Ÿšƒ','๐ŸšŽ','๐ŸšŒ','๐Ÿš','๐Ÿš™','๐Ÿš˜','๐Ÿš—','๐Ÿš•','๐Ÿš–','๐Ÿš›','๐Ÿšš','๐Ÿšจ','๐Ÿš“','๐Ÿš”','๐Ÿš’','๐Ÿš‘','๐Ÿš','๐Ÿšฒ','๐Ÿšก','๐ŸšŸ','๐Ÿš ','๐Ÿšœ','๐Ÿ’ˆ','๐Ÿš','๐ŸŽซ','๐Ÿšฆ','๐Ÿšฅ','โš ','๐Ÿšง','๐Ÿ”ฐ','โ›ฝ','๐Ÿฎ','๐ŸŽฐ','โ™จ','๐Ÿ—ฟ','๐ŸŽช','๐ŸŽญ','๐Ÿ“','๐Ÿšฉ','โฌ†','โฌ‡','โฌ…','โžก','๐Ÿ” ','๐Ÿ”ก','๐Ÿ”ค','โ†—','โ†–','โ†˜','โ†™','โ†”','โ†•','๐Ÿ”„','โ—€','โ–ถ','๐Ÿ”ผ','๐Ÿ”ฝ','โ†ฉ','โ†ช','โ„น','โช','โฉ','โซ','โฌ','โคต','โคด','๐Ÿ†—','๐Ÿ”€','๐Ÿ”','๐Ÿ”‚','๐Ÿ†•','๐Ÿ†™','๐Ÿ†’','๐Ÿ†“','๐Ÿ†–','๐Ÿ“ถ','๐ŸŽฆ','๐Ÿˆ','๐Ÿˆฏ','๐Ÿˆณ','๐Ÿˆต','๐Ÿˆด','๐Ÿˆฒ','๐Ÿ‰','๐Ÿˆน','๐Ÿˆบ','๐Ÿˆถ','๐Ÿˆš','๐Ÿšป','๐Ÿšน','๐Ÿšบ','๐Ÿšผ','๐Ÿšพ','๐Ÿšฐ','๐Ÿšฎ','๐Ÿ…ฟ','โ™ฟ','๐Ÿšญ','๐Ÿˆท','๐Ÿˆธ','๐Ÿˆ‚','โ“‚','๐Ÿ›‚','๐Ÿ›„','๐Ÿ›…','๐Ÿ›ƒ','๐Ÿ‰‘','ใŠ™','ใŠ—','๐Ÿ†‘','๐Ÿ†˜','๐Ÿ†”','๐Ÿšซ','๐Ÿ”ž','๐Ÿ“ต','๐Ÿšฏ','๐Ÿšฑ','๐Ÿšณ','๐Ÿšท','๐Ÿšธ','โ›”','โœณ','โ‡','โŽ','โœ…','โœด','๐Ÿ’Ÿ','๐Ÿ†š','๐Ÿ“ณ','๐Ÿ“ด','๐Ÿ…ฐ','๐Ÿ…ฑ','๐Ÿ†Ž','๐Ÿ…พ','๐Ÿ’ ','โžฟ','โ™ป','โ™ˆ','โ™‰','โ™Š','โ™‹','โ™Œ','โ™','โ™Ž','โ™','โ™','โ™‘','โ™’','โ™“','โ›Ž','๐Ÿ”ฏ','๐Ÿง','๐Ÿ’น','๐Ÿ’ฒ','๐Ÿ’ฑ','ยฉ','ยฎ','โ„ข','ใ€ฝ','ใ€ฐ','๐Ÿ”','๐Ÿ”š','๐Ÿ”™','๐Ÿ”›','๐Ÿ”œ','โŒ','โญ•','โ—','โ“','โ•','โ”','๐Ÿ”ƒ','๐Ÿ•›','๐Ÿ•ง','๐Ÿ•','๐Ÿ•œ','๐Ÿ•‘','๐Ÿ•','๐Ÿ•’','๐Ÿ•ž','๐Ÿ•“','๐Ÿ•Ÿ','๐Ÿ•”','๐Ÿ• ','๐Ÿ••','๐Ÿ•–','๐Ÿ•—','๐Ÿ•˜','๐Ÿ•™','๐Ÿ•š','๐Ÿ•ก','๐Ÿ•ข','๐Ÿ•ฃ','๐Ÿ•ค','๐Ÿ•ฅ','๐Ÿ•ฆ','โœ–','โž•','โž–','โž—','โ™ ','โ™ฅ','โ™ฃ','โ™ฆ','๐Ÿ’ฎ','๐Ÿ’ฏ','โœ”','โ˜‘','๐Ÿ”˜','๐Ÿ”—','โžฐ','๐Ÿ”ฑ','๐Ÿ”ฒ','๐Ÿ”ณ','โ—ผ','โ—ป','โ—พ','โ—ฝ','โ–ช','โ–ซ','๐Ÿ”บ','โฌœ','โฌ›','โšซ','โšช','๐Ÿ”ด','๐Ÿ”ต','๐Ÿ”ป','๐Ÿ”ถ','๐Ÿ”ท','๐Ÿ”ธ','๐Ÿ”น' + ]; + + res.send({ + success: true, + emoji: emojis[Math.floor(Math.random() * emojis.length)], + message: 'Happy emoji-ing! ๐ŸŒ' + }) +} + +module.exports = emojiController; From 59b206bf2de1a317a9d12818ce990ce7d02a6774 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 6 Mar 2018 22:13:53 +0100 Subject: [PATCH 22/37] Forgot a leading / --- seasoned_api/src/webserver/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/webserver/app.js b/seasoned_api/src/webserver/app.js index 58dc4fa..33b431b 100644 --- a/seasoned_api/src/webserver/app.js +++ b/seasoned_api/src/webserver/app.js @@ -109,7 +109,7 @@ router.post('/v1/git/dump', require('./controllers/git/dumpHook.js')); /** * misc */ - router.get('v1/emoji', require('./controllers/misc/emoji.js')); + router.get('/v1/emoji', require('./controllers/misc/emoji.js')); // REGISTER OUR ROUTES ------------------------------- // all of our routes will be prefixed with /api From 858f3f5d5713289414d746c0d2c3635df8356ff6 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Mar 2018 01:30:28 +0100 Subject: [PATCH 23/37] Can now get user admin status. --- seasoned_api/src/user/userRepository.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/seasoned_api/src/user/userRepository.js b/seasoned_api/src/user/userRepository.js index 5a0e9b1..684140e 100644 --- a/seasoned_api/src/user/userRepository.js +++ b/seasoned_api/src/user/userRepository.js @@ -9,6 +9,7 @@ class UserRepository { create: 'insert into user (user_name) values (?)', change: 'update user set password = ? where user_name = ?', retrieveHash: 'select * from user where user_name = ?', + getAdminByUser: 'select admin from user where user_name = ?' }; } @@ -49,6 +50,12 @@ class UserRepository { changePassword(user, password) { return this.database.run(this.queries.change, [password, user.username]); } + + isAdmin(user) { + return this.database.get(this.queries.getAdminByUser, user.username).then((row) => { + return row.admin; + }) + } } module.exports = UserRepository; From ba96e27c43927623bc018cd8627372b54dd98ad5 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Mar 2018 01:35:40 +0100 Subject: [PATCH 24/37] Alongside the token the value of admin state is also sent. --- seasoned_api/src/user/userRepository.js | 6 +++--- seasoned_api/src/webserver/controllers/user/login.js | 8 ++++++-- seasoned_api/src/webserver/controllers/user/register.js | 8 ++++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/seasoned_api/src/user/userRepository.js b/seasoned_api/src/user/userRepository.js index 684140e..4a6a148 100644 --- a/seasoned_api/src/user/userRepository.js +++ b/seasoned_api/src/user/userRepository.js @@ -9,7 +9,7 @@ class UserRepository { create: 'insert into user (user_name) values (?)', change: 'update user set password = ? where user_name = ?', retrieveHash: 'select * from user where user_name = ?', - getAdminByUser: 'select admin from user where user_name = ?' + getAdminStateByUser: 'select admin from user where user_name = ?' }; } @@ -51,8 +51,8 @@ class UserRepository { return this.database.run(this.queries.change, [password, user.username]); } - isAdmin(user) { - return this.database.get(this.queries.getAdminByUser, user.username).then((row) => { + checkAdmin(user) { + return this.database.get(this.queries.getAdminStateByUser, user.username).then((row) => { return row.admin; }) } diff --git a/seasoned_api/src/webserver/controllers/user/login.js b/seasoned_api/src/webserver/controllers/user/login.js index e839276..888c2b1 100644 --- a/seasoned_api/src/webserver/controllers/user/login.js +++ b/seasoned_api/src/webserver/controllers/user/login.js @@ -1,10 +1,12 @@ const User = require('src/user/user'); const Token = require('src/user/token'); const UserSecurity = require('src/user/userSecurity'); +const UserRepository = require('src/user/userRepository'); const configuration = require('src/config/configuration').getInstance(); const secret = configuration.get('authentication', 'secret'); const userSecurity = new UserSecurity(); +const userRepository = new UserRepository(); /** * Controller: Log in a user provided correct credentials. @@ -17,9 +19,11 @@ function loginController(req, res) { const password = req.body.password; userSecurity.login(user, password) - .then(() => { + .then(() => userRepository.checkAdmin(user)) + .then((checkAdmin) => { const token = new Token(user).toString(secret); - res.send({ success: true, token }); + const admin_state = checkAdmin == 1 ? true : false; + res.send({ success: true, token, admin: admin_state }); }) .catch((error) => { res.status(401).send({ success: false, error: error.message }); diff --git a/seasoned_api/src/webserver/controllers/user/register.js b/seasoned_api/src/webserver/controllers/user/register.js index 96322a5..63040c3 100644 --- a/seasoned_api/src/webserver/controllers/user/register.js +++ b/seasoned_api/src/webserver/controllers/user/register.js @@ -1,10 +1,12 @@ const User = require('src/user/user'); const Token = require('src/user/token'); const UserSecurity = require('src/user/userSecurity'); +const UserRepository = require('src/user/userRepository'); const configuration = require('src/config/configuration').getInstance(); const secret = configuration.get('authentication', 'secret'); const userSecurity = new UserSecurity(); +const userRepository = new UserRepository(); /** * Controller: Register a new user @@ -17,9 +19,11 @@ function registerController(req, res) { const password = req.body.password; userSecurity.createNewUser(user, password) - .then(() => { + .then(() => userRepository.checkAdmin(user)) + .then((checkAdmin) => { const token = new Token(user).toString(secret); - res.send({ success: true, message: 'Welcome to Seasoned!', token}); + const admin_state = checkAdmin == 1 ? true : false; + res.send({ success: true, message: 'Welcome to Seasoned!', token, admin: admin_state }); }) .catch((error) => { res.status(401).send({ success: false, error: error.message }); From 27c95375e254b35111539f80027619849e00488f Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Mar 2018 01:37:42 +0100 Subject: [PATCH 25/37] Reverted back to only be authenticated beacuse something wrong with getting the correct user. Will replace with admin check as middleware when fixed. --- seasoned_api/src/webserver/app.js | 2 +- seasoned_api/src/webserver/middleware/mustBeAdmin.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/seasoned_api/src/webserver/app.js b/seasoned_api/src/webserver/app.js index 33b431b..e038e1e 100644 --- a/seasoned_api/src/webserver/app.js +++ b/seasoned_api/src/webserver/app.js @@ -91,7 +91,7 @@ router.put('/v1/plex/request/:requestId', mustBeAuthenticated, require('./contro /** * Pirate */ -router.get('/v1/pirate/search', mustBeAdmin, require('./controllers/pirate/searchTheBay.js')); +router.get('/v1/pirate/search', mustBeAuthenticated, require('./controllers/pirate/searchTheBay.js')); router.post('/v1/pirate/add', mustBeAuthenticated, require('./controllers/pirate/addMagnet.js')); /** diff --git a/seasoned_api/src/webserver/middleware/mustBeAdmin.js b/seasoned_api/src/webserver/middleware/mustBeAdmin.js index 9d35d53..042bd40 100644 --- a/seasoned_api/src/webserver/middleware/mustBeAdmin.js +++ b/seasoned_api/src/webserver/middleware/mustBeAdmin.js @@ -11,6 +11,7 @@ const mustBeAdmin = (req, res, next) => { } else { database.get(`SELECT admin FROM user WHERE user_name IS ?`, req.loggedInUser.username) .then((isAdmin) => { + console.log(isAdmin, req.loggedInUser) if (isAdmin.admin == 0) { return res.status(401).send({ success: false, From ab2d3c67567213494d4a0d7aed6b23ac5ff89b79 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Mar 2018 14:57:18 +0100 Subject: [PATCH 26/37] Renamed function name and now returns 500 error when a problem is found. --- seasoned_api/src/webserver/controllers/pirate/addMagnet.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/seasoned_api/src/webserver/controllers/pirate/addMagnet.js b/seasoned_api/src/webserver/controllers/pirate/addMagnet.js index 9899831..ed6f7a3 100644 --- a/seasoned_api/src/webserver/controllers/pirate/addMagnet.js +++ b/seasoned_api/src/webserver/controllers/pirate/addMagnet.js @@ -8,7 +8,7 @@ const PirateRepository = require('src/pirate/pirateRepository'); -function updateRequested(req, res) { +function addMagnet(req, res) { const magnet = req.body.magnet; PirateRepository.AddMagnet(magnet) @@ -16,8 +16,8 @@ function updateRequested(req, res) { res.send(result); }) .catch((error) => { - res.status(401).send({ success: false, error: error.message }); + res.status(500).send({ success: false, error: error.message }); }); } -module.exports = updateRequested; +module.exports = addMagnet; From 453727db1bcc580dd47b86820089d16f6838df34 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Mar 2018 15:35:55 +0100 Subject: [PATCH 27/37] Fixed issue where the user was not being saved alongside the request. Also fixed what the list of requests are sorted by. --- seasoned_api/src/plex/requestRepository.js | 6 +++--- .../src/webserver/controllers/plex/submitRequest.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index 1958bb9..8b2d344 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -16,8 +16,8 @@ class RequestRepository { constructor(cache, database) { this.database = database || establishedDatabase; this.queries = { - insertRequest: "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_DATE, 'requested', ?, ?)", - fetchRequestedItems: 'SELECT * FROM requests ORDER BY requested_by ASC', + insertRequest: "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, ?, DEFAULT, DEFAULT, ?, ?)", + fetchRequestedItems: 'SELECT * FROM requests ORDER BY date ASC', fetchRequestedItemsByStatus: 'SELECT * FROM requests WHERE status IS ? AND type LIKE ?', updateRequestedById: 'UPDATE requests SET status = ? WHERE id is ? AND type is ?', checkIfIdRequested: 'SELECT * FROM requests WHERE id IS ? AND type IS ?', @@ -68,7 +68,7 @@ class RequestRepository { 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]); + this.database.run(this.queries.insertRequest, [movie.id, movie.title, movie.year, movie.poster_path, movie.background_path, user.username, ip, user_agent, movie.type]); }); } diff --git a/seasoned_api/src/webserver/controllers/plex/submitRequest.js b/seasoned_api/src/webserver/controllers/plex/submitRequest.js index 6afb085..8f95d3a 100644 --- a/seasoned_api/src/webserver/controllers/plex/submitRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/submitRequest.js @@ -15,7 +15,7 @@ function submitRequestController(req, res) { 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; + const user = req.headers.loggedInUser; requestRepository.sendRequest(id, type, ip, user_agent, user) .then(() => { From 40b539db68bfc11afb636471826eb229af4c054b Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Mar 2018 15:37:39 +0100 Subject: [PATCH 28/37] Reversed the sorting direction. --- seasoned_api/src/plex/requestRepository.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index 8b2d344..6dfe9c8 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -17,7 +17,7 @@ class RequestRepository { this.database = database || establishedDatabase; this.queries = { insertRequest: "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, ?, DEFAULT, DEFAULT, ?, ?)", - fetchRequestedItems: 'SELECT * FROM requests ORDER BY date ASC', + fetchRequestedItems: 'SELECT * FROM requests ORDER BY date DESC', fetchRequestedItemsByStatus: 'SELECT * FROM requests WHERE status IS ? AND type LIKE ?', updateRequestedById: 'UPDATE requests SET status = ? WHERE id is ? AND type is ?', checkIfIdRequested: 'SELECT * FROM requests WHERE id IS ? AND type IS ?', From 1a4aefda149b03709db789dd9a2534bab772eaf0 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Mar 2018 18:12:21 +0100 Subject: [PATCH 29/37] Get the user variable from req not req.headers --- seasoned_api/src/webserver/controllers/plex/submitRequest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/webserver/controllers/plex/submitRequest.js b/seasoned_api/src/webserver/controllers/plex/submitRequest.js index 8f95d3a..293d80c 100644 --- a/seasoned_api/src/webserver/controllers/plex/submitRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/submitRequest.js @@ -15,7 +15,7 @@ function submitRequestController(req, res) { 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; + const user = req.loggedInUser; requestRepository.sendRequest(id, type, ip, user_agent, user) .then(() => { From 37474de848a4d0ced2365086098f38f2706f4747 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 7 Mar 2018 18:14:07 +0100 Subject: [PATCH 30/37] Changed to resolve and reject the result from tmdb. And first get the username before sending user to another functoin. --- seasoned_api/src/plex/requestRepository.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index 8b2d344..baf37f2 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -16,7 +16,8 @@ class RequestRepository { constructor(cache, database) { this.database = database || establishedDatabase; this.queries = { - insertRequest: "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, ?, DEFAULT, DEFAULT, ?, ?)", + insertRequest: `INSERT INTO requests(id,title,year,poster_path,background_path,requested_by,ip,user_agent,type) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, fetchRequestedItems: 'SELECT * FROM requests ORDER BY date ASC', fetchRequestedItemsByStatus: 'SELECT * FROM requests WHERE status IS ? AND type LIKE ?', updateRequestedById: 'UPDATE requests SET status = ? WHERE id is ? AND type is ?', @@ -32,8 +33,7 @@ class RequestRepository { search(query, type, page) { return Promise.resolve() .then(() => tmdb.search(query, type, page)) - .then(result => result) - .catch(error => `error in the house${error}`); + .catch(error => Error(`error in the house${error}`)); } lookup(identifier, type = 'movie') { @@ -65,10 +65,12 @@ class RequestRepository { * @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'; } + return Promise.resolve() + .then(() => tmdb.lookup(identifier, type)) + .then((movie) => { + const username = user == undefined ? undefined : user.username; // Add request to database - this.database.run(this.queries.insertRequest, [movie.id, movie.title, movie.year, movie.poster_path, movie.background_path, user.username, ip, user_agent, movie.type]); + return this.database.run(this.queries.insertRequest, [movie.id, movie.title, movie.year, movie.poster_path, movie.background_path, username, ip, user_agent, movie.type]); }); } From 13401a318ac3190022e4294a9e0621b60c7cff10 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Thu, 8 Mar 2018 10:30:39 +0100 Subject: [PATCH 31/37] History was not wokring because upgrade to sqlite3. Now we do a stateless call to the database and reolve or reject the response. --- seasoned_api/src/searchHistory/searchHistory.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/seasoned_api/src/searchHistory/searchHistory.js b/seasoned_api/src/searchHistory/searchHistory.js index 2be86e7..4ebb899 100644 --- a/seasoned_api/src/searchHistory/searchHistory.js +++ b/seasoned_api/src/searchHistory/searchHistory.js @@ -15,8 +15,15 @@ class SearchHistory { * @returns {Promise} */ read(user) { - return this.database.all(this.queries.read, user.username) - .then(rows => rows.map(row => row.search_query)); + return new Promise((resolve, reject) => this.database.all(this.queries.read, user) + .then((result, error) => { + if (error) throw new Error(error); + resolve(result.map(row => row.search_query)); + }) + .catch((error) => { + console.log('Error when fetching history from database:', error) + reject('Unable to get history.'); + })); } /** @@ -26,7 +33,8 @@ class SearchHistory { * @returns {Promise} */ create(user, searchQuery) { - return this.database.run(this.queries.create, [searchQuery, user.username]) + return Promise.resolve() + .then(() => this.database.run(this.queries.create, [searchQuery, user])) .catch((error) => { if (error.message.includes('FOREIGN')) { throw new Error('Could not create search history.'); From 127db8b2fe6a846d6d5b781247cf9e7e895dae0d Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Thu, 8 Mar 2018 10:32:19 +0100 Subject: [PATCH 32/37] Errors when we have a user that was not signed in. Fixed to unpack the username value first, then pass it to the function. --- seasoned_api/src/webserver/controllers/plex/searchRequest.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/seasoned_api/src/webserver/controllers/plex/searchRequest.js b/seasoned_api/src/webserver/controllers/plex/searchRequest.js index 74873d4..a568c04 100644 --- a/seasoned_api/src/webserver/controllers/plex/searchRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/searchRequest.js @@ -10,15 +10,16 @@ const searchHistory = new SearchHistory(); function searchRequestController(req, res) { const user = req.loggedInUser; const { query, page, type } = req.query; + const username = user == undefined ? undefined : user.username; Promise.resolve() - .then(() => searchHistory.create(user, query)) + .then(() => searchHistory.create(username, query)) .then(() => requestRepository.search(query, page, type)) .then((searchResult) => { res.send(searchResult); }) .catch((error) => { - res.status(500).send({ success: false, error: error.message }); + res.status(500).send({ success: false, error: error }); }); } From 8fbd0eb9d8f1a0e9c7ba5dccab4bc6c9a990f42d Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Thu, 8 Mar 2018 10:33:04 +0100 Subject: [PATCH 33/37] Also unpacks the value of username before passing it to searchHistory. --- seasoned_api/src/webserver/controllers/user/history.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seasoned_api/src/webserver/controllers/user/history.js b/seasoned_api/src/webserver/controllers/user/history.js index 54b2ff0..2371c33 100644 --- a/seasoned_api/src/webserver/controllers/user/history.js +++ b/seasoned_api/src/webserver/controllers/user/history.js @@ -10,8 +10,9 @@ const searchHistory = new SearchHistory(); */ function historyController(req, res) { const user = req.loggedInUser; + const username = user == undefined ? undefined : user.username; - searchHistory.read(user) + searchHistory.read(username) .then((searchQueries) => { res.send({ success: true, searchQueries }); }) From 6a7b427ef36ff15d694a4935acc15f021f86d207 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Thu, 8 Mar 2018 10:36:13 +0100 Subject: [PATCH 34/37] Changed cache TTL to 3 hours. --- seasoned_api/src/tmdb/cache.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/tmdb/cache.js b/seasoned_api/src/tmdb/cache.js index 584df15..f55179e 100644 --- a/seasoned_api/src/tmdb/cache.js +++ b/seasoned_api/src/tmdb/cache.js @@ -33,7 +33,7 @@ class Cache { * @param {Number} timeToLive the number of seconds before entry expires * @returns {Object} */ - set(key, value, timeToLive = 172800) { + set(key, value, timeToLive = 10800) { const json = JSON.stringify(value); return Promise.resolve() .then(() => this.database.run(this.queries.create, [key, json, timeToLive])) From 47b499c0724bef1cbb9d88b2eb9035692c8114df Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Thu, 8 Mar 2018 16:35:17 +0100 Subject: [PATCH 35/37] Jackett sometimes returns a link to self that redirects to a magnet. The response is now parsed for if it is a link and gets the url it redirects to. --- seasoned_api/src/pirate/pirateRepository.js | 46 ++++++++++++++++----- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/seasoned_api/src/pirate/pirateRepository.js b/seasoned_api/src/pirate/pirateRepository.js index 8dce82b..dcb7895 100644 --- a/seasoned_api/src/pirate/pirateRepository.js +++ b/seasoned_api/src/pirate/pirateRepository.js @@ -1,11 +1,27 @@ const assert = require('assert'); +const http = require('http'); +const { URL } = require('url'); const PythonShell = require('python-shell'); +function getMagnetFromURL(url) { + return new Promise((resolve, reject) => { + const options = new URL(url); + if (options.protocol.includes('magnet')) + resolve(url) + + http.get(options, (res) => { + if (res.statusCode == 301) { + resolve(res.headers.location) + } + }); + }); +} + 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'], + args: [searchterm, '-s', 'jackett', '--print'], }; PythonShell.run('../app/torrent_search/torrentSearch/search.py', options, callback); @@ -13,21 +29,28 @@ async function find(searchterm, callback) { } -async function callPythonAddMagnet(magnet, callback) { - const options = { - pythonPath: '/usr/bin/python', - // pythonPath: '/Library/Frameworks/Python.framework/Versions/3.6/bin/python3', - args: [magnet], - }; +async function callPythonAddMagnet(url, callback) { + getMagnetFromURL(url) + .then((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); + }) + .catch((err) => { + console.log(err); + throw new Error(err); + }) } async function SearchPiratebay(query) { return await new Promise((resolve, reject) => find(query, (err, results) => { if (err) { /* eslint-disable no-console */ - console.log('THERE WAS A FUCKING ERROR!'); + console.log('THERE WAS A FUCKING ERROR!', err); reject(Error('There was a error when searching for torrents')); } if (results) { @@ -39,13 +62,14 @@ async function SearchPiratebay(query) { } async function AddMagnet(magnet) { - return await new Promise(resolve => callPythonAddMagnet(magnet, (err, results) => { + return await new Promise((resolve, reject) => callPythonAddMagnet(magnet, (err, results) => { if (err) { /* eslint-disable no-console */ console.log(err); + reject(Error('Enable to add torrent', err)) } /* eslint-disable no-console */ - console.log(results); + console.log('result/error:', err, results); resolve({ success: true }); })); } From d8078570eb41ed3705000f7fc77e1429e5ae7d03 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Fri, 9 Mar 2018 13:36:01 +0100 Subject: [PATCH 36/37] Changed the sort order when selecting all from requests. --- seasoned_api/src/plex/requestRepository.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index baf37f2..fefa027 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -18,7 +18,7 @@ class RequestRepository { this.queries = { insertRequest: `INSERT INTO requests(id,title,year,poster_path,background_path,requested_by,ip,user_agent,type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, - fetchRequestedItems: 'SELECT * FROM requests ORDER BY date ASC', + fetchRequestedItems: 'SELECT * FROM requests ORDER BY date DESC', fetchRequestedItemsByStatus: 'SELECT * FROM requests WHERE status IS ? AND type LIKE ?', updateRequestedById: 'UPDATE requests SET status = ? WHERE id is ? AND type is ?', checkIfIdRequested: 'SELECT * FROM requests WHERE id IS ? AND type IS ?', From 3a508b9843b4032c0ca7258ea65dd10702fbc219 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Fri, 9 Mar 2018 13:37:23 +0100 Subject: [PATCH 37/37] Because we sort requests by date we want to use a finer measurement of time to sort more correctly. --- seasoned_api/src/database/schemas/setup.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/database/schemas/setup.sql b/seasoned_api/src/database/schemas/setup.sql index 83b11d7..0616964 100644 --- a/seasoned_api/src/database/schemas/setup.sql +++ b/seasoned_api/src/database/schemas/setup.sql @@ -30,7 +30,7 @@ CREATE TABLE IF NOT EXISTS requests( background_path TEXT DEFAULT NULL, requested_by TEXT, ip TEXT, - requested_date DATE DEFAULT CURRENT_DATE NOT NULL, + date DATE DEFAULT CURRENT_TIMESTAMP, status CHAR(25) DEFAULT 'requested' NOT NULL, user_agent CHAR(255) DEFAULT NULL, type CHAR(50) DEFAULT 'movie'