mirror of
https://github.com/aleksilassila/reiverr.git
synced 2026-04-26 18:55:12 +02:00
feat: mark all series episodes as watched
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { ApiProperty, OmitType, PartialType } from '@nestjs/swagger';
|
||||
import { ApiProperty, OmitType, PartialType, PickType } from '@nestjs/swagger';
|
||||
import { PlayState } from './play-state.entity';
|
||||
|
||||
export class PlayStateDto extends PlayState {}
|
||||
@@ -22,9 +22,14 @@ export class PlayStateDto extends PlayState {}
|
||||
// }
|
||||
|
||||
export class UpdatePlayStateDto extends PartialType(
|
||||
OmitType(PlayStateDto, ['userId']),
|
||||
PickType(PlayStateDto, ['season', 'episode', 'watched', 'progress']),
|
||||
) {}
|
||||
|
||||
export class BulkUpdatePlayStateDto {
|
||||
@ApiProperty({ type: UpdatePlayStateDto, isArray: true })
|
||||
playStates: UpdatePlayStateDto[];
|
||||
}
|
||||
|
||||
export class MovieUserDataDto {
|
||||
@ApiProperty()
|
||||
tmdbId: string;
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { UserAccessControl } from 'src/auth/auth.guard';
|
||||
import { UpdatePlayStateDto } from './play-state.dto';
|
||||
import { BulkUpdatePlayStateDto, UpdatePlayStateDto } from './play-state.dto';
|
||||
import { PlayStatesService } from './play-states.service';
|
||||
|
||||
@ApiTags('users')
|
||||
@@ -42,7 +42,7 @@ export class PlayStatesController {
|
||||
return this.playStateService.deleteMoviePlayState(userId, tmdbId);
|
||||
}
|
||||
|
||||
@Put('show/tmdb/:tmdbId/season/:season/episode/:episode')
|
||||
@Put('series/tmdb/:tmdbId/season/:season/episode/:episode')
|
||||
async updateEpisodePlayStateByTmdbId(
|
||||
@Param('userId') userId: string,
|
||||
@Param('tmdbId') tmdbId: string,
|
||||
@@ -59,7 +59,7 @@ export class PlayStatesController {
|
||||
);
|
||||
}
|
||||
|
||||
@Delete('show/tmdb/:tmdbId/season/:season/episode/:episode')
|
||||
@Delete('series/tmdb/:tmdbId/season/:season/episode/:episode')
|
||||
async deleteEpisodePlayStateByTmdbId(
|
||||
@Param('userId') userId: string,
|
||||
@Param('tmdbId') tmdbId: string,
|
||||
@@ -73,4 +73,17 @@ export class PlayStatesController {
|
||||
episode,
|
||||
);
|
||||
}
|
||||
|
||||
@Put('series/tmdb/:tmdbId')
|
||||
async updateSeriesPlayStatesByTmdbId(
|
||||
@Param('userId') userId: string,
|
||||
@Param('tmdbId') tmdbId: string,
|
||||
@Body() body: BulkUpdatePlayStateDto,
|
||||
) {
|
||||
return this.playStateService.updateOrCreateSeriesPlayStates(
|
||||
userId,
|
||||
tmdbId,
|
||||
body.playStates,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { MediaType } from 'src/common/common.dto';
|
||||
import { Repository } from 'typeorm';
|
||||
import { UpdatePlayStateDto } from './play-state.dto';
|
||||
import { BulkUpdatePlayStateDto, UpdatePlayStateDto } from './play-state.dto';
|
||||
import { PlayState } from './play-state.entity';
|
||||
import { USER_PLAY_STATE_REPOSITORY } from './play-state.providers';
|
||||
|
||||
@@ -45,20 +45,64 @@ export class PlayStatesService {
|
||||
return playStates;
|
||||
}
|
||||
|
||||
async updateOrCreateMoviePlayState(
|
||||
async getPlayState(
|
||||
userId: string,
|
||||
tmdbId: string,
|
||||
playState: UpdatePlayStateDto,
|
||||
season?: number,
|
||||
episode?: number,
|
||||
): Promise<PlayState | undefined> {
|
||||
return this.playStateRepository.findOne({
|
||||
where: {
|
||||
userId,
|
||||
tmdbId,
|
||||
...(season ? { season } : {}),
|
||||
...(episode ? { episode } : {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private async getOrCreatePlayState(
|
||||
userId: string,
|
||||
tmdbId: string,
|
||||
options: {
|
||||
season?: number;
|
||||
episode?: number;
|
||||
mediaType: MediaType;
|
||||
save?: boolean;
|
||||
},
|
||||
) {
|
||||
let state = await this.findMoviePlayState(userId, tmdbId);
|
||||
let state = await this.getPlayState(
|
||||
userId,
|
||||
tmdbId,
|
||||
options.season,
|
||||
options.episode,
|
||||
);
|
||||
|
||||
if (!state) {
|
||||
state = this.playStateRepository.create();
|
||||
state.userId = userId;
|
||||
state.tmdbId = tmdbId;
|
||||
state.mediaType = MediaType.Movie;
|
||||
state.season = options.season;
|
||||
state.episode = options.episode;
|
||||
state.mediaType = options.mediaType;
|
||||
}
|
||||
|
||||
if (options.save) {
|
||||
return this.playStateRepository.save(state);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
async updateOrCreateMoviePlayState(
|
||||
userId: string,
|
||||
tmdbId: string,
|
||||
playState: UpdatePlayStateDto,
|
||||
) {
|
||||
const state = await this.getOrCreatePlayState(userId, tmdbId, {
|
||||
mediaType: MediaType.Movie,
|
||||
});
|
||||
|
||||
state.progress = playState.progress;
|
||||
state.watched = playState.watched;
|
||||
|
||||
@@ -72,28 +116,14 @@ export class PlayStatesService {
|
||||
episode: number,
|
||||
playState: UpdatePlayStateDto,
|
||||
) {
|
||||
let state = await this.findSeriesPlayStates(
|
||||
userId,
|
||||
tmdbId,
|
||||
const state = await this.getOrCreatePlayState(userId, tmdbId, {
|
||||
season,
|
||||
episode,
|
||||
).then((states) =>
|
||||
states.find(
|
||||
(state) => state.season === season && state.episode === episode,
|
||||
),
|
||||
);
|
||||
mediaType: MediaType.Episode,
|
||||
});
|
||||
|
||||
if (!state) {
|
||||
state = this.playStateRepository.create();
|
||||
state.userId = userId;
|
||||
state.tmdbId = tmdbId;
|
||||
state.season = season;
|
||||
state.episode = episode;
|
||||
state.mediaType = MediaType.Episode;
|
||||
}
|
||||
|
||||
state.progress = playState.progress;
|
||||
state.watched = playState.watched;
|
||||
state.progress = playState.progress ?? state.progress;
|
||||
state.watched = playState.watched ?? state.watched;
|
||||
|
||||
return this.playStateRepository.save(state);
|
||||
}
|
||||
@@ -109,12 +139,33 @@ export class PlayStatesService {
|
||||
season: number,
|
||||
episode: number,
|
||||
) {
|
||||
const state = await this.findSeriesPlayStates(
|
||||
userId,
|
||||
tmdbId,
|
||||
season,
|
||||
episode,
|
||||
const state = await this.getPlayState(userId, tmdbId, season, episode);
|
||||
|
||||
if (state) {
|
||||
return await this.playStateRepository.remove(state);
|
||||
}
|
||||
}
|
||||
|
||||
async updateOrCreateSeriesPlayStates(
|
||||
userId: string,
|
||||
tmdbId: string,
|
||||
playStates: UpdatePlayStateDto[],
|
||||
) {
|
||||
const states = await Promise.all(
|
||||
playStates.map(async (updatedState) => {
|
||||
const state = await this.getOrCreatePlayState(userId, tmdbId, {
|
||||
season: updatedState.season,
|
||||
episode: updatedState.episode,
|
||||
mediaType: MediaType.Episode,
|
||||
});
|
||||
|
||||
state.progress = updatedState.progress ?? state.progress;
|
||||
state.watched = updatedState.watched ?? state.watched;
|
||||
|
||||
return this.playStateRepository.save(state);
|
||||
}),
|
||||
);
|
||||
return await this.playStateRepository.remove(state);
|
||||
|
||||
return states;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,11 +81,12 @@ export class UserDataController {
|
||||
@Param('episode', ParseIntPipe) episode: number,
|
||||
): Promise<MovieUserDataDto> {
|
||||
const libraryItem = await this.libraryService.findByTmdbId(userId, tmdbId);
|
||||
const playState = await this.playStateService
|
||||
.findSeriesPlayStates(userId, tmdbId, season, episode)
|
||||
.then((states) =>
|
||||
states.find((s) => s.season === season && s.episode === episode),
|
||||
);
|
||||
const playState = await this.playStateService.getPlayState(
|
||||
userId,
|
||||
tmdbId,
|
||||
season,
|
||||
episode,
|
||||
);
|
||||
|
||||
return {
|
||||
tmdbId,
|
||||
|
||||
Reference in New Issue
Block a user