From 0916b58594a00db98c6701fdcaee4f3c3e08904e Mon Sep 17 00:00:00 2001 From: sct Date: Mon, 21 Dec 2020 01:40:23 +0900 Subject: [PATCH] fix(notifications): always update the media table when seasons become available --- ormconfig.js | 3 +- server/entity/Media.ts | 3 ++ server/index.ts | 7 ++- server/job/plexsync/index.ts | 25 +++++++++ .../1608477467935-AddLastSeasonChangeMedia.ts | 52 +++++++++++++++++++ 5 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 server/migration/1608477467935-AddLastSeasonChangeMedia.ts diff --git a/ormconfig.js b/ormconfig.js index 2c0afb735..2cc4533b2 100644 --- a/ormconfig.js +++ b/ormconfig.js @@ -2,6 +2,7 @@ const devConfig = { type: 'sqlite', database: 'config/db/db.sqlite3', synchronize: true, + migrationsRun: false, logging: false, entities: ['server/entity/**/*.ts'], migrations: ['server/migration/**/*.ts'], @@ -19,7 +20,7 @@ const prodConfig = { logging: false, entities: ['dist/entity/**/*.js'], migrations: ['dist/migration/**/*.js'], - migrationsRun: true, + migrationsRun: false, subscribers: ['dist/subscriber/**/*.js'], cli: { entitiesDir: 'dist/entity', diff --git a/server/entity/Media.ts b/server/entity/Media.ts index 0222e1043..7723fb9c9 100644 --- a/server/entity/Media.ts +++ b/server/entity/Media.ts @@ -92,6 +92,9 @@ class Media { @UpdateDateColumn() public updatedAt: Date; + @Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) + public lastSeasonChange: Date; + constructor(init?: Partial) { Object.assign(this, init); } diff --git a/server/index.ts b/server/index.ts index 87066254d..31364fae8 100644 --- a/server/index.ts +++ b/server/index.ts @@ -29,7 +29,12 @@ const handle = app.getRequestHandler(); app .prepare() .then(async () => { - await createConnection(); + const dbConnection = await createConnection(); + + await dbConnection.query('PRAGMA foreign_keys=OFF'); + await dbConnection.runMigrations(); + await dbConnection.query('PRAGMA foreign_keys=ON'); + // Load Settings const settings = getSettings().load(); diff --git a/server/job/plexsync/index.ts b/server/job/plexsync/index.ts index 55bb420f0..31880e197 100644 --- a/server/job/plexsync/index.ts +++ b/server/job/plexsync/index.ts @@ -190,6 +190,12 @@ class JobPlexSync { const newSeasons: Season[] = []; + const currentSeasonAvailable = ( + media?.seasons.filter( + (season) => season.status === MediaStatus.AVAILABLE + ) ?? [] + ).length; + seasons.forEach((season) => { const matchedPlexSeason = metadata.Children?.Metadata.find( (md) => Number(md.index) === season.season_number @@ -240,6 +246,25 @@ class JobPlexSync { if (media) { // Update existing media.seasons = [...media.seasons, ...newSeasons]; + + const newSeasonAvailable = ( + media.seasons.filter( + (season) => season.status === MediaStatus.AVAILABLE + ) ?? [] + ).length; + + // If at least one new season has become available, update + // the lastSeasonChange field so we can trigger notifications + if (newSeasonAvailable > currentSeasonAvailable) { + this.log( + `Detected ${ + newSeasonAvailable - currentSeasonAvailable + } new season(s) for ${tvShow.name}`, + 'debug' + ); + media.lastSeasonChange = new Date(); + } + media.status = isAllSeasons ? MediaStatus.AVAILABLE : MediaStatus.PARTIALLY_AVAILABLE; diff --git a/server/migration/1608477467935-AddLastSeasonChangeMedia.ts b/server/migration/1608477467935-AddLastSeasonChangeMedia.ts new file mode 100644 index 000000000..b1d3968a2 --- /dev/null +++ b/server/migration/1608477467935-AddLastSeasonChangeMedia.ts @@ -0,0 +1,52 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddLastSeasonChangeMedia1608477467935 + implements MigrationInterface { + name = 'AddLastSeasonChangeMedia1608477467935'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_7157aad07c73f6a6ae3bbd5ef5"`); + await queryRunner.query(`DROP INDEX "IDX_41a289eb1fa489c1bc6f38d9c3"`); + await queryRunner.query(`DROP INDEX "IDX_7ff2d11f6a83cb52386eaebe74"`); + await queryRunner.query( + `CREATE TABLE "temporary_media" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "mediaType" varchar NOT NULL, "tmdbId" integer NOT NULL, "tvdbId" integer, "imdbId" varchar, "status" integer NOT NULL DEFAULT (1), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "lastSeasonChange" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP), CONSTRAINT "UQ_7157aad07c73f6a6ae3bbd5ef5e" UNIQUE ("tmdbId"), CONSTRAINT "UQ_41a289eb1fa489c1bc6f38d9c3c" UNIQUE ("tvdbId"), CONSTRAINT "UQ_b4e05e8b45c9cc64e047db95463" UNIQUE ("imdbId"))` + ); + await queryRunner.query( + `INSERT INTO "temporary_media"("id", "mediaType", "tmdbId", "tvdbId", "imdbId", "status", "createdAt", "updatedAt", "lastSeasonChange") SELECT "id", "mediaType", "tmdbId", "tvdbId", "imdbId", "status", "createdAt", "updatedAt", "lastSeasonChange" FROM "media"` + ); + await queryRunner.query(`DROP TABLE "media"`); + await queryRunner.query(`ALTER TABLE "temporary_media" RENAME TO "media"`); + await queryRunner.query( + `CREATE INDEX "IDX_7157aad07c73f6a6ae3bbd5ef5" ON "media" ("tmdbId") ` + ); + await queryRunner.query( + `CREATE INDEX "IDX_41a289eb1fa489c1bc6f38d9c3" ON "media" ("tvdbId") ` + ); + await queryRunner.query( + `CREATE INDEX "IDX_7ff2d11f6a83cb52386eaebe74" ON "media" ("imdbId") ` + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_7ff2d11f6a83cb52386eaebe74"`); + await queryRunner.query(`DROP INDEX "IDX_41a289eb1fa489c1bc6f38d9c3"`); + await queryRunner.query(`DROP INDEX "IDX_7157aad07c73f6a6ae3bbd5ef5"`); + await queryRunner.query(`ALTER TABLE "media" RENAME TO "temporary_media"`); + await queryRunner.query( + `CREATE TABLE "media" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "mediaType" varchar NOT NULL, "tmdbId" integer NOT NULL, "tvdbId" integer, "imdbId" varchar, "status" integer NOT NULL DEFAULT (1), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), CONSTRAINT "UQ_7157aad07c73f6a6ae3bbd5ef5e" UNIQUE ("tmdbId"), CONSTRAINT "UQ_41a289eb1fa489c1bc6f38d9c3c" UNIQUE ("tvdbId"))` + ); + await queryRunner.query( + `INSERT INTO "media"("id", "mediaType", "tmdbId", "tvdbId", "imdbId", "status", "createdAt", "updatedAt") SELECT "id", "mediaType", "tmdbId", "tvdbId", "imdbId", "status", "createdAt", "updatedAt" FROM "temporary_media"` + ); + await queryRunner.query(`DROP TABLE "temporary_media"`); + await queryRunner.query( + `CREATE INDEX "IDX_7ff2d11f6a83cb52386eaebe74" ON "media" ("imdbId") ` + ); + await queryRunner.query( + `CREATE INDEX "IDX_41a289eb1fa489c1bc6f38d9c3" ON "media" ("tvdbId") ` + ); + await queryRunner.query( + `CREATE INDEX "IDX_7157aad07c73f6a6ae3bbd5ef5" ON "media" ("tmdbId") ` + ); + } +}