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,52 +1,73 @@
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");
/**
* 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) {
if (value == null || key == null) return null;
console.log(`redis://${host}:${port}`);
client = redis.createClient({
url: `redis://${host}:${port}`
});
const json = JSON.stringify(value);
client.set(key, json, (error, reply) => {
if (reply == "OK") {
// successfully set value with key, now set TTL for key
client.expire(key, timeToLive, e => {
if (e)
console.error(
"Unexpected error while setting expiration for key:",
key,
". Error:",
error
);
});
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) {}
return value;
}
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, TTL, e => {
if (e)
console.error(
"Unexpected error while setting expiration for key:",
key,
". Error:",
error
);
});
}
});
return value;
}
module.exports = Cache;
function get() {
return new Promise((resolve, reject) => {
client.get(key, (error, reply) => {
if (reply == null) {
return reject();
}
resolve(JSON.parse(reply));
});
});
}
module.exports = {
get,
set
};

View File

@@ -1,43 +1,47 @@
const path = require('path');
const Field = require('./field.js');
const path = require("path");
const Field = require("./field.js");
let instance = null;
class Config {
constructor() {
this.location = Config.determineLocation();
this.fields = require(`${this.location}`);
}
constructor() {
this.location = Config.determineLocation();
this.fields = require(`${this.location}`);
}
static getInstance() {
if (instance == null) {
instance = new Config();
}
return instance;
}
static getInstance() {
if (instance == null) {
instance = new Config();
}
return instance;
}
static determineLocation() {
return path.join(__dirname, '..', '..', process.env.SEASONED_CONFIG);
}
static determineLocation() {
return path.join(__dirname, "..", "..", process.env.SEASONED_CONFIG);
}
get(section, option) {
if (this.fields[section] === undefined || this.fields[section][option] === undefined) {
throw new Error(`Field "${section} => ${option}" does not exist.`);
}
get(section, option) {
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]);
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) {
throw new Error(`${section} => ${option} is empty.`);
}
if (field.value === undefined) {
throw new Error(`${section} => ${option} is empty.`);
}
return field.value;
}
return field.value;
}
}
module.exports = Config;

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

@@ -30,7 +30,7 @@ CREATE TABLE IF NOT EXISTS search_history (
foreign key(user_name) REFERENCES user(user_name) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS requests(
CREATE TABLE IF NOT EXISTS requests (
id NUMBER,
title TEXT,
year NUMBER,
@@ -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,120 +1,119 @@
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');
}
constructor(host) {
this.host = host;
this.connection = new sqlite3.Database(this.host);
this.execute("pragma foreign_keys = on;");
this.schemaDirectory = path.join(__dirname, "schemas");
}
/**
/**
* Connect to the database.
* @returns {Promise} succeeds if connection was established
*/
// connect() {
// let database = ;
// this.connection = database;
// return database;
// }
// connect() {
// let database = ;
// this.connection = database;
// return database;
// }
/**
/**
* Run a SQL query against the database.
* @param {String} sql SQL query
* @param {Array} parameters in the SQL query
* @returns {Promise}
*/
run(sql, parameters) {
return new Promise((resolve, reject) => {
this.connection.run(sql, parameters, (error, result) => {
if (error)
reject(error);
resolve(result)
});
run(sql, parameters) {
return new Promise((resolve, reject) => {
this.connection.run(sql, parameters, (error, result) => {
if (error) reject(error);
resolve(result);
});
}
});
}
/**
/**
* Run a SQL query against the database and retrieve all the rows.
* @param {String} sql SQL query
* @param {Array} parameters in the SQL query
* @returns {Promise}
*/
all(sql, parameters) {
return new Promise((resolve, reject) => {
this.connection.all(sql, parameters, (err, rows) => {
if (err) {
reject(err);
}
resolve(rows);
})
})
}
all(sql, parameters) {
return new Promise((resolve, reject) => {
this.connection.all(sql, parameters, (err, rows) => {
if (err) {
reject(err);
}
resolve(rows);
});
});
}
/**
/**
* Run a SQL query against the database and retrieve one row.
* @param {String} sql SQL query
* @param {Array} parameters in the SQL query
* @returns {Promise}
*/
get(sql, parameters) {
return new Promise((resolve, reject) => {
this.connection.get(sql, parameters, (err, rows) => {
if (err) {
reject(err);
}
resolve(rows);
})
})
}
get(sql, parameters) {
return new Promise((resolve, reject) => {
this.connection.get(sql, parameters, (err, rows) => {
if (err) {
reject(err);
}
resolve(rows);
});
});
}
/**
/**
* Run a SQL query against the database and retrieve the status.
* @param {String} sql SQL query
* @param {Array} parameters in the SQL query
* @returns {Promise}
*/
execute(sql) {
return new Promise(resolve => {
this.connection.exec(sql, (err, database) => {
if (err) {
console.log('ERROR: ', err);
reject(err);
}
resolve();
})
})
}
execute(sql) {
return new Promise(resolve => {
this.connection.exec(sql, (err, database) => {
if (err) {
console.log("ERROR: ", err);
reject(err);
}
resolve();
});
});
}
/**
/**
* Setup the database by running setup.sql file in schemas/.
* @returns {Promise}
*/
setUp() {
const setupSchema = this.readSqlFile('setup.sql');
return Promise.resolve(this.execute(setupSchema));
}
setUp() {
const setupSchema = this.readSqlFile("setup.sql");
return Promise.resolve(this.execute(setupSchema));
}
/**
/**
* Tears down the database by running tearDown.sql file in schemas/.
* @returns {Promise}
*/
tearDown() {
const tearDownSchema = this.readSqlFile('teardown.sql');
return Promise.resolve(this.execute(tearDownSchema));
}
tearDown() {
const tearDownSchema = this.readSqlFile("teardown.sql");
return Promise.resolve(this.execute(tearDownSchema));
}
/**
/**
* Returns the file contents of a SQL file in schemas/.
* @returns {String}
*/
readSqlFile(filename) {
const schemaPath = path.join(this.schemaDirectory, filename);
const schema = fs.readFileSync(schemaPath).toString('utf-8');
return schema;
}
readSqlFile(filename) {
const schemaPath = path.join(this.schemaDirectory, filename);
const schema = fs.readFileSync(schemaPath).toString("utf-8");
return schema;
}
}
module.exports = SqliteDatabase;

View File

@@ -1,22 +1,31 @@
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) {
super(title, year, type);
constructor(
title,
year,
type,
summary,
poster_path,
background_path,
added,
seasons,
episodes
) {
super(title, year, type);
this.summary = summary;
this.poster_path = poster_path;
this.background_path = background_path;
this.added = added;
this.summary = summary;
this.poster_path = poster_path;
this.background_path = background_path;
this.added = added;
this.seasons = seasons;
this.episodes = episodes;
}
this.seasons = seasons;
this.episodes = episodes;
}
print() {
super.print();
}
print() {
super.print();
}
}
module.exports = Plex;

View File

@@ -1,33 +1,46 @@
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) {
super(title, year, type);
// constructor(...args) {
constructor(
title,
year,
type,
id,
summary,
poster_path,
background_path,
popularity,
score,
release_status,
tagline,
seasons,
episodes
) {
super(title, year, type);
this.id = id;
this.summary = summary;
this.poster_path = poster_path;
this.background_path = background_path;
this.popularity = popularity;
this.score = score;
this.id = id;
this.summary = summary;
this.poster_path = poster_path;
this.background_path = background_path;
this.popularity = popularity;
this.score = score;
this.release_status = release_status;
this.tagline = tagline;
this.release_status = release_status;
this.tagline = tagline;
this.seasons = seasons;
this.episodes = episodes;
}
this.seasons = seasons;
this.episodes = episodes;
}
toString() {
return `${super.toString()} | ID: ${this.id}`;
}
toString() {
return `${super.toString()} | ID: ${this.id}`;
}
print() {
/* eslint-disable no-console */
console.log(this.toString());
}
print() {
/* eslint-disable no-console */
console.log(this.toString());
}
}
module.exports = TMDB;

View File

@@ -1,35 +1,35 @@
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(
{
url: `https://gatewayapi.com/rest/mtsms?token=${apiKey}`,
json: true,
body: {
sender,
message,
recipients: [{ msisdn: `47${recipient}` }]
request.post(
{
url: `https://gatewayapi.com/rest/mtsms?token=${apiKey}`,
json: true,
body: {
sender,
message,
recipients: [{ msisdn: `47${recipient}` }]
}
},
function (err, r, body) {
console.log(err ? err : body);
console.log("sms provider response:", body);
resolve();
}
},
function(err, r, body) {
console.log(err ? err : body);
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,10 +1,10 @@
const Movie = require('src/plex/types/movie');
const Movie = require("./types/movie");
function convertPlexToMovie(plexMovie) {
const movie = new Movie(plexMovie.title, plexMovie.year);
movie.rating = plexMovie.rating;
movie.tagline = plexMovie.tagline;
if (plexMovie.summary !== undefined) {
movie.summary = plexMovie.summary;
}

View File

@@ -1,24 +1,34 @@
const Plex = require('src/media_classes/plex');
const Plex = require("../media_classes/plex");
function translateAdded(date_string) {
return new Date(date_string * 1000);
return new Date(date_string * 1000);
}
function convertPlexToSeasoned(plex) {
const title = plex.title;
const year = plex.year;
const type = plex.type;
const summary = plex.summary;
const poster_path = plex.thumb;
const background_path = plex.art;
const added = translateAdded(plex.addedAt);
// const genre = plex.genre;
const seasons = plex.childCount;
const episodes = plex.leafCount;
const title = plex.title;
const year = plex.year;
const type = plex.type;
const summary = plex.summary;
const poster_path = plex.thumb;
const background_path = plex.art;
const added = translateAdded(plex.addedAt);
// const genre = plex.genre;
const seasons = plex.childCount;
const episodes = plex.leafCount;
const seasoned = new Plex(title, year, type, summary, poster_path, background_path, added, seasons, episodes);
// seasoned.print();
return seasoned;
const seasoned = new Plex(
title,
year,
type,
summary,
poster_path,
background_path,
added,
seasons,
episodes
);
// seasoned.print();
return seasoned;
}
module.exports = convertPlexToSeasoned;

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,19 +1,19 @@
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);
const plexStreamMedia = plexStream.Media[0];
stream.mediaInfo = convertStreamToMediaInfo(plexStreamMedia);
stream.player = convertStreamToPlayer(plexStream.Player);
const stream = convertPlexToSeasoned(plexStream);
const plexStreamMedia = plexStream.Media[0];
stream.mediaInfo = convertStreamToMediaInfo(plexStreamMedia);
stream.player = convertStreamToPlayer(plexStream.Player);
stream.user = convertStreamToUser(plexStream.User);
stream.playback = new ConvertStreamToPlayback(plexStreamMedia.Part[0]);
stream.user = convertStreamToUser(plexStream.User);
stream.playback = new ConvertStreamToPlayback(plexStreamMedia.Part[0]);
return stream;
return stream;
}
module.exports = convertPlexToStream;

View File

@@ -1,22 +1,22 @@
const MediaInfo = require('src/media_classes/mediaInfo');
const MediaInfo = require("../media_classes/mediaInfo");
function convertStreamToMediaInfo(plexStream) {
const mediaInfo = new MediaInfo();
const mediaInfo = new MediaInfo();
mediaInfo.duration = plexStream.duration;
mediaInfo.height = plexStream.height;
mediaInfo.width = plexStream.width;
mediaInfo.duration = plexStream.duration;
mediaInfo.height = plexStream.height;
mediaInfo.width = plexStream.width;
if (plexStream.bitrate) {
mediaInfo.bitrate = plexStream.bitrate;
}
mediaInfo.resolution = plexStream.videoResolution;
mediaInfo.framerate = plexStream.videoFrameRate;
mediaInfo.protocol = plexStream.protocol;
mediaInfo.container = plexStream.container;
mediaInfo.audioCodec = plexStream.audioCodec;
if (plexStream.bitrate) {
mediaInfo.bitrate = plexStream.bitrate;
}
mediaInfo.resolution = plexStream.videoResolution;
mediaInfo.framerate = plexStream.videoFrameRate;
mediaInfo.protocol = plexStream.protocol;
mediaInfo.container = plexStream.container;
mediaInfo.audioCodec = plexStream.audioCodec;
return mediaInfo;
return mediaInfo;
}
module.exports = convertStreamToMediaInfo;

View File

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

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,102 +1,110 @@
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) {
constructor(plexIP) {
this.plexIP = plexIP;
}
}
inPlex(tmdbResult) {
return Promise.resolve()
.then(() => this.search(tmdbResult.title))
.then(plexResult => this.compareTmdbToPlex(tmdbResult, plexResult))
.catch((error) => {
console.log(error)
tmdbResult.matchedInPlex = false;
return tmdbResult;
});
}
inPlex(tmdbResult) {
return Promise.resolve()
.then(() => this.search(tmdbResult.title))
.then(plexResult => this.compareTmdbToPlex(tmdbResult, plexResult))
.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 options = {
uri: uri,
headers: {
Accept: 'application/json',
},
json: true,
};
search(query) {
const queryUri = encodeURIComponent(query);
const uri = encodeURI(
`http://${this.plexIP}:32400/search?query=${queryUri}`
);
const options = {
uri: uri,
headers: {
Accept: "application/json"
},
json: true
};
return rp(options)
.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 }));
}
return rp(options)
.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
}));
}
compareTmdbToPlex(tmdb, plexResult) {
return Promise.resolve()
.then(() => {
if (plexResult.results.length === 0) {
tmdb.matchedInPlex = false
}
else {
// console.log('plex and tmdb:', plexResult, '\n', tmdb)
plexResult.results.map((plexItem) => {
if (tmdb.title === plexItem.title && tmdb.year === plexItem.year)
tmdb.matchedInPlex = true;
return tmdb;
});
}
return tmdb;
});
}
compareTmdbToPlex(tmdb, plexResult) {
return Promise.resolve().then(() => {
if (plexResult.results.length === 0) {
tmdb.matchedInPlex = false;
} else {
// console.log('plex and tmdb:', plexResult, '\n', tmdb)
plexResult.results.map(plexItem => {
if (tmdb.title === plexItem.title && tmdb.year === plexItem.year)
tmdb.matchedInPlex = true;
return tmdb;
});
}
return tmdb;
});
}
mapResults(response) {
return Promise.resolve()
.then(() => {
if (!response.MediaContainer.hasOwnProperty('Metadata')) return [[], 0];
mapResults(response) {
return Promise.resolve()
.then(() => {
if (!response.MediaContainer.hasOwnProperty("Metadata")) return [[], 0];
const mappedResults = response.MediaContainer.Metadata.filter((element) => {
return (element.type === 'movie' || element.type === 'show');
}).map((element) => convertPlexToSeasoned(element));
return [mappedResults, mappedResults.length];
})
.catch((error) => { throw new Error(error); });
}
const mappedResults = response.MediaContainer.Metadata.filter(
element => {
return element.type === "movie" || element.type === "show";
}
).map(element => convertPlexToSeasoned(element));
return [mappedResults, mappedResults.length];
})
.catch(error => {
throw new Error(error);
});
}
nowPlaying() {
const options = {
uri: `http://${this.plexIP}:32400/status/sessions`,
headers: {
Accept: 'application/json',
},
json: true,
};
nowPlaying() {
const options = {
uri: `http://${this.plexIP}:32400/status/sessions`,
headers: {
Accept: "application/json"
},
json: true
};
return rp(options)
.then((result) => {
if (result.MediaContainer.size > 0) {
const playing = result.MediaContainer.Metadata.map(convertPlexToStream);
return { size: Object.keys(playing).length, video: playing };
}
return { size: 0, video: [] };
})
.catch((err) => {
throw new Error(`Error handling plex playing. Error: ${err}`);
});
}
return rp(options)
.then(result => {
if (result.MediaContainer.size > 0) {
const playing =
result.MediaContainer.Metadata.map(convertPlexToStream);
return { size: Object.keys(playing).length, video: playing };
}
return { size: 0, video: [] };
})
.catch(err => {
throw new Error(`Error handling plex playing. Error: ${err}`);
});
}
// multipleInPlex(tmdbResults) {
// const results = tmdbResults.results.map(async (tmdb) => {
// return this.inPlex(tmdb)
// })
// return Promise.all(results)
// }
// multipleInPlex(tmdbResults) {
// const results = tmdbResults.results.map(async (tmdb) => {
// return this.inPlex(tmdb)
// })
// return Promise.all(results)
// }
}
module.exports = PlexRepository;

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,13 +1,13 @@
const Player = require('src/media_classes/player');
const Player = require("../../media_classes/player");
function convertStreamToPlayer(plexStream) {
const player = new Player(plexStream.device, plexStream.address);
player.platform = plexStream.platform;
player.product = plexStream.product;
player.title = plexStream.title;
player.state = plexStream.state;
const player = new Player(plexStream.device, plexStream.address);
player.platform = plexStream.platform;
player.product = plexStream.product;
player.title = plexStream.title;
player.state = plexStream.state;
return player;
return player;
}
module.exports = convertStreamToPlayer;

View File

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

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))
})
.then(([result, totalPages, totalRequests]) => Promise.resolve({
results: result, total_results: totalRequests, page: page, total_pages: totalPages
}))
.catch(error => { console.log(error);throw error })
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;
});
}
}

View File

@@ -1,52 +1,57 @@
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',
};
}
constructor(database) {
this.database = database || establishedDatabase;
this.queries = {
create:
"insert into search_history (search_query, user_name) values (?, ?)",
read: "select search_query from search_history where user_name = ? order by id desc"
};
}
/**
/**
* Retrive a search queries for a user from the database.
* @param {User} user existing user
* @returns {Promise}
*/
read(user) {
return 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.');
}));
}
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.");
})
);
}
/**
/**
* Creates a new search entry in the database.
* @param {String} username logged in user doing the search
* @param {String} searchQuery the query the user searched for
* @returns {Promise}
*/
create(username, searchQuery) {
return this.database.run(this.queries.create, [searchQuery, username])
.catch(error => {
if (error.message.includes('FOREIGN')) {
throw new Error('Could not create search history.');
}
create(username, searchQuery) {
return this.database
.run(this.queries.create, [searchQuery, username])
.catch(error => {
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'
}
});
}
throw {
success: false,
status: 500,
message: "An unexpected error occured",
source: "database"
};
});
}
}
module.exports = SearchHistory;

View File

@@ -1,62 +1,68 @@
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 = ?',
constructor(database) {
this.database = database || establishedDatabase;
this.queries = {
read: "SELECT * FROM stray_eps WHERE id = ?",
readAll: "SELECT id, name, season, episode, verified FROM stray_eps",
readAllFiltered:
"SELECT id, name, season, episode, verified FROM stray_eps WHERE verified = ",
checkVerified: "SELECT id FROM stray_eps WHERE verified = 0 AND id = ?",
verify: "UPDATE stray_eps SET verified = 1 WHERE id = ?"
};
}
read(strayId) {
return this.database.get(this.queries.read, strayId).then(row => {
assert.notEqual(
row,
undefined,
`Could not find list with id ${strayId}.`
);
return row;
});
}
readAll(verified = null) {
let dbSearchQuery = this.queries.readAll;
if (verified != null) {
dbSearchQuery = this.queries.readAllFiltered + verified.toString();
}
return this.database.all(dbSearchQuery).then(rows =>
rows.map(row => {
const stray = new Stray(row.id);
stray.name = row.name;
stray.season = row.season;
stray.episode = row.episode;
stray.verified = row.verified;
return stray;
})
);
}
verifyStray(strayId) {
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]
};
}
read(strayId) {
return this.database.get(this.queries.read, strayId).then((row) => {
assert.notEqual(row, undefined, `Could not find list with id ${strayId}.`);
return row;
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);
});
}
readAll(verified = null) {
let dbSearchQuery = this.queries.readAll;
if (verified != null) {
dbSearchQuery = this.queries.readAllFiltered + verified.toString();
}
return this.database.all(dbSearchQuery).then(rows =>
rows.map((row) => {
const stray = new Stray(row.id);
stray.name = row.name;
stray.season = row.season;
stray.episode = row.episode;
stray.verified = row.verified;
return stray;
}));
}
verifyStray(strayId) {
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],
};
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);
});
return this.database.run(this.queries.verify, strayId);
});
}
return this.database.run(this.queries.verify, strayId);
});
}
}
module.exports = StrayRepository;

View File

@@ -1,44 +1,48 @@
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, ' +
'DATETIME(created_at, "+" || time_to_live || " seconds") as expires ' +
'FROM cache WHERE key = ? AND now < expires',
create: 'INSERT OR REPLACE INTO cache (key, value, time_to_live) VALUES (?, ?, ?)',
};
}
constructor(database) {
this.database = database || establishedDatabase;
this.queries = {
read:
'SELECT value, time_to_live, created_at, DATETIME("now", "localtime") as now, ' +
'DATETIME(created_at, "+" || time_to_live || " seconds") as expires ' +
"FROM cache WHERE key = ? AND now < expires",
create:
"INSERT OR REPLACE INTO cache (key, value, time_to_live) VALUES (?, ?, ?)"
};
}
/**
* Retrieve an unexpired cache entry by key.
* @param {String} key of the cache entry
* @returns {Object}
*/
get(key) {
return Promise.resolve()
.then(() => this.database.get(this.queries.read, [key]))
.then(row => {
assert(row, 'Could not find cache entry with that key.');
return JSON.parse(row.value);
})
}
/**
* Retrieve an unexpired cache entry by key.
* @param {String} key of the cache entry
* @returns {Object}
*/
get(key) {
return Promise.resolve()
.then(() => this.database.get(this.queries.read, [key]))
.then(row => {
assert(row, "Could not find cache entry with that key.");
return JSON.parse(row.value);
});
}
/**
* Insert cache entry with key and value.
* @param {String} key of the cache entry
* @param {String} value of the cache entry
* @param {Number} timeToLive the number of seconds before entry expires
* @returns {Object}
*/
set(key, value, timeToLive = 10800) {
const json = JSON.stringify(value);
return Promise.resolve()
.then(() => this.database.run(this.queries.create, [key, json, timeToLive]))
.then(() => value);
}
/**
* Insert cache entry with key and value.
* @param {String} key of the cache entry
* @param {String} value of the cache entry
* @param {Number} timeToLive the number of seconds before entry expires
* @returns {Object}
*/
set(key, value, timeToLive = 10800) {
const json = JSON.stringify(value);
return Promise.resolve()
.then(() =>
this.database.run(this.queries.create, [key, json, timeToLive])
)
.then(() => value);
}
}
module.exports = Cache;

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,14 +100,20 @@ 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));
}
/**
* Retrieve a specific show by id from TMDB.
* @param {Number} identifier of the show you want to retrieve

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,15 +1,16 @@
const GitRepository = require('src/git/gitRepository');
const GitRepository = require("../../../git/gitRepository");
const gitRepository = new GitRepository();
function dumpHookController(req, res) {
gitRepository.dumpHook(req.body)
.then(() => {
res.status(200);
})
.catch((error) => {
res.status(500);
});
gitRepository
.dumpHook(req.body)
.then(() => {
res.status(200);
})
.catch(error => {
res.status(500);
});
}
module.exports = dumpHookController;

View File

@@ -1,15 +1,15 @@
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
// belong in tmdb.
// there should be a translate function from query params to
// tmdb list that is valid. Should it be a helper function or does it
// belong in tmdb.
// + could also have default value that are sent to the client.
// * have the same class create a getListNames() and a fetchList()
// * dicover list might be overkill_https://tinyurl.com/y7f8ragw
// + trending! https://tinyurl.com/ydywrqox
// by all, mediatype, or person. Can also define time periode to
// + trending! https://tinyurl.com/ydywrqox
// by all, mediatype, or person. Can also define time periode to
// get more trending view of what people are checking out.
// + newly created (tv/latest).
// + movie/latest
@@ -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({
status: 400,
message: `'${type}' is not a valid list type.`
}, res)
handleError(
{
status: 400,
message: `'${type}' is not a valid list type.`
},
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,25 +1,24 @@
/*
* @Author: KevinMidboe
* @Date: 2017-10-21 09:54:31
* @Last Modified by: KevinMidboe
* @Last Modified time: 2017-10-21 15:32:43
*/
* @Author: KevinMidboe
* @Date: 2017-10-21 09:54:31
* @Last Modified by: KevinMidboe
* @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;
const name = req.body.name;
const tmdb_id = req.body.tmdb_id;
const magnet = req.body.magnet;
const name = req.body.name;
const tmdb_id = req.body.tmdb_id;
PirateRepository.AddMagnet(magnet, name, tmdb_id)
.then((result) => {
res.send(result);
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
PirateRepository.AddMagnet(magnet, name, tmdb_id)
.then(result => {
res.send(result);
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}
module.exports = addMagnet;

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();
@@ -9,16 +9,21 @@ const requestRepository = new RequestRepository();
* @returns {Callback}
*/
function fetchRequestedController(req, res) {
// const user = req.loggedInUser;
const { status, page } = req.query;
// 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 });
})
.catch((error) => {
res.status(401).send({ success: false, message: error.message });
requestRepository
.fetchRequested(status, page)
.then(requestedItems => {
res.send({
success: true,
results: requestedItems,
total_results: requestedItems.length
});
})
.catch(error => {
res.status(401).send({ success: false, message: error.message });
});
}
module.exports = fetchRequestedController;

View File

@@ -1,16 +1,17 @@
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()
.then(movies => {
res.send(movies);
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
plexRepository
.nowPlaying()
.then(movies => {
res.send(movies);
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}
module.exports = playingController;

View File

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

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
@@ -9,17 +9,24 @@ const plex = new Plex(configuration.get('plex', 'ip'));
* @returns {Callback}
*/
function searchPlexController(req, res) {
const { query, type } = req.query;
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.'})
}
}).catch(error => {
res.status(500).send({ success: false, message: error.message });
});
const { query, type } = req.query;
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."
});
}
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}
module.exports = searchPlexController;

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
@@ -11,19 +11,25 @@ const plexRepository = new PlexRepository(configuration.get('plex', 'ip'));
* @returns {Callback}
*/
function searchMediaController(req, res) {
const { query } = req.query;
const { query } = req.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.' });
}
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
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."
});
}
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}
module.exports = searchMediaController;

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,12 +35,10 @@ function submitRequestController(req, res) {
console.log("show");
mediaFunction = tmdbShowInfo;
} else {
res
.status(422)
.send({
success: false,
message: 'Incorrect type. Allowed types: "movie" or "show"'
});
res.status(422).send({
success: false,
message: 'Incorrect type. Allowed types: "movie" or "show"'
});
}
if (mediaFunction === undefined) {

View File

@@ -1,4 +1,4 @@
const RequestRepository = require('src/plex/requestRepository');
const RequestRepository = require("../../../plex/requestRepository");
const requestRepository = new RequestRepository();
@@ -9,17 +9,18 @@ const requestRepository = new RequestRepository();
* @returns {Callback}
*/
function updateRequested(req, res) {
const id = req.params.requestId;
const type = req.body.type;
const status = req.body.status;
const id = req.params.requestId;
const type = req.body.type;
const status = req.body.status;
requestRepository.updateRequestedById(id, type, status)
.then(() => {
res.send({ success: true });
})
.catch((error) => {
res.status(401).send({ success: false, message: error.message });
});
requestRepository
.updateRequestedById(id, type, status)
.then(() => {
res.send({ success: true });
})
.catch(error => {
res.status(401).send({ success: false, message: error.message });
});
}
module.exports = updateRequested;

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
@@ -9,18 +9,18 @@ const plex = new Plex(configuration.get('plex', 'ip'));
* @returns {Callback}
*/
function watchDirectLink (req, res) {
const { title, year } = req.query;
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 });
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,16 +12,16 @@ 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()
.then(() => request.fetchAll(page, sort_by, sort_direction, filter, query))
.then(result => res.send(result))
.catch(error => {
res.status(404).send({ success: false, message: error.message });
});
.then(() => request.fetchAll(page, sort_by, sort_direction, filter, query))
.then(result => res.send(result))
.catch(error => {
res.status(404).send({ success: false, message: error.message });
});
}
module.exports = fetchAllRequests;

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,11 +36,9 @@ function multiSearchController(req, res) {
} else {
// TODO log unhandled errors
console.log("caugth multi search controller error", error);
res
.status(500)
.send({
message: `An unexpected error occured while searching with query: ${query}`
});
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,17 +1,17 @@
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) => {
res.send(strays);
})
.catch((error) => {
res.status(500).send({ success: false, message: error.message });
});
const { verified, page } = req.query;
strayRepository
.readAll(verified, page)
.then(strays => {
res.send(strays);
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}
module.exports = readStraysController;

View File

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

View File

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

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,24 +1,24 @@
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."
});
}
}
/**
* Controller: Retrieve information for a show
* Controller: Retrieve information for a show
* @param {Request} req http request variable
* @param {Response} res
* @returns {Callback}
@@ -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)
} catch(error) {
handleError(error, res)
res.send(show);
} catch (error) {
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,27 +1,31 @@
const establishedDatabase = require('src/database/database');
const establishedDatabase = require("../../database/database");
const mustBeAdmin = (req, res, next) => {
let database = establishedDatabase;
let database = establishedDatabase;
if (req.loggedInUser === undefined) {
return res.status(401).send({
success: false,
message: 'You must be logged in.',
if (req.loggedInUser === undefined) {
return res.status(401).send({
success: false,
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);
if (isAdmin.admin == 0) {
return res.status(401).send({
success: false,
message: "You must be logged in as a admin."
});
}
});
} 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,
message: 'You must be logged in as a admin.'
})
}
})
}
}
return next();
return next();
};
module.exports = mustBeAdmin;

View File

@@ -1,31 +1,35 @@
const establishedDatabase = require('src/database/database');
const establishedDatabase = require("../../database/database");
const mustHaveAccountLinkedToPlex = (req, res, next) => {
let database = establishedDatabase;
const loggedInUser = req.loggedInUser;
let database = establishedDatabase;
const loggedInUser = req.loggedInUser;
if (loggedInUser === undefined) {
return res.status(401).send({
success: false,
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)
if (loggedInUser === undefined) {
return res.status(401).send({
success: false,
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
)
.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.'
})
} else {
req.loggedInUser.plex_userid = plex_userid;
return next();
}
})
}
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."
});
} 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'), () => {
/* eslint-disable no-console */
console.log('seasonedAPI');
/* eslint-disable no-console */
console.log(`Database is located at ${config.get('database', 'host')}`);
/* eslint-disable no-console */
console.log(`Webserver is listening on ${config.get('webserver', 'port')}`);
module.exports = app.listen(config.get("webserver", "port"), () => {
/* eslint-disable no-console */
console.log("seasonedAPI");
/* eslint-disable no-console */
console.log(`Database is located at ${config.get("database", "host")}`);
/* eslint-disable no-console */
console.log(`Webserver is listening on ${config.get("webserver", "port")}`);
});

File diff suppressed because it is too large Load Diff

7915
yarn.lock

File diff suppressed because it is too large Load Diff