284 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
ea5bc36956 Merge pull request #111 from KevinMidboe/api/v2
Api/v2
2019-11-04 18:01:15 +01:00
002e663be1 Merge branch 'api/v2' into feature/plex-authentication 2019-11-04 17:55:27 +01:00
fd475265c1 Updated test to reflect changes to all error response objects. (changed from returning message in error key to message. 2019-11-04 17:54:08 +01:00
495a3b4838 Merged api/v2 into feature branch 2019-11-04 00:58:43 +01:00
b0804f8a08 Merge branch 'api/v2' of github.com:kevinmidboe/seasonedShows into api/v2 2019-11-04 00:57:45 +01:00
6b737b8ab4 Updated all controller responses to return message not error on errors. 2019-11-04 00:57:27 +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
5623344666 Merge branch 'master' into api/v2 2019-11-03 20:57:25 +01:00
f8cc19b510 Added rating and release_date when parsing movies and fixed respective tests 2019-11-03 20:56:46 +01:00
c589457a6c Removed unused mongoose package 2019-11-03 20:55:54 +01:00
b802a7b62b Moved, renamed, re-did and added a lot of stuff. Getting ready for the v2 upgrade 2019-11-03 20:33:30 +01:00
879a02b388 Finished movie credits and release dates 2019-11-03 16:01:19 +01:00
bc3d4881bd New release_dates endpoint for movie 2019-11-03 15:43:35 +01:00
ef8d4d90b2 Removed console log 2019-11-03 15:08:42 +01:00
d2d396bb7a Set cache TTL for credits to 1 day 2019-11-03 15:07:11 +01:00
500b75eaf6 We know there could be a 401 response so we handle it 2019-11-03 15:04:14 +01:00
9308d4ea9b Credits endpoint for movies 2019-11-03 15:02:45 +01:00
6c2c81a1a1 Updated movieInfo controller to also handle requesting release_dates as query parameter 2019-10-04 22:36:39 +02:00
90aa4d2485 Rewrote the movie & show list controller to be more abstract and easier to extend later 2019-10-04 21:21:52 +02:00
0ca3f81bf8 listController first defines all async functions as constant variables then module exports them all as a dict 2019-10-04 20:55:39 +02:00
b9831c6b3d Forgot to reasing variables after copy-pasting them in convertTmdbToMovie 2019-10-04 20:37:06 +02:00
4781e9ae65 Merge pull request #119 from KevinMidboe/snyk-fix-a43be890852096db7a469faa6c44f8ef
[Snyk] Fix for 3 vulnerable dependencies
2019-07-27 02:17:50 +02:00
snyk-test
eb0881f19e fix: client/package.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-JSYAML-173999
- https://snyk.io/vuln/SNYK-JS-JSYAML-174129
- https://snyk.io/vuln/npm:mem:20180117
2019-07-27 00:16:09 +00:00
bc4d73821d Upgraded webpack-dev-server to not have a screaming vulnerability 2019-07-27 02:05:38 +02:00
ab6144eb81 Update yarn lock, updated coveralls and mocha run under coverage command now uses required babel register 2019-07-27 02:03:11 +02:00
c3d87e2200 Merge pull request #117 from KevinMidboe/snyk-fix-9429d5dfb86996c66ac12aef1a5178b1
[Snyk] Fix for 2 vulnerable dependencies
2019-07-27 01:58:33 +02:00
e391ce7ef9 Merge pull request #112 from KevinMidboe/snyk-fix-5oeu5e
[Snyk] Fix for 4 vulnerable dependencies
2019-07-27 01:58:07 +02:00
ca707078d9 Merge branch 'master' into snyk-fix-5oeu5e 2019-07-27 01:57:08 +02:00
snyk-test
53228a2662 fix: client/package.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-JSYAML-173999
- https://snyk.io/vuln/SNYK-JS-JSYAML-174129
2019-07-26 23:56:40 +00:00
2a9fa27341 Merge pull request #113 from KevinMidboe/snyk-fix-25dne6
[Snyk] Fix for 1 vulnerable dependencies
2019-07-27 01:56:24 +02:00
3068281461 Update README.md 2019-07-27 01:55:43 +02:00
81e9fe5b15 Testing for a running application is a bit weird, disabling it for now 2019-07-27 01:42:44 +02:00
5d2e375213 Upgraded node version for travis from 8 to 11 2019-07-27 01:34:15 +02:00
7ede37039a info-success-response is now a list so need this reflected in this test also. Changed the port we test for to whats in our config/test.jsono 2019-07-27 01:30:08 +02:00
8e23ae5a27 Added babel for ES6 functionality. In this case the new import statements 2019-07-27 01:28:41 +02:00
04ba094a14 Throw more errors and cleanup some unmerged code 2019-07-26 21:55:59 +02:00
23f9911237 Throw errors when failing to create user 2019-07-26 21:54:13 +02:00
3b27af1f83 Error handling for themoviedb api response codes that are not 200. Started with 401 and 404. See issue #116 for info. 2019-07-26 21:52:20 +02:00
afb7af46b8 The test uses the cached to not need to query themoviedb, but the function that would in prod now saves a Class containing movie result and extras such as credits. 2019-07-26 21:09:58 +02:00
6ba8ca2add Updated search query response 2019-07-26 21:07:26 +02:00
135375cb94 instead of "describe" "xdescribe" was defined which made the test pending in results. This has now been resolved. 2019-07-26 21:06:45 +02:00
e5d5bdefd6 Updated cache key and cleaned up formatting 2019-07-26 21:05:45 +02:00
6f9ca9e067 Added package and commands for generating documentation and upgraded mocha 2019-07-26 20:56:33 +02:00
c42195d242 Removed swap file 2019-07-25 00:53:40 +02:00
a5aaf1bfca Merge branch 'api/v2' of github.com:KevinMidboe/seasonedShows into api/v2 2019-07-25 00:53:16 +02:00
af7b1f2424 Script for updating all requested and downloading request status to downloaded if exist in plex 2019-07-25 00:48:16 +02:00
6aba9774c6 When requesting all request elements we now also return the page as int not string 2019-07-25 00:47:17 +02:00
e19cfb5870 Updated formatting 2019-07-25 00:24:04 +02:00
144b27f128 Renamed token variable from user to username 2019-07-25 00:23:32 +02:00
12afbf6364 Tokens can also have a admin property. When admin is defined its included in the jwt token. 2019-07-25 00:13:28 +02:00
8a5ab204e1 Change node bcrypt package from bcrypt-nodejs to bcrypt. Change response message on invalid username/pass and changed to bcrypt syntax for compare and hash. 2019-07-24 23:02:06 +02:00
3f04d9bc56 Update script for updating all plex statuses of requestes. 2019-07-24 23:02:06 +02:00
de50805d1e Handle both status code 301 and 302 from jackett 2019-07-15 18:16:46 +02:00
3a9131a022 Removed, commented and added comments 2019-07-02 23:53:26 +02:00
77433e8505 Query of plex search is now encoded 2019-07-02 23:53:08 +02:00
3845000b3f Allow filtering for requested items by status 2019-06-28 23:32:11 +02:00
071fd54825 Pages for requests are only calulated for items not yet downloaded and use ceil isteadof floor to get last items on a page 2019-06-28 22:51:09 +02:00
537f237e83 Updated lock file 2019-06-28 22:45:31 +02:00
d3bc854e03 Pirate repository has relative and use virtuale python when running python commands 2019-06-28 22:44:39 +02:00
15826a00ba plexRepo now using class instance plexIp address 2019-06-28 22:42:11 +02:00
4019d63f3b Created example config and added development config to gitignore 2019-06-28 22:39:24 +02:00
91dcfaccb9 Rewrote posting request controller to handle body parameters and use new requestsRepository function istead of plexRepository functions 2019-06-28 22:31:52 +02:00
270a259cee Request list also gets and returns total pages 2019-06-28 21:51:43 +02:00
162d20ae52 Submitting requests now use requests repository 2019-06-28 21:51:11 +02:00
9f1badc1b1 Get a request item by id and type 2019-06-28 19:21:54 +02:00
ac027a97d6 Added pagination and removed sort & filtering for requested items 2019-06-28 18:50:30 +02:00
127db88ded Renamed function name and comment to make for sense. Also deconstruct page from query 2019-06-28 18:45:53 +02:00
4b07434615 Imported configuration with incorrect name 2019-06-05 00:05:54 +02:00
5d6f2baa34 plex hook should have post not get 2019-06-05 00:00:31 +02:00
1a1a7328a3 Map results with total_results before returing. TODO this should be mapped with all wanted list return vars 2019-06-04 23:54:39 +02:00
b9dec2344e Added timeout to plex requests and include error in error message when unable to search 2019-06-04 23:53:54 +02:00
476a34fb69 Changed the order of execution between getting tmdb movie and searching plex for it. Now we await tmdb movie and then check if exists in plex. This is better when we miss plex request 2019-06-04 23:47:10 +02:00
e3ed08e8dd Now a plex ip address is dynamically passed into the plexrepository, fetched from the config 2019-06-04 23:45:22 +02:00
70f6497404 All converter function from tmdb to movie, show and person takes optional cast object and maps to response 2019-06-04 23:35:21 +02:00
99bab3fb73 Movie and show can also return credits for a item. Enabled by query parameter credits=true 2019-06-04 23:32:38 +02:00
e6796aff8b Hotfix 🧯 for returning new poster object variable 2019-06-04 21:41:10 +02:00
1f9dc067e6 Plex params are now parsed with URI encoder. 2019-04-10 22:22:52 +02:00
snyk-bot
4eaa60b044 fix: seasoned_api/package.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-MPATH-72672
2018-12-13 03:19:03 +00:00
snyk-bot
7db8f752c5 fix: seasoned_api/package.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/npm:base64url:20180511
- https://snyk.io/vuln/npm:cryptiles:20180710
- https://snyk.io/vuln/npm:extend:20180424
- https://snyk.io/vuln/npm:stringstream:20180511
2018-12-08 03:59:04 +00:00
784aa2616a Fetchall gets docstring 2018-11-12 01:20:18 +01:00
7cb55ce054 Fetchall uses promises smarter. Now the utils functions also return promises to be able to nicely chain the steps a request needs to go through. Promise all lets us wait for all items return in the map function. Without the map function would return immidiately and resolve before the map operation completed. 2018-11-10 20:26:28 +01:00
87eb6de802 🔨 test now requests with id in body not in query params. 2018-11-10 01:57:19 +01:00
840816c930 request returns all requested items. Optional sort, query and filter params. 2018-11-10 01:50:24 +01:00
91d238de7c Request id is now passed as body param. Database default timestamp value changed to epoch time. 2018-11-09 22:13:00 +01:00
0ac17d3d0a Removed unused const declaration. 2018-11-01 00:24:47 +01:00
87c76e3f1d Tests now suppoer the new list endpoints. Also updated response for interstellar query (movieInfo). 2018-11-01 00:18:54 +01:00
e64c4d5d01 Lists are now reachable by movie or show / listname. Endpoints added & removed outdated comments. 2018-11-01 00:17:51 +01:00
22e57c03de Controller for movie and shows. Each have multiple small export functions; one for each list search type 2018-11-01 00:16:56 +01:00
d80386da40 Implementing lists lookups for movie and shows. Add new cachetags for the lists & created a helper function for returning response with convertFunction as parameter. 2018-11-01 00:15:49 +01:00
e7c66af3f6 Merge branch 'master' into api/v2 2018-10-30 21:02:47 +01:00
8ece7b84c4 test configuration also gets plex ip parameter. 2018-10-30 20:38:05 +01:00
4250b1bd17 request endpoint finds type by body not query. Better error handling on what goes wrong if incorrect type or missing body parameter. 2018-10-30 20:34:26 +01:00
7e46d32e30 More unit tests for checking correct definition of movie. Changed some test to match update functions in tmdb. 2018-10-30 20:32:55 +01:00
5a48158f07 Request now happens at /request with id parameter and query for type selection. Only allows movie or show type and is static set in the controller. AddRequest adds tmdb item to database with time of request. 2018-10-30 19:20:52 +01:00
161a466ab7 Rewrote how local plex library is indexed and what it returns. After searching plex the response is separated into three classes by types (movie, show & episode). Plex also has a function for inputing a (tmdb)movie object and searching for matches of name & type in plex. If a match the object matchedInPlex variable is set to true. 2018-10-29 21:01:16 +01:00
8f5bd44e4d Added endpoint for new plex search. 2018-10-29 20:57:22 +01:00
5d8869e042 Rewrote every function for searching and looking up items from tmdb library. Now there are separate functions for the four categories of search and three for info (multi, movie, show & person). Each function now has its own endpoint and matching controller. Converting tmdb results into a class has been alterted from using three classes; movie, show & person, and each have each their own convertTmdbTo function. Now the structure of the three types are more structured and no longer a single "seasoned" class object. 2018-10-29 20:55:18 +01:00
90b8ee005e Changed moviedb package to my own fork of it. The old package had vulnerabilities and needed updating. 2018-10-29 20:49:21 +01:00
1b0525063f New parameter in config and added axios package for new plex connect command. 2018-10-29 20:47:57 +01:00
41d6bba743 v2 endpoints added for clearer intent in endpoints. Two new controller categories; info and search. 2018-10-28 12:21:47 +01:00
8977a4b195 Merge pull request #109 from KevinMidboe/package/upgrade
Changed moviedb node package to my own fork (km-tmdb) with updated to…
2018-10-26 01:01:43 +02:00
7e0da028de Imported new version of moviedb package 2018-10-26 00:59:22 +02:00
2250cf2c4b Changed moviedb node package to my own fork (km-tmdb) with updated to vulnerability in the superagent package 2018-10-26 00:20:37 +02:00
b2bd7b6a1f Update README.md 2018-08-27 11:58:16 +02:00
a2ad7f5628 Removed old content 2018-08-27 11:56:28 +02:00
f85d31991f Removed versioneye badge 2018-08-27 11:54:48 +02:00
08dc2153ae Updated build config for codeclimate test reporting. 2018-08-26 10:56:50 +02:00
bc64e69b3e Fixed syntax error. 2018-08-13 00:01:51 +02:00
a29bca7361 Controller now expects three parameters for posting to addMagnet; magnet, name and tmdb_id. 2018-08-12 23:59:26 +02:00
d84aa5f173 Merge branch 'master' of github.com:KevinMidboe/seasonedShows 2018-08-12 23:55:40 +02:00
48ebd398bc Changed name values of tables. 2018-08-12 23:50:07 +02:00
1b95103acd Removed test that caused breaking changes. 2018-08-12 23:31:18 +02:00
6a1d6687eb Updated gitmodules 2018-07-28 19:00:32 +02:00
e849864bc2 Added delugeClient to gitmodules. 2018-07-28 18:55:39 +02:00
ecc2a67d48 Updated readme for cloning requrse submodules. 2018-07-28 17:55:28 +02:00
bfe0d55f71 Excetion node-pre-gyp failed for version check for sqlite3. The package was set to static version and needed a patch because of errors caused by newer versions of node. 2018-07-28 17:51:59 +02:00
634d4513eb Merge pull request #106 from KevinMidboe/remove_verified
Remove verified
2018-07-28 16:17:43 +02:00
0a1276a474 Merge pull request #105 from KevinMidboe/plex_api_update
Plex api update
2018-07-28 16:17:33 +02:00
3a34d8995e Merge pull request #104 from KevinMidboe/misc
Misc
2018-07-28 16:15:18 +02:00
918e629a06 Merge pull request #103 from KevinMidboe/stray_fixes
Stray fixes
2018-07-28 16:15:03 +02:00
7dd016a56e Changed the python run variable for stray eps. 2018-07-28 16:05:22 +02:00
c10bbcf518 Added update function to package.json fole. 2018-07-28 15:58:02 +02:00
3402a52633 Change to log the parent name of the element instead of the name of file. 2018-07-28 10:50:57 +02:00
86e9188a5c The api from plex has changed. This reflects the changes from Video to metadata in the api url. 2018-07-28 10:46:25 +02:00
8918b7906e Merge branch 'remove_verified' of github.com:KevinMidboe/seasonedShows into HEAD 2018-05-13 19:21:52 +02:00
7e028a461d Merge branch 'master' of github.com:KevinMidboe/seasonedShows into HEAD 2018-05-13 19:21:14 +02:00
fe5f0c815e Deluge is now imported and a Deluge class is created and remove function called for name of torrent that is being verified. 2018-05-13 19:18:45 +02:00
d02e79e59e Merge pull request #100 from KevinMidboe/linting
Linting
2018-05-09 11:00:02 +02:00
5b49216c9d Fixed linting issues for json objects and tailing semicolon. 2018-05-09 10:52:08 +02:00
657ab10034 Removed unused comments. 2018-05-06 18:36:26 +02:00
ed07c77b13 Updated files with tripple === and some linting issues. 2018-05-06 18:23:29 +02:00
4fe85d9fae Change the ordering of user requests to be newest-first. 2018-05-06 18:15:54 +02:00
b99b5b32ec Updated to use abspath of the file not the call location. 2018-05-06 18:09:13 +02:00
e8058c5e4c Update README.md 2018-04-19 21:13:14 +02:00
7332b7d474 Update README.md 2018-04-19 20:22:26 +02:00
7980f14426 Update README.md 2018-04-19 20:21:44 +02:00
65540fafbd Merge pull request #99 from KevinMidboe/dependency_update
Dependency update
2018-04-10 11:29:56 +02:00
64ede43dec Added custom rule for object-shorthand and comma-dangle. 2018-04-08 11:58:16 +02:00
bed12cff72 Set branch to master for the submodule torrent_search 2018-04-08 11:50:15 +02:00
59e7f96643 Updated submodule torrent_search with new commits. 2018-04-08 11:43:12 +02:00
71e9a5a46e Merge pull request #98 from KevinMidboe/strayParser_fix
Updated when parsing for show name allow names with numbers.
2018-04-06 16:27:42 +02:00
fce6dc7658 Updated when parsing for show name allow names with numbers. 2018-04-06 16:22:58 +02:00
baff59181c Update README.md 2018-04-04 23:22:18 +02:00
0592cca16b Updated string_decoder. 2018-04-04 23:08:00 +02:00
e4d5f5085c Updated yarn lockfile. 2018-04-04 14:41:01 +02:00
66a2a06f9b Compile error, if-statement. 2018-04-03 23:02:54 +02:00
e984feeb8d Would fail if the parent was not a directory. 2018-04-03 23:00:14 +02:00
490d015f80 Update README.md 2018-03-30 15:31:15 +02:00
f1cc2c4ebe Merge pull request #97 from KevinMidboe/coverage
Added coverage stats with nyc and coveralls
2018-03-22 18:30:12 +01:00
2f4421d9e0 Merge branch 'coverage' of github.com:kevinmidboe/seasonedShows into coverage 2018-03-22 18:25:01 +01:00
92cc094787 Removed old coverage script and updated travis config. 2018-03-22 18:24:42 +01:00
f30b46c384 Update README.md 2018-03-22 17:20:14 +01:00
d9f679603a Command in travis config was doc, not cov. 2018-03-22 17:17:23 +01:00
64bd9d1e14 Added support for travis upload test coverage to coveralls. 2018-03-22 15:09:59 +01:00
721826d454 Re-added request and removed superagent. 2018-03-22 13:24:57 +01:00
242fe3515c Removed and moved some dep to dev. 2018-03-22 13:23:30 +01:00
ccf40d2161 Merge pull request #96 from KevinMidboe/snyk-fix-6de5e99f
[Snyk] Fix for 42 vulnerable dependency paths
2018-03-22 12:59:36 +01:00
832b8ba539 Added license and description to package.json. Also updated packages node packages. 2018-03-22 12:56:04 +01:00
snyk-bot
0477e49eca fix: seasoned_api/package.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/npm:qs:20170213
- https://snyk.io/vuln/npm:qs:20140806
- https://snyk.io/vuln/npm:qs:20140806-1
- https://snyk.io/vuln/npm:mime:20170907
- https://snyk.io/vuln/npm:mime:20170907
- https://snyk.io/vuln/npm:fresh:20170908
- https://snyk.io/vuln/npm:debug:20170905
- https://snyk.io/vuln/npm:ms:20170412
- https://snyk.io/vuln/npm:qs:20170213
- https://snyk.io/vuln/npm:negotiator:20160616
- https://snyk.io/vuln/npm:ms:20151024
- https://snyk.io/vuln/npm:debug:20170905
- https://snyk.io/vuln/npm:ms:20170412
- https://snyk.io/vuln/npm:ms:20151024
- https://snyk.io/vuln/npm:hoek:20180212

Latest report for kevinmidboe/seasonedshows:seasoned_api/package.json:
https://snyk.io/test/github/kevinmidboe/seasonedshows?targetFile=seasoned_api/package.json
2018-03-22 11:34:42 +00:00
298 changed files with 14262 additions and 5450 deletions

View File

@@ -3,7 +3,7 @@
# @Author: KevinMidboe
# @Date: 2017-04-05 18:40:11
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-06-18 21:49:33
# @Last Modified time: 2018-04-03 22:58:20
import os.path, hashlib, time, glob, sqlite3, re, json, tweepy
import logging
from functools import reduce
@@ -61,7 +61,7 @@ class strayEpisode(object):
return hashlib.md5("b'{}'".format(self.parent).encode()).hexdigest()[:8]
def findSeriesName(self):
find = re.compile("^[a-zA-Z. ]*")
find = re.compile("^[a-zA-Z0-9. ]*")
m = re.match(find, self.parent)
if m:
name, hit = process.extractOne(m.group(0), getShowNames().keys())

View File

@@ -3,13 +3,15 @@
# @Author: KevinMidboe
# @Date: 2017-04-12 23:27:51
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-06-27 15:58:09
# @Last Modified time: 2018-05-13 19:17:17
import sys, sqlite3, json, os.path
import logging
import env_variables as env
import shutil
import delugeClient.deluge_cli as delugeCli
class episode(object):
def __init__(self, id):
self.id = id
@@ -91,8 +93,18 @@ def moveStray(strayId):
except FileNotFoundError:
logging.warning('Cannot remove ' + ep.typeDir('parent_input') + ', file no longer exists.')
# Remove from deluge client
logging.info('Removing {} for deluge'.format(ep.parent))
deluge = delugeCli.Deluge()
response = deluge.remove(ep.parent)
logging.info('Deluge response after delete: {}'.format(response))
if __name__ == '__main__':
if (os.path.exists(env.logfile)):
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
if (os.path.exists(os.path.join(dname, env.logfile))):
logging.basicConfig(filename=env.logfile, level=logging.INFO)
else:
print('Logfile could not be found at ' + env.logfile + '. Verifiy presence or disable logging in config.')

View File

@@ -12,7 +12,7 @@
},
"dependencies": {
"clean-webpack-plugin": "^0.1.17",
"css-loader": "^0.28.4",
"css-loader": "^1.0.0",
"html-webpack-plugin": "^2.28.0",
"path": "^0.12.7",
"react": "^15.6.1",
@@ -30,8 +30,8 @@
"redux-thunk": "^2.2.0",
"urijs": "^1.18.12",
"webfontloader": "^1.6.28",
"webpack": "^3.5.5",
"webpack-dev-server": "^2.4.5",
"webpack": "^4.0.0",
"webpack-dev-server": "^3.1.11",
"webpack-merge": "^4.1.0"
},
"devDependencies": {

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

7
.gitignore vendored
View File

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

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "torrent_search"]
path = torrent_search
url = https://github.com/KevinMidboe/torrent_search.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

@@ -1,11 +1,19 @@
language: node_js
node_js: '8.7.0'
node_js: '11.9.0'
git:
submodules: true
script:
yarn test
- yarn test
- yarn coverage
before_install:
- cd seasoned_api
before_script: yarn
- 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
- chmod +x ./cc-test-reporter
- ./cc-test-reporter before-build
after-script:
- ./cc-test-resporter after-build --exit-code $TRAVIS_TEST_RESULT
cache: false
os: linux

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"]

199
README.md
View File

@@ -1,41 +1,184 @@
# 🌶 seasonedShows
[![Build Status](https://travis-ci.org/KevinMidboe/seasonedShows.svg?branch=master)](https://travis-ci.org/KevinMidboe/seasonedShows)
[![Known Vulnerabilities](https://snyk.io/test/github/KevinMidboe/seasonedShows/badge.svg?targetFile=seasoned_api/package.json)](https://snyk.io/test/github/KevinMidboe/seasonedShows?targetFile=seasoned_api/package.json)
[![DUB](https://img.shields.io/dub/l/vibe-d.svg)]()
<h1 align="center">
🌶 seasonedShows
</h1>
Your customly *seasoned* movie and show requester, downloader and organizer.
📺 [Demo](https://kevinmidboe.com/request)
<h4 align="center"> Season your media library with the shows and movies that you and your friends want.</h4>
## About
The goal of this project is to create a full custom stack that can to everything surround downloading, organizing and notifiyng of new media. From the top down we have a website using [tmdb](https://www.themoviedb.com) api to search for from over 350k movies and 70k tv shows. Using [hjone72](https://github.com/hjone72/PlexAuth) great PHP reverse proxy we can have a secure way of allowing users to login with their plex credentials which limits request capabilites to only users that are authenticated to use your plex library.
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.
<p align="center">
<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=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>
</p>
<p align="center">
<a href="#demo-documentation">D & D</a>
<a href="#about">About</a>
<a href="#key-features">Key features</a>
<a href="#installation">Installation</a>
<a href="#setup">Setup</a>
<a href="#running">Running</a>
<a href="#daemon">Setup daemon</a>
<a href="#contributing">Contributing</a>
</p>
## <a name="demo-documentation"></a> Demo & Documentation
📺 [DEMO](https://request.movie)
📝 Documentation of 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.
## <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
### 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
## <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 git@github.com:KevinMidboe/seasonedShows.git`
- Type: `cd seasonedShows/`
- Install required packages
- yarn: `yarn install`
- npm: `npm install`
- Start server:
- 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 git@github.com:KevinMidboe/seasonedShows.git`
- Type: `cd seasonedShows/`
- Install required packages
- yarn: `yarn install`
- npm: `npm install`
- Start server:
- 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].
-- same --
(install yarn or npm in a different way)
After you have installed the required packages you will have a node_modules directory with all the packages required in packages.json.
### Requirements
- 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
## <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._
## <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.
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.
After approval by user the files are modified and moved to folders in resptected area. If error occours, pasteee link if log is sent to user.
#### External
+ Seasoned: request, discover and manage.
+ Stray: Overview of downloaded episodes before they are organized.
+ (+) Admin Panel: Overview of all stray episodes/movies.
#### Api
+ All communication between public website to server.
+ Plex: All querying to what is localy available in your plex library.
+ Stray (seasoned) -> also calls services (moveStray) through api.
+ Tmdb: Requesting information from tmdb.
+ (+) Admin Panel: Use secure login and session tokens to handle logged in viewer.
#### Services
+ Parse directories for new content.
+ Extract and save in db information about stray item.
+ Move a confirmed stray item.
+ (+) Search for torrents matching new content.

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,12 +0,0 @@
{
"extends": [
"airbnb-base"
],
"rules": {
"indent": ["error", 3],
"prefer-destructuring": 0,
"camelcase": 0,
"import/no-unresolved": 0,
"import/no-extraneous-dependencies": 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,24 +0,0 @@
{
"database": {
"host": "../shows.db"
},
"webserver": {
"port": 31459
},
"tmdb": {
"apiKey": ""
},
"raven": {
"DSN": ""
},
"mail": {
"host": "",
"user": "",
"password": "",
"user_pi": "",
"password_pi": ""
},
"authentication": {
"secret": "secret"
}
}

View File

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

View File

@@ -1,38 +0,0 @@
{
"name": "seasoned-api",
"main": "webserver/server.js",
"scripts": {
"start": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. node src/webserver/server.js",
"test": "cross-env SEASONED_CONFIG=conf/test.json NODE_PATH=. mocha --recursive test",
"coverage": "cross-env SEASONED_CONFIG=conf/test.json NODE_PATH=. istanbul cover -x script/autogenerate-documentation.js --include-all-sources --dir test/.coverage node_modules/mocha/bin/_mocha --recursive test/**/* -- --report lcovonly && cat test/.coverage/lcov.info | coveralls && rm -rf test/.coverage",
"lint": "./node_modules/.bin/eslint src/"
},
"dependencies": {
"bcrypt-nodejs": "^0.0.3",
"blanket": "^1.2.3",
"body-parser": "~1.0.1",
"codecov": "^3.0.0",
"cross-env": "^3.1.3",
"express": "~4.11.0",
"jsonwebtoken": "^8.0.1",
"mocha-lcov-reporter": "^1.3.0",
"mongoose": "^3.6.13",
"moviedb": "^0.2.10",
"node-cache": "^4.1.1",
"nodemailer": "^4.0.1",
"python-shell": "^0.4.0",
"raven": "^2.2.1",
"request": "^2.81.0",
"request-promise": "^4.2",
"sqlite3": "3.1.13"
},
"devDependencies": {
"eslint": "^4.9.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.8.0",
"istanbul": "^0.4.5",
"mocha": "^5.0.4",
"supertest": "^2.0.1",
"supertest-as-promised": "^4.0.1"
}
}

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}
*/
async 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}
*/
async 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}
*/
async 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}
*/
async 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