mirror of
https://github.com/sct/overseerr.git
synced 2025-12-26 16:27:17 +01:00
* feat(blacklist): add blacktag settings to main settings page * feat(blacklist): create blacktag logic and infrastructure * feat(blacklist): add scheduling for blacktags job * feat(blacklist): create blacktag ui badge for blacklist * docs(blacklist): document blacktags in using-jellyseerr * fix(blacklist): batch blacklist and media db removes to avoid expression tree too large error * feat(blacklist): allow easy import and export of blacktag configuration * fix(settings): don't copy the API key every time you press enter on the main settings * fix(blacklist): move filter inline with page title to match all the other pages * feat(blacklist): allow filtering between manually blacklisted and automatically blacklisted entries * docs(blacklist): reword blacktag documentation a little * refactor(blacklist): remove blacktag settings from public settings interfaces There's no reason for it to be there * refactor(blacklist): remove unused variable from processResults in blacktagsProcessor * refactor(blacklist): change all instances of blacktag to blacklistedTag and update doc to match * docs(blacklist): update general documentation for blacklisted tag settings * fix(blacklist): update setting use of "blacklisted tag" to match between modals * perf(blacklist): remove media type constraint from existing blacklist entry query Doesn't make sense to keep it because tmdbid has a unique constraint on it * fix(blacklist): remove whitespace line causing prettier to fail in CI * refactor(blacklist): swap out some != and == for !s and _s * fix(blacklist): merge back CopyButton changes, disable button when there's nothing to copy * refactor(blacklist): use axios instead of fetch for blacklisted tag queries * style(blacklist): use templated axios types and remove redundant try-catches
105 lines
2.5 KiB
TypeScript
105 lines
2.5 KiB
TypeScript
import { MediaStatus, type MediaType } from '@server/constants/media';
|
|
import dataSource from '@server/datasource';
|
|
import Media from '@server/entity/Media';
|
|
import { User } from '@server/entity/User';
|
|
import type { BlacklistItem } from '@server/interfaces/api/blacklistInterfaces';
|
|
import type { EntityManager } from 'typeorm';
|
|
import {
|
|
Column,
|
|
CreateDateColumn,
|
|
Entity,
|
|
Index,
|
|
JoinColumn,
|
|
ManyToOne,
|
|
OneToOne,
|
|
PrimaryGeneratedColumn,
|
|
Unique,
|
|
} from 'typeorm';
|
|
import type { ZodNumber, ZodOptional, ZodString } from 'zod';
|
|
|
|
@Entity()
|
|
@Unique(['tmdbId'])
|
|
export class Blacklist implements BlacklistItem {
|
|
@PrimaryGeneratedColumn()
|
|
public id: number;
|
|
|
|
@Column({ type: 'varchar' })
|
|
public mediaType: MediaType;
|
|
|
|
@Column({ nullable: true, type: 'varchar' })
|
|
title?: string;
|
|
|
|
@Column()
|
|
@Index()
|
|
public tmdbId: number;
|
|
|
|
@ManyToOne(() => User, (user) => user.id, {
|
|
eager: true,
|
|
})
|
|
user?: User;
|
|
|
|
@OneToOne(() => Media, (media) => media.blacklist, {
|
|
onDelete: 'CASCADE',
|
|
})
|
|
@JoinColumn()
|
|
public media: Media;
|
|
|
|
@Column({ nullable: true, type: 'varchar' })
|
|
public blacklistedTags?: string;
|
|
|
|
@CreateDateColumn()
|
|
public createdAt: Date;
|
|
|
|
constructor(init?: Partial<Blacklist>) {
|
|
Object.assign(this, init);
|
|
}
|
|
|
|
public static async addToBlacklist(
|
|
{
|
|
blacklistRequest,
|
|
}: {
|
|
blacklistRequest: {
|
|
mediaType: MediaType;
|
|
title?: ZodOptional<ZodString>['_output'];
|
|
tmdbId: ZodNumber['_output'];
|
|
blacklistedTags?: string;
|
|
};
|
|
},
|
|
entityManager?: EntityManager
|
|
): Promise<void> {
|
|
const em = entityManager ?? dataSource;
|
|
const blacklist = new this({
|
|
...blacklistRequest,
|
|
});
|
|
|
|
const mediaRepository = em.getRepository(Media);
|
|
let media = await mediaRepository.findOne({
|
|
where: {
|
|
tmdbId: blacklistRequest.tmdbId,
|
|
},
|
|
});
|
|
|
|
const blacklistRepository = em.getRepository(this);
|
|
|
|
await blacklistRepository.save(blacklist);
|
|
|
|
if (!media) {
|
|
media = new Media({
|
|
tmdbId: blacklistRequest.tmdbId,
|
|
status: MediaStatus.BLACKLISTED,
|
|
status4k: MediaStatus.BLACKLISTED,
|
|
mediaType: blacklistRequest.mediaType,
|
|
blacklist: Promise.resolve(blacklist),
|
|
});
|
|
|
|
await mediaRepository.save(media);
|
|
} else {
|
|
media.blacklist = Promise.resolve(blacklist);
|
|
media.status = MediaStatus.BLACKLISTED;
|
|
media.status4k = MediaStatus.BLACKLISTED;
|
|
|
|
await mediaRepository.save(media);
|
|
}
|
|
}
|
|
}
|