Skip to content

Commit

Permalink
feat: blacklist media items
Browse files Browse the repository at this point in the history
  • Loading branch information
JoaquinOlivero committed Jul 14, 2024
1 parent a4046a8 commit d7905dc
Show file tree
Hide file tree
Showing 20 changed files with 376 additions and 378 deletions.
113 changes: 56 additions & 57 deletions overseerr-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2829,63 +2829,6 @@ paths:
responses:
'204':
description: 'Flushed cache'
/settings/blacklist:
get:
summary: Returns blacklisted items
description: Returns list of all blacklisted media
tags:
- settings
parameters:
- in: query
name: take
schema:
type: number
nullable: true
example: 25
- in: query
name: skip
schema:
type: number
nullable: true
example: 0
- in: query
name: search
schema:
type: string
nullable: true
example: dune
responses:
'200':
description: Blacklisted items returned
content:
application/json:
schema:
type: object
properties:
pageInfo:
$ref: '#/components/schemas/PageInfo'
results:
type: array
items:
type: object
properties:
user:
$ref: '#/components/schemas/User'
createdAt:
type: string
example: 2024-04-21T01:55:44.000Z
id:
type: number
example: 1
mediaType:
type: string
example: movie
title:
type: string
example: Dune
tmdbId:
type: number
example: 438631
/settings/logs:
get:
summary: Returns logs
Expand Down Expand Up @@ -4113,6 +4056,62 @@ paths:
type: boolean
example: false
/blacklist:
get:
summary: Returns blacklisted items
description: Returns list of all blacklisted media
tags:
- settings
parameters:
- in: query
name: take
schema:
type: number
nullable: true
example: 25
- in: query
name: skip
schema:
type: number
nullable: true
example: 0
- in: query
name: search
schema:
type: string
nullable: true
example: dune
responses:
'200':
description: Blacklisted items returned
content:
application/json:
schema:
type: object
properties:
pageInfo:
$ref: '#/components/schemas/PageInfo'
results:
type: array
items:
type: object
properties:
user:
$ref: '#/components/schemas/User'
createdAt:
type: string
example: 2024-04-21T01:55:44.000Z
id:
type: number
example: 1
mediaType:
type: string
example: movie
title:
type: string
example: Dune
tmdbId:
type: number
example: 438631
post:
summary: Add media to blacklist
tags:
Expand Down
2 changes: 1 addition & 1 deletion server/entity/Blacklist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { MediaStatus, type MediaType } from '@server/constants/media';
import { getRepository } from '@server/datasource';
import Media from '@server/entity/Media';
import { User } from '@server/entity/User';
import type { BlacklistItem } from '@server/interfaces/api/discoverInterfaces';
import type { BlacklistItem } from '@server/interfaces/api/blacklistInterfaces';
import {
Column,
CreateDateColumn,
Expand Down
9 changes: 0 additions & 9 deletions server/interfaces/api/blacklistAdd.ts

This file was deleted.

14 changes: 14 additions & 0 deletions server/interfaces/api/blacklistInterfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { User } from '@server/entity/User';
import type { PaginatedResponse } from '@server/interfaces/api/common';

export interface BlacklistItem {
tmdbId: number;
mediaType: 'movie' | 'tv';
title?: string;
createdAt?: Date;
user: User;
}

export interface BlacklistResultsResponse extends PaginatedResponse {
results: BlacklistItem[];
}
10 changes: 0 additions & 10 deletions server/interfaces/api/discoverInterfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { User } from '@server/entity/User';

export interface GenreSliderItem {
id: number;
name: string;
Expand All @@ -19,11 +17,3 @@ export interface WatchlistResponse {
totalResults: number;
results: WatchlistItem[];
}

export interface BlacklistItem {
tmdbId: number;
mediaType: 'movie' | 'tv';
title?: string;
createdAt?: Date;
user: User;
}
5 changes: 0 additions & 5 deletions server/interfaces/api/settingsInterfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { BlacklistItem } from '@server/interfaces/api/discoverInterfaces';
import type { PaginatedResponse } from './common';

export type LogMessage = {
Expand Down Expand Up @@ -69,7 +68,3 @@ export interface StatusResponse {
commitsBehind: number;
restartRequired: boolean;
}

export interface BlacklistResultsResponse extends PaginatedResponse {
results: BlacklistItem[];
}
1 change: 0 additions & 1 deletion server/lib/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export enum Permission {
RECENT_VIEW = 67108864,
WATCHLIST_VIEW = 134217728,
MANAGE_BLACKLIST = 268435456,
MEDIA_BLACKLIST = 536870912,
VIEW_BLACKLIST = 1073741824,
}

Expand Down
66 changes: 63 additions & 3 deletions server/routes/blacklist.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,79 @@
import { MediaType } from '@server/constants/media';
import { getRepository } from '@server/datasource';
import { Blacklist } from '@server/entity/Blacklist';
import Media from '@server/entity/Media';
import { NotFoundError } from '@server/entity/Watchlist';
import { blacklistAdd } from '@server/interfaces/api/blacklistAdd';
import type { BlacklistResultsResponse } from '@server/interfaces/api/blacklistInterfaces';
import { Permission } from '@server/lib/permissions';
import logger from '@server/logger';
import { isAuthenticated } from '@server/middleware/auth';
import { Router } from 'express';
import rateLimit from 'express-rate-limit';
import { QueryFailedError } from 'typeorm';
import { z } from 'zod';

const blacklistRoutes = Router();

export const blacklistAdd = z.object({
tmdbId: z.coerce.number(),
mediaType: z.nativeEnum(MediaType),
title: z.coerce.string().optional(),
user: z.coerce.number(),
});

blacklistRoutes.get(
'/',
isAuthenticated([Permission.MANAGE_BLACKLIST, Permission.VIEW_BLACKLIST], {
type: 'or',
}),
rateLimit({ windowMs: 60 * 1000, max: 50 }),
async (req, res, next) => {
const pageSize = req.query.take ? Number(req.query.take) : 25;
const skip = req.query.skip ? Number(req.query.skip) : 0;
const search = (req.query.search as string) ?? '';

try {
let query = getRepository(Blacklist)
.createQueryBuilder('blacklist')
.leftJoinAndSelect('blacklist.user', 'user');

if (search.length > 0) {
query = query.where('blacklist.title like :title', {
title: `%${search}%`,
});
}

const [blacklistedItems, itemsCount] = await query
.orderBy('blacklist.createdAt', 'DESC')
.take(pageSize)
.skip(skip)
.getManyAndCount();

return res.status(200).json({
pageInfo: {
pages: Math.ceil(itemsCount / pageSize),
pageSize,
results: itemsCount,
page: Math.ceil(skip / pageSize) + 1,
},
results: blacklistedItems,
} as BlacklistResultsResponse);
} catch (error) {
logger.error('Something went wrong while retrieving blacklisted items', {
label: 'Blacklist',
errorMessage: error.message,
});
return next({
status: 500,
message: 'Unable to retrieve blacklisted items.',
});
}
}
);

blacklistRoutes.post(
'/',
isAuthenticated([Permission.MANAGE_BLACKLIST, Permission.MEDIA_BLACKLIST], {
isAuthenticated([Permission.MANAGE_BLACKLIST], {
type: 'or',
}),
async (req, res, next) => {
Expand Down Expand Up @@ -51,7 +111,7 @@ blacklistRoutes.post(

blacklistRoutes.delete(
'/:id',
isAuthenticated([Permission.MANAGE_BLACKLIST, Permission.MEDIA_BLACKLIST], {
isAuthenticated([Permission.MANAGE_BLACKLIST], {
type: 'or',
}),
async (req, res, next) => {
Expand Down
65 changes: 0 additions & 65 deletions server/routes/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import PlexTvAPI from '@server/api/plextv';
import TautulliAPI from '@server/api/tautulli';
import { ApiErrorCode } from '@server/constants/error';
import { getRepository } from '@server/datasource';
import { Blacklist } from '@server/entity/Blacklist';
import Media from '@server/entity/Media';
import { MediaRequest } from '@server/entity/MediaRequest';
import { User } from '@server/entity/User';
import type { PlexConnection } from '@server/interfaces/api/plexInterfaces';
import type {
BlacklistResultsResponse,
LogMessage,
LogsResultsResponse,
SettingsAboutResponse,
Expand Down Expand Up @@ -522,69 +520,6 @@ settingsRoutes.get(
}
);

settingsRoutes.get(
'/blacklist',
rateLimit({ windowMs: 60 * 1000, max: 50 }),
async (req, res, next) => {
if (
!req.user?.hasPermission(
[Permission.MANAGE_BLACKLIST, Permission.VIEW_BLACKLIST],
{ type: 'or' }
)
) {
return next({
status: 403,
message: 'You do not have permission to access blacklisted items.',
});
}
const pageSize = req.query.take ? Number(req.query.take) : 25;
const skip = req.query.skip ? Number(req.query.skip) : 0;
const search = (req.query.search as string) ?? '';

let blacklistedItems;

try {
if (search.length > 0) {
blacklistedItems = await getRepository(Blacklist)
.createQueryBuilder('blacklist')
.where('blacklist.title like :title', { title: `%${search}%` })
.leftJoinAndSelect('blacklist.user', 'user')
.orderBy('blacklist.createdAt', 'DESC')
.take(pageSize)
.skip(skip)
.getMany();
} else {
blacklistedItems = await getRepository(Blacklist)
.createQueryBuilder('blacklist')
.leftJoinAndSelect('blacklist.user', 'user')
.orderBy('blacklist.createdAt', 'DESC')
.take(pageSize)
.skip(skip)
.getMany();
}

return res.status(200).json({
pageInfo: {
pages: Math.ceil(blacklistedItems.length / pageSize),
pageSize,
results: blacklistedItems.length,
page: Math.ceil(skip / pageSize) + 1,
},
results: blacklistedItems,
} as BlacklistResultsResponse);
} catch (error) {
logger.error('Something went wrong while retrieving blacklisted items', {
label: 'Blacklist',
errorMessage: error.message,
});
return next({
status: 500,
message: 'Unable to retrieve blacklisted items.',
});
}
}
);

settingsRoutes.get(
'/logs',
rateLimit({ windowMs: 60 * 1000, max: 50 }),
Expand Down
Loading

0 comments on commit d7905dc

Please sign in to comment.