mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 15:48:05 +00:00
Co-authored-by: Alex Kim <alexkim@Alexs-MacBook-Pro.local> Co-authored-by: Fredrik Burmester <fredrik.burmester@gmail.com> Co-authored-by: Simon-Eklundh <simon.eklundh@proton.me>
115 lines
3.4 KiB
TypeScript
115 lines
3.4 KiB
TypeScript
/**
|
|
* Utility functions for querying downloaded series/episode data.
|
|
* Centralizes common filtering patterns to reduce duplication.
|
|
*/
|
|
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
|
import type { DownloadedItem } from "@/providers/Downloads/types";
|
|
|
|
/** Sort episodes by season then episode number */
|
|
const sortByEpisodeOrder = (a: BaseItemDto, b: BaseItemDto) =>
|
|
(a.ParentIndexNumber ?? 0) - (b.ParentIndexNumber ?? 0) ||
|
|
(a.IndexNumber ?? 0) - (b.IndexNumber ?? 0);
|
|
|
|
/**
|
|
* Get all downloaded episodes for a series, sorted by season and episode number.
|
|
*/
|
|
export function getDownloadedEpisodesForSeries(
|
|
downloadedItems: DownloadedItem[] | undefined,
|
|
seriesId: string,
|
|
): BaseItemDto[] {
|
|
if (!downloadedItems) return [];
|
|
return downloadedItems
|
|
.filter((f) => f.item.SeriesId === seriesId)
|
|
.map((f) => f.item)
|
|
.sort(sortByEpisodeOrder);
|
|
}
|
|
|
|
/**
|
|
* Get downloaded episodes for a specific season of a series.
|
|
*/
|
|
export function getDownloadedEpisodesForSeason(
|
|
downloadedItems: DownloadedItem[] | undefined,
|
|
seriesId: string,
|
|
seasonNumber: number,
|
|
): BaseItemDto[] {
|
|
return getDownloadedEpisodesForSeries(downloadedItems, seriesId).filter(
|
|
(ep) => ep.ParentIndexNumber === seasonNumber,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get downloaded episodes by seasonId (for carousel views).
|
|
*/
|
|
export function getDownloadedEpisodesBySeasonId(
|
|
downloadedItems: DownloadedItem[] | undefined,
|
|
seasonId: string,
|
|
): BaseItemDto[] {
|
|
if (!downloadedItems) return [];
|
|
return downloadedItems
|
|
.filter((f) => f.item.Type === "Episode" && f.item.SeasonId === seasonId)
|
|
.map((f) => f.item)
|
|
.sort(sortByEpisodeOrder);
|
|
}
|
|
|
|
/**
|
|
* Get unique season numbers from downloaded episodes for a series.
|
|
*/
|
|
export function getDownloadedSeasonNumbers(
|
|
downloadedItems: DownloadedItem[] | undefined,
|
|
seriesId: string,
|
|
): number[] {
|
|
const episodes = getDownloadedEpisodesForSeries(downloadedItems, seriesId);
|
|
return [
|
|
...new Set(
|
|
episodes
|
|
.map((ep) => ep.ParentIndexNumber)
|
|
.filter((n): n is number => n != null),
|
|
),
|
|
].sort((a, b) => a - b);
|
|
}
|
|
|
|
/**
|
|
* Build fake season objects from downloaded episodes.
|
|
* Useful for offline mode where we don't have actual season data.
|
|
*/
|
|
export function buildOfflineSeasons(
|
|
downloadedItems: DownloadedItem[] | undefined,
|
|
seriesId: string,
|
|
): BaseItemDto[] {
|
|
const episodes = getDownloadedEpisodesForSeries(downloadedItems, seriesId);
|
|
const seasonNumbers = getDownloadedSeasonNumbers(downloadedItems, seriesId);
|
|
|
|
return seasonNumbers.map((seasonNum) => {
|
|
const firstEpisode = episodes.find(
|
|
(ep) => ep.ParentIndexNumber === seasonNum,
|
|
);
|
|
return {
|
|
Id: `offline-season-${seasonNum}`,
|
|
IndexNumber: seasonNum,
|
|
Name: firstEpisode?.SeasonName || `Season ${seasonNum}`,
|
|
SeriesId: seriesId,
|
|
} as BaseItemDto;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Build a series-like object from downloaded episodes.
|
|
* Useful for offline mode where we don't have the actual series data.
|
|
*/
|
|
export function buildOfflineSeriesFromEpisodes(
|
|
downloadedItems: DownloadedItem[] | undefined,
|
|
seriesId: string,
|
|
): BaseItemDto | null {
|
|
const episodes = getDownloadedEpisodesForSeries(downloadedItems, seriesId);
|
|
if (episodes.length === 0) return null;
|
|
|
|
const firstEpisode = episodes[0];
|
|
return {
|
|
Id: seriesId,
|
|
Name: firstEpisode.SeriesName,
|
|
Type: "Series",
|
|
ProductionYear: firstEpisode.ProductionYear,
|
|
Overview: firstEpisode.SeriesName,
|
|
} as BaseItemDto;
|
|
}
|