import pLimit from "p-limit" ; import { getKanpai , getFirstMatch , LETTERBOXD_ORIGIN } from "./util" ; import * as cache from "../cache/index" ; import { logger } from "../logger" ; const moviesLogger = logger . child ( { module : 'MoviesDetails' } ) ; const IMDB_REGEX = /imdb\.com\/title\/(.*?)(\/|$)/i ; const TMDB_REGEX = /themoviedb\.org\/movie\/(.*?)(\/|$)/ ; export interface LetterboxdMovieDetails { slug : string ; name : string ; published : string ; imdb : string ; tmdb ? : string ; } export const getMoviesDetailCached = async ( slugs , concurrencyLimit = 7 , onDetail ? , shouldCancel ? ) => { slugs = slugs . filter ( slug => slug ) ; const limit = pLimit ( concurrencyLimit ) ; const movies = await Promise . all ( slugs . map ( async ( slug ) => { const detail = await limit ( ( ) => { if ( shouldCancel && shouldCancel ( ) ) { return ; } return getCachedMovieDetail ( slug ) ; } ) ; if ( onDetail && detail ) { onDetail ( detail ) ; } return detail ; } ) ) ; return movies . filter ( movie => movie ) ; } ; export const getMovieDetail = async ( slug ) => { const details = await getKanpai < LetterboxdMovieDetails > ( `${ LETTERBOXD_ORIGIN }${ slug }` , { name : '.headline-1' , published : '#featured-film-header .number' , imdb : [ '[data-track-action="imdb" i]' , '[href]' , getFirstMatch ( IMDB_REGEX ) ] , tmdb : [ '[data-track-action="tmdb" i]' , '[href]' , getFirstMatch ( TMDB_REGEX ) ] } ) ; details . slug = slug ; return details ; } ; export const getCachedMovieDetail = async ( slug ) => { if ( await cache . has ( slug ) ) { moviesLogger . debug ( `Fetched '${ slug }' from redis.` ) ; return await cache . get ( slug ) ; } const data = await getMovieDetail ( slug ) ; moviesLogger . debug ( `Fetched '${ slug }' live.` ) ; await cache . set ( slug , data ) ; return data ; } ;