Compare commits
	
		
			94 Commits
		
	
	
		
			v1.1.1
			...
			feat/types
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 379e025ab6 | |||
| 628ed52012 | |||
| 1815a429b0 | |||
| cfbd4965db | |||
| 31c4b8b7df | |||
| a4b2e8f51c | |||
| 11fb803838 | |||
| b2d2b0025c | |||
| ae9f3044bc | |||
| 0eab680527 | |||
| 4204515e91 | |||
| 19e99e8c43 | |||
| 007d34f994 | |||
| 5a1e18b839 | |||
| 56262a45c8 | |||
| 0efc109992 | |||
| 851af204ab | |||
| ccebf0d7b0 | |||
| 76fe986f39 | |||
| fbf1ae8dec | |||
| 9164b592bd | |||
| d77b427c3c | |||
| b56b1f6c0c | |||
| c8477fabaa | |||
| 014cac8b06 | |||
| 20d74cafb9 | |||
| 1690bbcdd0 | |||
| 7094aa2bb5 | |||
| 3660e88acf | |||
| d8f7f82127 | |||
| 0a4248bf30 | |||
| 92d139a156 | |||
| 5578bf854a | |||
| 5648b8fffa | |||
| 1b7a754224 | |||
| 5d91f1bae7 | |||
| cdcfae56e7 | |||
| f2c77e092d | |||
| d6ac7e55e9 | |||
| a3543090f2 | |||
| 041e944783 | |||
| bfd31ebd23 | |||
| 5036f4ca36 | |||
| 61b59ae3ea | |||
| 92c49ac523 | |||
| f680642f25 | |||
| f89486ae9e | |||
| 4d853565d1 | |||
| 91c81e5cf6 | |||
| 0ecbde9675 | |||
| d8e951c2ef | |||
| 90f3d86511 | |||
| c6791a7027 | |||
| 5b6a2c2651 | |||
| 4f7a22fff1 | |||
| 31b0c998a8 | |||
| 9ce5b476ef | |||
| 554f292e4c | |||
| d8985aaff7 | |||
| be889b8100 | |||
| b5bd672f44 | |||
| 4501bc5302 | |||
| b384e748af | |||
| c676f182b4 | |||
| 95d2b0095b | |||
| 8165cf8e85 | |||
| 14775744b0 | |||
| 559e32c059 | |||
| f4dbaf4c58 | |||
| 1d25914ae0 | |||
| 4d3d8c874c | |||
| 08433523b7 | |||
| fce8879994 | |||
| 505b126043 | |||
| 589bd7b08d | |||
| f0049ffb4e | |||
| 2b25397253 | |||
| 776f83553a | |||
| 815aaedffb | |||
| 578eff30fb | |||
| 943cbe5cb8 | |||
| f89db46bf2 | |||
| 085fb76e11 | |||
| aa4a1c2a57 | |||
| 74340afd16 | |||
| 2672266908 | |||
| f37786aa76 | |||
| 91f64e5cfb | |||
| a4d3123910 | |||
| bc6fe3ed48 | |||
| b23566509f | |||
| 341a07621d | |||
| 259ed9b06f | |||
| cddf06cbcc | 
| Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB | 
							
								
								
									
										1
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| **/node_modules | ||||
							
								
								
									
										111
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								.drone.yml
									
									
									
									
									
										Normal 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 | ||||
							
								
								
									
										35
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| { | ||||
| 	"root": true, | ||||
| 	"parserOptions": { | ||||
| 		"parser": "@typescript-eslint/parser", | ||||
| 		"ecmaVersion": 2020, | ||||
| 		"sourceType": "module" | ||||
| 	}, | ||||
| 	"extends": [ | ||||
| 		"eslint-config-airbnb-base", | ||||
| 		"plugin:@typescript-eslint/recommended", | ||||
| 		"plugin:prettier/recommended" | ||||
| 	], | ||||
| 	"plugins": ["mocha", "@typescript-eslint"], | ||||
| 	"rules": { | ||||
| 		"lines-between-class-members": [ | ||||
| 			"error", | ||||
| 			"always", | ||||
| 			{ "exceptAfterSingleLine": true } | ||||
| 		], | ||||
| 		"max-classes-per-file": 1, | ||||
| 		"no-empty": [ | ||||
| 			2, | ||||
| 			{ | ||||
| 				"allowEmptyCatch": true | ||||
| 			} | ||||
| 		], | ||||
| 		"no-promise-executor-return": 1, | ||||
| 		"no-shadow": "off", | ||||
| 		"no-underscore-dangle": "off", | ||||
| 		"@typescript-eslint/no-var-requires": "off" | ||||
| 	}, | ||||
| 	"env": { | ||||
| 		"mocha": true | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										0
									
								
								_config.yml → .github/_config.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								_config.yml → .github/_config.yml
									
									
									
									
										vendored
									
									
								
							
							
								
								
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,7 +1,12 @@ | ||||
| .DS_Store | ||||
|  | ||||
| development.json | ||||
| env | ||||
| configurations/development.json | ||||
| configurations/production.json | ||||
| .env | ||||
| shows.db | ||||
| lib/ | ||||
|  | ||||
| node_modules | ||||
| */package-lock.json | ||||
| .nyc_output | ||||
| yarn-error.log | ||||
|   | ||||
							
								
								
									
										10
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -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
									
								
							
							
						
						
									
										9
									
								
								.prettierrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| { | ||||
|   "tabWidth": 2, | ||||
|   "useTabs": false, | ||||
|   "semi": true, | ||||
|   "singleQuote": false, | ||||
|   "bracketSpacing": true, | ||||
|   "arrowParens": "avoid", | ||||
|   "trailingComma": "none" | ||||
| } | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										21
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| FROM node:18 | ||||
|  | ||||
| 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"] | ||||
|  | ||||
| LABEL org.opencontainers.image.source https://github.com/kevinmidboe/seasoned | ||||
							
								
								
									
										13
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								README.md
									
									
									
									
									
								
							| @@ -6,16 +6,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> | ||||
|   | ||||
							
								
								
									
										31
									
								
								configurations/development.json.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								configurations/development.json.example
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										31
									
								
								configurations/test.json
									
									
									
									
									
										Normal 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" | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										60
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| { | ||||
|   "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": "SEASONED_CONFIG=configurations/production.json NODE_ENV=production node lib/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", | ||||
|     "build": "yarn tsc", | ||||
|     "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/production.json node scripts/updateRequestsInPlex.js", | ||||
|     "docs": "yarn apiDocs; yarn classDocs", | ||||
|     "apiDocs": "", | ||||
|     "classDocs": "scripts/generate-class-docs.sh", | ||||
|     "postbuild": "cp -r src/database/schemas lib/database" | ||||
|   }, | ||||
|   "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", | ||||
|     "python-shell": "^0.5.0", | ||||
|     "raven": "^2.4.2", | ||||
|     "redis": "^3.0.2", | ||||
|     "sqlite3": "^5.0.1", | ||||
|     "typescript": "^4.7.4" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@babel/core": "^7.5.5", | ||||
|     "@babel/preset-env": "^7.5.5", | ||||
|     "@babel/register": "^7.5.5", | ||||
|     "@types/node": "^18.7.8", | ||||
|     "@typescript-eslint/eslint-plugin": "^5.33.1", | ||||
|     "@typescript-eslint/parser": "^5.33.1", | ||||
|     "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" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										44
									
								
								scripts/updateRequestsInPlex.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								scripts/updateRequestsInPlex.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| const Plex = require("src/plex/plex"); | ||||
| const configuration = require("src/config/configuration").getInstance(); | ||||
| const plex = new Plex(configuration.get("plex", "ip")); | ||||
| const establishedDatabase = require("src/database/database"); | ||||
|  | ||||
| const queries = { | ||||
|   getRequestsNotYetInPlex: `SELECT * FROM requests WHERE status = 'requested' OR status = 'downloading'`, | ||||
|   saveNewStatus: `UPDATE requests SET status = ? WHERE id IS ? and type IS ?` | ||||
| }; | ||||
|  | ||||
| const getByStatus = () => | ||||
|   establishedDatabase.all(queries.getRequestsNotYetInPlex); | ||||
|  | ||||
| const checkIfRequestExistInPlex = async request => { | ||||
|   request.existsInPlex = await plex.existsInPlex(request); | ||||
|   return request; | ||||
| }; | ||||
|  | ||||
| const commitNewStatus = (status, id, type, title) => { | ||||
|   console.log(type, title, "updated to:", status); | ||||
|   return establishedDatabase.run(queries.saveNewStatus, [status, id, type]); | ||||
| }; | ||||
|  | ||||
| const getNewRequestMatchesInPlex = async () => { | ||||
|   const requests = await getByStatus(); | ||||
|  | ||||
|   return Promise.all(requests.map(checkIfRequestExistInPlex)) | ||||
|     .catch(error => | ||||
|       console.log("error from checking plex for existance:", error) | ||||
|     ) | ||||
|     .then(matchedRequests => | ||||
|       matchedRequests.filter(request => request.existsInPlex) | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| const updateMatchInDb = (match, status) => { | ||||
|   return commitNewStatus(status, match.id, match.type, match.title); | ||||
| }; | ||||
|  | ||||
| getNewRequestMatchesInPlex() | ||||
|   .then(newMatches => | ||||
|     Promise.all(newMatches.map(match => updateMatchInDb(match, "downloaded"))) | ||||
|   ) | ||||
|   .then(() => process.exit(0)); | ||||
| @@ -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 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										66
									
								
								seasoned_api/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										66
									
								
								seasoned_api/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -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 | ||||
| @@ -1,25 +0,0 @@ | ||||
| { | ||||
| 	"database": { | ||||
| 		"host": "../shows.db" | ||||
| 	}, | ||||
| 	"webserver": { | ||||
| 		"port": 31459 | ||||
| 	}, | ||||
| 	"tmdb": { | ||||
| 		"apiKey": "" | ||||
| 	}, | ||||
| 	"plex": { | ||||
| 		"ip": "" | ||||
| 	}, | ||||
|   "tautulli": { | ||||
|     "apiKey": "", | ||||
|     "ip": "", | ||||
|     "port": "" | ||||
|   }, | ||||
| 	"raven": { | ||||
| 		"DSN": "" | ||||
| 	}, | ||||
| 	"authentication": { | ||||
|     "secret": "secret" | ||||
|  	} | ||||
| } | ||||
| @@ -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" | ||||
|     	} | ||||
| } | ||||
| @@ -1,55 +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", | ||||
|     "form-data": "^2.5.1", | ||||
|     "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" | ||||
|   } | ||||
| } | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -1,120 +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.execute('pragma foreign_keys = on;'); | ||||
|       this.schemaDirectory = path.join(__dirname, 'schemas'); | ||||
|    } | ||||
|  | ||||
|    /** | ||||
|    * Connect to the database. | ||||
|    * @returns {Promise} succeeds if connection was established | ||||
|    */ | ||||
|    // connect() { | ||||
|    //    let database = ; | ||||
|    //    this.connection = database; | ||||
|    //    return database; | ||||
|    // } | ||||
|  | ||||
|    /** | ||||
|    * 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; | ||||
| @@ -1,9 +0,0 @@ | ||||
|  | ||||
| class GitRepository { | ||||
|    static dumpHook(body) { | ||||
|       /* eslint-disable no-console */ | ||||
|       console.log(body); | ||||
|    } | ||||
| } | ||||
|  | ||||
| module.exports = GitRepository; | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -1,8 +0,0 @@ | ||||
| class User { | ||||
|    constructor(id, title) { | ||||
|       this.id = id; | ||||
|       this.title = title; | ||||
|    } | ||||
| } | ||||
|  | ||||
| module.exports = User; | ||||
| @@ -1,84 +0,0 @@ | ||||
| const assert = require('assert'); | ||||
| const http = require('http'); | ||||
| const { URL } = require('url'); | ||||
| const PythonShell = require('python-shell'); | ||||
|  | ||||
| const establishedDatabase = require('src/database/database'); | ||||
|  | ||||
| function getMagnetFromURL(url) { | ||||
|    return new Promise((resolve, reject) => { | ||||
|       const options = new URL(url); | ||||
|       if (options.protocol.includes('magnet')) | ||||
|          resolve(url) | ||||
|  | ||||
|       http.get(options, (res) => { | ||||
|          if (res.statusCode == 301 || res.statusCode == 302) { | ||||
|             resolve(res.headers.location) | ||||
|          } | ||||
|       }); | ||||
|    }); | ||||
| } | ||||
|  | ||||
| async function find(searchterm, callback) { | ||||
|    const options = { | ||||
|       pythonPath: '../torrent_search/env/bin/python3', | ||||
|       scriptPath: '../torrent_search', | ||||
|       args: [searchterm, '-s', 'jackett', '-f', '--print'] | ||||
|    } | ||||
|  | ||||
|    PythonShell.run('torrentSearch/search.py', options, callback); | ||||
|    // PythonShell does not support return | ||||
| } | ||||
|  | ||||
|  | ||||
| async function callPythonAddMagnet(url, callback) { | ||||
|    getMagnetFromURL(url) | ||||
|    .then((magnet) => { | ||||
|       const options = { | ||||
|         pythonPath: '../delugeClient/env/bin/python3', | ||||
|         scriptPath: '../delugeClient', | ||||
|         args: ['add', magnet] | ||||
|       }; | ||||
|  | ||||
|       PythonShell.run('deluge_cli.py', options, callback); | ||||
|    }) | ||||
|    .catch((err) => { | ||||
|       console.log(err); | ||||
|       throw new Error(err); | ||||
|    }) | ||||
| } | ||||
|  | ||||
| async function SearchPiratebay(query) { | ||||
|    return await new Promise((resolve, reject) => find(query, (err, results) => { | ||||
|       if (err) { | ||||
|          console.log('THERE WAS A FUCKING ERROR!\n', err); | ||||
|          reject(Error('There was a error when searching for torrents')); | ||||
|       } | ||||
|       if (results) { | ||||
|          resolve(JSON.parse(results, null, '\t')); | ||||
|       } | ||||
|    })); | ||||
| } | ||||
|  | ||||
| async function AddMagnet(magnet, name, tmdb_id) { | ||||
|    return await new Promise((resolve, reject) => callPythonAddMagnet(magnet, (err, results) => { | ||||
|       if (err) { | ||||
|          /* eslint-disable no-console */ | ||||
|          console.log(err); | ||||
|          reject(Error('Enable to add torrent', err))  | ||||
|       } | ||||
|       /* eslint-disable no-console */ | ||||
|       console.log('result/error:', err, results); | ||||
|  | ||||
|       database = establishedDatabase; | ||||
|       insert_query = "INSERT INTO requested_torrent(magnet,torrent_name,tmdb_id) \ | ||||
|          VALUES (?,?,?)"; | ||||
|  | ||||
|       let response = database.run(insert_query, [magnet, name, tmdb_id]); | ||||
|       console.log('Response from requsted_torrent insert: ' + response); | ||||
|  | ||||
|       resolve({ success: true }); | ||||
|    })); | ||||
| } | ||||
|  | ||||
| module.exports = { SearchPiratebay, AddMagnet }; | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user