fix(stalker): derive missing season numbers

This commit is contained in:
4gray committed 2026-07-20 22:00:06 +02:00
1 parent 1c3cc6c9fa
commit 8cfc64a3dc
5 files changed
+76 -14

No files matched your search

@@ -78,6 +78,44 @@ describe('stalker-series.adapters', () => {
expect(firstEpisode.id).not.toBe(mapped['1'][1].id);
});
it('derives missing VOD-series season numbers from natural season order', () => {
const mapped = mapVodSeriesEpisodes([
{
id: 'season-2',
video_id: 'v1',
name: 'Season 2',
season_number: '',
episodes: [
{
id: 'episode-2',
series_number: 1,
name: 'Second season pilot',
},
],
isLoading: false,
isExpanded: false,
},
{
id: 'season-1',
video_id: 'v1',
name: 'Season 1',
season_number: '',
episodes: [
{
id: 'episode-1',
series_number: 1,
name: 'Pilot',
},
],
isLoading: false,
isExpanded: false,
},
]);
expect(mapped['Season 1'][0].season).toBe(1);
expect(mapped['Season 2'][0].season).toBe(2);
});
it('maps embedded series payload into regular season episodes', () => {
const regularSeasons = mapRegularSeriesSeasons(
{
@@ -7,6 +7,11 @@ import {
} from './models';
import { isStalkerSeriesFlag } from './stalker-vod.utils';
const naturalSeasonCollator = new Intl.Collator(undefined, {
numeric: true,
sensitivity: 'base',
});
export interface VodSeriesSeasonVm {
id: string;
video_id: string;
@@ -154,7 +159,7 @@ export function mapVodSeriesEpisodes(
seasons.forEach((season) => {
const seasonKey = season.season_number || season.name || season.id;
const seasonNum = toEpisodeNumber(seasonKey) || 1;
const seasonNum = getVodSeriesSeasonNumber(season, seasons);
mapped[seasonKey] = (season.episodes ?? []).map((episode) => {
const episodeNum =
@@ -230,3 +235,24 @@ export function mapRegularSeriesEpisodes(
export function getVodSeriesSeasonKey(season: VodSeriesSeasonVm): string {
return season.season_number || season.name || season.id;
}
export function getVodSeriesSeasonNumber(
season: VodSeriesSeasonVm,
seasons: ReadonlyArray<VodSeriesSeasonVm>
): number {
const parsedSeasonNumber = Number(season.season_number);
if (Number.isInteger(parsedSeasonNumber) && parsedSeasonNumber > 0) {
return parsedSeasonNumber;
}
const orderedSeasons = [...seasons].sort((seasonA, seasonB) =>
naturalSeasonCollator.compare(
getVodSeriesSeasonKey(seasonA),
getVodSeriesSeasonKey(seasonB)
)
);
const seasonIndex = orderedSeasons.findIndex(
(candidate) => candidate.id === season.id
);
return seasonIndex >= 0 ? seasonIndex + 1 : 1;
}
@@ -6,6 +6,7 @@ import {
} from '@iptvnator/portal/shared/util';
import {
getVodSeriesSeasonKey,
getVodSeriesSeasonNumber,
type VodSeriesSeasonVm,
} from '@iptvnator/portal/stalker/data-access';
import type {
@@ -160,16 +161,8 @@ function getLazyVodSeriesEpisodeLabel(
season: VodSeriesSeasonVm,
seasons: ReadonlyArray<VodSeriesSeasonVm>
): string {
const seasonIndex = seasons.findIndex((item) => item.id === season.id);
const parsedSeasonNumber = Number(season.season_number);
const seasonNumber =
Number.isInteger(parsedSeasonNumber) && parsedSeasonNumber > 0
? parsedSeasonNumber
: getFallbackSeasonNumber(seasonIndex);
return formatSeriesEpisodeCode(seasonNumber, 1);
}
function getFallbackSeasonNumber(seasonIndex: number): number {
return seasonIndex >= 0 ? seasonIndex + 1 : 1;
return formatSeriesEpisodeCode(
getVodSeriesSeasonNumber(season, seasons),
1
);
}