|
|
@ -3,9 +3,12 @@ import TheMovieDb from "@lib/tmdb"; |
|
|
|
import { env, secret } from "@server/util"; |
|
|
|
import { readFile } from "fs/promises"; |
|
|
|
import TVDB from "tvdb-v4"; |
|
|
|
import { request, Agent } from "https"; |
|
|
|
import Service from "./Service"; |
|
|
|
import TvDb from "./TvDb"; |
|
|
|
|
|
|
|
const CACHE_CLEAR_INTERVAL = 1000*10; // 60 seconds
|
|
|
|
|
|
|
|
export default class MovieSearch extends Service |
|
|
|
{ |
|
|
|
protected tmdb!: TheMovieDb; |
|
|
@ -15,8 +18,23 @@ export default class MovieSearch extends Service |
|
|
|
*/ |
|
|
|
protected tvdb!: TvDb; |
|
|
|
|
|
|
|
/** |
|
|
|
* Hold a cache of recently fetch movie IMDB ids to speed up request times |
|
|
|
*/ |
|
|
|
protected imdbCache: { [imdbId: string]: number }; |
|
|
|
|
|
|
|
/** |
|
|
|
* Hold the clear cache interval reference |
|
|
|
*/ |
|
|
|
private __clearCacheInterval: NodeJS.Timeout | null; |
|
|
|
|
|
|
|
/** |
|
|
|
* Create a new Movie Search service instance |
|
|
|
*/ |
|
|
|
public constructor(app: Application) { |
|
|
|
super("Movie Search", app); |
|
|
|
this.imdbCache = {}; |
|
|
|
this.__clearCacheInterval = null; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
@ -41,13 +59,69 @@ export default class MovieSearch extends Service |
|
|
|
// no-op
|
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Store an IMDb ID in cache |
|
|
|
*/ |
|
|
|
protected cacheImdbId(id: string) { |
|
|
|
this.imdbCache[id] = Date.now() + CACHE_CLEAR_INTERVAL; |
|
|
|
if (this.__clearCacheInterval === null) { |
|
|
|
this.__clearCacheInterval = setInterval(() => this.cleanImdbCache(), CACHE_CLEAR_INTERVAL); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Clean the IMDb cache |
|
|
|
*/ |
|
|
|
protected cleanImdbCache() { |
|
|
|
let now = Date.now(); |
|
|
|
let remaining = 0; |
|
|
|
for (let key in this.imdbCache) { |
|
|
|
if (now > this.imdbCache[key]) { |
|
|
|
delete this.imdbCache[key]; |
|
|
|
} else { |
|
|
|
remaining++; |
|
|
|
} |
|
|
|
} |
|
|
|
if (remaining == 0) { |
|
|
|
clearInterval(<NodeJS.Timeout>this.__clearCacheInterval); |
|
|
|
this.__clearCacheInterval = null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Interface -----------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/** |
|
|
|
* Verify the IMDb ID exists |
|
|
|
*/ |
|
|
|
public verifyImdbId(id: string) { |
|
|
|
return new Promise<boolean>((resolve, reject) => { |
|
|
|
// If the ID is cached, no need to fetch it
|
|
|
|
if (id in this.imdbCache) { |
|
|
|
resolve(true); |
|
|
|
} |
|
|
|
// Verify the movie exists on IMDb by checking for a 404
|
|
|
|
let req = request({ method: "HEAD", host: "www.imdb.com", path: `/title/${id}/` }, (response) => { |
|
|
|
response.resume(); |
|
|
|
if (response.statusCode == undefined) { |
|
|
|
reject(); |
|
|
|
return; |
|
|
|
} |
|
|
|
resolve(response.statusCode === 200); |
|
|
|
response.destroy(); |
|
|
|
}); |
|
|
|
req.end(); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get the details of a movie |
|
|
|
*/ |
|
|
|
public async details(id: number) { |
|
|
|
return await this.tmdb.movie(id); |
|
|
|
let movie = await this.tmdb.movie(id); |
|
|
|
if (movie.imdb_id != null) { |
|
|
|
this.cacheImdbId(movie.imdb_id); |
|
|
|
} |
|
|
|
return movie; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|