UNPKG

@episodehunter/thetvdb

Version:
222 lines 8.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ensureArray = exports.handelHttpError = exports.getHigestRating = exports.TheTvDb = void 0; const node_fetch_1 = require("node-fetch"); const custom_erros_1 = require("./custom-erros"); const abort_controller_1 = require("abort-controller"); const noop = () => undefined; const logWrapper = (log, msg) => (val) => { log(msg); return val; }; class TheTvDb { constructor(apikey, options) { this.jwt = undefined; this.apikey = apikey; this.fetch = (options === null || options === void 0 ? void 0 : options.fetch) || node_fetch_1.default; const defaultNextTimeout = (currentTimeout) => { if (currentTimeout > 4000) { return null; } return currentTimeout + 1000; }; this.options = { timeout: (options === null || options === void 0 ? void 0 : options.timeout) || 2000, nextTimeout: (options === null || options === void 0 ? void 0 : options.nextTimeout) || defaultNextTimeout }; } get token() { if (!this.jwt) { this.jwt = this.fetchToken(); } return this.jwt; } fetchShow(theTvDbId, log = noop) { return this.get('https://api.thetvdb.com/series/' + theTvDbId, log) .then(handelHttpError) .then(res => res.json()) .then(logWrapper(log, `Done, getting back`)) .then(res => res.data); } async fetchShowEpisodes(theTvDbId, log = noop) { var _a; let episodes = []; let nextPageToLoad = 1; while (nextPageToLoad) { const response = await this.fetchEpisodePage(theTvDbId, nextPageToLoad, log); nextPageToLoad = (_a = response.links) === null || _a === void 0 ? void 0 : _a.next; episodes = [...episodes, ...response.data]; } return episodes; } /** * Fetch the latest episodes. * Will return somewhere between 0 and numberOfEpisodes + 99 episodes */ async fetchLatestShowEpisodes(theTvDbId, numberOfEpisodes, log = noop) { var _a; const response = await this.fetchEpisodePage(theTvDbId, 1, log); const lastPage = ((_a = response.links) === null || _a === void 0 ? void 0 : _a.last) || 1; if (lastPage === 1) { return response.data; } else if (lastPage === 2) { const result = await this.fetchEpisodePage(theTvDbId, 2, log); return [...response.data, ...result.data]; } let nextPageToLoad = lastPage; let episodes = []; while (episodes.length < numberOfEpisodes && nextPageToLoad) { const result = await this.fetchEpisodePage(theTvDbId, nextPageToLoad, log); episodes = [...result.data, ...episodes]; nextPageToLoad = result.links.prev; } return episodes; } fetchLastUpdateShowsList(lastUpdate, log = noop) { return this.get('https://api.thetvdb.com/updated/query?fromTime=' + lastUpdate, log) .then(handelHttpError) .then(res => res.json()) .then(res => res.data) .then(data => ensureArray(data)); } fetchEpisodeImage(episodeId, log = noop) { return this.get('https://api.thetvdb.com/episodes/' + episodeId, log) .then(handelHttpError) .then(res => res.json()) .then(res => res.data) .then((episode) => episode.filename) .then(rejectIfNot(new custom_erros_1.NotFound())) .then(filename => this.fetchImage(filename, log)); } fetchShowPoster(showId, log = noop) { return this.get(`https://api.thetvdb.com/series/${showId}/images/query?keyType=poster`, log) .then(handelHttpError) .then(res => res.json()) .then(res => res.data) .then(getHigestRating) .then(rejectIfNot(new custom_erros_1.NotFound())) .then(image => image.fileName) .then(filename => this.fetchImage(filename, log)); } fetchShowFanart(showId, log = noop) { return this.get(`https://api.thetvdb.com/series/${showId}/images/query?keyType=fanart`, log) .then(handelHttpError) .then(res => res.json()) .then(res => res.data) .then(getHigestRating) .then(rejectIfNot(new custom_erros_1.NotFound())) .then(image => image.fileName) .then(filename => this.fetchImage(filename, log)); } fetchEpisodePage(theTvDbId, page, log = noop) { return this.get(`https://api.thetvdb.com/series/${theTvDbId}/episodes?page=${page}`, log) .then(res => { // The tv db API has a bug where the next page can give a 404 if (res.status === 404) { return { data: [], links: {} }; } handelHttpError(res); return res.json(); }) .then(res => { return { data: ensureArray(res.data), links: res.links }; }) .then(logWrapper(log, `Done, getting back`)); } fetchImage(filename, log) { log(`Making request to: 'https://www.thetvdb.com/banners/${filename}'`); return this.fetch('https://www.thetvdb.com/banners/' + filename) .then(handelHttpError) .then(logWrapper(log, 'Parse the response as a buffer')) .then(response => response.buffer()) .then(logWrapper(log, 'Done and done')); } async get(url, log, timeout = this.options.timeout) { log('Making request to ' + url); const token = await this.token; const controller = new abort_controller_1.default(); const timeoutId = setTimeout(() => controller.abort(), timeout); try { const result = await this.fetch(url, { method: 'GET', headers: { Authorization: 'Bearer ' + token }, signal: controller.signal }); // The current type to not accept signal clearTimeout(timeoutId); log('We got a result from ' + url); return result; } catch (error) { clearTimeout(timeoutId); if (error.name === 'AbortError') { log(`Did not recive any reposne within ${timeout} ms. url: ` + url); const nextTimeout = this.options.nextTimeout(timeout); if (!nextTimeout) { log(`Giving up. url: ` + url); throw new custom_erros_1.Timeout(`Timeout after ${timeout} ms for url: ${url}`); } return this.get(url, log, nextTimeout); } if (error) { log(`Could not get any respone. ${error.name} ${error.message}. url: ` + url); } else { log(`Could not get any respone. url: ` + url); } throw error; } } fetchToken() { return this.fetch('https://api.thetvdb.com/login', { method: 'POST', body: JSON.stringify({ apikey: this.apikey }), headers: { 'Content-Type': 'application/json' } }) .then(handelHttpError) .then(res => res.json()) .then(result => result.token); } } exports.TheTvDb = TheTvDb; function getHigestRating(images) { return ensureArray(images).reduce((acc, image) => { if (image.ratingsInfo.average > acc.ratingsInfo.average) { return image; } else { return acc; } }, images[0]); } exports.getHigestRating = getHigestRating; function handelHttpError(res) { if (res.status === 404) { throw new custom_erros_1.NotFound(); } if (!res.ok) { throw new Error('Unable to make the http request: ' + res.statusText); } return res; } exports.handelHttpError = handelHttpError; function ensureArray(data) { if (Array.isArray(data)) { return data; } return []; } exports.ensureArray = ensureArray; function rejectIfNot(error) { return (val) => val ? Promise.resolve(val) : Promise.reject(error); } //# sourceMappingURL=the-tv-db.js.map