0.14.0-3 Analyze fix
This commit is contained in:
@@ -5,9 +5,58 @@ const logger = require('./logger').child('TMDB');
|
||||
|
||||
const TMDB_BASE_URL = 'https://api.themoviedb.org/3';
|
||||
const TMDB_IMAGE_BASE_URL = 'https://image.tmdb.org/t/p';
|
||||
const TMDB_TIMEOUT_MS = 10000;
|
||||
const TMDB_TIMEOUT_MS = 15000;
|
||||
|
||||
class TmdbService {
|
||||
isAbortError(error) {
|
||||
const name = String(error?.name || '').trim().toLowerCase();
|
||||
const message = String(error?.message || '').trim().toLowerCase();
|
||||
return name === 'aborterror' || message.includes('aborted');
|
||||
}
|
||||
|
||||
classifyRequestError(error) {
|
||||
if (this.isAbortError(error)) {
|
||||
return 'timeout';
|
||||
}
|
||||
const statusCode = Number(error?.statusCode || 0) || null;
|
||||
if (statusCode === 401 || statusCode === 403) {
|
||||
return 'auth';
|
||||
}
|
||||
if (statusCode >= 500) {
|
||||
return 'upstream';
|
||||
}
|
||||
if (statusCode >= 400) {
|
||||
return 'request_failed';
|
||||
}
|
||||
return 'network';
|
||||
}
|
||||
|
||||
readFailureCode(rows) {
|
||||
const value = rows && typeof rows.tmdbFailureCode === 'string'
|
||||
? rows.tmdbFailureCode
|
||||
: '';
|
||||
const normalized = String(value || '').trim().toLowerCase();
|
||||
return normalized || null;
|
||||
}
|
||||
|
||||
attachFailureCode(rows, failureCode = null) {
|
||||
const output = Array.isArray(rows) ? rows : [];
|
||||
const normalized = String(failureCode || '').trim().toLowerCase();
|
||||
if (!normalized) {
|
||||
return output;
|
||||
}
|
||||
try {
|
||||
Object.defineProperty(output, 'tmdbFailureCode', {
|
||||
value: normalized,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
} catch (_error) {
|
||||
output.tmdbFailureCode = normalized;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
normalizeNameList(values = [], options = {}) {
|
||||
const maxItems = Math.max(1, Number(options.maxItems || 10));
|
||||
const source = Array.isArray(values) ? values : [];
|
||||
@@ -130,24 +179,30 @@ class TmdbService {
|
||||
}
|
||||
const language = await this.resolveLanguage(options.language);
|
||||
|
||||
const data = await this.request('/search/tv', {
|
||||
query: {
|
||||
query: normalizedQuery,
|
||||
first_air_date_year: options.year || undefined,
|
||||
language,
|
||||
page: options.page || 1,
|
||||
include_adult: false
|
||||
}
|
||||
}).catch((error) => {
|
||||
let data = null;
|
||||
try {
|
||||
data = await this.request('/search/tv', {
|
||||
query: {
|
||||
query: normalizedQuery,
|
||||
first_air_date_year: options.year || undefined,
|
||||
language,
|
||||
page: options.page || 1,
|
||||
include_adult: false
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
const failureCode = this.classifyRequestError(error);
|
||||
logger.warn('search:failed', {
|
||||
query: normalizedQuery,
|
||||
error: error?.message || String(error)
|
||||
error: error?.message || String(error),
|
||||
failureCode,
|
||||
statusCode: Number(error?.statusCode || 0) || null
|
||||
});
|
||||
return null;
|
||||
});
|
||||
return this.attachFailureCode([], failureCode);
|
||||
}
|
||||
|
||||
const rows = Array.isArray(data?.results) ? data.results : [];
|
||||
return rows
|
||||
const normalizedRows = rows
|
||||
.map((row) => ({
|
||||
id: Number(row?.id || 0) || null,
|
||||
title: String(row?.name || row?.original_name || '').trim() || null,
|
||||
@@ -162,6 +217,7 @@ class TmdbService {
|
||||
popularity: Number(row?.popularity || 0) || 0
|
||||
}))
|
||||
.filter((row) => row.id && row.title);
|
||||
return this.attachFailureCode(normalizedRows, null);
|
||||
}
|
||||
|
||||
async getSeriesDetails(seriesId, options = {}) {
|
||||
@@ -366,8 +422,9 @@ class TmdbService {
|
||||
|
||||
async searchSeriesWithSeasons(query, options = {}) {
|
||||
const candidates = await this.searchSeries(query, options);
|
||||
const failureCode = this.readFailureCode(candidates);
|
||||
if (candidates.length === 0) {
|
||||
return [];
|
||||
return this.attachFailureCode([], failureCode);
|
||||
}
|
||||
|
||||
const limit = Math.max(1, Math.min(10, Number(options.limit || 5)));
|
||||
@@ -387,7 +444,8 @@ class TmdbService {
|
||||
}));
|
||||
}));
|
||||
|
||||
return expanded.flat().filter((item) => item?.tmdbId && item?.title);
|
||||
const normalized = expanded.flat().filter((item) => item?.tmdbId && item?.title);
|
||||
return this.attachFailureCode(normalized, failureCode);
|
||||
}
|
||||
|
||||
async searchSeriesWithSeason(query, seasonNumber, options = {}) {
|
||||
@@ -397,8 +455,9 @@ class TmdbService {
|
||||
}
|
||||
|
||||
const candidates = await this.searchSeries(query, options);
|
||||
const failureCode = this.readFailureCode(candidates);
|
||||
if (candidates.length === 0) {
|
||||
return [];
|
||||
return this.attachFailureCode([], failureCode);
|
||||
}
|
||||
|
||||
const limit = Math.max(1, Math.min(10, Number(options.limit || 5)));
|
||||
@@ -417,11 +476,12 @@ class TmdbService {
|
||||
};
|
||||
}));
|
||||
|
||||
return withSeasons
|
||||
const normalized = withSeasons
|
||||
.filter((candidate) => candidate.season && candidate.season.episodeCount > 0)
|
||||
.map((candidate) => this.buildSeriesMetadataCandidate(candidate, {
|
||||
seasonNumber: normalizedSeason
|
||||
}));
|
||||
return this.attachFailureCode(normalized, failureCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user