mirror of
https://github.com/aleksilassila/reiverr.git
synced 2026-04-27 03:05:10 +02:00
refactor: library items & metadata for performance
This commit is contained in:
@@ -20,7 +20,7 @@ import {
|
||||
PaginationParamsDto,
|
||||
SuccessResponseDto,
|
||||
} from 'src/common/common.dto';
|
||||
import { LibraryItemDto } from './library.dto';
|
||||
import { LibraryItemDto, LibraryItemDto2 } from './library.dto';
|
||||
import { LibraryService } from './library.service';
|
||||
|
||||
@ApiTags('users')
|
||||
@@ -30,11 +30,11 @@ export class LibraryController {
|
||||
constructor(private libraryService: LibraryService) {}
|
||||
|
||||
@Get()
|
||||
@PaginatedApiOkResponse(LibraryItemDto)
|
||||
@PaginatedApiOkResponse(LibraryItemDto2)
|
||||
async getLibraryItems(
|
||||
@GetPaginationParams() pagination: PaginationParamsDto,
|
||||
@Param('userId') userId: string,
|
||||
): Promise<PaginatedResponseDto<LibraryItemDto>> {
|
||||
): Promise<PaginatedResponseDto<LibraryItemDto2>> {
|
||||
// const user = await this.userService.findOne(userId);
|
||||
|
||||
const items = await this.libraryService.getLibraryItemDtos(
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import { ApiProperty, PickType } from '@nestjs/swagger';
|
||||
import { MovieDto } from 'src/metadata/metadata.dto';
|
||||
import { Series } from 'src/metadata/metadata.entity';
|
||||
import { MovieMetadata, SeriesMetadata } from 'src/metadata/metadata.entity';
|
||||
import { LibraryItem } from './library.entity';
|
||||
import {
|
||||
TmdbMovie,
|
||||
TmdbMovieFull,
|
||||
TmdbSeries,
|
||||
} from 'src/metadata/tmdb/tmdb.dto';
|
||||
import { MediaType } from 'src/common/common.dto';
|
||||
|
||||
export class LibraryItemDto extends PickType(LibraryItem, [
|
||||
'tmdbId',
|
||||
@@ -12,9 +18,147 @@ export class LibraryItemDto extends PickType(LibraryItem, [
|
||||
@ApiProperty({ type: MovieDto, required: false })
|
||||
movieMetadata?: MovieDto;
|
||||
|
||||
@ApiProperty({ type: Series, required: false })
|
||||
seriesMetadata?: Series;
|
||||
@ApiProperty({ type: SeriesMetadata, required: false })
|
||||
seriesMetadata?: SeriesMetadata;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
watched?: boolean;
|
||||
}
|
||||
|
||||
class NextEpisodeToAir {
|
||||
@ApiProperty({ required: false })
|
||||
air_date?: string;
|
||||
}
|
||||
|
||||
class Season {
|
||||
@ApiProperty({ required: false })
|
||||
air_date?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
episode_count?: number;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
id?: number;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
name?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
overview?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
poster_path?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
season_number?: number;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
vote_average?: number;
|
||||
}
|
||||
|
||||
export class LibraryItemDto2
|
||||
extends PickType(LibraryItem, [
|
||||
'tmdbId',
|
||||
'mediaType',
|
||||
'playStates',
|
||||
'createdAt',
|
||||
])
|
||||
implements TmdbMovie, TmdbSeries
|
||||
{
|
||||
// TmdbMovie & TmdbSeries
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
id?: number;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
poster_path?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
vote_average?: number;
|
||||
|
||||
// TmdbMovie only
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
title?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
release_date?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
runtime?: number;
|
||||
|
||||
// TmdbSeries only
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
name?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
first_air_date?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
last_air_date?: string;
|
||||
|
||||
@ApiProperty({ required: false, type: NextEpisodeToAir })
|
||||
next_episode_to_air?: NextEpisodeToAir;
|
||||
|
||||
@ApiProperty({ required: false, isArray: true, type: Season })
|
||||
seasons?: Season[];
|
||||
|
||||
// Library Item
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
watched?: boolean;
|
||||
|
||||
static create(options: {
|
||||
libraryItem: LibraryItem;
|
||||
movieMetadata?: MovieMetadata;
|
||||
seriesMetadata?: SeriesMetadata;
|
||||
}): LibraryItemDto2 {
|
||||
const { libraryItem, movieMetadata, seriesMetadata } = options;
|
||||
|
||||
if (!movieMetadata && !seriesMetadata) {
|
||||
throw new Error(
|
||||
'At least one of movieMetadata or seriesMetadata must be provided',
|
||||
);
|
||||
}
|
||||
|
||||
let watched = false;
|
||||
|
||||
if (libraryItem.mediaType === MediaType.Movie) {
|
||||
watched = libraryItem.playStates?.some((state) => state.watched) ?? false;
|
||||
} else if (
|
||||
libraryItem.mediaType === MediaType.Series &&
|
||||
seriesMetadata?.tmdbSeries?.last_episode_to_air
|
||||
) {
|
||||
const { season_number: season, episode_number: episode } =
|
||||
seriesMetadata?.tmdbSeries.last_episode_to_air;
|
||||
watched =
|
||||
libraryItem.playStates?.some(
|
||||
(state) =>
|
||||
state.season === season &&
|
||||
state.episode === episode &&
|
||||
state.watched,
|
||||
) ?? false;
|
||||
}
|
||||
|
||||
return {
|
||||
...libraryItem,
|
||||
watched,
|
||||
id: movieMetadata?.tmdbMovie.id ?? seriesMetadata?.tmdbSeries.id,
|
||||
poster_path:
|
||||
movieMetadata?.tmdbMovie.poster_path ??
|
||||
seriesMetadata?.tmdbSeries.poster_path,
|
||||
vote_average:
|
||||
movieMetadata?.tmdbMovie.vote_average ??
|
||||
seriesMetadata?.tmdbSeries.vote_average,
|
||||
title: movieMetadata?.tmdbMovie.title,
|
||||
release_date: movieMetadata?.tmdbMovie.release_date,
|
||||
runtime: movieMetadata?.tmdbMovie.runtime,
|
||||
name: seriesMetadata?.tmdbSeries.name,
|
||||
first_air_date: seriesMetadata?.tmdbSeries.first_air_date,
|
||||
last_air_date: seriesMetadata?.tmdbSeries.last_air_date,
|
||||
next_episode_to_air: seriesMetadata?.tmdbSeries.next_episode_to_air,
|
||||
seasons: seriesMetadata?.tmdbSeries.seasons,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Repository } from 'typeorm';
|
||||
import { LibraryItem } from './library.entity';
|
||||
import { MediaType, PaginationParamsDto } from 'src/common/common.dto';
|
||||
import { LibraryItemDto } from './library.dto';
|
||||
import { LibraryItemDto, LibraryItemDto2 } from './library.dto';
|
||||
import { MetadataService } from 'src/metadata/metadata.service';
|
||||
import { USER_LIBRARY_REPOSITORY } from './library.providers';
|
||||
|
||||
@@ -17,7 +17,7 @@ export class LibraryService {
|
||||
async getLibraryItemDtos(
|
||||
userId: string,
|
||||
pagination: PaginationParamsDto,
|
||||
): Promise<LibraryItemDto[]> {
|
||||
): Promise<LibraryItemDto2[]> {
|
||||
const items = await this.getLibraryItems(userId, pagination);
|
||||
|
||||
return Promise.all(
|
||||
@@ -26,34 +26,16 @@ export class LibraryService {
|
||||
item.mediaType === MediaType.Series
|
||||
? await this.metadataService.getSeriesByTmdbId(item.tmdbId)
|
||||
: undefined;
|
||||
let watched = false;
|
||||
const movieMetadata =
|
||||
item.mediaType === MediaType.Movie
|
||||
? await this.metadataService.getMovieByTmdbId(item.tmdbId)
|
||||
: undefined;
|
||||
|
||||
if (item.mediaType === MediaType.Movie) {
|
||||
watched = item.playStates?.some((state) => state.watched) ?? false;
|
||||
} else if (
|
||||
item.mediaType === MediaType.Series &&
|
||||
seriesMetadata.tmdbSeries?.last_episode_to_air
|
||||
) {
|
||||
const { season_number: season, episode_number: episode } =
|
||||
seriesMetadata.tmdbSeries.last_episode_to_air;
|
||||
watched =
|
||||
item.playStates?.some(
|
||||
(state) =>
|
||||
state.season === season &&
|
||||
state.episode === episode &&
|
||||
state.watched,
|
||||
) ?? false;
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
watched,
|
||||
movieMetadata:
|
||||
item.mediaType === MediaType.Movie
|
||||
? await this.metadataService.getMovieByTmdbId(item.tmdbId)
|
||||
: undefined,
|
||||
return LibraryItemDto2.create({
|
||||
libraryItem: item,
|
||||
seriesMetadata,
|
||||
};
|
||||
movieMetadata,
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user