129 Commits

Author SHA1 Message Date
3424325be4 Refactor: Python packages should be installed as modules, and not use source files (#149)
* Python packages should be installed as modules, and not use source files

* Use child_process spawn to call command and return data

* Consistent error rejection & resolve around spawn calls.

* Updated README to remove submodule ref & added how to install pip pcks.

* Resovled linting issue

* Removed python-shell package

* Disable stray functionality, unused & has dep to python-shell

* Uncommented/disabled python-shell dependency in strayRepository.
2022-10-02 16:05:29 +02:00
d6e5bdbd91 Updated docker image source repo url position within docker file 2022-09-25 17:08:01 +02:00
395dbe92f3 Updated docker image source repo url 2022-09-25 17:01:44 +02:00
212a6864f1 Fix: Redis call chain (#147)
* Moved redis mock client to separate file

* To keep cache response & api response consistent, alter call chain

* Resolved linting issues
2022-09-25 13:39:48 +02:00
c3f041d27f Simplified how we fetch and update requests that have landed in plex (#146) 2022-09-25 13:39:33 +02:00
2b6ad301a8 Resolved exception where readWithoutUserData was not defined (#145) 2022-09-25 13:39:23 +02:00
6732ed988d Register plex instance with token parameter for authenticated calls to plex (#144) 2022-09-25 13:39:07 +02:00
696f9f989c Fix: Plex errors (#141)
* inPlex function returns promise for more consistent return types

* plexUserId should default to null on falsey
2022-08-25 17:28:29 +02:00
93d394c2fe Return parsed json from redis cache (#142) 2022-08-25 17:20:52 +02:00
13470d7372 Custom errors for view hsitory/tautulli exceptions (#140) 2022-08-25 17:20:39 +02:00
7168950dfe Feat: es modules (#139)
* All file imports change from commonjs to es-module

* Improved plex error responses back from api

* Converted viewHistory to es module

* Es-module requires file extension, updated all imports

* Fix esmodule not having __dirname defined in scope

* Replace dynamic-require with fs readFileSync

* Short message service module function is exported as default

* Resolved lint issues & ignore import/extension rule until typescript

* All tests file imports changed from commonjs to es-module

* Import json fixtures with new helper
2022-08-25 17:19:23 +02:00
628ed52012 Fix: Tests lint and src folder (#138)
* Automaticly fixable eslint issues, mostly 3 -> 2 space indentation

* fix: updated plex_userid to camelcase

* Linted and some consistency refactor on middleware

* eslint uses ecmaversion 2020 & allow empty catch rule

* Started linting source files

* Fixed eslint errors & improved a lot of error handling

* Set 2 eslint rules as warning temporarly

* Updated all import statements to be relative

* Updated mocha & nyc, resolved all lint issues in tests/

* Updated mocha & nyc. Removed production config. Updated gitignore

* Updated test commands to omit system tests, no exit code

* Updated test configuration w/ missing keys

* Chai modules defined in package.json & resolved linting errors

* Dockerfile copies development.example -> production.json. Simplified commands

* All api calls from tests use same chaiHttp implementation

Removes a list of fetch alternatives after being replaced by chaiHttp:
 - request
 - request-promise
 - supertest
 - supertest-as-promised

* Tests should use redis (mock) cache, not tmdb sqlite cache

* Disabled test asADeveloperIWantTheServerToStart

* Re-enable tests/system

* Use chaiHttp in asAUserIWantToRequestAMovie.

* Fixed redis expire & mock implmentation

* Replaced all fetch alternatives from source code and package.json

* Pass error from tmdb api back to client as errorMessage

* Updated authentication middleware to handle checks consitenctly

* Prevent assert error when checking request status, returns success 200

* Resolved merge conflicts

* Only build and publish docker container when branch master
2022-08-20 17:41:46 +02:00
1815a429b0 Fix: Linter warnings (#137)
* Automaticly fixable eslint issues, mostly 3 -> 2 space indentation

* fix: updated plex_userid to camelcase

* Linted and some consistency refactor on middleware

* eslint uses ecmaversion 2020 & allow empty catch rule

* Started linting source files

* Fixed eslint errors & improved a lot of error handling

* Set 2 eslint rules as warning temporarly
2022-08-20 17:21:25 +02:00
cfbd4965db Merge pull request #136 from KevinMidboe/feat/emoji-from-codepoint
Feat: Emoji from code point
2022-08-19 10:18:35 +02:00
31c4b8b7df Replaced travis CI badge with Drone CI 2022-08-19 10:18:16 +02:00
a4b2e8f51c Instead of having a list of emojis, generate from code point 2022-08-19 10:08:34 +02:00
11fb803838 Removed seasoned_api folder 2022-08-19 10:06:18 +02:00
b2d2b0025c Merge pull request #134 from KevinMidboe/chore/seasoned_api-src-files
Chore: Seasoned api src files
2022-08-19 10:05:00 +02:00
ae9f3044bc Removed vue reference in prettierc (#135) 2022-08-19 10:04:01 +02:00
0eab680527 Include yarn lock into docker container build 2022-08-19 01:28:40 +02:00
4204515e91 Updated COPY and RUN commands for new project dir structure 2022-08-19 01:24:55 +02:00
19e99e8c43 Updated eslint config & prepared ts config 2022-08-19 01:14:18 +02:00
007d34f994 Updated dockerfile with new config dir in root 2022-08-19 01:10:16 +02:00
5a1e18b839 All entrypoints updated after moving seasoned_api contents to root dir 2022-08-19 01:04:45 +02:00
56262a45c8 Moved contents of seasoned_api up to root folder 2022-08-19 01:03:27 +02:00
0efc109992 Moved old webpage, app & client into .archive folder 2022-08-19 00:44:25 +02:00
851af204ab Remove python submodules 2022-08-19 00:43:41 +02:00
ccebf0d7b0 Merge pull request #132 from KevinMidboe/feat/drone-ci
Feat Drone CI & dockerize
2022-08-18 20:44:35 +02:00
76fe986f39 Merge branch 'feat/drone-ci' of github.com:KevinMidboe/seasonedShows into feat/drone-ci 2022-08-17 01:00:33 +02:00
fbf1ae8dec Moved github files to .github/ 2022-08-17 01:00:09 +02:00
9164b592bd Copy folder seasoned_api not just contents, matches project structure 2022-08-17 00:59:34 +02:00
d77b427c3c Copy folder seasoned_api not just contents, matches project structure 2022-08-17 00:40:58 +02:00
b56b1f6c0c Environment variables now take presedence over local config 2022-08-17 00:20:17 +02:00
c8477fabaa If redis fails to connect use a mock client to not crash 2022-08-17 00:19:22 +02:00
014cac8b06 Remove installing redis-server from apt on build 2022-08-17 00:18:34 +02:00
20d74cafb9 gchr repo name all lowercase 2022-08-16 01:22:35 +02:00
1690bbcdd0 Temporarly build and publish docker container on all push 2022-08-16 01:15:58 +02:00
7094aa2bb5 Updated all imports to be relative to itself 2022-08-16 01:15:36 +02:00
3660e88acf Moved package.json up to root folder 2022-08-16 01:13:07 +02:00
d8f7f82127 Drone config w/ install and build docker container steps 2022-08-16 00:42:23 +02:00
0a4248bf30 Setup dockerfile for seasoned api project
TODO remove apt installing redis and running service internally
2022-08-16 00:41:33 +02:00
92d139a156 Prevent foreign key to user, no user crashes server 2022-08-16 00:40:56 +02:00
5578bf854a Updated default config 2022-08-16 00:39:01 +02:00
5648b8fffa Merge pull request #130 from KevinMidboe/feat/cookie-authentication
Feat/cookie authentication
2022-08-15 23:59:12 +02:00
1b7a754224 Merge pull request #131 from KevinMidboe/feat/credits
Feat/credits
2022-08-15 23:58:54 +02:00
5d91f1bae7 TODO sms code 2022-08-15 23:51:18 +02:00
cdcfae56e7 Allow set-cookie & allow credentials 2022-08-15 23:39:39 +02:00
f2c77e092d Safer imports in credits 2022-08-15 23:38:53 +02:00
d6ac7e55e9 Better matching when getting matchin plex title & year 2022-08-15 23:38:35 +02:00
a3543090f2 Translate plex query params to fixed 2022-08-15 23:37:07 +02:00
041e944783 Upgraded bcrypt & sqlite3 2022-08-15 23:36:02 +02:00
bfd31ebd23 Linting 2022-03-06 11:59:32 +01:00
5036f4ca36 Read and pass adult search query param consistently for movie, show & person info 2022-03-06 11:57:45 +01:00
61b59ae3ea Person info now handles optional credits query parameter 2022-03-06 11:55:32 +01:00
92c49ac523 Registered endpoint for person credits 2022-03-06 11:54:56 +01:00
f680642f25 When fetching credits for person we get movie & show objects, now handled here. 2022-03-06 11:54:22 +01:00
f89486ae9e Sepearate controller and tmdb function for fetching personCredits 2022-03-06 11:53:45 +01:00
4d853565d1 Person gets biography & place_of_birth attributes 2022-03-06 11:50:20 +01:00
91c81e5cf6 Use cookie-parser, updated tokenToUser middleware & set logout endpoint 2022-03-06 10:39:34 +01:00
0ecbde9675 Logout endpoint for deleting auth cookie 2022-03-06 10:36:24 +01:00
d8e951c2ef Can now pass settings to new Token. 2022-03-06 10:34:48 +01:00
90f3d86511 Removed unused Promise resolves 2022-03-06 10:34:39 +01:00
c6791a7027 Login and register builds and sets cookie auth token 2022-03-06 10:31:58 +01:00
5b6a2c2651 Linting 2022-03-06 10:27:09 +01:00
4f7a22fff1 New tokenToUser middleware checks both header and cookie for Auth token 2022-03-06 10:17:56 +01:00
31b0c998a8 Removed filter option when searching jackett 2022-01-03 19:28:50 +01:00
9ce5b476ef Prettierrc file 2022-01-03 19:28:42 +01:00
554f292e4c Don't fail request when plex failes existance check 2022-01-03 19:28:09 +01:00
d8985aaff7 Correctly use username from req.loggedInUser 2022-01-03 19:17:27 +01:00
be889b8100 Lining 2022-01-03 19:06:11 +01:00
b5bd672f44 More accurate checks for what response contains and throws error if it does not exist. 2022-01-03 18:38:32 +01:00
4501bc5302 Updated yarn lock file 2022-01-03 18:33:45 +01:00
b384e748af Updated and moved update requests to /scripts 2022-01-03 18:32:48 +01:00
c676f182b4 Cache time in HR & future cache bust function 2022-01-03 18:31:28 +01:00
95d2b0095b Linting 2022-01-03 18:23:49 +01:00
8165cf8e85 Keep whitespace when sanitizing string 2022-01-03 18:04:10 +01:00
14775744b0 Linting 2022-01-03 18:03:53 +01:00
559e32c059 Use list index 1 results 2022-01-03 18:02:58 +01:00
f4dbaf4c58 Translate symbol + to space in query 2022-01-03 18:02:45 +01:00
1d25914ae0 Linting 2022-01-03 17:56:00 +01:00
4d3d8c874c Moved cors allowed origins to conf file. 2020-04-08 23:17:45 +02:00
08433523b7 Correctly export poster_path from person tmdb response object. 2020-04-08 23:09:37 +02:00
fce8879994 Searching with adult parameter is now handled and also cached correctly. 2020-04-08 23:08:42 +02:00
505b126043 Cleanup, removed comments and logs. 2020-04-08 23:07:09 +02:00
589bd7b08d Better comparison between plex and tmdb. Now also checks if plexTitle starts with tmdbTitle. 2020-04-08 23:05:56 +02:00
f0049ffb4e Merge pull request #129 from KevinMidboe/feat/redis-cache
Feat/redis cache
2020-04-08 23:04:06 +02:00
2b25397253 Misc updates to caching from plex and tmdb. 2020-04-08 23:01:33 +02:00
776f83553a Changed more instances of tmdb to new TMDB constructor not needing cache instance anymore. 2020-04-08 22:59:23 +02:00
815aaedffb Changed tmdb constructor to have apiKey as first parameter. If cache is not defined we use redis. 2020-04-08 22:54:19 +02:00
578eff30fb Id of request has been incorrectly saved as string, this has dictated the returntype to the frontend. Now set from string to int. 2020-04-08 21:58:37 +02:00
943cbe5cb8 Return rejected promise and don't set cache if key or value is null. 2020-04-08 21:57:49 +02:00
f89db46bf2 findPlexItemByTitleAndYear returns a promise so we await its response. 2020-02-21 23:09:42 +01:00
085fb76e11 Cache pirate respons for 3 hours in redis. 2020-02-21 22:09:42 +01:00
aa4a1c2a57 Registed route watch-link, by title & year
Fetch watch link for plex item matching query parameters title and year.
2020-02-21 21:53:51 +01:00
74340afd16 Full re-write. Refactored, cache and watchlink.
- Now the api calls to plex are cached.
- Search function has been refactored.
- Exists in plex has been re-written to use findPlexItemByTitleAndYear
if anything is found we return true. findPlexItemByTitleAndYear is then
also used for our new endpoint to get direct watch link for plex item.
Function parameters are title and year. Title is used when querying plex
and year is used with title to match correct plex search result. The
direct link includes the machine identifier so a function was added to
get system information from plex (read: 'PLEX_URL/' e.g. base path).
2020-02-21 21:53:19 +01:00
2672266908 Simplified every function towards tmdb by having the shared functionality separated into a function. 2020-02-21 21:47:00 +01:00
f37786aa76 Redis cache script with get and set functions.
This replaces old way of caching to sqlite. Still have same
functionality, so users of old cache functions just need to rename their
import.
2020-02-21 18:11:39 +01:00
91f64e5cfb Redis new dependency 2020-02-21 18:09:04 +01:00
a4d3123910 Stricter check for plex search results. 2020-01-16 21:25:45 +01:00
bc6fe3ed48 Encode search query before searching plex. 2020-01-16 21:25:13 +01:00
b23566509f Merge pull request #128 from KevinMidboe/fix/match-list-plex
Fixed issue matching list of plex object to tmdb.
2020-01-16 21:22:34 +01:00
341a07621d Fixed issue matching list of plex object to tmdb.
We have a Plex function that allows us to input a tmdb object and a plex
search result too see if the tmdb object has anything similar when
searching in plex.
Fixed an issue where plex returned a list of items. This list is now
mapped over each list element.
2020-01-16 21:21:40 +01:00
259ed9b06f Error. Fixed capitalization of file name. 2019-12-25 21:12:29 +01:00
cddf06cbcc Travis should make a copy of the example development config. 2019-12-23 02:08:20 +01:00
318d1e331b Merge pull request #124 from KevinMidboe/feature/plex-authentication
Feature plex authentication
2019-12-23 01:39:43 +01:00
5923cbf051 Incorrect query parameter. Changed from (the not defined) plex_userid to username. 2019-12-22 13:49:16 +01:00
291bdf089c Forget to rename copied link function to unlink 2019-12-22 13:42:13 +01:00
8eacde9ccc Moved tautulli config settings to be fetched from our configuration (either env variable or conf/development.json. 2019-12-22 13:36:13 +01:00
f8847c62f2 UserRepository handles updating db settings better.
Moved the plex_userid to settings to expanded with functions for
updating and fetching settings, each with its own helper function
towards the database.
Since we had a linkPlexUserId function and we dont want plex_userid to
be updated from the updatesettings function we moved unlinking to a
separate endpoint and class function.
Also a new controller and endpoints for getting and updating settings.
2019-12-22 13:30:18 +01:00
ddb7e7379d Every instance of sqlite database should have foreign_keys constraints on 2019-12-22 13:14:12 +01:00
720fb69648 Indentation 2019-12-22 12:45:01 +01:00
fedacf498e Changed input parameter from name from user to username, cause we just get the username string. 2019-12-22 12:44:45 +01:00
9022853502 Sql schema now has requested_by as a foreign key for user_name and on delete set null clause. 2019-12-22 12:43:12 +01:00
c1b96e17ca Moved database row plex_userid from user to a new table settings. Currently includes plex_userid, emoji and darkmode with user_name as a foreign key to user.user_name. 2019-12-20 21:45:31 +01:00
a5248f0631 TODO comment for login 2019-11-25 23:38:52 +01:00
e2d85c6242 Merged into master branch 2019-11-24 19:26:56 +01:00
510c014549 Added endpoint for getting plays grouped by days of week. 2019-11-11 17:59:16 +01:00
2650497986 Tautulli will serve all the tautulli api calls. Mostly this will be used by user requests for getting stats related to the logged in user. WIP but currently watch time stats, plays by number of days, and view history has been implemented.
TODO:
 - Error handling if tautulli request fails.
 - Filter the responses and/or limit them from tautulli
 - Handle parsing variable parameters from request
2019-11-04 23:11:00 +01:00
639f0ec17a Created middleware to check if the user has a plex user linked to seasoned account. If not respond with 403 meaning you did have a authorization key, but this is forbidden; explaining in the response message that no plex account user id was found for this user and to please authenticate their plex account at authenticate endpoint. 2019-11-04 23:04:42 +01:00
977d05c6f2 Refactor. Responses should return error string in object key message not error. 2019-11-04 22:58:42 +01:00
601fc1d0de Renamed search_history controller to searchHistory 2019-11-04 22:57:59 +01:00
acc26a2f09 Renamed user history to search_history and fixed an issue where search history received the entire user object and not just the username 2019-11-04 20:32:41 +01:00
5d3a5dc8a4 Removed unused console log 2019-11-04 18:46:42 +01:00
3bb9bd84d9 Merge branch 'master' into feature/plex-authentication 2019-11-04 18:24:19 +01:00
002e663be1 Merge branch 'api/v2' into feature/plex-authentication 2019-11-04 17:55:27 +01:00
495a3b4838 Merged api/v2 into feature branch 2019-11-04 00:58:43 +01:00
9e2a0101c9 Added new formdata pacakge 2019-11-04 00:44:57 +01:00
05b001de2e Created endpoint for authenticating with plex and linking your plex user to the logged in seasoned user. User database table gets a new plex_userid column. This will be used to fetch tautulli stats for your account. 2019-11-04 00:43:42 +01:00
1f9dc067e6 Plex params are now parsed with URI encoder. 2019-04-10 22:22:52 +02:00
319 changed files with 13814 additions and 11320 deletions

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

1
.dockerignore Normal file
View File

@@ -0,0 +1 @@
**/node_modules

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

25
.eslintrc.json Normal file
View File

@@ -0,0 +1,25 @@
{
"root": true,
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"extends": ["eslint-config-airbnb-base", "plugin:prettier/recommended"],
"plugins": ["mocha"],
"rules": {
"import/extensions": 0,
"max-classes-per-file": 1,
"no-empty": [
2,
{
"allowEmptyCatch": true
}
],
"no-promise-executor-return": 1,
"no-shadow": "off",
"no-underscore-dangle": "off"
},
"env": {
"mocha": true
}
}

18
.eslintrc.ts.json Normal file
View File

@@ -0,0 +1,18 @@
{
"root": true,
"parserOptions": {
"parser": "@typescript-eslint/parser",
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint-config-airbnb-base",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"rules": {
"no-underscore-dangle": "off",
"no-shadow": "off",
"@typescript-eslint/no-shadow": ["error"]
}
}

View File

8
.gitignore vendored
View File

@@ -1,7 +1,11 @@
.DS_Store
development.json
env
configurations/development.json
configurations/production.json
.env
shows.db
node_modules
*/package-lock.json
.nyc_output
yarn-error.log

10
.gitmodules vendored
View File

@@ -1,10 +0,0 @@
# Docs : https://git-scm.com/book/en/v2/Git-Tools-Submodules
[submodule "torrent_search"]
path = torrent_search
url = https://github.com/KevinMidboe/torrent_search.git
branch = master
[submodule "delugeClient"]
path = delugeClient
url = https://github.com/KevinMidboe/delugeClient.git

9
.prettierrc Normal file
View File

@@ -0,0 +1,9 @@
{
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": false,
"bracketSpacing": true,
"arrowParens": "avoid",
"trailingComma": "none"
}

View File

@@ -7,6 +7,7 @@ script:
- yarn coverage
before_install:
- cd seasoned_api
- cp conf/development.json.example conf/development.json
before_script:
- yarn
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter

20
Dockerfile Normal file
View File

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

133
README.md
View File

@@ -1,4 +1,3 @@
<h1 align="center">
🌶 seasonedShows
</h1>
@@ -6,16 +5,19 @@
<h4 align="center"> Season your media library with the shows and movies that you and your friends want.</h4>
<p align="center">
<a href="https://travis-ci.org/KevinMidboe/seasonedShows">
<img src="https://travis-ci.org/KevinMidboe/seasonedShows.svg?branch=master"
alt="Travis CI">
<a href="https://drone.schleppe.cloud/KevinMidboe/seasonedShows">
<img src="https://drone.schleppe.cloud/api/badges/KevinMidboe/seasonedShows/status.svg"
alt="Drone CI">
</a>
<a href="https://coveralls.io/github/KevinMidboe/seasonedShows?branch=api/v2">
<img src="https://coveralls.io/repos/github/KevinMidboe/seasonedShows/badge.svg?branch=api/v2" alt="">
</a>
<a href="https://snyk.io/test/github/KevinMidboe/seasonedShows?targetFile=seasoned_api/package.json">
<img src="https://snyk.io/test/github/KevinMidboe/seasonedShows/badge.svg?targetFile=seasoned_api/package.json" alt="">
<a href="https://snyk.io/test/github/KevinMidboe/seasonedShows?targetFile=package.json">
<img src="https://snyk.io/test/github/KevinMidboe/seasonedShows/badge.svg?targetFile=package.json" alt="">
</a>
<a href="https://opensource.org/licenses/MIT">
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="">
</a>
@@ -33,63 +35,73 @@
</p>
## <a name="demo-documentation"></a> Demo & Documentation
📺 [DEMO](https://kevinmidboe.com/request)
📺 [DEMO](https://request.movie)
📝 Documentation of the api.
💖 Checkout my [fancy vue.js page](https://github.com/KevinMidboe/seasonedRequest) for interfacing the api.
💖 Checkout my [fancy vue.js page](https://github.com/KevinMidboe/seasoned) for interfacing the api.
## <a name="about"></a> About
This is the backend api for [seasoned request] that allows for uesrs to request movies and shows by fetching movies from themoviedb api and checks them with your plex library to identify if a movie is already present or not. This api allows to search my query, get themoviedb movie lists like popular and now playing, all while checking if the item is already in your plex library. Your friends can create users to see what movies or shows they have requested and searched for.
The api also uses torrent_search to search for matching torrents and returns results from any site or service available from torrent_search. As a admin of the site you can query torrent_search and return a magnet link that can be added to a autoadd folder of your favorite torrent client.
This is the backend api for [seasoned request] that allows for uesrs to request movies and shows by fetching movies from themoviedb api and checks them with your plex library to identify if a movie is already present or not. This api allows to search my query, get themoviedb movie lists like popular and now playing, all while checking if the item is already in your plex library. Your friends can create users to see what movies or shows they have requested and searched for.
The api also uses torrent_search to search for matching torrents and returns results from any site or service available from torrent_search. As a admin of the site you can query torrent_search and return a magnet link that can be added to a autoadd folder of your favorite torrent client.
## <a name="key-features"></a> Key features
### Code
- Uses [tmdb api](https://www.themoviedb.org/documentation/api) with over 350k movies and 70k tv shows
- Written asynchronously
- Uses caching for external requests
- Test coverage
- CI and dependency integrated
- Use either config file or env_variables
- Uses [tmdb api](https://www.themoviedb.org/documentation/api) with over 350k movies and 70k tv shows
- Written asynchronously
- Uses caching for external requests
- Test coverage
- CI and dependency integrated
- Use either config file or env_variables
### Functionality
- Queries plex library to check if items exists
- Create admin and normal user accounts
- [torrent_search](https://github.com/KevinMidboe/torrent_search) to search for torrents
- Fetch curated lists from tmdb
- Queries plex library to check if items exists
- Create admin and normal user accounts
- [torrent_search](https://github.com/KevinMidboe/torrent_search) to search for torrents
- Fetch curated lists from tmdb
## <a name="installation"></a> Installation
Before we can use seasonedShows we need to download node and a package manager. For instructions on how to install [yarn](https://yarnpkg.com/en/) or [npm](https://www.npmjs.com) package managers refer to [wiki: install package manager](https://github.com/KevinMidboe/seasonedShows/wiki/Install-package-manager). This api is written with express using node.js as the JavaScript runtime engine. To download node.js head over the the official [node.js download page](https://nodejs.org/en/download/).
### Install seasonedShows
After you have downloaded a package manager and node.js javascript engine, the following will guide you through how to download, install and run seasonedShows.
### macOS
- Open terminal
- Install git. This can be done by running `xcode-select --install` in your favorite terminal.
- Install a package manager, refer to this [wiki page] for yarn or [wiki page] for npm
- Type: `git clone --recurse-submodules git@github.com:KevinMidboe/seasonedShows.git`
- Type: `git clone git@github.com:KevinMidboe/seasonedShows.git`
- Type: `cd seasonedShows/`
- Install required packages
* yarn: `yarn install`
* npm: `npm install`
- yarn: `yarn install`
- npm: `npm install`
- Start server:
* yarn: `yarn start`
* npm: `npm run start`
- yarn: `yarn start`
- npm: `npm run start`
- seasonedShows will now be running at http://localhost:31459
- To have seasonedShows run headless on startup, check out this wiki page to [install as a daemon].
### Linux
- Open terminal
- Install git
* Ubuntu/Debian: `sudo apt-get install git-core`
* Fedora: `sudo yum install git`
- Type: `git clone --recurse-submodules git@github.com:KevinMidboe/seasonedShows.git`
- Ubuntu/Debian: `sudo apt-get install git-core`
- Fedora: `sudo yum install git`
- Type: `git clone git@github.com:KevinMidboe/seasonedShows.git`
- Type: `cd seasonedShows/`
- Install required packages
* yarn: `yarn install`
* npm: `npm install`
- yarn: `yarn install`
- npm: `npm install`
- Start server:
* yarn: `yarn start`
* npm: `npm run start`
- yarn: `yarn start`
- npm: `npm run start`
- seasonedShows will now be running at http://localhost:31459
- To have seasonedShows run headless on startup, check out this wiki page to [install as a daemon].
@@ -98,42 +110,73 @@ After you have downloaded a package manager and node.js javascript engine, the f
After you have installed the required packages you will have a node_modules directory with all the packages required in packages.json.
### Requirements
- Node 7.6 < [wiki page]
- Plex library
## <a name="setup"></a> Setup and/ configuration
There is a config file template, what the values mean and how to change them.
Also show how to hide file from git if not want to show up as uncommitted file.
Also set variables in environment.
- Node 18 < [wiki page]
- Plex library
- Optional:
- redis
- deluge
- jackett
## <a name="setup"></a> Setup and configuration
Make a copy of configuration file in `configurations/` folder.
For use during development and with `yarn dev` command:
```bash
cp configurations/development.json.example configurations/development.json
```
For use during production and with `yarn start` command:
```bash
cp configurations/development.json.example configurations/production.json
```
Most important values to change here is adding [TMDB api key](https://developers.themoviedb.org/3/getting-started/introduction) and plex server IP.
### Optional setup
To allow authenticated or admin users add items [delugeClient](https://github.com/kevinmidboe/delugeClient) & [torrentSearch](https://github.com/KevinMidboe/torrent_search) can be setup to fetch and add magnet files. Both require python version >= 3.8 and can be downloaded using following pip command:
```bash
pip3 install delugeClient_kevin torrent_search
```
Both of these need to be configured, view their separate README's or find configuration files under `$HOME/.config/`.
## <a name="running"></a> Running/using
yarn/npm start. (can also say this above)
How to create service on linux. This means that
How to create service on linux. This means that
## <a name="daemon"></a> Setup a daemon
The next step is to setup seasonedShows api to run in the background as a daemon. I have written a [wiki page](https://github.com/KevinMidboe/seasonedShows/wiki/Install-as-a-daemon) on how to create a daemon on several unix distors and macOS.
*Please don't hesitate to add your own system if you get it running on something that is not yet lists on the formentioned wiki page.*
_Please don't hesitate to add your own system if you get it running on something that is not yet lists on the formentioned wiki page._
## <a name="contributing"></a> Contributing
- Fork it!
- Create your feature branch: git checkout -b my-new-feature
- Commit your changes: git commit -am 'Add some feature'
- Push to the branch: git push origin my-new-feature
- Submit a pull request
## Api documentation
The goal of this project is to create a full custom stack that can to everything surround downloading, organizing and notifiyng of new media. From the top down we have a website using [tmdb](https://www.themoviedb.com) api to search for from over 350k movies and 70k tv shows. Using [hjone72](https://github.com/hjone72/PlexAuth) great PHP reverse proxy we can have a secure way of allowing users to login with their plex credentials which limits request capabilites to only users that are authenticated to use your plex library.
seasonedShows is a intelligent organizer for your tv show episodes. It is made to automate and simplify to process of renaming and moving newly downloaded tv show episodes following Plex file naming and placement.
The goal of this project is to create a full custom stack that can to everything surround downloading, organizing and notifiyng of new media. From the top down we have a website using [tmdb](https://www.themoviedb.com) api to search for from over 350k movies and 70k tv shows. Using [hjone72](https://github.com/hjone72/PlexAuth) great PHP reverse proxy we can have a secure way of allowing users to login with their plex credentials which limits request capabilites to only users that are authenticated to use your plex library.
seasonedShows is a intelligent organizer for your tv show episodes. It is made to automate and simplify to process of renaming and moving newly downloaded tv show episodes following Plex file naming and placement.
So this is a multipart system that lets your plex users request movies, and then from the admin page the owner can.
## Installation
There are two main ways of
There are two main ways of
## Architecture
The flow of the system will first check for new folders in your tv shows directory, if a new file is found it's contents are analyzed, stored and tweets suggested changes to it's contents to use_admin.
Then there is a script for looking for replies on twitter by user_admin, if caanges are needed, it handles the changes specified and updates dtabbase.

View File

@@ -0,0 +1,31 @@
{
"database": {
"host": "./shows.db"
},
"redis": {
"host": "localhost",
"port": 6379
},
"webserver": {
"port": 31459,
"origins": []
},
"tmdb": {
"apiKey": ""
},
"plex": {
"ip": "localhost",
"token": ""
},
"tautulli": {
"apiKey": "",
"ip": "",
"port": ""
},
"raven": {
"DSN": ""
},
"authentication": {
"secret": "secret"
}
}

31
configurations/test.json Normal file
View File

@@ -0,0 +1,31 @@
{
"database": {
"host": ":memory:"
},
"redis": {
"host": "localhost",
"port": 6379
},
"webserver": {
"port": 31400,
"origins": []
},
"tmdb": {
"apiKey": "bogus-api-key"
},
"plex": {
"ip": "localhost",
"token": ""
},
"tautulli": {
"apiKey": "",
"ip": "",
"port": ""
},
"raven": {
"DSN": ""
},
"authentication": {
"secret": "secret"
}
}

55
package.json Normal file
View File

@@ -0,0 +1,55 @@
{
"name": "seasoned-api",
"description": "Packages needed to build and commands to run seasoned api node server.",
"license": {
"type": "MIT",
"url": "https://www.opensource.org/licenses/mit-license.php"
},
"main": "webserver/server.js",
"type": "module",
"scripts": {
"start": "SEASONED_CONFIG=configurations/production.json NODE_ENV=production node src/webserver/server.js",
"dev": "SEASONED_CONFIG=configurations/development.json NODE_ENV=development node src/webserver/server.js",
"test": "SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit tests/system",
"coverage:upload": "SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit && nyc report --reporter=text-lcov | coveralls",
"coverage": "SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit && nyc report",
"lint": "eslint src tests",
"update": "SEASONED_CONFIG=configurations/development.json node scripts/updateRequestsInPlex.js",
"docs": "yarn apiDocs; yarn classDocs",
"apiDocs": "",
"classDocs": "scripts/generate-class-docs.sh"
},
"dependencies": {
"bcrypt": "^5.0.1",
"body-parser": "~1.18.2",
"cookie-parser": "^1.4.6",
"express": "~4.16.0",
"form-data": "^2.5.1",
"jsonwebtoken": "^8.5.1",
"km-moviedb": "^0.2.12",
"raven": "^2.4.2",
"redis": "^3.0.2",
"sqlite3": "^5.0.1"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/register": "^7.5.5",
"@types/node": "^12.6.8",
"chai": "^4.3.6",
"chai-http": "^4.3.0",
"coveralls": "^3.0.5",
"documentation": "^12.0.3",
"eslint": "^8.22.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-mocha": "10.1.0",
"eslint-plugin-prettier": "^4.2.1",
"istanbul": "^0.4.5",
"mocha": "8.4.0",
"mocha-lcov-reporter": "^1.3.0",
"nyc": "15.1.0",
"prettier": "^2.7.1"
}
}

View File

@@ -0,0 +1,41 @@
import Plex from "../src/plex/plex.js";
import establishedDatabase from "../src/database/database.js";
import Configuration from "../src/config/configuration.js";
const configuration = Configuration.getInstance();
const plex = new Plex(
configuration.get("plex", "ip"),
configuration.get("plex", "token")
);
const queries = {
getRequestsNotYetInPlex: `SELECT * FROM requests WHERE status = 'requested' OR status = 'downloading'`,
saveNewStatus: `UPDATE requests SET status = ? WHERE id IS ? and type IS ?`
};
const getRequestsNotYetInPlex = () =>
establishedDatabase.all(queries.getRequestsNotYetInPlex);
async function getNewRequestMatchesInPlex() {
const requests = await getRequestsNotYetInPlex();
const exists = await Promise.all(
requests.map(request => plex.existsInPlex(request))
);
return requests.filter(() => exists.shift());
}
function commitNewStatus(status, id, type, title) {
console.log(`${type} ${title} updated to: ${status}`);
return establishedDatabase.run(queries.saveNewStatus, [status, id, type]);
}
function updateMatchInDb(match, status) {
return commitNewStatus(status, match.id, match.type, match.title);
}
getNewRequestMatchesInPlex()
.then(newMatches =>
Promise.all(newMatches.map(match => updateMatchInDb(match, "downloaded")))
)
.finally(() => process.exit(0));

View File

@@ -1,14 +0,0 @@
{
"extends": [
"airbnb-base"
],
"rules": {
"indent": ["error", 3],
"prefer-destructuring": 0,
"camelcase": 0,
"import/no-unresolved": 0,
"import/no-extraneous-dependencies": 0,
"object-shorthand": 0,
"comma-dangle": 0
}
}

View File

@@ -1,66 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# - - - - -
# My own gitignore files and folders
shows.db
conf/development.json
# conf/development-prod.json

View File

@@ -1,20 +0,0 @@
{
"database": {
"host": "../shows.db"
},
"webserver": {
"port": 31459
},
"tmdb": {
"apiKey": ""
},
"plex": {
"ip": ""
},
"raven": {
"DSN": ""
},
"authentication": {
"secret": "secret"
}
}

View File

@@ -1,20 +0,0 @@
{
"database": {
"host": ":memory:"
},
"webserver": {
"port": 31400
},
"tmdb": {
"apiKey": "bogus-api-key"
},
"plex": {
"ip": "0.0.0.0"
},
"raven": {
"DSN": ""
},
"authentication": {
"secret": "secret"
}
}

View File

@@ -1,57 +0,0 @@
{
"name": "seasoned-api",
"description": "Packages needed to build and commands to run seasoned api node server.",
"license": {
"type": "MIT",
"url": "https://www.opensource.org/licenses/mit-license.php"
},
"main": "webserver/server.js",
"scripts": {
"start": "cross-env SEASONED_CONFIG=conf/development.json PROD=true 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",
"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 src/plex/updateRequestsInPlex.js",
"docs": "yarn apiDocs; yarn classDocs",
"apiDocs": "",
"classDocs": "./script/generate-class-docs.sh"
},
"dependencies": {
"axios": "^0.18.0",
"bcrypt": "^3.0.6",
"body-parser": "~1.18.2",
"cross-env": "~5.1.4",
"express": "~4.16.0",
"express-graphql": "^0.9.0",
"express-reload": "^1.2.0",
"graphql": "^14.5.8",
"jsonwebtoken": "^8.2.0",
"km-moviedb": "^0.2.12",
"node-cache": "^4.1.1",
"node-fetch": "^2.6.0",
"python-shell": "^0.5.0",
"raven": "^2.4.2",
"request": "^2.87.0",
"request-promise": "^4.2",
"sqlite3": "^4.0.0"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/node": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/register": "^7.5.5",
"@types/node": "^12.6.8",
"coveralls": "^3.0.5",
"documentation": "^12.0.3",
"eslint": "^4.9.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.8.0",
"istanbul": "^0.4.5",
"mocha": "^6.2.0",
"mocha-lcov-reporter": "^1.3.0",
"nyc": "^11.6.0",
"supertest": "^3.0.0",
"supertest-as-promised": "^4.0.1",
"typescript": "^3.5.3"
}
}

View File

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

View File

@@ -1,15 +0,0 @@
class EnvironmentVariables {
constructor(variables) {
this.variables = variables || process.env;
}
get(variable) {
return this.variables[variable];
}
has(variable) {
return this.get(variable) !== undefined;
}
}
module.exports = EnvironmentVariables;

View File

@@ -1,49 +0,0 @@
const Filters = require('./filters.js');
const EnvironmentVariables = require('./environmentVariables.js');
class Field {
constructor(rawValue, environmentVariables) {
this.rawValue = rawValue;
this.filters = new Filters(rawValue);
this.valueWithoutFilters = this.filters.removeFiltersFromValue();
this.environmentVariables = new EnvironmentVariables(environmentVariables);
}
get value() {
if (this.filters.isEmpty()) {
return this.valueWithoutFilters;
}
if (this.filters.has('base64') && !this.filters.has('env')) {
return Field.base64Decode(this.valueWithoutFilters);
}
if (this.environmentVariables.has(this.valueWithoutFilters) &&
this.environmentVariables.get(this.valueWithoutFilters) === '') {
return undefined;
}
if (!this.filters.has('base64') && this.filters.has('env')) {
if (this.environmentVariables.has(this.valueWithoutFilters)) {
return this.environmentVariables.get(this.valueWithoutFilters);
}
return undefined;
}
if (this.filters.has('env') && this.filters.has('base64')) {
if (this.environmentVariables.has(this.valueWithoutFilters)) {
const encodedEnvironmentVariable = this.environmentVariables.get(this.valueWithoutFilters);
return Field.base64Decode(encodedEnvironmentVariable);
}
return undefined;
}
return this.valueWithoutFilters;
}
static base64Decode(string) {
return new Buffer(string, 'base64').toString('utf-8');
}
}
module.exports = Field;

View File

@@ -1,34 +0,0 @@
class Filters {
constructor(value) {
this.value = value;
this.delimiter = '|';
}
get filters() {
return this.value.split(this.delimiter).slice(0, -1);
}
isEmpty() {
return !this.hasValidType() || this.value.length === 0;
}
has(filter) {
return this.filters.includes(filter);
}
hasValidType() {
return (typeof this.value === 'string');
}
removeFiltersFromValue() {
if (this.hasValidType() === false) {
return this.value;
}
let filtersCombined = this.filters.join(this.delimiter);
filtersCombined += this.filters.length >= 1 ? this.delimiter : '';
return this.value.replace(filtersCombined, '');
}
}
module.exports = Filters;

View File

@@ -1,14 +0,0 @@
const configuration = require('src/config/configuration').getInstance();
const SqliteDatabase = require('src/database/sqliteDatabase');
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());
module.exports = database;

View File

@@ -1,119 +0,0 @@
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.schemaDirectory = path.join(__dirname, 'schemas');
}
/**
* Connect to the database.
* @returns {Promise} succeeds if connection was established
*/
// 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 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);
})
})
}
/**
* 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);
})
})
}
/**
* 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();
})
})
}
/**
* 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));
}
/**
* 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));
}
/**
* 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;
}
}
module.exports = SqliteDatabase;

View File

@@ -1,9 +0,0 @@
class GitRepository {
static dumpHook(body) {
/* eslint-disable no-console */
console.log(body);
}
}
module.exports = GitRepository;

View File

@@ -1,19 +0,0 @@
class Media {
constructor(title, year, type) {
this.title = title;
this.year = year;
this.type = type;
}
toString() {
return `N: ${this.title} | Y: ${this.year} | T: ${this.type}`;
}
print() {
/* eslint-disable no-console */
console.log(this.toString());
}
}
module.exports = Media;

View File

@@ -1,15 +0,0 @@
class MediaInfo {
constructor() {
this.duration = undefined;
this.height = undefined;
this.width = undefined;
this.bitrate = undefined;
this.resolution = undefined;
this.framerate = undefined;
this.protocol = undefined;
this.container = undefined;
this.audioCodec = undefined;
}
}
module.exports = MediaInfo;

View File

@@ -1,12 +0,0 @@
class Player {
constructor(device, address) {
this.device = device;
this.ip = address;
this.platform = undefined;
this.product = undefined;
this.title = undefined;
this.state = undefined;
}
}
module.exports = Player;

View File

@@ -1,22 +0,0 @@
const Media = require('src/media_classes/media');
class Plex extends Media {
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.seasons = seasons;
this.episodes = episodes;
}
print() {
super.print();
}
}
module.exports = Plex;

View File

@@ -1,33 +0,0 @@
const Media = require('src/media_classes/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);
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.seasons = seasons;
this.episodes = episodes;
}
toString() {
return `${super.toString()} | ID: ${this.id}`;
}
print() {
/* eslint-disable no-console */
console.log(this.toString());
}
}
module.exports = TMDB;

View File

@@ -1,8 +0,0 @@
class User {
constructor(id, title) {
this.id = id;
this.title = title;
}
}
module.exports = User;

Some files were not shown because too many files have changed in this diff Show More