feat(api): decouple media requests from media info

This commit is contained in:
sct
2020-09-21 00:01:38 +09:00
parent 4aa74319e0
commit 8577db1be1
21 changed files with 409 additions and 264 deletions

View File

@@ -1,7 +1,7 @@
import { Router } from 'express';
import TheMovieDb from '../api/themoviedb';
import { mapMovieResult, mapTvResult } from '../models/Search';
import { MediaRequest } from '../entity/MediaRequest';
import Media from '../entity/Media';
const discoverRoutes = Router();
@@ -13,7 +13,7 @@ discoverRoutes.get('/movies', async (req, res) => {
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(
const media = await Media.getRelatedMedia(
data.results.map((result) => result.id)
);
@@ -24,7 +24,7 @@ discoverRoutes.get('/movies', async (req, res) => {
results: data.results.map((result) =>
mapMovieResult(
result,
requests.find((req) => req.mediaId === result.id)
media.find((req) => req.tmdbId === result.id)
)
),
});
@@ -38,7 +38,7 @@ discoverRoutes.get('/tv', async (req, res) => {
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(
const media = await Media.getRelatedMedia(
data.results.map((result) => result.id)
);
@@ -49,7 +49,7 @@ discoverRoutes.get('/tv', async (req, res) => {
results: data.results.map((result) =>
mapTvResult(
result,
requests.find((req) => req.mediaId === result.id)
media.find((req) => req.tmdbId === result.id)
)
),
});

View File

@@ -3,6 +3,7 @@ import TheMovieDb from '../api/themoviedb';
import { mapMovieDetails } from '../models/Movie';
import { MediaRequest } from '../entity/MediaRequest';
import { mapMovieResult } from '../models/Search';
import Media from '../entity/Media';
const movieRoutes = Router();
@@ -14,9 +15,9 @@ movieRoutes.get('/:id', async (req, res) => {
language: req.query.language as string,
});
const request = await MediaRequest.getRequest(movie.id);
const media = await Media.getMedia(movie.id);
return res.status(200).json(mapMovieDetails(movie, request));
return res.status(200).json(mapMovieDetails(movie, media));
});
movieRoutes.get('/:id/recommendations', async (req, res) => {
@@ -28,7 +29,7 @@ movieRoutes.get('/:id/recommendations', async (req, res) => {
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(
const media = await Media.getRelatedMedia(
results.results.map((result) => result.id)
);
@@ -39,7 +40,7 @@ movieRoutes.get('/:id/recommendations', async (req, res) => {
results: results.results.map((result) =>
mapMovieResult(
result,
requests.find((req) => req.mediaId === result.id)
media.find((req) => req.tmdbId === result.id)
)
),
});
@@ -54,7 +55,7 @@ movieRoutes.get('/:id/similar', async (req, res) => {
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(
const media = await Media.getRelatedMedia(
results.results.map((result) => result.id)
);
@@ -65,7 +66,7 @@ movieRoutes.get('/:id/similar', async (req, res) => {
results: results.results.map((result) =>
mapMovieResult(
result,
requests.find((req) => req.mediaId === result.id)
media.find((req) => req.tmdbId === result.id)
)
),
});

View File

@@ -2,8 +2,12 @@ import { Router } from 'express';
import { isAuthenticated } from '../middleware/auth';
import { Permission } from '../lib/permissions';
import { getRepository } from 'typeorm';
import { MediaRequest, MediaRequestStatus } from '../entity/MediaRequest';
import { MediaRequest } from '../entity/MediaRequest';
import TheMovieDb from '../api/themoviedb';
import Media from '../entity/Media';
import MovieRequest from '../entity/MovieRequest';
import { MediaStatus, MediaRequestStatus, MediaType } from '../constants/media';
import TvRequest from '../entity/TvRequest';
const requestRoutes = Router();
@@ -15,10 +19,12 @@ requestRoutes.get('/', async (req, res, next) => {
order: {
id: 'DESC',
},
relations: ['media'],
take: 20,
})
: await requestRepository.find({
where: { requestedBy: { id: req.user?.id } },
relations: ['media'],
order: {
id: 'DESC',
},
@@ -36,26 +42,59 @@ requestRoutes.post(
isAuthenticated(Permission.REQUEST),
async (req, res, next) => {
const tmdb = new TheMovieDb();
const requestRepository = getRepository(MediaRequest);
const mediaRepository = getRepository(Media);
try {
const media =
const tmdbMedia =
req.body.mediaType === 'movie'
? await tmdb.getMovie({ movieId: req.body.mediaId })
: await tmdb.getTvShow({ tvId: req.body.mediaId });
const request = new MediaRequest({
mediaId: media.id,
mediaType: req.body.mediaType,
requestedBy: req.user,
// If the user is an admin or has the "auto approve" permission, automatically approve the request
status: req.user?.hasPermission(Permission.AUTO_APPROVE)
? MediaRequestStatus.APPROVED
: MediaRequestStatus.PENDING,
let media = await mediaRepository.findOne({
where: { tmdbId: req.body.mediaId },
});
await requestRepository.save(request);
if (!media) {
media = new Media({
tmdbId: tmdbMedia.id,
tvdbId: tmdbMedia.external_ids.tvdb_id,
status: MediaStatus.PENDING,
mediaType: req.body.mediaType,
});
await mediaRepository.save(media);
}
return res.status(201).json(request);
if (req.body.mediaType === 'movie') {
const requestRepository = getRepository(MovieRequest);
const request = new MovieRequest({
media,
requestedBy: req.user,
// If the user is an admin or has the "auto approve" permission, automatically approve the request
status: req.user?.hasPermission(Permission.AUTO_APPROVE)
? MediaRequestStatus.APPROVED
: MediaRequestStatus.PENDING,
});
await requestRepository.save(request);
return res.status(201).json(request);
} else if (req.body.mediaType === 'tv') {
const requestRepository = getRepository(TvRequest);
const request = new TvRequest({
media,
requestedBy: req.user,
// If the user is an admin or has the "auto approve" permission, automatically approve the request
status: req.user?.hasPermission(Permission.AUTO_APPROVE)
? MediaRequestStatus.APPROVED
: MediaRequestStatus.PENDING,
});
await requestRepository.save(request);
return res.status(201).json(request);
}
next({ status: 500, message: 'Invalid media type' });
} catch (e) {
next({ message: e.message, status: 500 });
}
@@ -96,7 +135,7 @@ requestRoutes.delete('/:requestId', async (req, res, next) => {
});
}
requestRepository.delete(request.id);
await requestRepository.delete(request.id);
return res.status(200).json(request);
} catch (e) {
@@ -106,7 +145,7 @@ requestRoutes.delete('/:requestId', async (req, res, next) => {
requestRoutes.get<{
requestId: string;
status: 'pending' | 'approve' | 'decline' | 'available';
status: 'pending' | 'approve' | 'decline';
}>(
'/:requestId/:status',
isAuthenticated(Permission.MANAGE_REQUESTS),
@@ -131,9 +170,6 @@ requestRoutes.get<{
case 'decline':
newStatus = MediaRequestStatus.DECLINED;
break;
case 'available':
newStatus = MediaRequestStatus.AVAILABLE;
break;
}
request.status = newStatus;

View File

@@ -1,7 +1,7 @@
import { Router } from 'express';
import TheMovieDb from '../api/themoviedb';
import { mapSearchResults } from '../models/Search';
import { MediaRequest } from '../entity/MediaRequest';
import Media from '../entity/Media';
const searchRoutes = Router();
@@ -14,7 +14,7 @@ searchRoutes.get('/', async (req, res) => {
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(
const media = await Media.getRelatedMedia(
results.results.map((result) => result.id)
);
@@ -22,7 +22,7 @@ searchRoutes.get('/', async (req, res) => {
page: results.page,
totalPages: results.total_pages,
totalResults: results.total_results,
results: mapSearchResults(results.results, requests),
results: mapSearchResults(results.results, media),
});
});

View File

@@ -3,6 +3,7 @@ import TheMovieDb from '../api/themoviedb';
import { MediaRequest } from '../entity/MediaRequest';
import { mapTvDetails } from '../models/Tv';
import { mapTvResult } from '../models/Search';
import Media from '../entity/Media';
const tvRoutes = Router();
@@ -14,9 +15,9 @@ tvRoutes.get('/:id', async (req, res) => {
language: req.query.language as string,
});
const request = await MediaRequest.getRequest(tv.id);
const media = await Media.getMedia(tv.id);
return res.status(200).json(mapTvDetails(tv, request));
return res.status(200).json(mapTvDetails(tv, media));
});
tvRoutes.get('/:id/recommendations', async (req, res) => {
@@ -28,7 +29,7 @@ tvRoutes.get('/:id/recommendations', async (req, res) => {
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(
const media = await Media.getRelatedMedia(
results.results.map((result) => result.id)
);
@@ -39,7 +40,7 @@ tvRoutes.get('/:id/recommendations', async (req, res) => {
results: results.results.map((result) =>
mapTvResult(
result,
requests.find((req) => req.mediaId === result.id)
media.find((req) => req.tmdbId === result.id)
)
),
});
@@ -54,7 +55,7 @@ tvRoutes.get('/:id/similar', async (req, res) => {
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(
const media = await Media.getRelatedMedia(
results.results.map((result) => result.id)
);
@@ -65,7 +66,7 @@ tvRoutes.get('/:id/similar', async (req, res) => {
results: results.results.map((result) =>
mapTvResult(
result,
requests.find((req) => req.mediaId === result.id)
media.find((req) => req.tmdbId === result.id)
)
),
});