import { HTMLElement, parse } from 'node-html-parser'; import { CSFDFilmTypes } from '../dto/global'; import { CSFDMovie, MovieJsonLd } from '../dto/movie'; import { fetchPage } from '../fetchers'; import { getLocalizedCreatorLabel, getMovieBoxMovies, getMovieColorRating, getMovieDescriptions, getMovieDuration, getMovieGenres, getMovieGroup, getMovieOrigins, getMoviePoster, getMoviePremieres, getMovieRandomPhoto, getMovieRating, getMovieRatingCount, getMovieTags, getMovieTitle, getMovieTitlesOther, getMovieTrivia, getMovieType, getMovieVods, getMovieYear } from '../helpers/movie.helper'; import { CSFDOptions } from '../types'; import { movieUrl } from '../vars'; export class MovieScraper { public async movie(movieId: number, options?: CSFDOptions): Promise { const id = Number(movieId); if (isNaN(id)) { throw new Error('node-csfd-api: movieId must be a valid number'); } const url = movieUrl(id, { language: options?.language }); const response = await fetchPage(url, { ...options?.request }); const movieHtml = parse(response); const pageClasses = movieHtml.querySelector('.page-content').classNames.split(' '); const asideNode = movieHtml.querySelector('.aside-movie-profile'); const movieNode = movieHtml.querySelector('.main-movie-profile'); const jsonLdString = movieHtml.querySelector('script[type="application/ld+json"]').innerText; let jsonLd: MovieJsonLd | null = null; try { jsonLd = JSON.parse(jsonLdString); } catch (e) { console.error('node-csfd-api: Error parsing JSON-LD', e); } return this.buildMovie(+movieId, movieNode, asideNode, pageClasses, jsonLd, options); } private buildMovie( movieId: number, el: HTMLElement, asideEl: HTMLElement, pageClasses: string[], jsonLd: MovieJsonLd | null, options: CSFDOptions ): CSFDMovie { return { id: movieId, title: getMovieTitle(el), year: getMovieYear(jsonLd), duration: getMovieDuration(jsonLd, el), descriptions: getMovieDescriptions(el), genres: getMovieGenres(el), type: getMovieType(el) as CSFDFilmTypes, url: movieUrl(movieId, { language: options?.language }), origins: getMovieOrigins(el), colorRating: getMovieColorRating(pageClasses), rating: getMovieRating(asideEl), ratingCount: getMovieRatingCount(asideEl), titlesOther: getMovieTitlesOther(el), poster: getMoviePoster(el), photo: getMovieRandomPhoto(el), trivia: getMovieTrivia(el), creators: { directors: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'directors')), writers: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'writers')), cinematography: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'cinematography')), music: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'music')), actors: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'actors')), basedOn: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'basedOn')), producers: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'producers')), filmEditing: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'filmEditing')), costumeDesign: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'costumeDesign')), productionDesign: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'productionDesign')) }, vod: getMovieVods(asideEl), tags: getMovieTags(asideEl), premieres: getMoviePremieres(asideEl), related: getMovieBoxMovies(asideEl, 'Související'), similar: getMovieBoxMovies(asideEl, 'Podobné') }; } }