build(deps): bump dependencies (#2796)
This commit is contained in:
committed by
GitHub
parent
821bb79d83
commit
0fa84eae8d
101
package.json
101
package.json
@@ -10,9 +10,9 @@
|
|||||||
"lint": "eslint \"./server/**/*.{ts,tsx}\" \"./src/**/*.{ts,tsx}\" --cache",
|
"lint": "eslint \"./server/**/*.{ts,tsx}\" \"./src/**/*.{ts,tsx}\" --cache",
|
||||||
"start": "NODE_ENV=production node dist/index.js",
|
"start": "NODE_ENV=production node dist/index.js",
|
||||||
"i18n:extract": "extract-messages -l=en -o src/i18n/locale -d en --flat true --overwriteDefault true \"./src/**/!(*.test).{ts,tsx}\"",
|
"i18n:extract": "extract-messages -l=en -o src/i18n/locale -d en --flat true --overwriteDefault true \"./src/**/!(*.test).{ts,tsx}\"",
|
||||||
"migration:generate": "ts-node --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:generate",
|
"migration:generate": "ts-node --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:generate -d server/datasource.ts",
|
||||||
"migration:create": "ts-node --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:create",
|
"migration:create": "ts-node --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:create -d server/datasource.ts",
|
||||||
"migration:run": "ts-node --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:run",
|
"migration:run": "ts-node --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:run -d server/datasource.ts",
|
||||||
"format": "prettier --loglevel warn --write --cache .",
|
"format": "prettier --loglevel warn --write --cache .",
|
||||||
"format:check": "prettier --check --cache .",
|
"format:check": "prettier --check --cache .",
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
@@ -26,86 +26,87 @@
|
|||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.5.0",
|
"@headlessui/react": "^1.6.4",
|
||||||
"@heroicons/react": "^1.0.6",
|
"@heroicons/react": "^1.0.6",
|
||||||
"@supercharge/request-ip": "^1.2.0",
|
"@supercharge/request-ip": "^1.2.0",
|
||||||
"@svgr/webpack": "^6.2.1",
|
"@svgr/webpack": "^6.2.1",
|
||||||
"@tanem/react-nprogress": "^4.0.10",
|
"@tanem/react-nprogress": "^5.0.0",
|
||||||
"ace-builds": "^1.4.14",
|
"ace-builds": "^1.5.2",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.27.2",
|
||||||
"axios-rate-limit": "^1.3.0",
|
"axios-rate-limit": "^1.3.0",
|
||||||
"bcrypt": "^5.0.1",
|
"bcrypt": "^5.0.1",
|
||||||
"bowser": "^2.11.0",
|
"bowser": "^2.11.0",
|
||||||
"connect-typeorm": "^1.1.4",
|
"connect-typeorm": "^1.1.4",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"copy-to-clipboard": "^3.3.1",
|
"copy-to-clipboard": "^3.3.1",
|
||||||
"country-flag-icons": "^1.4.21",
|
"country-flag-icons": "^1.5.4",
|
||||||
"csurf": "^1.11.0",
|
"csurf": "^1.11.0",
|
||||||
"email-templates": "^8.0.10",
|
"date-fns": "^2.28.0",
|
||||||
"express": "^4.17.3",
|
"email-templates": "^9.0.0",
|
||||||
"express-openapi-validator": "^4.13.6",
|
"express": "^4.18.1",
|
||||||
"express-rate-limit": "^6.3.0",
|
"express-openapi-validator": "^4.13.8",
|
||||||
"express-session": "^1.17.2",
|
"express-rate-limit": "^6.4.0",
|
||||||
|
"express-session": "^1.17.3",
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
"gravatar-url": "^3.1.0",
|
"gravatar-url": "3.1.0",
|
||||||
"intl": "^1.2.5",
|
"intl": "^1.2.5",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"next": "12.1.0",
|
"next": "12.1.0",
|
||||||
"node-cache": "^5.1.2",
|
"node-cache": "^5.1.2",
|
||||||
"node-gyp": "^9.0.0",
|
"node-gyp": "^9.0.0",
|
||||||
"node-schedule": "^2.1.0",
|
"node-schedule": "^2.1.0",
|
||||||
"nodemailer": "^6.7.2",
|
"nodemailer": "^6.7.5",
|
||||||
"openpgp": "^5.2.0",
|
"openpgp": "^5.2.1",
|
||||||
"plex-api": "^5.3.2",
|
"plex-api": "^5.3.2",
|
||||||
"pug": "^3.0.2",
|
"pug": "^3.0.2",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-ace": "^9.5.0",
|
"react-ace": "^10.1.0",
|
||||||
"react-animate-height": "^2.0.23",
|
"react-animate-height": "^2.1.2",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"react-intersection-observer": "^8.33.1",
|
"react-intersection-observer": "^9.2.0",
|
||||||
"react-intl": "5.24.7",
|
"react-intl": "^5.25.1",
|
||||||
"react-markdown": "^8.0.0",
|
"react-markdown": "^8.0.3",
|
||||||
"react-select": "^5.2.2",
|
"react-select": "^5.3.2",
|
||||||
"react-spring": "^9.4.4",
|
"react-spring": "^9.4.5",
|
||||||
"react-toast-notifications": "^2.5.1",
|
"react-toast-notifications": "^2.5.1",
|
||||||
"react-transition-group": "^4.4.2",
|
"react-transition-group": "^4.4.2",
|
||||||
"react-truncate-markup": "^5.1.0",
|
"react-truncate-markup": "^5.1.0",
|
||||||
"react-use-clipboard": "1.0.7",
|
"react-use-clipboard": "1.0.8",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"secure-random-password": "^0.2.3",
|
"secure-random-password": "^0.2.3",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.7",
|
||||||
"sqlite3": "^5.0.2",
|
"sqlite3": "^5.0.8",
|
||||||
"swagger-ui-express": "^4.3.0",
|
"swagger-ui-express": "^4.4.0",
|
||||||
"swr": "^1.2.2",
|
"swr": "^1.3.0",
|
||||||
"typeorm": "0.2.45",
|
"typeorm": "0.3.6",
|
||||||
"web-push": "^3.4.5",
|
"web-push": "^3.5.0",
|
||||||
"winston": "^3.6.0",
|
"winston": "^3.7.2",
|
||||||
"winston-daily-rotate-file": "^4.6.1",
|
"winston-daily-rotate-file": "^4.6.1",
|
||||||
"xml2js": "^0.4.23",
|
"xml2js": "^0.4.23",
|
||||||
"yamljs": "^0.3.0",
|
"yamljs": "^0.3.0",
|
||||||
"yup": "^0.32.11"
|
"yup": "^0.32.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.17.6",
|
"@babel/cli": "^7.17.10",
|
||||||
"@commitlint/cli": "^16.2.1",
|
"@commitlint/cli": "^17.0.1",
|
||||||
"@commitlint/config-conventional": "^16.2.1",
|
"@commitlint/config-conventional": "^17.0.0",
|
||||||
"@semantic-release/changelog": "^6.0.1",
|
"@semantic-release/changelog": "^6.0.1",
|
||||||
"@semantic-release/commit-analyzer": "^9.0.2",
|
"@semantic-release/commit-analyzer": "^9.0.2",
|
||||||
"@semantic-release/exec": "^6.0.3",
|
"@semantic-release/exec": "^6.0.3",
|
||||||
"@semantic-release/git": "^10.0.1",
|
"@semantic-release/git": "^10.0.1",
|
||||||
"@tailwindcss/aspect-ratio": "^0.4.0",
|
"@tailwindcss/aspect-ratio": "^0.4.0",
|
||||||
"@tailwindcss/forms": "^0.5.0",
|
"@tailwindcss/forms": "^0.5.2",
|
||||||
"@tailwindcss/typography": "^0.5.2",
|
"@tailwindcss/typography": "^0.5.2",
|
||||||
"@types/bcrypt": "^5.0.0",
|
"@types/bcrypt": "^5.0.0",
|
||||||
"@types/cookie-parser": "^1.4.2",
|
"@types/cookie-parser": "^1.4.3",
|
||||||
"@types/country-flag-icons": "^1.2.0",
|
"@types/country-flag-icons": "^1.2.0",
|
||||||
"@types/csurf": "^1.11.2",
|
"@types/csurf": "^1.11.2",
|
||||||
"@types/email-templates": "^8.0.4",
|
"@types/email-templates": "^8.0.4",
|
||||||
"@types/express": "^4.17.13",
|
"@types/express": "^4.17.13",
|
||||||
"@types/express-session": "^1.17.4",
|
"@types/express-session": "^1.17.4",
|
||||||
"@types/lodash": "^4.14.179",
|
"@types/lodash": "^4.14.182",
|
||||||
"@types/node": "^17.0.21",
|
"@types/node": "^17.0.36",
|
||||||
"@types/node-schedule": "^1.3.2",
|
"@types/node-schedule": "^2.1.0",
|
||||||
"@types/nodemailer": "^6.4.4",
|
"@types/nodemailer": "^6.4.4",
|
||||||
"@types/react": "^17.0.40",
|
"@types/react": "^17.0.40",
|
||||||
"@types/react-dom": "^17.0.13",
|
"@types/react-dom": "^17.0.13",
|
||||||
@@ -114,12 +115,12 @@
|
|||||||
"@types/semver": "^7.3.9",
|
"@types/semver": "^7.3.9",
|
||||||
"@types/swagger-ui-express": "^4.1.3",
|
"@types/swagger-ui-express": "^4.1.3",
|
||||||
"@types/web-push": "^3.3.2",
|
"@types/web-push": "^3.3.2",
|
||||||
"@types/xml2js": "^0.4.9",
|
"@types/xml2js": "^0.4.11",
|
||||||
"@types/yamljs": "^0.2.31",
|
"@types/yamljs": "^0.2.31",
|
||||||
"@types/yup": "^0.29.13",
|
"@types/yup": "^0.29.14",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.14.0",
|
"@typescript-eslint/eslint-plugin": "^5.27.0",
|
||||||
"@typescript-eslint/parser": "^5.14.0",
|
"@typescript-eslint/parser": "^5.27.0",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.7",
|
||||||
"babel-plugin-react-intl": "^8.2.25",
|
"babel-plugin-react-intl": "^8.2.25",
|
||||||
"babel-plugin-react-intl-auto": "^3.3.0",
|
"babel-plugin-react-intl-auto": "^3.3.0",
|
||||||
"commitizen": "^4.2.4",
|
"commitizen": "^4.2.4",
|
||||||
@@ -133,19 +134,19 @@
|
|||||||
"eslint-plugin-jsx-a11y": "^6.6.1",
|
"eslint-plugin-jsx-a11y": "^6.6.1",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"eslint-plugin-react": "^7.30.1",
|
"eslint-plugin-react": "^7.30.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.5.0",
|
||||||
"extract-react-intl-messages": "^4.1.1",
|
"extract-react-intl-messages": "^4.1.1",
|
||||||
"husky": "^7.0.4",
|
"husky": "^8.0.1",
|
||||||
"lint-staged": "^12.3.5",
|
"lint-staged": "^12.4.3",
|
||||||
"nodemon": "^2.0.15",
|
"nodemon": "^2.0.16",
|
||||||
"postcss": "^8.4.8",
|
"postcss": "^8.4.14",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"prettier-plugin-organize-imports": "^3.0.1",
|
"prettier-plugin-organize-imports": "^3.0.1",
|
||||||
"prettier-plugin-tailwindcss": "^0.1.13",
|
"prettier-plugin-tailwindcss": "^0.1.13",
|
||||||
"semantic-release": "^19.0.2",
|
"semantic-release": "^19.0.2",
|
||||||
"semantic-release-docker-buildx": "^1.0.1",
|
"semantic-release-docker-buildx": "^1.0.1",
|
||||||
"tailwindcss": "^3.1.7",
|
"tailwindcss": "^3.1.7",
|
||||||
"ts-node": "^10.7.0",
|
"ts-node": "^10.8.0",
|
||||||
"typescript": "^4.7.4"
|
"typescript": "^4.7.4"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
const devConfig = {
|
import 'reflect-metadata';
|
||||||
|
import type { DataSourceOptions, EntityTarget, Repository } from 'typeorm';
|
||||||
|
import { DataSource } from 'typeorm';
|
||||||
|
|
||||||
|
const devConfig: DataSourceOptions = {
|
||||||
type: 'sqlite',
|
type: 'sqlite',
|
||||||
database: process.env.CONFIG_DIRECTORY
|
database: process.env.CONFIG_DIRECTORY
|
||||||
? `${process.env.CONFIG_DIRECTORY}/db/db.sqlite3`
|
? `${process.env.CONFIG_DIRECTORY}/db/db.sqlite3`
|
||||||
@@ -10,31 +14,30 @@ const devConfig = {
|
|||||||
entities: ['server/entity/**/*.ts'],
|
entities: ['server/entity/**/*.ts'],
|
||||||
migrations: ['server/migration/**/*.ts'],
|
migrations: ['server/migration/**/*.ts'],
|
||||||
subscribers: ['server/subscriber/**/*.ts'],
|
subscribers: ['server/subscriber/**/*.ts'],
|
||||||
cli: {
|
|
||||||
entitiesDir: 'server/entity',
|
|
||||||
migrationsDir: 'server/migration',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const prodConfig = {
|
const prodConfig: DataSourceOptions = {
|
||||||
type: 'sqlite',
|
type: 'sqlite',
|
||||||
database: process.env.CONFIG_DIRECTORY
|
database: process.env.CONFIG_DIRECTORY
|
||||||
? `${process.env.CONFIG_DIRECTORY}/db/db.sqlite3`
|
? `${process.env.CONFIG_DIRECTORY}/db/db.sqlite3`
|
||||||
: 'config/db/db.sqlite3',
|
: 'config/db/db.sqlite3',
|
||||||
synchronize: false,
|
synchronize: false,
|
||||||
|
migrationsRun: false,
|
||||||
logging: false,
|
logging: false,
|
||||||
enableWAL: true,
|
enableWAL: true,
|
||||||
entities: ['dist/entity/**/*.js'],
|
entities: ['dist/entity/**/*.js'],
|
||||||
migrations: ['dist/migration/**/*.js'],
|
migrations: ['dist/migration/**/*.js'],
|
||||||
migrationsRun: false,
|
|
||||||
subscribers: ['dist/subscriber/**/*.js'],
|
subscribers: ['dist/subscriber/**/*.js'],
|
||||||
cli: {
|
|
||||||
entitiesDir: 'dist/entity',
|
|
||||||
migrationsDir: 'dist/migration',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const finalConfig =
|
const dataSource = new DataSource(
|
||||||
process.env.NODE_ENV !== 'production' ? devConfig : prodConfig;
|
process.env.NODE_ENV !== 'production' ? devConfig : prodConfig
|
||||||
|
);
|
||||||
|
|
||||||
module.exports = finalConfig;
|
export const getRepository = <Entity>(
|
||||||
|
target: EntityTarget<Entity>
|
||||||
|
): Repository<Entity> => {
|
||||||
|
return dataSource.getRepository(target);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default dataSource;
|
||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
Column,
|
Column,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
Entity,
|
Entity,
|
||||||
getRepository,
|
|
||||||
In,
|
In,
|
||||||
Index,
|
Index,
|
||||||
OneToMany,
|
OneToMany,
|
||||||
@@ -15,6 +14,7 @@ import SonarrAPI from '../api/servarr/sonarr';
|
|||||||
import { MediaStatus, MediaType } from '../constants/media';
|
import { MediaStatus, MediaType } from '../constants/media';
|
||||||
import type { DownloadingItem } from '../lib/downloadtracker';
|
import type { DownloadingItem } from '../lib/downloadtracker';
|
||||||
import downloadTracker from '../lib/downloadtracker';
|
import downloadTracker from '../lib/downloadtracker';
|
||||||
|
import { getRepository } from '../datasource';
|
||||||
import { getSettings } from '../lib/settings';
|
import { getSettings } from '../lib/settings';
|
||||||
import logger from '../logger';
|
import logger from '../logger';
|
||||||
import Issue from './Issue';
|
import Issue from './Issue';
|
||||||
@@ -37,7 +37,7 @@ class Media {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const media = await mediaRepository.find({
|
const media = await mediaRepository.find({
|
||||||
tmdbId: In(finalIds),
|
where: { tmdbId: In(finalIds) },
|
||||||
});
|
});
|
||||||
|
|
||||||
return media;
|
return media;
|
||||||
@@ -56,10 +56,10 @@ class Media {
|
|||||||
try {
|
try {
|
||||||
const media = await mediaRepository.findOne({
|
const media = await mediaRepository.findOne({
|
||||||
where: { tmdbId: id, mediaType },
|
where: { tmdbId: id, mediaType },
|
||||||
relations: ['requests', 'issues'],
|
relations: { requests: true, issues: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
return media;
|
return media ?? undefined;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(e.message);
|
logger.error(e.message);
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import {
|
|||||||
Column,
|
Column,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
Entity,
|
Entity,
|
||||||
getRepository,
|
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
OneToMany,
|
OneToMany,
|
||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
@@ -20,6 +19,7 @@ import SonarrAPI from '../api/servarr/sonarr';
|
|||||||
import TheMovieDb from '../api/themoviedb';
|
import TheMovieDb from '../api/themoviedb';
|
||||||
import { ANIME_KEYWORD_ID } from '../api/themoviedb/constants';
|
import { ANIME_KEYWORD_ID } from '../api/themoviedb/constants';
|
||||||
import { MediaRequestStatus, MediaStatus, MediaType } from '../constants/media';
|
import { MediaRequestStatus, MediaStatus, MediaType } from '../constants/media';
|
||||||
|
import { getRepository } from '../datasource';
|
||||||
import notificationManager, { Notification } from '../lib/notifications';
|
import notificationManager, { Notification } from '../lib/notifications';
|
||||||
import { getSettings } from '../lib/settings';
|
import { getSettings } from '../lib/settings';
|
||||||
import logger from '../logger';
|
import logger from '../logger';
|
||||||
@@ -206,7 +206,7 @@ export class MediaRequest {
|
|||||||
const mediaRepository = getRepository(Media);
|
const mediaRepository = getRepository(Media);
|
||||||
const media = await mediaRepository.findOne({
|
const media = await mediaRepository.findOne({
|
||||||
where: { id: this.media.id },
|
where: { id: this.media.id },
|
||||||
relations: ['requests'],
|
relations: { requests: true },
|
||||||
});
|
});
|
||||||
if (!media) {
|
if (!media) {
|
||||||
logger.error('Media data not found', {
|
logger.error('Media data not found', {
|
||||||
@@ -271,7 +271,7 @@ export class MediaRequest {
|
|||||||
const mediaRepository = getRepository(Media);
|
const mediaRepository = getRepository(Media);
|
||||||
const fullMedia = await mediaRepository.findOneOrFail({
|
const fullMedia = await mediaRepository.findOneOrFail({
|
||||||
where: { id: this.media.id },
|
where: { id: this.media.id },
|
||||||
relations: ['requests'],
|
relations: { requests: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -542,7 +542,7 @@ export class MediaRequest {
|
|||||||
|
|
||||||
const media = await mediaRepository.findOne({
|
const media = await mediaRepository.findOne({
|
||||||
where: { id: this.media.id },
|
where: { id: this.media.id },
|
||||||
relations: ['requests'],
|
relations: { requests: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!media) {
|
if (!media) {
|
||||||
@@ -669,7 +669,7 @@ export class MediaRequest {
|
|||||||
// We grab media again here to make sure we have the latest version of it
|
// We grab media again here to make sure we have the latest version of it
|
||||||
const media = await mediaRepository.findOne({
|
const media = await mediaRepository.findOne({
|
||||||
where: { id: this.media.id },
|
where: { id: this.media.id },
|
||||||
relations: ['requests'],
|
relations: { requests: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!media) {
|
if (!media) {
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import {
|
|||||||
Column,
|
Column,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
Entity,
|
Entity,
|
||||||
getRepository,
|
|
||||||
MoreThan,
|
|
||||||
Not,
|
Not,
|
||||||
OneToMany,
|
OneToMany,
|
||||||
OneToOne,
|
OneToOne,
|
||||||
@@ -18,12 +16,14 @@ import {
|
|||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
import { MediaRequestStatus, MediaType } from '../constants/media';
|
import { MediaRequestStatus, MediaType } from '../constants/media';
|
||||||
import { UserType } from '../constants/user';
|
import { UserType } from '../constants/user';
|
||||||
|
import { getRepository } from '../datasource';
|
||||||
import type { QuotaResponse } from '../interfaces/api/userInterfaces';
|
import type { QuotaResponse } from '../interfaces/api/userInterfaces';
|
||||||
import PreparedEmail from '../lib/email';
|
import PreparedEmail from '../lib/email';
|
||||||
import type { PermissionCheckOptions } from '../lib/permissions';
|
import type { PermissionCheckOptions } from '../lib/permissions';
|
||||||
import { hasPermission, Permission } from '../lib/permissions';
|
import { hasPermission, Permission } from '../lib/permissions';
|
||||||
import { getSettings } from '../lib/settings';
|
import { getSettings } from '../lib/settings';
|
||||||
import logger from '../logger';
|
import logger from '../logger';
|
||||||
|
import { AfterDate } from '../utils/dateHelpers';
|
||||||
import Issue from './Issue';
|
import Issue from './Issue';
|
||||||
import { MediaRequest } from './MediaRequest';
|
import { MediaRequest } from './MediaRequest';
|
||||||
import SeasonRequest from './SeasonRequest';
|
import SeasonRequest from './SeasonRequest';
|
||||||
@@ -252,13 +252,14 @@ export class User {
|
|||||||
if (movieQuotaDays) {
|
if (movieQuotaDays) {
|
||||||
movieDate.setDate(movieDate.getDate() - movieQuotaDays);
|
movieDate.setDate(movieDate.getDate() - movieQuotaDays);
|
||||||
}
|
}
|
||||||
const movieQuotaStartDate = movieDate.toJSON();
|
|
||||||
|
|
||||||
const movieQuotaUsed = movieQuotaLimit
|
const movieQuotaUsed = movieQuotaLimit
|
||||||
? await requestRepository.count({
|
? await requestRepository.count({
|
||||||
where: {
|
where: {
|
||||||
requestedBy: this,
|
requestedBy: {
|
||||||
createdAt: MoreThan(movieQuotaStartDate),
|
id: this.id,
|
||||||
|
},
|
||||||
|
createdAt: AfterDate(movieDate),
|
||||||
type: MediaType.MOVIE,
|
type: MediaType.MOVIE,
|
||||||
status: Not(MediaRequestStatus.DECLINED),
|
status: Not(MediaRequestStatus.DECLINED),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import session from 'express-session';
|
|||||||
import next from 'next';
|
import next from 'next';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import swaggerUi from 'swagger-ui-express';
|
import swaggerUi from 'swagger-ui-express';
|
||||||
import { createConnection, getRepository } from 'typeorm';
|
|
||||||
import YAML from 'yamljs';
|
import YAML from 'yamljs';
|
||||||
import PlexAPI from './api/plexapi';
|
import PlexAPI from './api/plexapi';
|
||||||
|
import dataSource, { getRepository } from './datasource';
|
||||||
import { Session } from './entity/Session';
|
import { Session } from './entity/Session';
|
||||||
import { User } from './entity/User';
|
import { User } from './entity/User';
|
||||||
import { startJobs } from './job/schedule';
|
import { startJobs } from './job/schedule';
|
||||||
@@ -43,7 +43,7 @@ const handle = app.getRequestHandler();
|
|||||||
app
|
app
|
||||||
.prepare()
|
.prepare()
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
const dbConnection = await createConnection();
|
const dbConnection = await dataSource.initialize();
|
||||||
|
|
||||||
// Run migrations in production
|
// Run migrations in production
|
||||||
if (process.env.NODE_ENV === 'production') {
|
if (process.env.NODE_ENV === 'production') {
|
||||||
@@ -63,8 +63,8 @@ app
|
|||||||
) {
|
) {
|
||||||
const userRepository = getRepository(User);
|
const userRepository = getRepository(User);
|
||||||
const admin = await userRepository.findOne({
|
const admin = await userRepository.findOne({
|
||||||
select: ['id', 'plexToken'],
|
select: { id: true, plexToken: true },
|
||||||
order: { id: 'ASC' },
|
where: { id: 1 },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (admin) {
|
if (admin) {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import {
|
import {
|
||||||
hasNotificationType,
|
hasNotificationType,
|
||||||
Notification,
|
Notification,
|
||||||
shouldSendAdminNotification,
|
shouldSendAdminNotification,
|
||||||
} from '..';
|
} from '..';
|
||||||
import { IssueStatus, IssueTypeName } from '../../../constants/issue';
|
import { IssueStatus, IssueTypeName } from '../../../constants/issue';
|
||||||
|
import { getRepository } from '../../../datasource';
|
||||||
import { User } from '../../../entity/User';
|
import { User } from '../../../entity/User';
|
||||||
import logger from '../../../logger';
|
import logger from '../../../logger';
|
||||||
import type { NotificationAgentDiscord } from '../../settings';
|
import type { NotificationAgentDiscord } from '../../settings';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { EmailOptions } from 'email-templates';
|
import type { EmailOptions } from 'email-templates';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import { Notification, shouldSendAdminNotification } from '..';
|
import { Notification, shouldSendAdminNotification } from '..';
|
||||||
import { IssueType, IssueTypeName } from '../../../constants/issue';
|
import { IssueType, IssueTypeName } from '../../../constants/issue';
|
||||||
import { MediaType } from '../../../constants/media';
|
import { MediaType } from '../../../constants/media';
|
||||||
|
import { getRepository } from '../../../datasource';
|
||||||
import { User } from '../../../entity/User';
|
import { User } from '../../../entity/User';
|
||||||
import logger from '../../../logger';
|
import logger from '../../../logger';
|
||||||
import PreparedEmail from '../../email';
|
import PreparedEmail from '../../email';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import {
|
import {
|
||||||
hasNotificationType,
|
hasNotificationType,
|
||||||
Notification,
|
Notification,
|
||||||
shouldSendAdminNotification,
|
shouldSendAdminNotification,
|
||||||
} from '..';
|
} from '..';
|
||||||
import { IssueStatus, IssueTypeName } from '../../../constants/issue';
|
import { IssueStatus, IssueTypeName } from '../../../constants/issue';
|
||||||
|
import { getRepository } from '../../../datasource';
|
||||||
import { User } from '../../../entity/User';
|
import { User } from '../../../entity/User';
|
||||||
import logger from '../../../logger';
|
import logger from '../../../logger';
|
||||||
import type { NotificationAgentPushbullet } from '../../settings';
|
import type { NotificationAgentPushbullet } from '../../settings';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import {
|
import {
|
||||||
hasNotificationType,
|
hasNotificationType,
|
||||||
Notification,
|
Notification,
|
||||||
shouldSendAdminNotification,
|
shouldSendAdminNotification,
|
||||||
} from '..';
|
} from '..';
|
||||||
import { IssueStatus, IssueTypeName } from '../../../constants/issue';
|
import { IssueStatus, IssueTypeName } from '../../../constants/issue';
|
||||||
|
import { getRepository } from '../../../datasource';
|
||||||
import { User } from '../../../entity/User';
|
import { User } from '../../../entity/User';
|
||||||
import logger from '../../../logger';
|
import logger from '../../../logger';
|
||||||
import type { NotificationAgentPushover } from '../../settings';
|
import type { NotificationAgentPushover } from '../../settings';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import {
|
import {
|
||||||
hasNotificationType,
|
hasNotificationType,
|
||||||
Notification,
|
Notification,
|
||||||
shouldSendAdminNotification,
|
shouldSendAdminNotification,
|
||||||
} from '..';
|
} from '..';
|
||||||
import { IssueStatus, IssueTypeName } from '../../../constants/issue';
|
import { IssueStatus, IssueTypeName } from '../../../constants/issue';
|
||||||
|
import { getRepository } from '../../../datasource';
|
||||||
import { User } from '../../../entity/User';
|
import { User } from '../../../entity/User';
|
||||||
import logger from '../../../logger';
|
import logger from '../../../logger';
|
||||||
import type { NotificationAgentTelegram } from '../../settings';
|
import type { NotificationAgentTelegram } from '../../settings';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { getRepository } from 'typeorm';
|
|
||||||
import webpush from 'web-push';
|
import webpush from 'web-push';
|
||||||
import { Notification, shouldSendAdminNotification } from '..';
|
import { Notification, shouldSendAdminNotification } from '..';
|
||||||
import { IssueType, IssueTypeName } from '../../../constants/issue';
|
import { IssueType, IssueTypeName } from '../../../constants/issue';
|
||||||
import { MediaType } from '../../../constants/media';
|
import { MediaType } from '../../../constants/media';
|
||||||
|
import { getRepository } from '../../../datasource';
|
||||||
import { User } from '../../../entity/User';
|
import { User } from '../../../entity/User';
|
||||||
import { UserPushSubscription } from '../../../entity/UserPushSubscription';
|
import { UserPushSubscription } from '../../../entity/UserPushSubscription';
|
||||||
import logger from '../../../logger';
|
import logger from '../../../logger';
|
||||||
@@ -158,7 +158,7 @@ class WebPushAgent
|
|||||||
true)
|
true)
|
||||||
) {
|
) {
|
||||||
const notifySubs = await userPushSubRepository.find({
|
const notifySubs = await userPushSubRepository.find({
|
||||||
where: { user: payload.notifyUser.id },
|
where: { user: { id: payload.notifyUser.id } },
|
||||||
});
|
});
|
||||||
|
|
||||||
pushSubs.push(...notifySubs);
|
pushSubs.push(...notifySubs);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import TheMovieDb from '../../api/themoviedb';
|
import TheMovieDb from '../../api/themoviedb';
|
||||||
import { MediaStatus, MediaType } from '../../constants/media';
|
import { MediaStatus, MediaType } from '../../constants/media';
|
||||||
|
import { getRepository } from '../../datasource';
|
||||||
import Media from '../../entity/Media';
|
import Media from '../../entity/Media';
|
||||||
import Season from '../../entity/Season';
|
import Season from '../../entity/Season';
|
||||||
import logger from '../../logger';
|
import logger from '../../logger';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { uniqWith } from 'lodash';
|
import { uniqWith } from 'lodash';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import animeList from '../../../api/animelist';
|
import animeList from '../../../api/animelist';
|
||||||
import type { PlexLibraryItem, PlexMetadata } from '../../../api/plexapi';
|
import type { PlexLibraryItem, PlexMetadata } from '../../../api/plexapi';
|
||||||
import PlexAPI from '../../../api/plexapi';
|
import PlexAPI from '../../../api/plexapi';
|
||||||
import type { TmdbTvDetails } from '../../../api/themoviedb/interfaces';
|
import type { TmdbTvDetails } from '../../../api/themoviedb/interfaces';
|
||||||
|
import { getRepository } from '../../../datasource';
|
||||||
import { User } from '../../../entity/User';
|
import { User } from '../../../entity/User';
|
||||||
import cacheManager from '../../cache';
|
import cacheManager from '../../cache';
|
||||||
import type { Library } from '../../settings';
|
import type { Library } from '../../settings';
|
||||||
@@ -62,8 +62,8 @@ class PlexScanner
|
|||||||
try {
|
try {
|
||||||
const userRepository = getRepository(User);
|
const userRepository = getRepository(User);
|
||||||
const admin = await userRepository.findOne({
|
const admin = await userRepository.findOne({
|
||||||
select: ['id', 'plexToken'],
|
select: { id: true, plexToken: true },
|
||||||
order: { id: 'ASC' },
|
where: { id: 1 },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!admin) {
|
if (!admin) {
|
||||||
@@ -144,7 +144,9 @@ class PlexScanner
|
|||||||
'info'
|
'info'
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.log('Scan interrupted', 'error', { errorMessage: e.message });
|
this.log('Scan interrupted', 'error', {
|
||||||
|
errorMessage: e.message,
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
this.endRun(sessionId);
|
this.endRun(sessionId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { uniqWith } from 'lodash';
|
import { uniqWith } from 'lodash';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import type { SonarrSeries } from '../../../api/servarr/sonarr';
|
import type { SonarrSeries } from '../../../api/servarr/sonarr';
|
||||||
import SonarrAPI from '../../../api/servarr/sonarr';
|
import SonarrAPI from '../../../api/servarr/sonarr';
|
||||||
import type { TmdbTvDetails } from '../../../api/themoviedb/interfaces';
|
import type { TmdbTvDetails } from '../../../api/themoviedb/interfaces';
|
||||||
|
import { getRepository } from '../../../datasource';
|
||||||
import Media from '../../../entity/Media';
|
import Media from '../../../entity/Media';
|
||||||
import type { SonarrSettings } from '../../settings';
|
import type { SonarrSettings } from '../../settings';
|
||||||
import { getSettings } from '../../settings';
|
import { getSettings } from '../../settings';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { getRepository } from 'typeorm';
|
import { getRepository } from '../datasource';
|
||||||
import { User } from '../entity/User';
|
import { User } from '../entity/User';
|
||||||
import type { Permission, PermissionCheckOptions } from '../lib/permissions';
|
import type { Permission, PermissionCheckOptions } from '../lib/permissions';
|
||||||
import { getSettings } from '../lib/settings';
|
import { getSettings } from '../lib/settings';
|
||||||
|
|
||||||
export const checkUser: Middleware = async (req, _res, next) => {
|
export const checkUser: Middleware = async (req, _res, next) => {
|
||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
let user: User | undefined;
|
let user: User | undefined | null;
|
||||||
|
|
||||||
if (req.header('X-API-Key') === settings.main.apiKey) {
|
if (req.header('X-API-Key') === settings.main.apiKey) {
|
||||||
const userRepository = getRepository(User);
|
const userRepository = getRepository(User);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import PlexTvAPI from '../api/plextv';
|
import PlexTvAPI from '../api/plextv';
|
||||||
import { UserType } from '../constants/user';
|
import { UserType } from '../constants/user';
|
||||||
|
import { getRepository } from '../datasource';
|
||||||
import { User } from '../entity/User';
|
import { User } from '../entity/User';
|
||||||
import { Permission } from '../lib/permissions';
|
import { Permission } from '../lib/permissions';
|
||||||
import { getSettings } from '../lib/settings';
|
import { getSettings } from '../lib/settings';
|
||||||
@@ -64,8 +64,8 @@ authRoutes.post('/plex', async (req, res, next) => {
|
|||||||
await userRepository.save(user);
|
await userRepository.save(user);
|
||||||
} else {
|
} else {
|
||||||
const mainUser = await userRepository.findOneOrFail({
|
const mainUser = await userRepository.findOneOrFail({
|
||||||
select: ['id', 'plexToken', 'plexId'],
|
select: { id: true, plexToken: true, plexId: true },
|
||||||
order: { id: 'ASC' },
|
where: { id: 1 },
|
||||||
});
|
});
|
||||||
const mainPlexTv = new PlexTvAPI(mainUser.plexToken ?? '');
|
const mainPlexTv = new PlexTvAPI(mainUser.plexToken ?? '');
|
||||||
|
|
||||||
@@ -204,8 +204,8 @@ authRoutes.post('/local', async (req, res, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mainUser = await userRepository.findOneOrFail({
|
const mainUser = await userRepository.findOneOrFail({
|
||||||
select: ['id', 'plexToken', 'plexId'],
|
select: { id: true, plexToken: true, plexId: true },
|
||||||
order: { id: 'ASC' },
|
where: { id: 1 },
|
||||||
});
|
});
|
||||||
const mainPlexTv = new PlexTvAPI(mainUser.plexToken ?? '');
|
const mainPlexTv = new PlexTvAPI(mainUser.plexToken ?? '');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import { IssueStatus, IssueType } from '../constants/issue';
|
import { IssueStatus, IssueType } from '../constants/issue';
|
||||||
|
import { getRepository } from '../datasource';
|
||||||
import Issue from '../entity/Issue';
|
import Issue from '../entity/Issue';
|
||||||
import IssueComment from '../entity/IssueComment';
|
import IssueComment from '../entity/IssueComment';
|
||||||
import Media from '../entity/Media';
|
import Media from '../entity/Media';
|
||||||
@@ -365,7 +365,7 @@ issueRoutes.delete(
|
|||||||
try {
|
try {
|
||||||
const issue = await issueRepository.findOneOrFail({
|
const issue = await issueRepository.findOneOrFail({
|
||||||
where: { id: Number(req.params.issueId) },
|
where: { id: Number(req.params.issueId) },
|
||||||
relations: ['createdBy'],
|
relations: { createdBy: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import { getRepository } from 'typeorm';
|
import { getRepository } from '../datasource';
|
||||||
import IssueComment from '../entity/IssueComment';
|
import IssueComment from '../entity/IssueComment';
|
||||||
import { Permission } from '../lib/permissions';
|
import { Permission } from '../lib/permissions';
|
||||||
import logger from '../logger';
|
import logger from '../logger';
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import type { FindOneOptions, FindOperator } from 'typeorm';
|
import type { FindOneOptions } from 'typeorm';
|
||||||
import { getRepository, In } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
import TautulliAPI from '../api/tautulli';
|
import TautulliAPI from '../api/tautulli';
|
||||||
import { MediaStatus, MediaType } from '../constants/media';
|
import { MediaStatus, MediaType } from '../constants/media';
|
||||||
|
import { getRepository } from '../datasource';
|
||||||
import Media from '../entity/Media';
|
import Media from '../entity/Media';
|
||||||
import { User } from '../entity/User';
|
import { User } from '../entity/User';
|
||||||
import type {
|
import type {
|
||||||
@@ -22,8 +23,7 @@ mediaRoutes.get('/', async (req, res, next) => {
|
|||||||
const pageSize = req.query.take ? Number(req.query.take) : 20;
|
const pageSize = req.query.take ? Number(req.query.take) : 20;
|
||||||
const skip = req.query.skip ? Number(req.query.skip) : 0;
|
const skip = req.query.skip ? Number(req.query.skip) : 0;
|
||||||
|
|
||||||
let statusFilter: MediaStatus | FindOperator<MediaStatus> | undefined =
|
let statusFilter = undefined;
|
||||||
undefined;
|
|
||||||
|
|
||||||
switch (req.query.filter) {
|
switch (req.query.filter) {
|
||||||
case 'available':
|
case 'available':
|
||||||
@@ -152,7 +152,7 @@ mediaRoutes.delete(
|
|||||||
const mediaRepository = getRepository(Media);
|
const mediaRepository = getRepository(Media);
|
||||||
|
|
||||||
const media = await mediaRepository.findOneOrFail({
|
const media = await mediaRepository.findOneOrFail({
|
||||||
where: { id: req.params.id },
|
where: { id: Number(req.params.id) },
|
||||||
});
|
});
|
||||||
|
|
||||||
await mediaRepository.remove(media);
|
await mediaRepository.remove(media);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import TheMovieDb from '../api/themoviedb';
|
import TheMovieDb from '../api/themoviedb';
|
||||||
import { MediaRequestStatus, MediaStatus, MediaType } from '../constants/media';
|
import { MediaRequestStatus, MediaStatus, MediaType } from '../constants/media';
|
||||||
|
import { getRepository } from '../datasource';
|
||||||
import Media from '../entity/Media';
|
import Media from '../entity/Media';
|
||||||
import { MediaRequest } from '../entity/MediaRequest';
|
import { MediaRequest } from '../entity/MediaRequest';
|
||||||
import SeasonRequest from '../entity/SeasonRequest';
|
import SeasonRequest from '../entity/SeasonRequest';
|
||||||
@@ -232,7 +232,7 @@ requestRoutes.post('/', async (req, res, next) => {
|
|||||||
|
|
||||||
let media = await mediaRepository.findOne({
|
let media = await mediaRepository.findOne({
|
||||||
where: { tmdbId: req.body.mediaId, mediaType: req.body.mediaType },
|
where: { tmdbId: req.body.mediaId, mediaType: req.body.mediaType },
|
||||||
relations: ['requests'],
|
relations: { requests: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!media) {
|
if (!media) {
|
||||||
@@ -528,7 +528,7 @@ requestRoutes.get('/:requestId', async (req, res, next) => {
|
|||||||
try {
|
try {
|
||||||
const request = await requestRepository.findOneOrFail({
|
const request = await requestRepository.findOneOrFail({
|
||||||
where: { id: Number(req.params.requestId) },
|
where: { id: Number(req.params.requestId) },
|
||||||
relations: ['requestedBy', 'modifiedBy'],
|
relations: { requestedBy: true, modifiedBy: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -560,9 +560,11 @@ requestRoutes.put<{ requestId: string }>(
|
|||||||
const requestRepository = getRepository(MediaRequest);
|
const requestRepository = getRepository(MediaRequest);
|
||||||
const userRepository = getRepository(User);
|
const userRepository = getRepository(User);
|
||||||
try {
|
try {
|
||||||
const request = await requestRepository.findOne(
|
const request = await requestRepository.findOne({
|
||||||
Number(req.params.requestId)
|
where: {
|
||||||
);
|
id: Number(req.params.requestId),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!request) {
|
if (!request) {
|
||||||
return next({ status: 404, message: 'Request not found.' });
|
return next({ status: 404, message: 'Request not found.' });
|
||||||
@@ -628,7 +630,7 @@ requestRoutes.put<{ requestId: string }>(
|
|||||||
// Get existing media so we can work with all the requests
|
// Get existing media so we can work with all the requests
|
||||||
const media = await mediaRepository.findOneOrFail({
|
const media = await mediaRepository.findOneOrFail({
|
||||||
where: { tmdbId: request.media.tmdbId, mediaType: MediaType.TV },
|
where: { tmdbId: request.media.tmdbId, mediaType: MediaType.TV },
|
||||||
relations: ['requests'],
|
relations: { requests: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get all requested seasons that are not part of this request we are editing
|
// Get all requested seasons that are not part of this request we are editing
|
||||||
@@ -698,7 +700,7 @@ requestRoutes.delete('/:requestId', async (req, res, next) => {
|
|||||||
try {
|
try {
|
||||||
const request = await requestRepository.findOneOrFail({
|
const request = await requestRepository.findOneOrFail({
|
||||||
where: { id: Number(req.params.requestId) },
|
where: { id: Number(req.params.requestId) },
|
||||||
relations: ['requestedBy', 'modifiedBy'],
|
relations: { requestedBy: true, modifiedBy: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -735,7 +737,7 @@ requestRoutes.post<{
|
|||||||
try {
|
try {
|
||||||
const request = await requestRepository.findOneOrFail({
|
const request = await requestRepository.findOneOrFail({
|
||||||
where: { id: Number(req.params.requestId) },
|
where: { id: Number(req.params.requestId) },
|
||||||
relations: ['requestedBy', 'modifiedBy'],
|
relations: { requestedBy: true, modifiedBy: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
await request.updateParentStatus();
|
await request.updateParentStatus();
|
||||||
@@ -763,7 +765,7 @@ requestRoutes.post<{
|
|||||||
try {
|
try {
|
||||||
const request = await requestRepository.findOneOrFail({
|
const request = await requestRepository.findOneOrFail({
|
||||||
where: { id: Number(req.params.requestId) },
|
where: { id: Number(req.params.requestId) },
|
||||||
relations: ['requestedBy', 'modifiedBy'],
|
relations: { requestedBy: true, modifiedBy: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
let newStatus: MediaRequestStatus;
|
let newStatus: MediaRequestStatus;
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import { merge, omit, set, sortBy } from 'lodash';
|
|||||||
import { rescheduleJob } from 'node-schedule';
|
import { rescheduleJob } from 'node-schedule';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
import PlexAPI from '../../api/plexapi';
|
import PlexAPI from '../../api/plexapi';
|
||||||
import PlexTvAPI from '../../api/plextv';
|
import PlexTvAPI from '../../api/plextv';
|
||||||
import TautulliAPI from '../../api/tautulli';
|
import TautulliAPI from '../../api/tautulli';
|
||||||
|
import { getRepository } from '../../datasource';
|
||||||
import Media from '../../entity/Media';
|
import Media from '../../entity/Media';
|
||||||
import { MediaRequest } from '../../entity/MediaRequest';
|
import { MediaRequest } from '../../entity/MediaRequest';
|
||||||
import { User } from '../../entity/User';
|
import { User } from '../../entity/User';
|
||||||
@@ -93,8 +93,8 @@ settingsRoutes.post('/plex', async (req, res, next) => {
|
|||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
try {
|
try {
|
||||||
const admin = await userRepository.findOneOrFail({
|
const admin = await userRepository.findOneOrFail({
|
||||||
select: ['id', 'plexToken'],
|
select: { id: true, plexToken: true },
|
||||||
order: { id: 'ASC' },
|
where: { id: 1 },
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.assign(settings.plex, req.body);
|
Object.assign(settings.plex, req.body);
|
||||||
@@ -129,8 +129,8 @@ settingsRoutes.get('/plex/devices/servers', async (req, res, next) => {
|
|||||||
const userRepository = getRepository(User);
|
const userRepository = getRepository(User);
|
||||||
try {
|
try {
|
||||||
const admin = await userRepository.findOneOrFail({
|
const admin = await userRepository.findOneOrFail({
|
||||||
select: ['id', 'plexToken'],
|
select: { id: true, plexToken: true },
|
||||||
order: { id: 'ASC' },
|
where: { id: 1 },
|
||||||
});
|
});
|
||||||
const plexTvClient = admin.plexToken
|
const plexTvClient = admin.plexToken
|
||||||
? new PlexTvAPI(admin.plexToken)
|
? new PlexTvAPI(admin.plexToken)
|
||||||
@@ -208,8 +208,8 @@ settingsRoutes.get('/plex/library', async (req, res) => {
|
|||||||
if (req.query.sync) {
|
if (req.query.sync) {
|
||||||
const userRepository = getRepository(User);
|
const userRepository = getRepository(User);
|
||||||
const admin = await userRepository.findOneOrFail({
|
const admin = await userRepository.findOneOrFail({
|
||||||
select: ['id', 'plexToken'],
|
select: { id: true, plexToken: true },
|
||||||
order: { id: 'ASC' },
|
where: { id: 1 },
|
||||||
});
|
});
|
||||||
const plexapi = new PlexAPI({ plexToken: admin.plexToken });
|
const plexapi = new PlexAPI({ plexToken: admin.plexToken });
|
||||||
|
|
||||||
@@ -284,8 +284,8 @@ settingsRoutes.get(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const admin = await userRepository.findOneOrFail({
|
const admin = await userRepository.findOneOrFail({
|
||||||
select: ['id', 'plexToken'],
|
select: { id: true, plexToken: true },
|
||||||
order: { id: 'ASC' },
|
where: { id: 1 },
|
||||||
});
|
});
|
||||||
const plexApi = new PlexTvAPI(admin.plexToken ?? '');
|
const plexApi = new PlexTvAPI(admin.plexToken ?? '');
|
||||||
const plexUsers = (await plexApi.getUsers()).MediaContainer.User.map(
|
const plexUsers = (await plexApi.getUsers()).MediaContainer.User.map(
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import gravatarUrl from 'gravatar-url';
|
import gravatarUrl from 'gravatar-url';
|
||||||
import { findIndex, sortBy } from 'lodash';
|
import { findIndex, sortBy } from 'lodash';
|
||||||
import { getRepository, In, Not } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
import PlexTvAPI from '../../api/plextv';
|
import PlexTvAPI from '../../api/plextv';
|
||||||
import TautulliAPI from '../../api/tautulli';
|
import TautulliAPI from '../../api/tautulli';
|
||||||
import { MediaType } from '../../constants/media';
|
import { MediaType } from '../../constants/media';
|
||||||
import { UserType } from '../../constants/user';
|
import { UserType } from '../../constants/user';
|
||||||
|
import { getRepository } from '../../datasource';
|
||||||
import Media from '../../entity/Media';
|
import Media from '../../entity/Media';
|
||||||
import { MediaRequest } from '../../entity/MediaRequest';
|
import { MediaRequest } from '../../entity/MediaRequest';
|
||||||
import { User } from '../../entity/User';
|
import { User } from '../../entity/User';
|
||||||
@@ -277,8 +278,12 @@ router.put<
|
|||||||
|
|
||||||
const userRepository = getRepository(User);
|
const userRepository = getRepository(User);
|
||||||
|
|
||||||
const users = await userRepository.findByIds(req.body.ids, {
|
const users: User[] = await userRepository.find({
|
||||||
...(!isOwner ? { id: Not(1) } : {}),
|
where: {
|
||||||
|
id: In(
|
||||||
|
isOwner ? req.body.ids : req.body.ids.filter((id) => Number(id) !== 1)
|
||||||
|
),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const updatedUsers = await Promise.all(
|
const updatedUsers = await Promise.all(
|
||||||
@@ -345,7 +350,7 @@ router.delete<{ id: string }>(
|
|||||||
|
|
||||||
const user = await userRepository.findOne({
|
const user = await userRepository.findOne({
|
||||||
where: { id: Number(req.params.id) },
|
where: { id: Number(req.params.id) },
|
||||||
relations: ['requests'],
|
relations: { requests: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@@ -404,8 +409,8 @@ router.post(
|
|||||||
|
|
||||||
// taken from auth.ts
|
// taken from auth.ts
|
||||||
const mainUser = await userRepository.findOneOrFail({
|
const mainUser = await userRepository.findOneOrFail({
|
||||||
select: ['id', 'plexToken'],
|
select: { id: true, plexToken: true },
|
||||||
order: { id: 'ASC' },
|
where: { id: 1 },
|
||||||
});
|
});
|
||||||
const mainPlexTv = new PlexTvAPI(mainUser.plexToken ?? '');
|
const mainPlexTv = new PlexTvAPI(mainUser.plexToken ?? '');
|
||||||
|
|
||||||
@@ -519,7 +524,7 @@ router.get<{ id: string }, UserWatchDataResponse>(
|
|||||||
try {
|
try {
|
||||||
const user = await getRepository(User).findOneOrFail({
|
const user = await getRepository(User).findOneOrFail({
|
||||||
where: { id: Number(req.params.id) },
|
where: { id: Number(req.params.id) },
|
||||||
select: ['id', 'plexId'],
|
select: { id: true, plexId: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
const tautulli = new TautulliAPI(settings);
|
const tautulli = new TautulliAPI(settings);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import { getRepository } from 'typeorm';
|
|
||||||
import { canMakePermissionsChange } from '.';
|
import { canMakePermissionsChange } from '.';
|
||||||
|
import { getRepository } from '../../datasource';
|
||||||
import { User } from '../../entity/User';
|
import { User } from '../../entity/User';
|
||||||
import { UserSettings } from '../../entity/UserSettings';
|
import { UserSettings } from '../../entity/UserSettings';
|
||||||
import type {
|
import type {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { createConnection, getRepository } from 'typeorm';
|
|
||||||
import { copyFileSync } from 'fs';
|
import { copyFileSync } from 'fs';
|
||||||
import { UserType } from '../constants/user';
|
import { UserType } from '../constants/user';
|
||||||
import { User } from '../entity/User';
|
import { User } from '../entity/User';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import dataSource, { getRepository } from '../datasource';
|
||||||
|
|
||||||
const prepareDb = async () => {
|
const prepareDb = async () => {
|
||||||
// Copy over test settings.json
|
// Copy over test settings.json
|
||||||
@@ -12,7 +12,7 @@ const prepareDb = async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Connect to DB and seed test data
|
// Connect to DB and seed test data
|
||||||
const dbConnection = await createConnection();
|
const dbConnection = await dataSource.initialize();
|
||||||
|
|
||||||
await dbConnection.dropDatabase();
|
await dbConnection.dropDatabase();
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { sortBy } from 'lodash';
|
import { sortBy } from 'lodash';
|
||||||
import type { EntitySubscriberInterface, InsertEvent } from 'typeorm';
|
import type { EntitySubscriberInterface, InsertEvent } from 'typeorm';
|
||||||
import { EventSubscriber, getRepository } from 'typeorm';
|
import { EventSubscriber } from 'typeorm';
|
||||||
import TheMovieDb from '../api/themoviedb';
|
import TheMovieDb from '../api/themoviedb';
|
||||||
import { IssueType, IssueTypeName } from '../constants/issue';
|
import { IssueType, IssueTypeName } from '../constants/issue';
|
||||||
import { MediaType } from '../constants/media';
|
import { MediaType } from '../constants/media';
|
||||||
|
import { getRepository } from '../datasource';
|
||||||
import IssueComment from '../entity/IssueComment';
|
import IssueComment from '../entity/IssueComment';
|
||||||
import Media from '../entity/Media';
|
import Media from '../entity/Media';
|
||||||
import notificationManager, { Notification } from '../lib/notifications';
|
import notificationManager, { Notification } from '../lib/notifications';
|
||||||
@@ -27,7 +28,7 @@ export class IssueCommentSubscriber
|
|||||||
const issue = (
|
const issue = (
|
||||||
await getRepository(IssueComment).findOneOrFail({
|
await getRepository(IssueComment).findOneOrFail({
|
||||||
where: { id: entity.id },
|
where: { id: entity.id },
|
||||||
relations: ['issue'],
|
relations: { issue: true },
|
||||||
})
|
})
|
||||||
).issue;
|
).issue;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { truncate } from 'lodash';
|
import { truncate } from 'lodash';
|
||||||
import type { EntitySubscriberInterface, UpdateEvent } from 'typeorm';
|
import type { EntitySubscriberInterface, UpdateEvent } from 'typeorm';
|
||||||
import { EventSubscriber, getRepository, Not } from 'typeorm';
|
import { EventSubscriber, In, Not } from 'typeorm';
|
||||||
import TheMovieDb from '../api/themoviedb';
|
import TheMovieDb from '../api/themoviedb';
|
||||||
import { MediaRequestStatus, MediaStatus, MediaType } from '../constants/media';
|
import { MediaRequestStatus, MediaStatus, MediaType } from '../constants/media';
|
||||||
|
import { getRepository } from '../datasource';
|
||||||
import Media from '../entity/Media';
|
import Media from '../entity/Media';
|
||||||
import { MediaRequest } from '../entity/MediaRequest';
|
import { MediaRequest } from '../entity/MediaRequest';
|
||||||
import Season from '../entity/Season';
|
import Season from '../entity/Season';
|
||||||
@@ -24,7 +25,9 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
|
|||||||
const requestRepository = getRepository(MediaRequest);
|
const requestRepository = getRepository(MediaRequest);
|
||||||
const relatedRequests = await requestRepository.find({
|
const relatedRequests = await requestRepository.find({
|
||||||
where: {
|
where: {
|
||||||
media: entity,
|
media: {
|
||||||
|
id: entity.id,
|
||||||
|
},
|
||||||
is4k,
|
is4k,
|
||||||
status: Not(MediaRequestStatus.DECLINED),
|
status: Not(MediaRequestStatus.DECLINED),
|
||||||
},
|
},
|
||||||
@@ -84,7 +87,7 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
|
|||||||
)
|
)
|
||||||
.map((season) => season.seasonNumber);
|
.map((season) => season.seasonNumber);
|
||||||
const oldSeasonIds = dbEntity.seasons.map((season) => season.id);
|
const oldSeasonIds = dbEntity.seasons.map((season) => season.id);
|
||||||
const oldSeasons = await seasonRepository.findByIds(oldSeasonIds);
|
const oldSeasons = await seasonRepository.findBy({ id: In(oldSeasonIds) });
|
||||||
const oldAvailableSeasons = oldSeasons
|
const oldAvailableSeasons = oldSeasons
|
||||||
.filter(
|
.filter(
|
||||||
(season) =>
|
(season) =>
|
||||||
@@ -104,7 +107,9 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
|
|||||||
for (const changedSeasonNumber of changedSeasons) {
|
for (const changedSeasonNumber of changedSeasons) {
|
||||||
const requests = await requestRepository.find({
|
const requests = await requestRepository.find({
|
||||||
where: {
|
where: {
|
||||||
media: entity,
|
media: {
|
||||||
|
id: entity.id,
|
||||||
|
},
|
||||||
is4k,
|
is4k,
|
||||||
status: Not(MediaRequestStatus.DECLINED),
|
status: Not(MediaRequestStatus.DECLINED),
|
||||||
},
|
},
|
||||||
@@ -167,7 +172,7 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
|
|||||||
const requestRepository = getRepository(MediaRequest);
|
const requestRepository = getRepository(MediaRequest);
|
||||||
|
|
||||||
const requests = await requestRepository.find({
|
const requests = await requestRepository.find({
|
||||||
where: { media: event.id },
|
where: { media: { id: event.id } },
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const request of requests) {
|
for (const request of requests) {
|
||||||
|
|||||||
4
server/utils/dateHelpers.ts
Normal file
4
server/utils/dateHelpers.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { addYears } from 'date-fns';
|
||||||
|
import { Between } from 'typeorm';
|
||||||
|
|
||||||
|
export const AfterDate = (date: Date) => Between(date, addYears(date, 100));
|
||||||
Reference in New Issue
Block a user