feat: add collections (#484)

closes #418
This commit is contained in:
sct
2020-12-24 16:31:56 +09:00
committed by GitHub
parent f2ebba7b1d
commit a333a09582
13 changed files with 526 additions and 17 deletions

View File

@@ -190,6 +190,12 @@ export interface TmdbMovieDetails {
cast: TmdbCreditCast[];
crew: TmdbCreditCrew[];
};
belongs_to_collection?: {
id: number;
name: string;
poster_path?: string;
backdrop_path?: string;
};
external_ids: TmdbExternalIds;
}
@@ -344,6 +350,15 @@ export interface TmdbSeasonWithEpisodes extends TmdbTvSeasonResult {
external_ids: TmdbExternalIds;
}
export interface TmdbCollection {
id: number;
name: string;
overview?: string;
poster_path?: string;
backdrop_path?: string;
parts: TmdbMovieResult[];
}
class TheMovieDb {
private apiKey = 'db55323b8d3e4154498498a75642b381';
private axios: AxiosInstance;
@@ -866,6 +881,29 @@ class TheMovieDb {
);
}
}
public async getCollection({
collectionId,
language = 'en-US',
}: {
collectionId: number;
language?: string;
}): Promise<TmdbCollection> {
try {
const response = await this.axios.get<TmdbCollection>(
`/collection/${collectionId}`,
{
params: {
language,
},
}
);
return response.data;
} catch (e) {
throw new Error(`[TMDB] Failed to fetch collection: ${e.message}`);
}
}
}
export default TheMovieDb;

View File

@@ -0,0 +1,29 @@
import { TmdbCollection } from '../api/themoviedb';
import Media from '../entity/Media';
import { mapMovieResult, MovieResult } from './Search';
export interface Collection {
id: number;
name: string;
overview?: string;
posterPath?: string;
backdropPath?: string;
parts: MovieResult[];
}
export const mapCollection = (
collection: TmdbCollection,
media: Media[]
): Collection => ({
id: collection.id,
name: collection.name,
overview: collection.overview,
posterPath: collection.poster_path,
backdropPath: collection.backdrop_path,
parts: collection.parts.map((part) =>
mapMovieResult(
part,
media?.find((req) => req.tmdbId === part.id)
)
),
});

View File

@@ -46,6 +46,12 @@ export interface MovieDetails {
cast: Cast[];
crew: Crew[];
};
collection?: {
id: number;
name: string;
posterPath?: string;
backdropPath?: string;
};
mediaInfo?: Media;
externalIds: ExternalIds;
}
@@ -87,6 +93,14 @@ export const mapMovieDetails = (
cast: movie.credits.cast.map(mapCast),
crew: movie.credits.crew.map(mapCrew),
},
collection: movie.belongs_to_collection
? {
id: movie.belongs_to_collection.id,
name: movie.belongs_to_collection.name,
posterPath: movie.belongs_to_collection.poster_path,
backdropPath: movie.belongs_to_collection.backdrop_path,
}
: undefined,
externalIds: mapExternalIds(movie.external_ids),
mediaInfo: media,
});

View File

@@ -0,0 +1,27 @@
import { Router } from 'express';
import TheMovieDb from '../api/themoviedb';
import Media from '../entity/Media';
import { mapCollection } from '../models/Collection';
const collectionRoutes = Router();
collectionRoutes.get<{ id: string }>('/:id', async (req, res, next) => {
const tmdb = new TheMovieDb();
try {
const collection = await tmdb.getCollection({
collectionId: Number(req.params.id),
language: req.query.language as string,
});
const media = await Media.getRelatedMedia(
collection.parts.map((part) => part.id)
);
return res.status(200).json(mapCollection(collection, media));
} catch (e) {
return next({ status: 404, message: 'Collection does not exist' });
}
});
export default collectionRoutes;

View File

@@ -12,6 +12,7 @@ import movieRoutes from './movie';
import tvRoutes from './tv';
import mediaRoutes from './media';
import personRoutes from './person';
import collectionRoutes from './collection';
const router = Router();
@@ -34,6 +35,7 @@ router.use('/movie', isAuthenticated(), movieRoutes);
router.use('/tv', isAuthenticated(), tvRoutes);
router.use('/media', isAuthenticated(), mediaRoutes);
router.use('/person', isAuthenticated(), personRoutes);
router.use('/collection', isAuthenticated(), collectionRoutes);
router.use('/auth', authRoutes);
router.get('/', (_req, res) => {