mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2026-01-01 04:08:45 -05:00
feat(add watchlist): adding midding functionality from overserr
feat(add watchlist): adding missing functionality from overserr
This commit is contained in:
148
server/entity/Watchlist.ts
Normal file
148
server/entity/Watchlist.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import TheMovieDb from '@server/api/themoviedb';
|
||||
import { MediaType } from '@server/constants/media';
|
||||
import { getRepository } from '@server/datasource';
|
||||
import Media from '@server/entity/Media';
|
||||
import { User } from '@server/entity/User';
|
||||
import type { WatchlistItem } from '@server/interfaces/api/discoverInterfaces';
|
||||
import logger from '@server/logger';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
Index,
|
||||
ManyToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
Unique,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
export class DuplicateWatchlistRequestError extends Error {}
|
||||
export class NotFoundError extends Error {
|
||||
constructor(message = 'Not found') {
|
||||
super(message);
|
||||
this.name = 'NotFoundError';
|
||||
}
|
||||
}
|
||||
|
||||
@Entity()
|
||||
@Unique('UNIQUE_USER_DB', ['tmdbId', 'requestedBy'])
|
||||
export class Watchlist implements WatchlistItem {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ type: 'varchar' })
|
||||
public ratingKey = '';
|
||||
|
||||
@Column({ type: 'varchar' })
|
||||
public mediaType: MediaType;
|
||||
|
||||
@Column({ type: 'varchar' })
|
||||
title = '';
|
||||
|
||||
@Column()
|
||||
@Index()
|
||||
public tmdbId: number;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.watchlists, {
|
||||
eager: true,
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
public requestedBy: User;
|
||||
|
||||
@ManyToOne(() => Media, (media) => media.watchlists, {
|
||||
eager: true,
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
public media: Media;
|
||||
|
||||
@CreateDateColumn()
|
||||
public createdAt: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
public updatedAt: Date;
|
||||
|
||||
constructor(init?: Partial<Watchlist>) {
|
||||
Object.assign(this, init);
|
||||
}
|
||||
|
||||
public static async createWatchlist(
|
||||
watchlistRequest: Watchlist,
|
||||
user: User
|
||||
): Promise<Watchlist> {
|
||||
const watchlistRepository = getRepository(this);
|
||||
const mediaRepository = getRepository(Media);
|
||||
const tmdb = new TheMovieDb();
|
||||
|
||||
const tmdbMedia =
|
||||
watchlistRequest.mediaType === MediaType.MOVIE
|
||||
? await tmdb.getMovie({ movieId: watchlistRequest.tmdbId })
|
||||
: await tmdb.getTvShow({ tvId: watchlistRequest.tmdbId });
|
||||
|
||||
const existing = await watchlistRepository
|
||||
.createQueryBuilder('watchlist')
|
||||
.leftJoinAndSelect('watchlist.requestedBy', 'user')
|
||||
.where('user.id = :userId', { userId: user.id })
|
||||
.andWhere('watchlist.tmdbId = :tmdbId', {
|
||||
tmdbId: watchlistRequest.tmdbId,
|
||||
})
|
||||
.andWhere('watchlist.mediaType = :mediaType', {
|
||||
mediaType: watchlistRequest.mediaType,
|
||||
})
|
||||
.getMany();
|
||||
|
||||
if (existing && existing.length > 0) {
|
||||
logger.warn('Duplicate request for watchlist blocked', {
|
||||
tmdbId: watchlistRequest.tmdbId,
|
||||
mediaType: watchlistRequest.mediaType,
|
||||
label: 'Watchlist',
|
||||
});
|
||||
|
||||
throw new DuplicateWatchlistRequestError();
|
||||
}
|
||||
|
||||
let media = await mediaRepository.findOne({
|
||||
where: {
|
||||
tmdbId: watchlistRequest.tmdbId,
|
||||
mediaType: watchlistRequest.mediaType,
|
||||
},
|
||||
});
|
||||
|
||||
if (!media) {
|
||||
media = new Media({
|
||||
tmdbId: tmdbMedia.id,
|
||||
tvdbId: tmdbMedia.external_ids.tvdb_id,
|
||||
mediaType: watchlistRequest.mediaType,
|
||||
});
|
||||
}
|
||||
|
||||
const watchlist = new this({
|
||||
...watchlistRequest,
|
||||
requestedBy: user,
|
||||
media,
|
||||
});
|
||||
|
||||
await mediaRepository.save(media);
|
||||
await watchlistRepository.save(watchlist);
|
||||
return watchlist;
|
||||
}
|
||||
|
||||
public static async deleteWatchlist(
|
||||
tmdbId: Watchlist['tmdbId'],
|
||||
user: User
|
||||
): Promise<Watchlist | null> {
|
||||
const watchlistRepository = getRepository(this);
|
||||
const watchlist = await watchlistRepository.findOneBy({
|
||||
tmdbId,
|
||||
requestedBy: { id: user.id },
|
||||
});
|
||||
if (!watchlist) {
|
||||
throw new NotFoundError('not Found');
|
||||
}
|
||||
|
||||
if (watchlist) {
|
||||
await watchlistRepository.delete(watchlist.id);
|
||||
}
|
||||
|
||||
return watchlist;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user