fix(scanner): fix jellyfin scanner with tvdb provider

This commit is contained in:
TOomaAh
2025-03-20 02:29:11 +01:00
parent 5232950ac8
commit 3952312884
2 changed files with 96 additions and 22 deletions

View File

@@ -132,7 +132,29 @@ class Tvdb extends ExternalAPI implements TvShowIndexer {
tvdbId: number;
language?: string;
}): Promise<TmdbTvDetails> {
return await this.tmdb.getTvShow({ tvId: tvdbId, language: language });
try {
const tmdbTvShow = await this.tmdb.getShowByTvdbId({
tvdbId: tvdbId,
language,
});
try {
await this.refreshToken();
const validTvdbId = this.getTvdbIdFromTmdb(tmdbTvShow);
if (this.isValidTvdbId(validTvdbId)) {
return this.enrichTmdbShowWithTvdbData(tmdbTvShow, validTvdbId);
}
return tmdbTvShow;
} catch (error) {
return tmdbTvShow;
}
} catch (error) {
this.handleError('Failed to fetch TV show details', error);
throw error;
}
}
public async getTvShow({
@@ -143,18 +165,25 @@ class Tvdb extends ExternalAPI implements TvShowIndexer {
language?: string;
}): Promise<TmdbTvDetails> {
try {
await this.refreshToken();
const tmdbTvShow = await this.tmdb.getTvShow({ tvId, language });
const tvdbId = this.getTvdbIdFromTmdb(tmdbTvShow);
if (this.isValidTvdbId(tvdbId)) {
return await this.enrichTmdbShowWithTvdbData(tmdbTvShow, tvdbId);
try {
await this.refreshToken();
const tvdbId = this.getTvdbIdFromTmdb(tmdbTvShow);
if (this.isValidTvdbId(tvdbId)) {
return await this.enrichTmdbShowWithTvdbData(tmdbTvShow, tvdbId);
}
return tmdbTvShow;
} catch (error) {
this.handleError('Failed to fetch TV show details', error);
return tmdbTvShow;
}
return tmdbTvShow;
} catch (error) {
this.handleError('Failed to fetch TV show details', error);
throw error;
return this.tmdb.getTvShow({ tvId, language });
}
}
@@ -167,26 +196,32 @@ class Tvdb extends ExternalAPI implements TvShowIndexer {
seasonNumber: number;
language?: string;
}): Promise<TmdbSeasonWithEpisodes> {
await this.refreshToken();
if (seasonNumber === 0) {
return this.createEmptySeasonResponse(tvId);
}
try {
const tmdbTvShow = await this.tmdb.getTvShow({ tvId, language });
const tvdbId = this.getTvdbIdFromTmdb(tmdbTvShow);
if (!this.isValidTvdbId(tvdbId)) {
try {
await this.refreshToken();
const tvdbId = this.getTvdbIdFromTmdb(tmdbTvShow);
if (!this.isValidTvdbId(tvdbId)) {
return await this.tmdb.getTvSeason({ tvId, seasonNumber, language });
}
return await this.getTvdbSeasonData(tvdbId, seasonNumber, tvId);
} catch (error) {
this.handleError('Failed to fetch TV season details', error);
return await this.tmdb.getTvSeason({ tvId, seasonNumber, language });
}
return await this.getTvdbSeasonData(tvdbId, seasonNumber, tvId);
} catch (error) {
logger.error(
`[TVDB] Failed to fetch TV season details: ${error.message}`
);
return await this.tmdb.getTvSeason({ tvId, seasonNumber, language });
throw error;
}
}

View File

@@ -1,8 +1,12 @@
import type { TvShowIndexer } from '@server/api/indexer';
import type { JellyfinLibraryItem } from '@server/api/jellyfin';
import JellyfinAPI from '@server/api/jellyfin';
import { getMetadataProvider } from '@server/api/metadata';
import TheMovieDb from '@server/api/themoviedb';
import type { TmdbTvDetails } from '@server/api/themoviedb/interfaces';
import { ANIME_KEYWORD_ID } from '@server/api/themoviedb/constants';
import type {
TmdbKeyword,
TmdbTvDetails,
} from '@server/api/themoviedb/interfaces';
import { MediaStatus, MediaType } from '@server/constants/media';
import { MediaServerType } from '@server/constants/server';
import { getRepository } from '@server/datasource';
@@ -31,7 +35,6 @@ interface SyncStatus {
class JellyfinScanner {
private sessionId: string;
private tmdb: TheMovieDb;
private tvShowIndexer: TvShowIndexer;
private jfClient: JellyfinAPI;
private items: JellyfinLibraryItem[] = [];
private progress = 0;
@@ -195,6 +198,42 @@ class JellyfinScanner {
}
}
private async getTvShow({
tmdbId,
tvdbId,
}: {
tmdbId?: number;
tvdbId?: number;
}): Promise<TmdbTvDetails> {
let tvShow;
if (tmdbId) {
tvShow = await this.tmdb.getTvShow({
tvId: Number(tmdbId),
});
} else if (tvdbId) {
tvShow = await this.tmdb.getShowByTvdbId({
tvdbId: Number(tvdbId),
});
} else {
throw new Error('No ID provided');
}
const indexer = tvShow.keywords.results.some(
(keyword: TmdbKeyword) => keyword.id === ANIME_KEYWORD_ID
)
? await getMetadataProvider('anime')
: await getMetadataProvider('tv');
if (!(indexer instanceof TheMovieDb)) {
tvShow = await indexer.getTvShow({
tvId: Number(tmdbId),
});
}
return tvShow;
}
private async processShow(jellyfinitem: JellyfinLibraryItem) {
const mediaRepository = getRepository(Media);
@@ -215,8 +254,8 @@ class JellyfinScanner {
if (metadata.ProviderIds.Tmdb) {
try {
tvShow = await this.tvShowIndexer.getTvShow({
tvId: Number(metadata.ProviderIds.Tmdb),
tvShow = await this.getTvShow({
tmdbId: Number(metadata.ProviderIds.Tmdb),
});
} catch {
this.log('Unable to find TMDb ID for this title.', 'debug', {
@@ -226,8 +265,8 @@ class JellyfinScanner {
}
if (!tvShow && metadata.ProviderIds.Tvdb) {
try {
tvShow = await this.tvShowIndexer.getShowByTvdbId({
tvdbId: Number(metadata.ProviderIds.Tvdb),
tvShow = await this.getTvShow({
tvdbId: Number(metadata.ProviderIds.Tmdb),
});
} catch {
this.log('Unable to find TVDb ID for this title.', 'debug', {