Skip to content

Commit 3e281f8

Browse files
Merge pull request #52 from SebastianMorel/test
Fixed issue where long running seasons got wrong streams
2 parents 1271491 + 09eceb3 commit 3e281f8

2 files changed

Lines changed: 136 additions & 11 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ AIOLists is a stateless open source list management addon for Stremio. The proje
2626
## Planned Features in Order
2727
- ~~Speed up the loading time of lists in Stremio~~
2828
- ~~Merged and Anime Search~~
29+
- Fix issues:
30+
- Rework genre filtering
31+
- Add sorting option for MDBList added without key
2932
- Support for Streams/TV lists from external addons
3033
- Randomize option for lists without sort options
3134
- Better TMDB list support

src/integrations/tmdb.js

Lines changed: 133 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,9 @@ async function batchConvertImdbToTmdbIds(imdbIds, userBearerToken = DEFAULT_TMDB
632632
async function fetchTmdbMetadata(tmdbId, type, language = 'en-US', userBearerToken = DEFAULT_TMDB_BEARER_TOKEN) {
633633
if (!tmdbId) return null;
634634

635-
const cacheKey = `tmdb_${type}_${tmdbId}_${language}`;
635+
// Include version in cache key to invalidate old cached data with incorrect episode numbering
636+
const EPISODE_NUMBERING_VERSION = 'v2';
637+
const cacheKey = `tmdb_${type}_${tmdbId}_${language}_${EPISODE_NUMBERING_VERSION}`;
636638
const cachedResult = tmdbCache.get(cacheKey);
637639
if (cachedResult) {
638640
return cachedResult === 'null' ? null : cachedResult;
@@ -789,13 +791,85 @@ function convertTmdbToStremioFormat(tmdbData, type) {
789791
if (!isMovie && tmdbData.seasons_with_episodes) {
790792

791793

794+
// Detect if this is likely an anime with absolute episode numbering
795+
// This happens when TMDB uses continuous numbering across seasons
796+
let isAnimeWithAbsoluteNumbering = false;
797+
let totalEpisodesProcessed = 0;
798+
799+
// Check if any season has episodes with numbers that seem to be absolute rather than season-relative
800+
for (const season of tmdbData.seasons_with_episodes) {
801+
if (season.episodes && season.episodes.length > 0) {
802+
const firstEpisode = season.episodes[0];
803+
const lastEpisode = season.episodes[season.episodes.length - 1];
804+
805+
// If the first episode number is much higher than 1 and doesn't match the expected pattern
806+
// for season-relative numbering, this is likely absolute numbering
807+
if (firstEpisode.episode_number > season.episodes.length * 2) {
808+
isAnimeWithAbsoluteNumbering = true;
809+
console.log(`[TMDB] Absolute numbering detected: Season ${season.season_number} starts with episode ${firstEpisode.episode_number} but has ${season.episodes.length} episodes`);
810+
break;
811+
}
812+
813+
// If we see episodes with numbers like 100+ in what should be early seasons
814+
if (season.season_number <= 5 && firstEpisode.episode_number >= 100) {
815+
isAnimeWithAbsoluteNumbering = true;
816+
console.log(`[TMDB] Absolute numbering detected: Season ${season.season_number} has episodes starting from ${firstEpisode.episode_number}`);
817+
break;
818+
}
819+
820+
// Additional check: if episode numbers don't reset between seasons
821+
if (totalEpisodesProcessed > 0 && firstEpisode.episode_number > totalEpisodesProcessed + 10) {
822+
// There's a gap, but if the gap is too large, it's probably absolute numbering
823+
isAnimeWithAbsoluteNumbering = true;
824+
console.log(`[TMDB] Absolute numbering detected: Episode numbering gap between seasons (expected ~${totalEpisodesProcessed + 1}, got ${firstEpisode.episode_number})`);
825+
break;
826+
} else if (totalEpisodesProcessed > 0 && firstEpisode.episode_number > totalEpisodesProcessed) {
827+
// Episodes continue from previous season without resetting - clear sign of absolute numbering
828+
isAnimeWithAbsoluteNumbering = true;
829+
console.log(`[TMDB] Absolute numbering detected: Episodes continue from previous season (${totalEpisodesProcessed} -> ${firstEpisode.episode_number})`);
830+
break;
831+
}
832+
833+
totalEpisodesProcessed += season.episodes.length;
834+
}
835+
}
836+
837+
// Additional check for series with many episodes in later seasons starting with high numbers
838+
// This catches cases like One Piece where early detection might miss it
839+
if (!isAnimeWithAbsoluteNumbering) {
840+
for (const season of tmdbData.seasons_with_episodes) {
841+
if (season.episodes && season.episodes.length > 10) { // Only check seasons with substantial episode counts
842+
const avgEpisodeNumber = season.episodes.reduce((sum, ep) => sum + ep.episode_number, 0) / season.episodes.length;
843+
// If the average episode number is much higher than what we'd expect for season-relative numbering
844+
if (avgEpisodeNumber > season.season_number * 50) { // Very conservative threshold
845+
isAnimeWithAbsoluteNumbering = true;
846+
console.log(`[TMDB] Absolute numbering detected: Season ${season.season_number} has average episode number ${avgEpisodeNumber.toFixed(1)}`);
847+
break;
848+
}
849+
}
850+
}
851+
}
852+
853+
console.log(`[TMDB] Processing ${tmdbData.name} - Anime absolute numbering detected: ${isAnimeWithAbsoluteNumbering}`);
854+
792855
tmdbData.seasons_with_episodes.forEach(season => {
793856
if (season.episodes && Array.isArray(season.episodes)) {
794-
season.episodes.forEach(episode => {
857+
season.episodes.forEach((episode, episodeIndex) => {
858+
// Calculate proper episode number for the season
859+
let seasonEpisodeNumber = episode.episode_number;
860+
861+
if (isAnimeWithAbsoluteNumbering) {
862+
// For anime with absolute numbering, use the position within the season
863+
// rather than the absolute episode number
864+
seasonEpisodeNumber = episodeIndex + 1;
865+
866+
console.log(`[TMDB] Converted episode ${episode.episode_number} to season ${season.season_number} episode ${seasonEpisodeNumber} for ${tmdbData.name}`);
867+
}
868+
795869
// Use IMDB ID for episode IDs if available, otherwise use TMDB format
796870
const episodeId = imdbId && imdbId.startsWith('tt') ?
797-
`${imdbId}:${season.season_number}:${episode.episode_number}` :
798-
`${tmdbId}:${season.season_number}:${episode.episode_number}`;
871+
`${imdbId}:${season.season_number}:${seasonEpisodeNumber}` :
872+
`${tmdbId}:${season.season_number}:${seasonEpisodeNumber}`;
799873

800874
// Format air date if available
801875
let airDateFormatted = null;
@@ -805,22 +879,24 @@ function convertTmdbToStremioFormat(tmdbData, type) {
805879

806880
videos.push({
807881
id: episodeId,
808-
name: episode.name || `Episode ${episode.episode_number}`,
882+
name: episode.name || `Episode ${seasonEpisodeNumber}`,
809883
season: season.season_number,
810-
number: episode.episode_number,
811-
episode: episode.episode_number,
884+
number: seasonEpisodeNumber, // Use season-relative number
885+
episode: seasonEpisodeNumber, // Use season-relative number
812886
thumbnail: episode.still_path ? `https://image.tmdb.org/t/p/w500${episode.still_path}` : undefined,
813887
overview: episode.overview || "",
814888
description: episode.overview || "",
815889
rating: episode.vote_average ? parseFloat(episode.vote_average).toFixed(1) : "0",
816890
firstAired: airDateFormatted,
817-
released: airDateFormatted
891+
released: airDateFormatted,
892+
// Keep absolute number as additional metadata for reference
893+
absoluteNumber: isAnimeWithAbsoluteNumbering ? episode.episode_number : undefined
818894
});
819895
});
820896
}
821897
});
822898

823-
// Sort episodes by season and episode number
899+
// Sort episodes by season and episode number (now using season-relative numbers)
824900
videos.sort((a, b) => {
825901
if (a.season !== b.season) {
826902
return a.season - b.season;
@@ -1099,16 +1175,62 @@ function clearTmdbCaches() {
10991175
imdbToTmdbCache.clear();
11001176
}
11011177

1178+
// Test function to verify anime episode numbering fix (for development/debugging)
1179+
async function testAnimeEpisodeNumbering(tmdbId = 37854, bearerToken = null) {
1180+
console.log(`[TMDB Test] Testing anime episode numbering for TMDB ID: ${tmdbId}`);
1181+
1182+
try {
1183+
const metadata = await fetchTmdbMetadata(tmdbId, 'series', 'en-US', bearerToken);
1184+
1185+
if (metadata && metadata.videos && metadata.videos.length > 0) {
1186+
console.log(`[TMDB Test] Found ${metadata.videos.length} episodes for ${metadata.name}`);
1187+
1188+
// Show sample episodes from different seasons
1189+
const sampleEpisodes = metadata.videos.filter((ep, index) =>
1190+
index < 5 || // First 5 episodes
1191+
(ep.season === 22 && ep.episode <= 50) || // Season 22 episodes 1-50
1192+
ep.episode > 1000 // High numbered episodes
1193+
).slice(0, 20);
1194+
1195+
console.log(`[TMDB Test] Sample episodes:`);
1196+
sampleEpisodes.forEach(ep => {
1197+
console.log(` Season ${ep.season} Episode ${ep.episode}: ${ep.name} (ID: ${ep.id})${ep.absoluteNumber ? ` [Absolute: ${ep.absoluteNumber}]` : ''}`);
1198+
});
1199+
1200+
// Check for the specific case mentioned in the issue
1201+
const season22Episodes = metadata.videos.filter(ep => ep.season === 22 && ep.episode >= 45 && ep.episode <= 50);
1202+
if (season22Episodes.length > 0) {
1203+
console.log(`[TMDB Test] Season 22 episodes 45-50 for verification:`);
1204+
season22Episodes.forEach(ep => {
1205+
console.log(` S22E${ep.episode}: ${ep.name} (ID: ${ep.id})${ep.absoluteNumber ? ` [Absolute: ${ep.absoluteNumber}]` : ''}`);
1206+
});
1207+
}
1208+
1209+
return metadata;
1210+
} else {
1211+
console.log(`[TMDB Test] No episodes found for series ${tmdbId}`);
1212+
return null;
1213+
}
1214+
} catch (error) {
1215+
console.error(`[TMDB Test] Error testing anime episode numbering:`, error.message);
1216+
return null;
1217+
}
1218+
}
1219+
11021220
module.exports = {
1103-
validateTMDBKey,
1221+
createTmdbRequestToken,
1222+
createTmdbSession,
1223+
getTmdbAccountDetails,
11041224
getTmdbAuthUrl,
11051225
authenticateTmdb,
11061226
fetchTmdbLists,
11071227
fetchTmdbListItems,
1228+
validateTMDBKey,
11081229
convertImdbToTmdbId,
11091230
batchConvertImdbToTmdbIds,
11101231
fetchTmdbMetadata,
11111232
batchFetchTmdbMetadata,
11121233
fetchTmdbGenres,
1113-
clearTmdbCaches
1234+
clearTmdbCaches,
1235+
testAnimeEpisodeNumbering // Export test function
11141236
};

0 commit comments

Comments
 (0)