mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
fix(plex-sync): store plex added date and sort recently added by it
This commit is contained in:
@@ -2976,7 +2976,7 @@ paths:
|
||||
name: sort
|
||||
schema:
|
||||
type: string
|
||||
enum: [added, modified]
|
||||
enum: [added, modified, mediaAdded]
|
||||
default: added
|
||||
responses:
|
||||
'200':
|
||||
|
@@ -9,6 +9,8 @@ export interface PlexLibraryItem {
|
||||
guid: string;
|
||||
parentGuid?: string;
|
||||
grandparentGuid?: string;
|
||||
addedAt: number;
|
||||
updatedAt: number;
|
||||
type: 'movie' | 'show' | 'season' | 'episode';
|
||||
}
|
||||
|
||||
@@ -48,6 +50,8 @@ export interface PlexMetadata {
|
||||
parentIndex?: number;
|
||||
leafCount: number;
|
||||
viewedLeafCount: number;
|
||||
addedAt: number;
|
||||
updatedAt: number;
|
||||
Media: Media[];
|
||||
}
|
||||
|
||||
|
@@ -101,6 +101,9 @@ class Media {
|
||||
@Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
|
||||
public lastSeasonChange: Date;
|
||||
|
||||
@Column({ type: 'datetime', nullable: true })
|
||||
public mediaAddedAt: Date;
|
||||
|
||||
constructor(init?: Partial<Media>) {
|
||||
Object.assign(this, init);
|
||||
}
|
||||
|
@@ -111,6 +111,7 @@ class JobPlexSync {
|
||||
existing.status !== MediaStatus.AVAILABLE
|
||||
) {
|
||||
existing.status = MediaStatus.AVAILABLE;
|
||||
existing.mediaAddedAt = new Date(plexitem.addedAt * 1000);
|
||||
changedExisting = true;
|
||||
}
|
||||
|
||||
@@ -123,6 +124,11 @@ class JobPlexSync {
|
||||
changedExisting = true;
|
||||
}
|
||||
|
||||
if (!existing.mediaAddedAt && !changedExisting) {
|
||||
existing.mediaAddedAt = new Date(plexitem.addedAt * 1000);
|
||||
changedExisting = true;
|
||||
}
|
||||
|
||||
if (changedExisting) {
|
||||
await mediaRepository.save(existing);
|
||||
this.log(
|
||||
@@ -144,6 +150,7 @@ class JobPlexSync {
|
||||
? MediaStatus.AVAILABLE
|
||||
: MediaStatus.UNKNOWN;
|
||||
newMedia.mediaType = MediaType.MOVIE;
|
||||
newMedia.mediaAddedAt = new Date(plexitem.addedAt * 1000);
|
||||
await mediaRepository.save(newMedia);
|
||||
this.log(`Saved ${plexitem.title}`);
|
||||
}
|
||||
@@ -208,6 +215,7 @@ class JobPlexSync {
|
||||
existing.status !== MediaStatus.AVAILABLE
|
||||
) {
|
||||
existing.status = MediaStatus.AVAILABLE;
|
||||
existing.mediaAddedAt = new Date(plexitem.addedAt * 1000);
|
||||
changedExisting = true;
|
||||
}
|
||||
|
||||
@@ -220,6 +228,11 @@ class JobPlexSync {
|
||||
changedExisting = true;
|
||||
}
|
||||
|
||||
if (!existing.mediaAddedAt && !changedExisting) {
|
||||
existing.mediaAddedAt = new Date(plexitem.addedAt * 1000);
|
||||
changedExisting = true;
|
||||
}
|
||||
|
||||
if (changedExisting) {
|
||||
await mediaRepository.save(existing);
|
||||
this.log(
|
||||
@@ -240,6 +253,7 @@ class JobPlexSync {
|
||||
const newMedia = new Media();
|
||||
newMedia.imdbId = tmdbMovie.external_ids.imdb_id;
|
||||
newMedia.tmdbId = tmdbMovie.id;
|
||||
newMedia.mediaAddedAt = new Date(plexitem.addedAt * 1000);
|
||||
newMedia.status =
|
||||
hasOtherResolution || (!this.enable4kMovie && has4k)
|
||||
? MediaStatus.AVAILABLE
|
||||
@@ -266,10 +280,7 @@ class JobPlexSync {
|
||||
);
|
||||
if (episodes) {
|
||||
for (const episode of episodes) {
|
||||
const special = await animeList.getSpecialEpisode(
|
||||
tvdbId,
|
||||
episode.index
|
||||
);
|
||||
const special = animeList.getSpecialEpisode(tvdbId, episode.index);
|
||||
if (special) {
|
||||
if (special.tmdbId) {
|
||||
await this.processMovieWithId(episode, undefined, special.tmdbId);
|
||||
@@ -519,6 +530,7 @@ class JobPlexSync {
|
||||
'debug'
|
||||
);
|
||||
media.lastSeasonChange = new Date();
|
||||
media.mediaAddedAt = new Date(plexitem.addedAt * 1000);
|
||||
}
|
||||
|
||||
if (new4kSeasonAvailable > current4kSeasonAvailable) {
|
||||
@@ -531,6 +543,10 @@ class JobPlexSync {
|
||||
media.lastSeasonChange = new Date();
|
||||
}
|
||||
|
||||
if (!media.mediaAddedAt) {
|
||||
media.mediaAddedAt = new Date(plexitem.addedAt * 1000);
|
||||
}
|
||||
|
||||
media.status = isAllStandardSeasons
|
||||
? MediaStatus.AVAILABLE
|
||||
: media.seasons.some(
|
||||
@@ -553,6 +569,7 @@ class JobPlexSync {
|
||||
seasons: newSeasons,
|
||||
tmdbId: tvShow.id,
|
||||
tvdbId: tvShow.external_ids.tvdb_id,
|
||||
mediaAddedAt: new Date(plexitem.addedAt * 1000),
|
||||
status: isAllStandardSeasons
|
||||
? MediaStatus.AVAILABLE
|
||||
: newSeasons.some(
|
||||
|
52
server/migration/1610522845513-AddMediaAddedFieldToMedia.ts
Normal file
52
server/migration/1610522845513-AddMediaAddedFieldToMedia.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class AddMediaAddedFieldToMedia1610522845513
|
||||
implements MigrationInterface {
|
||||
name = 'AddMediaAddedFieldToMedia1610522845513';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP INDEX "IDX_7ff2d11f6a83cb52386eaebe74"`);
|
||||
await queryRunner.query(`DROP INDEX "IDX_41a289eb1fa489c1bc6f38d9c3"`);
|
||||
await queryRunner.query(`DROP INDEX "IDX_7157aad07c73f6a6ae3bbd5ef5"`);
|
||||
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), "status4k" integer NOT NULL DEFAULT (1), "mediaAddedAt" datetime, CONSTRAINT "UQ_41a289eb1fa489c1bc6f38d9c3c" UNIQUE ("tvdbId"))`
|
||||
);
|
||||
await queryRunner.query(
|
||||
`INSERT INTO "temporary_media"("id", "mediaType", "tmdbId", "tvdbId", "imdbId", "status", "createdAt", "updatedAt", "lastSeasonChange", "status4k") SELECT "id", "mediaType", "tmdbId", "tvdbId", "imdbId", "status", "createdAt", "updatedAt", "lastSeasonChange", "status4k" FROM "media"`
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "media"`);
|
||||
await queryRunner.query(`ALTER TABLE "temporary_media" RENAME TO "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") `
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP INDEX "IDX_7157aad07c73f6a6ae3bbd5ef5"`);
|
||||
await queryRunner.query(`DROP INDEX "IDX_41a289eb1fa489c1bc6f38d9c3"`);
|
||||
await queryRunner.query(`DROP INDEX "IDX_7ff2d11f6a83cb52386eaebe74"`);
|
||||
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')), "lastSeasonChange" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP), "status4k" integer NOT NULL DEFAULT (1), CONSTRAINT "UQ_41a289eb1fa489c1bc6f38d9c3c" UNIQUE ("tvdbId"))`
|
||||
);
|
||||
await queryRunner.query(
|
||||
`INSERT INTO "media"("id", "mediaType", "tmdbId", "tvdbId", "imdbId", "status", "createdAt", "updatedAt", "lastSeasonChange", "status4k") SELECT "id", "mediaType", "tmdbId", "tvdbId", "imdbId", "status", "createdAt", "updatedAt", "lastSeasonChange", "status4k" FROM "temporary_media"`
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "temporary_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") `
|
||||
);
|
||||
}
|
||||
}
|
@@ -47,6 +47,10 @@ mediaRoutes.get('/', async (req, res, next) => {
|
||||
updatedAt: 'DESC',
|
||||
};
|
||||
break;
|
||||
case 'mediaAdded':
|
||||
sortFilter = {
|
||||
mediaAddedAt: 'DESC',
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
|
@@ -69,7 +69,7 @@ const Discover: React.FC = () => {
|
||||
);
|
||||
|
||||
const { data: media, error: mediaError } = useSWR<MediaResultsResponse>(
|
||||
'/api/v1/media?filter=available&take=20&sort=modified'
|
||||
'/api/v1/media?filter=available&take=20&sort=mediaAdded'
|
||||
);
|
||||
|
||||
const {
|
||||
|
Reference in New Issue
Block a user