Feat Drone CI & dockerize 🐳 #132

Merged
KevinMidboe merged 15 commits from feat/drone-ci into master 2022-08-18 18:44:36 +00:00
81 changed files with 9189 additions and 8705 deletions

2
.dockerignore Normal file
View File

@@ -0,0 +1,2 @@
**/node_modules
**/yarn.lock

111
.drone.yml Normal file
View File

@@ -0,0 +1,111 @@
---
kind: pipeline
type: docker
name: seasoned api build
platform:
os: linux
arch: amd64
volumes:
- name: cache
host:
path: /tmp/cache
steps:
- name: Load cached packages
image: sinlead/drone-cache:1.0.0
settings:
action: load
key: yarn.lock
mount: node_modules
prefix: yarn-modules-seasoned_api
volumes:
- name: cache
path: /cache
- name: Install dependencies
image: node:18.2.0
commands:
- node -v
- yarn --version
- yarn
- name: Cache packages
image: sinlead/drone-cache:1.0.0
settings:
action: save
key: yarn.lock
mount: node_modules
prefix: yarn-modules-seasoned_api
volumes:
- name: cache
path: /cache
# - name: Compile typescript
# image: node:18.2.0
# commands:
# - yarn build:ts
- name: Run test suite
image: node:18.2.0
commands:
- yarn test
failure: ignore
- name: Lint project using eslint
image: node:18.2.0
commands:
- yarn lint
failure: ignore
- name: Build and publish docker image
image: plugins/docker
settings:
registry: ghcr.io
repo: ghcr.io/kevinmidboe/seasoned_shows
dockerfile: Dockerfile
username:
from_secret: GITHUB_USERNAME
password:
from_secret: GITHUB_PASSWORD
tags: latest
environment:
TMDB_APIKEY:
from_secret: TMDB_APIKEY
PLEX_IP:
from_secret: PLEX_IP
PLEX_TOKEN:
from_secret: PLEX_TOKEN
# when:
# event:
# - push
# branch:
# - master
# - name: deploy
# image: appleboy/drone-ssh
# pull: true
# secrets:
# - ssh_key
# when:
# event:
# - push
# branch:
# - master
# - drone-test
# status: success
# settings:
# host: 10.0.0.54
# username: root
# key:
# from_secret: ssh_key
# command_timeout: 600s
# script:
# - /home/kevin/deploy/seasoned.sh
trigger:
event:
include:
- push
# - pull_request

View File

3
.gitignore vendored
View File

@@ -1,7 +1,8 @@
.DS_Store
development.json
env
.env
shows.db
node_modules
*/package-lock.json

19
Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
FROM node:18
RUN mkdir -p /opt/seasonedShows/seasoned_api
WORKDIR /opt/seasonedShows
COPY seasoned_api/ seasoned_api
COPY package.json .
RUN apt update
RUN apt install node-pre-gyp -y
RUN yarn
RUN cp seasoned_api/conf/development.json.example seasoned_api/conf/development.json
EXPOSE 31459
CMD ["yarn", "start"]
LABEL org.opencontainers.image.source https://github.com/kevinmidboe/seasoned

View File

@@ -7,14 +7,14 @@
},
"main": "webserver/server.js",
"scripts": {
"start": "cross-env SEASONED_CONFIG=conf/development.json NODE_ENV=production NODE_PATH=. babel-node src/webserver/server.js",
"test": "cross-env SEASONED_CONFIG=conf/test.json NODE_PATH=. mocha --require @babel/register --recursive test/unit test/system",
"start": "yarn cross-env SEASONED_CONFIG=conf/development.json NODE_ENV=production babel-node seasoned_api/src/webserver/server.js",
"test": "cross-env SEASONED_CONFIG=conf/test.json NODE_PATH=. mocha --require @babel/register --recursive seasoned_api/test/unit seasoned_api/test//system",
"coverage": "cross-env SEASONED_CONFIG=conf/test.json NODE_PATH=. nyc mocha --require @babel/register --recursive test && nyc report --reporter=text-lcov | coveralls",
"lint": "./node_modules/.bin/eslint src/",
"update": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. node scripts/updateRequestsInPlex.js",
"lint": "eslint seasoned_api/src",
"update": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. node seasoned_api/scripts/updateRequestsInPlex.js",
"docs": "yarn apiDocs; yarn classDocs",
"apiDocs": "",
"classDocs": "./script/generate-class-docs.sh"
"classDocs": "seasoned_api/script/generate-class-docs.sh"
},
"dependencies": {
"axios": "^0.18.0",

View File

@@ -2,6 +2,10 @@
"database": {
"host": "../shows.db"
},
"redis": {
"host": "localhost",
"port": 6379
},
"webserver": {
"port": 31459,
"origins": []
@@ -10,7 +14,8 @@
"apiKey": ""
},
"plex": {
"ip": ""
"ip": "localhost",
"token": ""
},
"tautulli": {
"apiKey": "",

View File

@@ -1,39 +1,46 @@
const redis = require("redis")
const client = redis.createClient()
const { promisify } = require("util");
const configuration = require("../config/configuration").getInstance();
class Cache {
/**
* Retrieve an unexpired cache entry by key.
* @param {String} key of the cache entry
* @returns {Promise}
*/
get(key) {
return new Promise((resolve, reject) => {
client.get(key, (error, reply) => {
if (reply == null) {
return reject();
}
let client;
resolve(JSON.parse(reply));
try {
const redis = require("redis");
console.log("Trying to connect with redis..");
const host = configuration.get("redis", "host");
const port = configuration.get("redis", "port");
console.log(`redis://${host}:${port}`);
client = redis.createClient({
url: `redis://${host}:${port}`
});
});
}
/**
* Insert cache entry with key and value.
* @param {String} key of the cache entry
* @param {String} value of the cache entry
* @param {Number} timeToLive the number of seconds before entry expires
* @returns {Object}
*/
set(key, value, timeToLive = 10800) {
client.on("connect", () => console.log("Redis connection established!"));
client.on("error", function (err) {
client.quit();
console.error("Unable to connect to redis, setting up redis-mock.");
client = {
get: function () {
console.log("redis-dummy get", arguments[0]);
return Promise.resolve();
},
set: function () {
console.log("redis-dummy set", arguments[0]);
return Promise.resolve();
}
};
});
} catch (e) {}
function set(key, value, TTL = 10800) {
if (value == null || key == null) return null;
const json = JSON.stringify(value);
client.set(key, json, (error, reply) => {
if (reply == "OK") {
// successfully set value with key, now set TTL for key
client.expire(key, timeToLive, e => {
client.expire(key, TTL, e => {
if (e)
console.error(
"Unexpected error while setting expiration for key:",
@@ -47,6 +54,20 @@ class Cache {
return value;
}
function get() {
return new Promise((resolve, reject) => {
client.get(key, (error, reply) => {
if (reply == null) {
return reject();
}
module.exports = Cache;
resolve(JSON.parse(reply));
});
});
}
module.exports = {
get,
set
};

View File

@@ -1,5 +1,5 @@
const path = require('path');
const Field = require('./field.js');
const path = require("path");
const Field = require("./field.js");
let instance = null;
@@ -17,19 +17,23 @@ class Config {
}
static determineLocation() {
return path.join(__dirname, '..', '..', process.env.SEASONED_CONFIG);
return path.join(__dirname, "..", "..", process.env.SEASONED_CONFIG);
}
get(section, option) {
if (this.fields[section] === undefined || this.fields[section][option] === undefined) {
if (
this.fields[section] === undefined ||
this.fields[section][option] === undefined
) {
throw new Error(`Field "${section} => ${option}" does not exist.`);
}
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; }
const envField =
process.env[[section.toUpperCase(), option.toUpperCase()].join("_")];
if (envField !== undefined && envField.length !== 0) {
return envField;
}
if (field.value === undefined) {

View File

@@ -1,14 +1,13 @@
const configuration = require('src/config/configuration').getInstance();
const SqliteDatabase = require('src/database/sqliteDatabase');
const configuration = require("../config/configuration").getInstance();
const SqliteDatabase = require("./sqliteDatabase");
const database = new SqliteDatabase(configuration.get('database', 'host'));
const database = new SqliteDatabase(configuration.get("database", "host"));
/**
* This module establishes a connection to the database
* specified in the confgiuration file. It tries to setup
* the required tables after successfully connecting.
* If the tables already exists, it simply proceeds.
*/
Promise.resolve()
.then(() => database.setUp());
Promise.resolve().then(() => database.setUp());
module.exports = database;

View File

@@ -41,8 +41,8 @@ CREATE TABLE IF NOT EXISTS requests(
date DATE DEFAULT CURRENT_TIMESTAMP,
status CHAR(25) DEFAULT 'requested' NOT NULL,
user_agent CHAR(255) DEFAULT NULL,
type CHAR(50) DEFAULT 'movie',
foreign key(requested_by) REFERENCES user(user_name) ON DELETE SET NULL
type CHAR(50) DEFAULT 'movie'
-- foreign key(requested_by) REFERENCES user(user_name) ON DELETE SET NULL
);
CREATE TABLE IF NOT EXISTS request(

View File

@@ -1,13 +1,13 @@
const fs = require('fs');
const path = require('path');
const sqlite3 = require('sqlite3').verbose();
const fs = require("fs");
const path = require("path");
const sqlite3 = require("sqlite3").verbose();
class SqliteDatabase {
constructor(host) {
this.host = host;
this.connection = new sqlite3.Database(this.host);
this.execute('pragma foreign_keys = on;');
this.schemaDirectory = path.join(__dirname, 'schemas');
this.execute("pragma foreign_keys = on;");
this.schemaDirectory = path.join(__dirname, "schemas");
}
/**
@@ -29,9 +29,8 @@ class SqliteDatabase {
run(sql, parameters) {
return new Promise((resolve, reject) => {
this.connection.run(sql, parameters, (error, result) => {
if (error)
reject(error);
resolve(result)
if (error) reject(error);
resolve(result);
});
});
}
@@ -49,8 +48,8 @@ class SqliteDatabase {
reject(err);
}
resolve(rows);
})
})
});
});
}
/**
@@ -66,8 +65,8 @@ class SqliteDatabase {
reject(err);
}
resolve(rows);
})
})
});
});
}
/**
@@ -80,12 +79,12 @@ class SqliteDatabase {
return new Promise(resolve => {
this.connection.exec(sql, (err, database) => {
if (err) {
console.log('ERROR: ', err);
console.log("ERROR: ", err);
reject(err);
}
resolve();
})
})
});
});
}
/**
@@ -93,7 +92,7 @@ class SqliteDatabase {
* @returns {Promise}
*/
setUp() {
const setupSchema = this.readSqlFile('setup.sql');
const setupSchema = this.readSqlFile("setup.sql");
return Promise.resolve(this.execute(setupSchema));
}
@@ -102,7 +101,7 @@ class SqliteDatabase {
* @returns {Promise}
*/
tearDown() {
const tearDownSchema = this.readSqlFile('teardown.sql');
const tearDownSchema = this.readSqlFile("teardown.sql");
return Promise.resolve(this.execute(tearDownSchema));
}
@@ -112,7 +111,7 @@ class SqliteDatabase {
*/
readSqlFile(filename) {
const schemaPath = path.join(this.schemaDirectory, filename);
const schema = fs.readFileSync(schemaPath).toString('utf-8');
const schema = fs.readFileSync(schemaPath).toString("utf-8");
return schema;
}
}

View File

@@ -1,8 +1,17 @@
const Media = require('src/media_classes/media');
const Media = require("./media");
class Plex extends Media {
constructor(title, year, type, summary, poster_path, background_path, added, seasons, episodes) {
constructor(
title,
year,
type,
summary,
poster_path,
background_path,
added,
seasons,
episodes
) {
super(title, year, type);
this.summary = summary;

View File

@@ -1,9 +1,22 @@
const Media = require('src/media_classes/media');
const Media = require("./media");
class TMDB extends Media {
// constructor(...args) {
constructor(title, year, type, id, summary, poster_path, background_path, popularity, score, release_status, tagline, seasons, episodes) {
constructor(
title,
year,
type,
id,
summary,
poster_path,
background_path,
popularity,
score,
release_status,
tagline,
seasons,
episodes
) {
super(title, year, type);
this.id = id;

View File

@@ -1,16 +1,16 @@
const request = require("request");
const configuration = require('src/config/configuration').getInstance();
const configuration = require("../config/configuration").getInstance();
const sendSMS = (message) => {
const apiKey = configuration.get('sms', 'apikey')
const sendSMS = message => {
const apiKey = configuration.get("sms", "apikey");
if (!apiKey) {
console.warning("api key for sms not set, cannot send sms.")
return null
console.warning("api key for sms not set, cannot send sms.");
return null;
}
const sender = configuration.get('sms', 'sender')
const recipient = configuration.get('sms', 'recipient')
const sender = configuration.get("sms", "sender");
const recipient = configuration.get("sms", "recipient");
return new Promise((resolve, reject) => {
request.post(
@@ -25,11 +25,11 @@ const sendSMS = (message) => {
},
function (err, r, body) {
console.log(err ? err : body);
console.log("sms provider response:", body)
resolve()
console.log("sms provider response:", body);
resolve();
}
);
})
}
});
};
module.exports = { sendSMS }
module.exports = { sendSMS };

View File

@@ -3,10 +3,9 @@ const http = require("http");
const { URL } = require("url");
const PythonShell = require("python-shell");
const establishedDatabase = require("src/database/database");
const establishedDatabase = require("../database/database");
const RedisCache = require("src/cache/redis");
const cache = new RedisCache();
const cache = require("../cache/redis");
function getMagnetFromURL(url) {
return new Promise((resolve, reject) => {

View File

@@ -1,7 +1,11 @@
const Episode = require('src/plex/types/episode');
const Episode = require("./types/episode");
function convertPlexToEpisode(plexEpisode) {
const episode = new Episode(plexEpisode.title, plexEpisode.grandparentTitle, plexEpisode.year);
const episode = new Episode(
plexEpisode.title,
plexEpisode.grandparentTitle,
plexEpisode.year
);
episode.season = plexEpisode.parentIndex;
episode.episode = plexEpisode.index;
episode.summary = plexEpisode.summary;
@@ -12,7 +16,7 @@ function convertPlexToEpisode(plexEpisode) {
}
if (plexEpisode.originallyAvailableAt !== undefined) {
episode.airdate = new Date(plexEpisode.originallyAvailableAt)
episode.airdate = new Date(plexEpisode.originallyAvailableAt);
}
return episode;

View File

@@ -1,4 +1,4 @@
const Movie = require('src/plex/types/movie');
const Movie = require("./types/movie");
function convertPlexToMovie(plexMovie) {
const movie = new Movie(plexMovie.title, plexMovie.year);

View File

@@ -1,4 +1,4 @@
const Plex = require('src/media_classes/plex');
const Plex = require("../media_classes/plex");
function translateAdded(date_string) {
return new Date(date_string * 1000);
@@ -16,7 +16,17 @@ function convertPlexToSeasoned(plex) {
const seasons = plex.childCount;
const episodes = plex.leafCount;
const seasoned = new Plex(title, year, type, summary, poster_path, background_path, added, seasons, episodes);
const seasoned = new Plex(
title,
year,
type,
summary,
poster_path,
background_path,
added,
seasons,
episodes
);
// seasoned.print();
return seasoned;
}

View File

@@ -1,4 +1,4 @@
const Show = require('src/plex/types/show');
const Show = require("./types/show");
function convertPlexToShow(plexShow) {
const show = new Show(plexShow.title, plexShow.year);

View File

@@ -1,8 +1,8 @@
const convertPlexToSeasoned = require('src/plex/convertPlexToSeasoned');
const convertStreamToMediaInfo = require('src/plex/convertStreamToMediaInfo');
const convertStreamToPlayer = require('src/plex/stream/convertStreamToPlayer');
const convertStreamToUser = require('src/plex/stream/convertStreamToUser');
const ConvertStreamToPlayback = require('src/plex/stream/convertStreamToPlayback');
const convertPlexToSeasoned = require("./convertPlexToSeasoned");
const convertStreamToMediaInfo = require("./convertStreamToMediaInfo");
const convertStreamToPlayer = require("./stream/convertStreamToPlayer");
const convertStreamToUser = require("./stream/convertStreamToUser");
const ConvertStreamToPlayback = require("./stream/convertStreamToPlayback");
function convertPlexToStream(plexStream) {
const stream = convertPlexToSeasoned(plexStream);

View File

@@ -1,4 +1,4 @@
const MediaInfo = require('src/media_classes/mediaInfo');
const MediaInfo = require("../media_classes/mediaInfo");
function convertStreamToMediaInfo(plexStream) {
const mediaInfo = new MediaInfo();

View File

@@ -1,4 +1,4 @@
const configuration = require('src/config/configuration').getInstance();
const configuration = require("../config/configuration").getInstance();
function hookDumpController(req, res) {
console.log(req);

View File

@@ -1,12 +1,11 @@
const fetch = require("node-fetch");
const convertPlexToMovie = require("src/plex/convertPlexToMovie");
const convertPlexToShow = require("src/plex/convertPlexToShow");
const convertPlexToEpisode = require("src/plex/convertPlexToEpisode");
const convertPlexToMovie = require("./convertPlexToMovie");
const convertPlexToShow = require("./convertPlexToShow");
const convertPlexToEpisode = require("./convertPlexToEpisode");
const { Movie, Show, Person } = require("src/tmdb/types");
const { Movie, Show, Person } = require("../tmdb/types");
const RedisCache = require("src/cache/redis");
const redisCache = new RedisCache();
const redisCache = require("../cache/redis");
const sanitize = string => string.toLowerCase().replace(/[^\w]/gi, "");

View File

@@ -1,6 +1,6 @@
const convertPlexToSeasoned = require('src/plex/convertPlexToSeasoned');
const convertPlexToStream = require('src/plex/convertPlexToStream');
const rp = require('request-promise');
const convertPlexToSeasoned = require("./convertPlexToSeasoned");
const convertPlexToStream = require("./convertPlexToStream");
const rp = require("request-promise");
class PlexRepository {
constructor(plexIP) {
@@ -11,42 +11,45 @@ class PlexRepository {
return Promise.resolve()
.then(() => this.search(tmdbResult.title))
.then(plexResult => this.compareTmdbToPlex(tmdbResult, plexResult))
.catch((error) => {
console.log(error)
.catch(error => {
console.log(error);
tmdbResult.matchedInPlex = false;
return tmdbResult;
});
}
search(query) {
const queryUri = encodeURIComponent(query)
const uri = encodeURI(`http://${this.plexIP}:32400/search?query=${queryUri}`)
const queryUri = encodeURIComponent(query);
const uri = encodeURI(
`http://${this.plexIP}:32400/search?query=${queryUri}`
);
const options = {
uri: uri,
headers: {
Accept: 'application/json',
Accept: "application/json"
},
json: true,
json: true
};
return rp(options)
.catch((error) => {
console.log(error)
throw new Error('Unable to search plex.')
.catch(error => {
console.log(error);
throw new Error("Unable to search plex.");
})
.then(result => this.mapResults(result))
.then(([mappedResults, resultCount]) => ({ results: mappedResults, total_results: resultCount }));
.then(([mappedResults, resultCount]) => ({
results: mappedResults,
total_results: resultCount
}));
}
compareTmdbToPlex(tmdb, plexResult) {
return Promise.resolve()
.then(() => {
return Promise.resolve().then(() => {
if (plexResult.results.length === 0) {
tmdb.matchedInPlex = false
}
else {
tmdb.matchedInPlex = false;
} else {
// console.log('plex and tmdb:', plexResult, '\n', tmdb)
plexResult.results.map((plexItem) => {
plexResult.results.map(plexItem => {
if (tmdb.title === plexItem.title && tmdb.year === plexItem.year)
tmdb.matchedInPlex = true;
return tmdb;
@@ -59,34 +62,39 @@ class PlexRepository {
mapResults(response) {
return Promise.resolve()
.then(() => {
if (!response.MediaContainer.hasOwnProperty('Metadata')) return [[], 0];
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));
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); });
.catch(error => {
throw new Error(error);
});
}
nowPlaying() {
const options = {
uri: `http://${this.plexIP}:32400/status/sessions`,
headers: {
Accept: 'application/json',
Accept: "application/json"
},
json: true,
json: true
};
return rp(options)
.then((result) => {
.then(result => {
if (result.MediaContainer.size > 0) {
const playing = result.MediaContainer.Metadata.map(convertPlexToStream);
const playing =
result.MediaContainer.Metadata.map(convertPlexToStream);
return { size: Object.keys(playing).length, video: playing };
}
return { size: 0, video: [] };
})
.catch((err) => {
.catch(err => {
throw new Error(`Error handling plex playing. Error: ${err}`);
});
}

View File

@@ -1,7 +1,7 @@
const PlexRepository = require("src/plex/plexRepository");
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const establishedDatabase = require("src/database/database");
const PlexRepository = require("./plexRepository");
const configuration = require("../config/configuration").getInstance();
const TMDB = require("../tmdb/tmdb");
const establishedDatabase = require("../database/database");
const plexRepository = new PlexRepository(configuration.get("plex", "ip"));
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));

View File

@@ -1,4 +1,4 @@
const Player = require('src/media_classes/player');
const Player = require("../../media_classes/player");
function convertStreamToPlayer(plexStream) {
const player = new Player(plexStream.device, plexStream.address);

View File

@@ -1,4 +1,4 @@
const User = require('src/media_classes/user');
const User = require("../../media_classes/user");
function convertStreamToUser(plexStream) {
return new User(plexStream.id, plexStream.title);

View File

@@ -1,28 +1,34 @@
const assert = require('assert')
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const establishedDatabase = require('src/database/database');
const utils = require('./utils');
const assert = require("assert");
const configuration = require("../config/configuration").getInstance();
const TMDB = require("../tmdb/tmdb");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const establishedDatabase = require("../database/database");
const utils = require("./utils");
class RequestRepository {
constructor(database) {
this.database = database || establishedDatabase;
this.queries = {
add: 'insert into requests (id,title,year,poster_path,background_path,requested_by,ip,user_agent,type) values(?,?,?,?,?,?,?,?,?)',
fetchAll: 'select * from requests where status != "downloaded" order by date desc LIMIT 25 OFFSET ?*25-25',
fetchAllFilteredStatus: 'select * from requests where status = ? order by date desc LIMIT 25 offset ?*25-25',
totalRequests: 'select count(*) as totalRequests from requests where status != "downloaded"',
totalRequestsFilteredStatus: 'select count(*) as totalRequests from requests where status = ?',
add: "insert into requests (id,title,year,poster_path,background_path,requested_by,ip,user_agent,type) values(?,?,?,?,?,?,?,?,?)",
fetchAll:
'select * from requests where status != "downloaded" order by date desc LIMIT 25 OFFSET ?*25-25',
fetchAllFilteredStatus:
"select * from requests where status = ? order by date desc LIMIT 25 offset ?*25-25",
totalRequests:
'select count(*) as totalRequests from requests where status != "downloaded"',
totalRequestsFilteredStatus:
"select count(*) as totalRequests from requests where status = ?",
fetchAllSort: `select id, type from request order by ? ?`,
fetchAllFilter: `select id, type from request where ? is "?"`,
fetchAllQuery: `select id, type from request where title like "%?%" or year like "%?%"`,
fetchAllFilterAndSort: `select id, type from request where ? is "?" order by ? ?`,
downloaded: '(select status from requests where id is request.id and type is request.type limit 1)',
downloaded:
"(select status from requests where id is request.id and type is request.type limit 1)",
// deluge: '(select status from deluge_torrent where id is request.id and type is request.type limit 1)',
// fetchAllFilterStatus: 'select * from request where '
readWithoutUserData: 'select id, title, year, type, status, date from requests where id is ? and type is ?',
read: 'select id, title, year, type, status, requested_by, ip, date, user_agent from requests where id is ? and type is ?'
readWithoutUserData:
"select id, title, year, type, status, date from requests where id is ? and type is ?",
read: "select id, title, year, type, status, requested_by, ip, date, user_agent from requests where id is ? and type is ?"
};
}
@@ -31,52 +37,58 @@ class RequestRepository {
if (query !== undefined) {
const dbParams = [query, query];
const dbquery = this.queries.fetchAllQuery
const dbquery = this.queries.fetchAllQuery;
dbQuery = dbquery.split('').map((char) => char === '?' ? dbParams.shift() : char).join('')
}
else if (by !== undefined && filter !== undefined) {
dbQuery = dbquery
.split("")
.map(char => (char === "?" ? dbParams.shift() : char))
.join("");
} else if (by !== undefined && filter !== undefined) {
const paramToColumnAndValue = {
movie: ['type', 'movie'],
show: ['type', 'show']
}
movie: ["type", "movie"],
show: ["type", "show"]
};
const dbParams = paramToColumnAndValue[filter].concat([by, direction]);
const query = this.queries.fetchAllFilterAndSort;
dbQuery = query.split('').map((char) => char === '?' ? dbParams.shift() : char).join('')
}
else if (by !== undefined) {
dbQuery = query
.split("")
.map(char => (char === "?" ? dbParams.shift() : char))
.join("");
} else if (by !== undefined) {
const dbParams = [by, direction];
const query = this.queries.fetchAllSort;
dbQuery = query.split('').map((char) => char === '?' ? dbParams.shift() : char).join('')
}
else if (filter !== undefined) {
dbQuery = query
.split("")
.map(char => (char === "?" ? dbParams.shift() : char))
.join("");
} else if (filter !== undefined) {
const paramToColumnAndValue = {
movie: ['type', 'movie'],
show: ['type', 'show'],
downloaded: [this.queries.downloaded, 'downloaded']
movie: ["type", "movie"],
show: ["type", "show"],
downloaded: [this.queries.downloaded, "downloaded"]
// downloading: [this.database.delugeStatus, 'downloading']
}
const dbParams = paramToColumnAndValue[filter]
};
const dbParams = paramToColumnAndValue[filter];
const query = this.queries.fetchAllFilter;
dbQuery = query.split('').map((char) => char === '?' ? dbParams.shift() : char).join('')
}
else {
dbQuery = query
.split("")
.map(char => (char === "?" ? dbParams.shift() : char))
.join("");
} else {
dbQuery = this.queries.fetchAll;
}
return dbQuery
return dbQuery;
}
mapToTmdbByType(rows) {
return rows.map((row) => {
if (row.type === 'movie')
return tmdb.movieInfo(row.id)
else if (row.type === 'show')
return tmdb.showInfo(row.id)
})
return rows.map(row => {
if (row.type === "movie") return tmdb.movieInfo(row.id);
else if (row.type === "show") return tmdb.showInfo(row.id);
});
}
/**
@@ -87,14 +99,31 @@ class RequestRepository {
requestFromTmdb(tmdb, ip, user_agent, username) {
return Promise.resolve()
.then(() => this.database.get(this.queries.read, [tmdb.id, tmdb.type]))
.then(row => assert.equal(row, undefined, 'Id has already been requested'))
.then(() => this.database.run(this.queries.add, [tmdb.id, tmdb.title, tmdb.year, tmdb.poster, tmdb.backdrop, username, ip, user_agent, tmdb.type]))
.catch((error) => {
if (error.name === 'AssertionError' || error.message.endsWith('been requested')) {
throw new Error('This id is already requested', error.message);
.then(row =>
assert.equal(row, undefined, "Id has already been requested")
)
.then(() =>
this.database.run(this.queries.add, [
tmdb.id,
tmdb.title,
tmdb.year,
tmdb.poster,
tmdb.backdrop,
username,
ip,
user_agent,
tmdb.type
])
)
.catch(error => {
if (
error.name === "AssertionError" ||
error.message.endsWith("been requested")
) {
throw new Error("This id is already requested", error.message);
}
console.log('Error @ request.addTmdb:', error);
throw new Error('Could not add request');
console.log("Error @ request.addTmdb:", error);
throw new Error("Could not add request");
});
}
@@ -105,9 +134,10 @@ class RequestRepository {
* @returns {Promise}
*/
getRequestByIdAndType(id, type) {
return this.database.get(this.queries.readWithoutUserData, [id, type])
return this.database
.get(this.queries.readWithoutUserData, [id, type])
.then(row => {
assert(row, 'Could not find request item with that id and type')
assert(row, "Could not find request item with that id and type");
return {
id: row.id,
title: row.title,
@@ -115,8 +145,8 @@ class RequestRepository {
type: row.type,
status: row.status,
requested_date: new Date(row.date)
}
})
};
});
}
/**
@@ -127,40 +157,68 @@ class RequestRepository {
* @param {String} query param to filter result on. Filters on title and year
* @returns {Promise}
*/
fetchAll(page=1, sort_by=undefined, sort_direction='asc', filter=undefined, query=undefined) {
fetchAll(
page = 1,
sort_by = undefined,
sort_direction = "asc",
filter = undefined,
query = undefined
) {
// TODO implemented sort and filter
page = parseInt(page)
let fetchQuery = this.queries.fetchAll
let fetchTotalResults = this.queries.totalRequests
let fetchParams = [page]
page = parseInt(page);
let fetchQuery = this.queries.fetchAll;
let fetchTotalResults = this.queries.totalRequests;
let fetchParams = [page];
if (filter && (filter === 'downloading' || filter === 'downloaded' || filter === 'requested')) {
console.log('tes')
fetchQuery = this.queries.fetchAllFilteredStatus
fetchTotalResults = this.queries.totalRequestsFilteredStatus
fetchParams = [filter, page]
if (
filter &&
(filter === "downloading" ||
filter === "downloaded" ||
filter === "requested")
) {
console.log("tes");
fetchQuery = this.queries.fetchAllFilteredStatus;
fetchTotalResults = this.queries.totalRequestsFilteredStatus;
fetchParams = [filter, page];
} else {
filter = undefined
filter = undefined;
}
return Promise.resolve()
.then((dbQuery) => this.database.all(fetchQuery, fetchParams))
.then(async (rows) => {
const sqliteResponse = await this.database.get(fetchTotalResults, filter ? filter : undefined)
const totalRequests = sqliteResponse['totalRequests']
const totalPages = Math.ceil(totalRequests / 26)
.then(dbQuery => this.database.all(fetchQuery, fetchParams))
.then(async rows => {
const sqliteResponse = await this.database.get(
fetchTotalResults,
filter ? filter : undefined
);
const totalRequests = sqliteResponse["totalRequests"];
const totalPages = Math.ceil(totalRequests / 26);
return [ rows.map(item => {
item.poster = item.poster_path; delete item.poster_path;
item.backdrop = item.background_path; delete item.background_path;
return item
}), totalPages, totalRequests ]
return Promise.all(this.mapToTmdbByType(rows))
return [
rows.map(item => {
item.poster = item.poster_path;
delete item.poster_path;
item.backdrop = item.background_path;
delete item.background_path;
return item;
}),
totalPages,
totalRequests
];
return Promise.all(this.mapToTmdbByType(rows));
})
.then(([result, totalPages, totalRequests]) => Promise.resolve({
results: result, total_results: totalRequests, page: page, total_pages: totalPages
}))
.catch(error => { console.log(error);throw error })
.then(([result, totalPages, totalRequests]) =>
Promise.resolve({
results: result,
total_results: totalRequests,
page: page,
total_pages: totalPages
})
)
.catch(error => {
console.log(error);
throw error;
});
}
}

View File

@@ -1,11 +1,12 @@
const establishedDatabase = require('src/database/database');
const establishedDatabase = require("../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',
create:
"insert into search_history (search_query, user_name) values (?, ?)",
read: "select search_query from search_history where user_name = ? order by id desc"
};
}
@@ -15,15 +16,18 @@ class SearchHistory {
* @returns {Promise}
*/
read(user) {
return new Promise((resolve, reject) => this.database.all(this.queries.read, user)
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.');
}));
.catch(error => {
console.log("Error when fetching history from database:", error);
reject("Unable to get history.");
})
);
}
/**
@@ -33,18 +37,19 @@ class SearchHistory {
* @returns {Promise}
*/
create(username, searchQuery) {
return this.database.run(this.queries.create, [searchQuery, username])
return this.database
.run(this.queries.create, [searchQuery, username])
.catch(error => {
if (error.message.includes('FOREIGN')) {
throw new Error('Could not create search history.');
if (error.message.includes("FOREIGN")) {
throw new Error("Could not create search history.");
}
throw {
success: false,
status: 500,
message: 'An unexpected error occured',
source: 'database'
}
message: "An unexpected error occured",
source: "database"
};
});
}
}

View File

@@ -1,23 +1,28 @@
const assert = require('assert');
const Stray = require('src/seasoned/stray');
const establishedDatabase = require('src/database/database');
const pythonShell = require('python-shell');
const assert = require("assert");
const Stray = require("./stray");
const establishedDatabase = require("../database/database");
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 = ?',
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 this.database.get(this.queries.read, strayId).then(row => {
assert.notEqual(
row,
undefined,
`Could not find list with id ${strayId}.`
);
return row;
});
}
@@ -28,30 +33,31 @@ class StrayRepository {
dbSearchQuery = this.queries.readAllFiltered + verified.toString();
}
return this.database.all(dbSearchQuery).then(rows =>
rows.map((row) => {
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) => {
return this.database.get(this.queries.checkVerified, strayId).then(row => {
assert.notEqual(row, undefined, `Stray '${strayId}' already verified.`);
const options = {
pythonPath: '../app/env/bin/python3',
args: [strayId],
pythonPath: "../app/env/bin/python3",
args: [strayId]
};
pythonShell.run('../app/moveSeasoned.py', options, (err, results) => {
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);
console.log("results: %j", results);
});
return this.database.run(this.queries.verify, strayId);

View File

@@ -1,14 +1,16 @@
const assert = require('assert');
const establishedDatabase = require('src/database/database');
const assert = require("assert");
const establishedDatabase = require("../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, ' +
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 (?, ?, ?)',
"FROM cache WHERE key = ? AND now < expires",
create:
"INSERT OR REPLACE INTO cache (key, value, time_to_live) VALUES (?, ?, ?)"
};
}
@@ -21,9 +23,9 @@ class Cache {
return Promise.resolve()
.then(() => this.database.get(this.queries.read, [key]))
.then(row => {
assert(row, 'Could not find cache entry with that key.');
assert(row, "Could not find cache entry with that key.");
return JSON.parse(row.value);
})
});
}
/**
@@ -36,7 +38,9 @@ class Cache {
set(key, value, timeToLive = 10800) {
const json = JSON.stringify(value);
return Promise.resolve()
.then(() => this.database.run(this.queries.create, [key, json, timeToLive]))
.then(() =>
this.database.run(this.queries.create, [key, json, timeToLive])
)
.then(() => value);
}
}

View File

@@ -1,14 +1,7 @@
const moviedb = require("km-moviedb");
const RedisCache = require("src/cache/redis");
const redisCache = new RedisCache();
const redisCache = require("../cache/redis");
const {
Movie,
Show,
Person,
Credits,
ReleaseDates
} = require("src/tmdb/types");
const { Movie, Show, Person, Credits, ReleaseDates } = require("./types");
const tmdbErrorResponse = (error, typeString = undefined) => {
if (error.status === 404) {
@@ -107,12 +100,18 @@ class TMDB {
* @returns {Promise} movie release dates object
*/
movieReleaseDates(identifier) {
const query = { id: identifier }
const cacheKey = `tmdb/${this.cacheTags.movieReleaseDates}:${identifier}`
const query = { id: identifier };
const cacheKey = `tmdb/${this.cacheTags.movieReleaseDates}:${identifier}`;
return this.getFromCacheOrFetchFromTmdb(cacheKey, 'movieReleaseDates', query)
.then(releaseDates => this.cache.set(cacheKey, releaseDates, this.defaultTTL))
.then(releaseDates => ReleaseDates.convertFromTmdbResponse(releaseDates))
return this.getFromCacheOrFetchFromTmdb(
cacheKey,
"movieReleaseDates",
query
)
.then(releaseDates =>
this.cache.set(cacheKey, releaseDates, this.defaultTTL)
)
.then(releaseDates => ReleaseDates.convertFromTmdbResponse(releaseDates));
}
/**

View File

@@ -1,4 +1,4 @@
const User = require("src/user/user");
const User = require("./user");
const jwt = require("jsonwebtoken");
class Token {

View File

@@ -1,5 +1,5 @@
const assert = require("assert");
const establishedDatabase = require("src/database/database");
const establishedDatabase = require("../database/database");
class UserRepository {
constructor(database) {

View File

@@ -1,5 +1,5 @@
const bcrypt = require("bcrypt");
const UserRepository = require("src/user/userRepository");
const UserRepository = require("./userRepository");
class UserSecurity {
constructor(database) {

View File

@@ -3,7 +3,7 @@ const Raven = require("raven");
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");
const configuration = require("src/config/configuration").getInstance();
const configuration = require("../config/configuration").getInstance();
const reqTokenToUser = require("./middleware/reqTokenToUser");
const mustBeAuthenticated = require("./middleware/mustBeAuthenticated");

View File

@@ -1,13 +1,14 @@
const GitRepository = require('src/git/gitRepository');
const GitRepository = require("../../../git/gitRepository");
const gitRepository = new GitRepository();
function dumpHookController(req, res) {
gitRepository.dumpHook(req.body)
gitRepository
.dumpHook(req.body)
.then(() => {
res.status(200);
})
.catch((error) => {
.catch(error => {
res.status(500);
});
}

View File

@@ -1,6 +1,6 @@
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
// there should be a translate function from query params to
// tmdb list that is valid. Should it be a helper function or does it
@@ -18,44 +18,57 @@ function handleError(error, res) {
const { status, message } = error;
if (status && message) {
res.status(status).send({ success: false, message })
res.status(status).send({ success: false, message });
} else {
console.log('caught list controller error', error)
res.status(500).send({ message: 'An unexpected error occured while requesting list'})
console.log("caught list controller error", error);
res
.status(500)
.send({ message: "An unexpected error occured while requesting list" });
}
}
function handleListResponse(response, res) {
return res.send(response)
.catch(error => handleError(error, res))
return res.send(response).catch(error => handleError(error, res));
}
function fetchTmdbList(req, res, listname, type) {
const { page } = req.query;
if (type === 'movie') {
return tmdb.movieList(listname, page)
if (type === "movie") {
return tmdb
.movieList(listname, page)
.then(listResponse => res.send(listResponse))
.catch(error => handleError(error, res))
} else if (type === 'show') {
return tmdb.showList(listname, page)
.catch(error => handleError(error, res));
} else if (type === "show") {
return tmdb
.showList(listname, page)
.then(listResponse => res.send(listResponse))
.catch(error => handleError(error, res))
.catch(error => handleError(error, res));
}
handleError({
handleError(
{
status: 400,
message: `'${type}' is not a valid list type.`
}, res)
},
res
);
}
const nowPlayingMovies = (req, res) => fetchTmdbList(req, res, 'miscNowPlayingMovies', 'movie')
const popularMovies = (req, res) => fetchTmdbList(req, res, 'miscPopularMovies', 'movie')
const topRatedMovies = (req, res) => fetchTmdbList(req, res, 'miscTopRatedMovies', 'movie')
const upcomingMovies = (req, res) => fetchTmdbList(req, res, 'miscUpcomingMovies', 'movie')
const nowPlayingShows = (req, res) => fetchTmdbList(req, res, 'tvOnTheAir', 'show')
const popularShows = (req, res) => fetchTmdbList(req, res, 'miscPopularTvs', 'show')
const topRatedShows = (req, res) => fetchTmdbList(req, res, 'miscTopRatedTvs', 'show')
const nowPlayingMovies = (req, res) =>
fetchTmdbList(req, res, "miscNowPlayingMovies", "movie");
const popularMovies = (req, res) =>
fetchTmdbList(req, res, "miscPopularMovies", "movie");
const topRatedMovies = (req, res) =>
fetchTmdbList(req, res, "miscTopRatedMovies", "movie");
const upcomingMovies = (req, res) =>
fetchTmdbList(req, res, "miscUpcomingMovies", "movie");
const nowPlayingShows = (req, res) =>
fetchTmdbList(req, res, "tvOnTheAir", "show");
const popularShows = (req, res) =>
fetchTmdbList(req, res, "miscPopularTvs", "show");
const topRatedShows = (req, res) =>
fetchTmdbList(req, res, "miscTopRatedTvs", "show");
module.exports = {
nowPlayingMovies,
@@ -65,4 +78,4 @@ module.exports = {
nowPlayingShows,
popularShows,
topRatedShows
}
};

View File

@@ -1,24 +1,30 @@
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const movieCreditsController = (req, res) => {
const movieId = req.params.id;
tmdb.movieCredits(movieId)
tmdb
.movieCredits(movieId)
.then(credits => res.send(credits.createJsonResponse()))
.catch(error => {
const { status, message } = error;
if (status && message) {
res.status(status).send({ success: false, message })
res.status(status).send({ success: false, message });
} else {
// TODO log unhandled errors
console.log('caugth movie credits controller error', error)
res.status(500).send({ message: 'An unexpected error occured while requesting movie credits' })
}
})
console.log("caugth movie credits controller error", error);
res
.status(500)
.send({
message:
"An unexpected error occured while requesting movie credits"
});
}
});
};
module.exports = movieCreditsController;

View File

@@ -1,6 +1,6 @@
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const Plex = require("src/plex/plex");
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const Plex = require("../../../plex/plex");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const plex = new Plex(configuration.get("plex", "ip"));
@@ -58,7 +58,7 @@ async function movieInfoController(req, res) {
} else {
console.log("Unkown error from plex!");
}
console.log(error);
console.log(error?.message);
}
}

View File

@@ -1,24 +1,30 @@
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const movieReleaseDatesController = (req, res) => {
const movieId = req.params.id;
tmdb.movieReleaseDates(movieId)
tmdb
.movieReleaseDates(movieId)
.then(releaseDates => res.send(releaseDates.createJsonResponse()))
.catch(error => {
const { status, message } = error;
if (status && message) {
res.status(status).send({ success: false, message })
res.status(status).send({ success: false, message });
} else {
// TODO log unhandled errors : here our at tmdbReleaseError ?
console.log('caugth release dates controller error', error)
res.status(500).send({ message: 'An unexpected error occured while requesting movie credits' })
}
})
console.log("caugth release dates controller error", error);
res
.status(500)
.send({
message:
"An unexpected error occured while requesting movie credits"
});
}
});
};
module.exports = movieReleaseDatesController;

View File

@@ -1,5 +1,5 @@
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const personCreditsController = (req, res) => {

View File

@@ -1,5 +1,5 @@
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
function handleError(error, res) {

View File

@@ -1,4 +1,3 @@
/*
* @Author: KevinMidboe
* @Date: 2017-10-21 09:54:31
@@ -6,7 +5,7 @@
* @Last Modified time: 2017-10-21 15:32:43
*/
const PirateRepository = require('src/pirate/pirateRepository');
const PirateRepository = require("../../../pirate/pirateRepository");
function addMagnet(req, res) {
const magnet = req.body.magnet;
@@ -14,7 +13,7 @@ function addMagnet(req, res) {
const tmdb_id = req.body.tmdb_id;
PirateRepository.AddMagnet(magnet, name, tmdb_id)
.then((result) => {
.then(result => {
res.send(result);
})
.catch(error => {

View File

@@ -5,7 +5,7 @@
* @Last Modified time: 2018-02-26 19:56:32
*/
const PirateRepository = require("src/pirate/pirateRepository");
const PirateRepository = require("../../../pirate/pirateRepository");
// const pirateRepository = new PirateRepository();
/**

View File

@@ -1,4 +1,4 @@
const RequestRepository = require('src/plex/requestRepository.js');
const RequestRepository = require("../../../plex/requestRepository.js");
const requestRepository = new RequestRepository();
@@ -12,11 +12,16 @@ function fetchRequestedController(req, res) {
// const user = req.loggedInUser;
const { status, page } = req.query;
requestRepository.fetchRequested(status, page)
.then((requestedItems) => {
res.send({ success: true, results: requestedItems, total_results: requestedItems.length });
requestRepository
.fetchRequested(status, page)
.then(requestedItems => {
res.send({
success: true,
results: requestedItems,
total_results: requestedItems.length
});
})
.catch((error) => {
.catch(error => {
res.status(401).send({ success: false, message: error.message });
});
}

View File

@@ -1,10 +1,11 @@
const PlexRepository = require('src/plex/plexRepository');
const configuration = require('src/config/configuration').getInstance();
const PlexRepository = require("../../../plex/plexRepository");
const configuration = require("../../../config/configuration").getInstance();
const plexRepository = new PlexRepository(configuration.get('plex', 'ip'));
const plexRepository = new PlexRepository(configuration.get("plex", "ip"));
function playingController(req, res) {
plexRepository.nowPlaying()
plexRepository
.nowPlaying()
.then(movies => {
res.send(movies);
})

View File

@@ -1,4 +1,4 @@
const RequestRepository = require('src/plex/requestRepository');
const RequestRepository = require("../../../plex/requestRepository");
const requestRepository = new RequestRepository();
@@ -11,10 +11,12 @@ const requestRepository = new RequestRepository();
function readRequestController(req, res) {
const mediaId = req.params.mediaId;
const { type } = req.query;
requestRepository.lookup(mediaId, type)
requestRepository
.lookup(mediaId, type)
.then(movies => {
res.send(movies);
}).catch(error => {
})
.catch(error => {
res.status(404).send({ success: false, message: error.message });
});
}

View File

@@ -1,6 +1,6 @@
const configuration = require('src/config/configuration').getInstance();
const Plex = require('src/plex/plex');
const plex = new Plex(configuration.get('plex', 'ip'));
const configuration = require("../../../config/configuration").getInstance();
const Plex = require("../../../plex/plex");
const plex = new Plex(configuration.get("plex", "ip"));
/**
* Controller: Search plex for movies, shows and episodes by query
@@ -10,14 +10,21 @@ const plex = new Plex(configuration.get('plex', 'ip'));
*/
function searchPlexController(req, res) {
const { query, type } = req.query;
plex.search(query, type)
plex
.search(query, type)
.then(movies => {
if (movies.length > 0) {
res.send(movies);
} else {
res.status(404).send({ success: false, message: 'Search query did not give any results from plex.'})
res
.status(404)
.send({
success: false,
message: "Search query did not give any results from plex."
});
}
}).catch(error => {
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}

View File

@@ -1,7 +1,7 @@
const PlexRepository = require('src/plex/plexRepository');
const configuration = require('src/config/configuration').getInstance();
const PlexRepository = require("../../../plex/plexRepository");
const configuration = require("../../../config/configuration").getInstance();
const plexRepository = new PlexRepository(configuration.get('plex', 'ip'));
const plexRepository = new PlexRepository(configuration.get("plex", "ip"));
/**
* Controller: Search for media and check existence
@@ -13,12 +13,18 @@ const plexRepository = new PlexRepository(configuration.get('plex', 'ip'));
function searchMediaController(req, res) {
const { query } = req.query;
plexRepository.search(query)
plexRepository
.search(query)
.then(media => {
if (media !== undefined || media.length > 0) {
res.send(media);
} else {
res.status(404).send({ success: false, message: 'Search query did not return any results.' });
res
.status(404)
.send({
success: false,
message: "Search query did not return any results."
});
}
})
.catch(error => {

View File

@@ -1,6 +1,6 @@
const SearchHistory = require("src/searchHistory/searchHistory");
const Cache = require("src/tmdb/cache");
const RequestRepository = require("src/plex/requestRepository.js");
const SearchHistory = require("../../../searchHistory/searchHistory");
const Cache = require("../../../tmdb/cache");
const RequestRepository = require("../../../plex/requestRepository.js");
const cache = new Cache();
const requestRepository = new RequestRepository(cache);

View File

@@ -1,6 +1,6 @@
const configuration = require("src/config/configuration").getInstance();
const RequestRepository = require("src/request/request");
const TMDB = require("src/tmdb/tmdb");
const configuration = require("../../../config/configuration").getInstance();
const RequestRepository = require("../../../request/request");
const TMDB = require("../../../tmdb/tmdb");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const request = new RequestRepository();
@@ -35,9 +35,7 @@ function submitRequestController(req, res) {
console.log("show");
mediaFunction = tmdbShowInfo;
} else {
res
.status(422)
.send({
res.status(422).send({
success: false,
message: 'Incorrect type. Allowed types: "movie" or "show"'
});

View File

@@ -1,4 +1,4 @@
const RequestRepository = require('src/plex/requestRepository');
const RequestRepository = require("../../../plex/requestRepository");
const requestRepository = new RequestRepository();
@@ -13,11 +13,12 @@ function updateRequested(req, res) {
const type = req.body.type;
const status = req.body.status;
requestRepository.updateRequestedById(id, type, status)
requestRepository
.updateRequestedById(id, type, status)
.then(() => {
res.send({ success: true });
})
.catch((error) => {
.catch(error => {
res.status(401).send({ success: false, message: error.message });
});
}

View File

@@ -1,6 +1,6 @@
const configuration = require('src/config/configuration').getInstance();
const Plex = require('src/plex/plex');
const plex = new Plex(configuration.get('plex', 'ip'));
const configuration = require("../../../config/configuration").getInstance();
const Plex = require("../../../plex/plex");
const plex = new Plex(configuration.get("plex", "ip"));
/**
* Controller: Search plex for movies, shows and episodes by query
@@ -12,12 +12,12 @@ const plex = new Plex(configuration.get('plex', 'ip'));
function watchDirectLink(req, res) {
const { title, year } = req.query;
plex.getDirectLinkByTitleAndYear(title, year)
plex
.getDirectLinkByTitleAndYear(title, year)
.then(plexDirectLink => {
if (plexDirectLink == false)
res.status(404).send({ success: true, link: null })
else
res.status(200).send({ success: true, link: plexDirectLink })
res.status(404).send({ success: true, link: null });
else res.status(200).send({ success: true, link: plexDirectLink });
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });

View File

@@ -1,4 +1,4 @@
const RequestRepository = require('src/request/request');
const RequestRepository = require("../../../request/request");
const request = new RequestRepository();
/**
@@ -12,8 +12,8 @@ function fetchAllRequests(req, res) {
let sort_by = sort;
let sort_direction = undefined;
if (sort !== undefined && sort.includes(':')) {
[sort_by, sort_direction] = sort.split(':')
if (sort !== undefined && sort.includes(":")) {
[sort_by, sort_direction] = sort.split(":");
}
Promise.resolve()

View File

@@ -1,4 +1,4 @@
const RequestRepository = require('src/request/request');
const RequestRepository = require("../../../request/request");
const request = new RequestRepository();
/**
@@ -11,7 +11,8 @@ function fetchAllRequests(req, res) {
const id = req.params.id;
const { type } = req.query;
request.getRequestByIdAndType(id, type)
request
.getRequestByIdAndType(id, type)
.then(result => res.send(result))
.catch(error => {
res.status(404).send({ success: false, message: error.message });

View File

@@ -1,6 +1,6 @@
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const RequestRepository = require("src/request/request");
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const RequestRepository = require("../../../request/request");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const request = new RequestRepository();
// const { sendSMS } = require("src/notifications/sms");

View File

@@ -1,6 +1,6 @@
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const SearchHistory = require("src/searchHistory/searchHistory");
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const SearchHistory = require("../../../searchHistory/searchHistory");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const searchHistory = new SearchHistory();

View File

@@ -1,6 +1,6 @@
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const SearchHistory = require("src/searchHistory/searchHistory");
const configuration = require("../../..//config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const SearchHistory = require("../../../searchHistory/searchHistory");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const searchHistory = new SearchHistory();
@@ -36,9 +36,7 @@ function multiSearchController(req, res) {
} else {
// TODO log unhandled errors
console.log("caugth multi search controller error", error);
res
.status(500)
.send({
res.status(500).send({
message: `An unexpected error occured while searching with query: ${query}`
});
}

View File

@@ -1,6 +1,6 @@
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const SearchHistory = require("src/searchHistory/searchHistory");
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const SearchHistory = require("../../../searchHistory/searchHistory");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const searchHistory = new SearchHistory();

View File

@@ -1,6 +1,6 @@
const SearchHistory = require("src/searchHistory/searchHistory");
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const SearchHistory = require("../../../searchHistory/searchHistory");
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const searchHistory = new SearchHistory();

View File

@@ -1,15 +1,15 @@
const StrayRepository = require('src/seasoned/strayRepository');
const StrayRepository = require("../../../seasoned/strayRepository");
const strayRepository = new StrayRepository();
function readStraysController(req, res) {
const { verified, page } = req.query;
strayRepository.readAll(verified, page)
.then((strays) => {
strayRepository
.readAll(verified, page)
.then(strays => {
res.send(strays);
})
.catch((error) => {
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}

View File

@@ -1,15 +1,16 @@
const StrayRepository = require('src/seasoned/strayRepository');
const StrayRepository = require("../../../seasoned/strayRepository");
const strayRepository = new StrayRepository();
function strayByIdController(req, res) {
const id = req.params.strayId;
strayRepository.read(id)
.then((stray) => {
strayRepository
.read(id)
.then(stray => {
res.send(stray);
})
.catch((error) => {
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}

View File

@@ -1,15 +1,16 @@
const StrayRepository = require('src/seasoned/strayRepository');
const StrayRepository = require("../../../seasoned/strayRepository");
const strayRepository = new StrayRepository();
function verifyStrayController(req, res) {
const id = req.params.strayId;
strayRepository.verifyStray(id)
strayRepository
.verifyStray(id)
.then(() => {
res.send({ success: true, message: 'Episode verified' });
res.send({ success: true, message: "Episode verified" });
})
.catch((error) => {
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}

View File

@@ -1,23 +1,28 @@
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const showCreditsController = (req, res) => {
const showId = req.params.id;
tmdb.showCredits(showId)
tmdb
.showCredits(showId)
.then(credits => res.send(credits.createJsonResponse()))
.catch(error => {
const { status, message } = error;
if (status && message) {
res.status(status).send({ success: false, message })
res.status(status).send({ success: false, message });
} else {
// TODO log unhandled errors
console.log('caugth show credits controller error', error)
res.status(500).send({ message: 'An unexpected error occured while requesting show credits' })
}
})
console.log("caugth show credits controller error", error);
res
.status(500)
.send({
message: "An unexpected error occured while requesting show credits"
});
}
});
};
module.exports = showCreditsController;

View File

@@ -1,19 +1,19 @@
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const Plex = require('src/plex/plex');
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const plex = new Plex(configuration.get('plex', 'ip'));
const configuration = require("../../../config/configuration").getInstance();
const TMDB = require("../../../tmdb/tmdb");
const Plex = require("../../../plex/plex");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const plex = new Plex(configuration.get("plex", "ip"));
function handleError(error, res) {
const { status, message } = error;
if (status && message) {
res.status(status).send({ success: false, message })
res.status(status).send({ success: false, message });
} else {
console.log('caught showinfo controller error', error)
console.log("caught showinfo controller error", error);
res.status(500).send({
message: 'An unexpected error occured while requesting show info.'
})
message: "An unexpected error occured while requesting show info."
});
}
}
@@ -28,26 +28,27 @@ async function showInfoController(req, res) {
const showId = req.params.id;
let { credits, check_existance } = req.query;
credits && credits.toLowerCase() === 'true' ? credits = true : credits = false
check_existance && check_existance.toLowerCase() === 'true' ? check_existance = true : check_existance = false
credits && credits.toLowerCase() === "true"
? (credits = true)
: (credits = false);
check_existance && check_existance.toLowerCase() === "true"
? (check_existance = true)
: (check_existance = false);
let tmdbQueue = [tmdb.showInfo(showId)]
if (credits)
tmdbQueue.push(tmdb.showCredits(showId))
let tmdbQueue = [tmdb.showInfo(showId)];
if (credits) tmdbQueue.push(tmdb.showCredits(showId));
try {
const [Show, Credits] = await Promise.all(tmdbQueue)
const [Show, Credits] = await Promise.all(tmdbQueue);
const show = Show.createJsonResponse()
if (credits)
show.credits = Credits.createJsonResponse()
const show = Show.createJsonResponse();
if (credits) show.credits = Credits.createJsonResponse();
if (check_existance)
show.exists_in_plex = await plex.existsInPlex(show)
if (check_existance) show.exists_in_plex = await plex.existsInPlex(show);
res.send(show)
res.send(show);
} catch (error) {
handleError(error, res)
handleError(error, res);
}
}

View File

@@ -1,4 +1,4 @@
const UserRepository = require("src/user/userRepository");
const UserRepository = require("../../../user/userRepository");
const userRepository = new UserRepository();
const fetch = require("node-fetch");
const FormData = require("form-data");

View File

@@ -1,8 +1,8 @@
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 User = require("../../../user/user");
const Token = require("../../../user/token");
const UserSecurity = require("../../../user/userSecurity");
const UserRepository = require("../../../user/userRepository");
const configuration = require("../../../config/configuration").getInstance();
const secret = configuration.get("authentication", "secret");
const userSecurity = new UserSecurity();

View File

@@ -1,8 +1,8 @@
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 User = require("../../../user/user");
const Token = require("../../../user/token");
const UserSecurity = require("../../../user/userSecurity");
const UserRepository = require("../../../user/userRepository");
const configuration = require("../../../config/configuration").getInstance();
const secret = configuration.get("authentication", "secret");
const userSecurity = new UserSecurity();

View File

@@ -1,4 +1,4 @@
const RequestRepository = require("src/plex/requestRepository.js");
const RequestRepository = require("../../../plex/requestRepository.js");
const requestRepository = new RequestRepository();

View File

@@ -1,4 +1,4 @@
const SearchHistory = require("src/searchHistory/searchHistory");
const SearchHistory = require("../../../searchHistory/searchHistory");
const searchHistory = new SearchHistory();

View File

@@ -1,4 +1,4 @@
const UserRepository = require("src/user/userRepository");
const UserRepository = require("../../../user/userRepository");
const userRepository = new UserRepository();
/**
* Controller: Retrieves settings of a logged in user

View File

@@ -1,5 +1,5 @@
const configuration = require("src/config/configuration").getInstance();
const Tautulli = require("src/tautulli/tautulli");
const configuration = require("../../../config/configuration").getInstance();
const Tautulli = require("../../../tautulli/tautulli");
const apiKey = configuration.get("tautulli", "apiKey");
const ip = configuration.get("tautulli", "ip");
const port = configuration.get("tautulli", "port");

View File

@@ -1,4 +1,4 @@
const establishedDatabase = require('src/database/database');
const establishedDatabase = require("../../database/database");
const mustBeAdmin = (req, res, next) => {
let database = establishedDatabase;
@@ -6,19 +6,23 @@ const mustBeAdmin = (req, res, next) => {
if (req.loggedInUser === undefined) {
return res.status(401).send({
success: false,
message: 'You must be logged in.',
message: "You must be logged in."
});
} else {
database.get(`SELECT admin FROM user WHERE user_name IS ?`, req.loggedInUser.username)
.then((isAdmin) => {
console.log(isAdmin, req.loggedInUser)
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,
message: 'You must be logged in as a admin.'
})
message: "You must be logged in as a admin."
});
}
})
});
}
return next();

View File

@@ -1,4 +1,4 @@
const establishedDatabase = require('src/database/database');
const establishedDatabase = require("../../database/database");
const mustHaveAccountLinkedToPlex = (req, res, next) => {
let database = establishedDatabase;
@@ -7,25 +7,29 @@ const mustHaveAccountLinkedToPlex = (req, res, next) => {
if (loggedInUser === undefined) {
return res.status(401).send({
success: false,
message: 'You must have your account linked to a plex account.',
message: "You must have your account linked to a plex account."
});
} else {
database.get(`SELECT plex_userid FROM settings WHERE user_name IS ?`, loggedInUser.username)
database
.get(
`SELECT plex_userid FROM settings WHERE user_name IS ?`,
loggedInUser.username
)
.then(row => {
const plex_userid = row.plex_userid;
if (plex_userid === null || plex_userid === undefined) {
return res.status(403).send({
success: false,
message: 'No plex account user id found for your user. Please authenticate your plex account at /user/authenticate.'
})
message:
"No plex account user id found for your user. Please authenticate your plex account at /user/authenticate."
});
} else {
req.loggedInUser.plex_userid = plex_userid;
return next();
}
})
});
}
};
module.exports = mustHaveAccountLinkedToPlex;

View File

@@ -1,6 +1,6 @@
/* eslint-disable no-param-reassign */
const configuration = require("src/config/configuration").getInstance();
const Token = require("src/user/token");
const configuration = require("../../config/configuration").getInstance();
const Token = require("../../user/token");
const secret = configuration.get("authentication", "secret");

View File

@@ -1,11 +1,11 @@
const config = require('src/config/configuration').getInstance();
const app = require('./app');
const config = require("../config/configuration").getInstance();
const app = require("./app");
module.exports = app.listen(config.get('webserver', 'port'), () => {
module.exports = app.listen(config.get("webserver", "port"), () => {
/* eslint-disable no-console */
console.log('seasonedAPI');
console.log("seasonedAPI");
/* eslint-disable no-console */
console.log(`Database is located at ${config.get('database', 'host')}`);
console.log(`Database is located at ${config.get("database", "host")}`);
/* eslint-disable no-console */
console.log(`Webserver is listening on ${config.get('webserver', 'port')}`);
console.log(`Webserver is listening on ${config.get("webserver", "port")}`);
});

File diff suppressed because it is too large Load Diff

7915
yarn.lock

File diff suppressed because it is too large Load Diff