From 6f4bc10f5af77eba8794bb3345533eed170ed9fc Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Sun, 10 Mar 2024 21:38:55 +0000 Subject: [PATCH] Fix series parsing --- .../src/lib/services/metadata_service.ts | 10 ++-- .../lib/services/torrent_entries_service.ts | 1 + .../src/lib/services/torrent_file_service.ts | 58 ++++++++++++++++--- .../lib/services/torrent_subtitle_service.ts | 2 +- 4 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index 593e66a..f10cc46 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -141,9 +141,9 @@ export class MetadataService implements IMetadataService { ? body.meta.videos.map(video => ({ name: video.name, season: video.season, - episode: video.episode, + episode: video.number, imdbSeason: video.season, - imdbEpisode: video.episode, + imdbEpisode: video.number, })) : [], episodeCount: body.meta?.videos @@ -204,13 +204,13 @@ export class MetadataService implements IMetadataService { private getIMDbIdFromNameToImdb = (name: string, info: IMetaDataQuery): Promise => { const {year} = info; - const {type} = info; + const type = info.type === TorrentType.Movie ? 'movie' : 'series'; return new Promise((resolve, reject) => { - nameToImdb({name, year, type}, function (err: Error, res: string) { + nameToImdb({name, year, type}, function (err: Error | null, res: string) { if (res) { resolve(res); } else { - reject(err || new Error('Failed IMDbId search')); + reject(err || new Error('Failed to get IMDb id from name-to-imdb')); } }); }); diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts index edded71..72e6fea 100644 --- a/src/node/consumer/src/lib/services/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -92,6 +92,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { const newVideo: IFileCreationAttributes = {...video, infoHash: video.infoHash, title: video.title}; if (!newVideo.kitsuId) { newVideo.kitsuId = 0; + newVideo.kitsuEpisode = 0; } return this.repository.createFile(newVideo) }))) diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index df85bca..3b29d5e 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -195,6 +195,10 @@ export class TorrentFileService implements ITorrentFileService { title: file.path || file.title, size: file.size, imdbId: torrent?.imdbId?.toString() || file?.imdbId?.toString() || '', + kitsuId: torrent?.kitsuId || file.kitsuId || 0, + imdbSeason: file.imdbSeason, + imdbEpisode: file.imdbEpisode, + kitsuEpisode: file.kitsuEpisode, }]); } return Promise.resolve([]); @@ -206,11 +210,11 @@ export class TorrentFileService implements ITorrentFileService { title: file.path || file.title, size: file.size, imdbId: file?.imdbId?.toString() || torrent?.imdbId?.toString() || '', - imdbSeason: file.season, + imdbSeason: file.imdbSeason, season: file.season, imdbEpisode: file.episodes && file.episodes[index], episode: file.episodes && file.episodes[index], - kitsuEpisode: file.episodes && file.episodes[index], + kitsuEpisode: file.kitsuId && file.kitsuId !== 0 && file.episodes && file.episodes[index], episodes: file.episodes, kitsuId: parseInt(file.kitsuId?.toString() || torrent.kitsuId?.toString() || '0') || 0, }))) @@ -493,13 +497,21 @@ export class TorrentFileService implements ITorrentFileService { const episodeMapping = seasonMapping && file && file.episodes && file.episodes[0] && seasonMapping[file.episodes[0]] || null; if (episodeMapping && Number.isInteger(episodeMapping.season)) { - file.imdbId = metadata.imdbId?.toString(); + file.imdbId = metadata.imdbId?.toString() !== "NaN" ? metadata.imdbId?.toString() : file.imdbId; file.season = episodeMapping.season; file.episodes = file.episodes && file.episodes.map(ep => (seasonMapping && seasonMapping[ep]) ? Number(seasonMapping[ep].episode) : 0); } else { - file.season = undefined; file.episodes = undefined; } + + if (file.imdbId && file.season && file.episodes?.length > 0 && file.imdbEpisode === undefined && file.episode === undefined) { + file.imdbEpisode = file.episodes[0]; + file.episode = file.episodes[0]; + file.imdbSeason = file.season; + } + + this.patchMissingImdbValues(file); + this.patchMissingKitsuValues(file); }); } else if (metadata.videos.some(video => video.episode)) { // imdb episode info is base @@ -512,7 +524,7 @@ export class TorrentFileService implements ITorrentFileService { if (seriesMapping[file.season]) { const seasonMapping = seriesMapping[file.season]; - file.imdbId = metadata.imdbId?.toString(); + file.imdbId = metadata.imdbId?.toString() !== "NaN" ? metadata.imdbId?.toString() : file.imdbId; file.kitsuId = seasonMapping[file.episodes[0]] && parseInt(seasonMapping[file.episodes[0]].id || '0') || 0; file.episodes = file.episodes.map(ep => seasonMapping[ep]?.episode) .filter((ep): ep is number => ep !== undefined); @@ -532,7 +544,7 @@ export class TorrentFileService implements ITorrentFileService { if (differentTitlesCount >= 1 && (isAbsoluteOrder || isNormalOrder)) { const {season} = file; const [episode] = file.episodes; - file.imdbId = metadata.imdbId?.toString(); + file.imdbId = metadata.imdbId?.toString() !== "NaN" ? metadata.imdbId?.toString() : file.imdbId; file.season = file.season - 1; file.episodes = file.episodes.map(ep => isAbsoluteOrder ? ep : ep + skippedCount); const currentEpisode = seriesMapping[season][episode]; @@ -549,17 +561,35 @@ export class TorrentFileService implements ITorrentFileService { // sometimes series might be named with sequel season but it's not a season on imdb and a new title // eslint-disable-next-line prefer-destructuring const seasonMapping = seriesMapping[1]; - file.imdbId = metadata.imdbId?.toString(); + file.imdbId = metadata.imdbId?.toString() !== "NaN" ? metadata.imdbId?.toString() : file.imdbId; file.season = 1; file.kitsuId = parseInt(seasonMapping[file.episodes[0]].id || '0') || 0; file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].episode) .filter((ep): ep is number => ep !== undefined); } + + this.patchMissingImdbValues(file); + this.patchMissingKitsuValues(file); }); } return files; }; + private patchMissingKitsuValues = (file: IFileAttributes) : void => { + if (file.kitsuId !== 0 && file.kitsuId !== undefined && file.season && file.episodes?.length > 0 && file.imdbEpisode === undefined && file.episode === undefined) { + file.kitsuEpisode = file.episodes[0]; + file.episode = file.episodes[0]; + } + }; + + private patchMissingImdbValues = (file: IFileAttributes) : void => { + if (file.imdbId && file.season && file.episodes?.length > 0 && file.imdbEpisode === undefined && file.episode === undefined) { + file.imdbEpisode = file.episodes[0]; + file.episode = file.episodes[0]; + file.imdbSeason = file.season; + } + }; + private needsCinemetaMetadataForAnime = (files: IFileAttributes[], metadata: IMetadataResponse): boolean => { if (!metadata || !metadata.imdbId || !metadata.videos || !metadata.videos.length) { return false; @@ -649,7 +679,7 @@ export class TorrentFileService implements ITorrentFileService { private isFeaturette = (video: IFileAttributes): boolean => /featurettes?\/|extras-grym/i.test(video.path!); private parseSeriesVideo = (video: IFileAttributes): IFileAttributes => { - const videoInfo = parse(video.title); + const videoInfo = parse(video.path); // the episode may be in a folder containing season number if (!Number.isInteger(videoInfo.season) && video.path?.includes('/')) { const folders = video.path?.split('/'); @@ -691,7 +721,17 @@ export class TorrentFileService implements ITorrentFileService { videoInfo.episode = videoInfo.episodes && videoInfo.episodes[0]; } - return {...video, ...videoInfo}; + let response : IFileAttributes = {...video, ...videoInfo}; + + if (video.imdbId && video.imdbId !== "0") { + response = {...response, imdbEpisode: videoInfo.episode, imdbSeason: videoInfo.season}; + } + + if (video.kitsuId && video.kitsuId !== 0) { + response = {...response, kitsuEpisode: videoInfo.episode}; + } + + return response; }; private isMovieVideo = (torrent: IParsedTorrent, video: IFileAttributes, otherVideos: IFileAttributes[], hasMovies: boolean): boolean => { diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts index 654418d..b9865e1 100644 --- a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -41,7 +41,7 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { return Object.assign(video, { fileName: fileName, folderName: folderName, - ...this.parseFilename(video.title.toString() || '') + ...this.parseFilename(video.path || '') }); }