feat(xtream): enhance VOD details handling with fallback mechanisms and metadata validation

- Updated XtreamUrlService to handle missing stream IDs and extensions gracefully.
- Modified XtreamSelectionItem interface to allow for empty info arrays and null values.
- Introduced findVodCatalogItem function in XtreamStore for better catalog item retrieval.
- Added unit tests for fallback view model generation in vod-details-fallback.util.spec.ts.
- Created vod-details-fallback.util.ts to manage fallback view model construction and metadata checks.
- Updated vod-details-route.component.html to display fallback information when metadata is unavailable.
- Enhanced styling for fallback notes and status indicators in vod-details-route.component.scss.
- Implemented comprehensive tests for VodDetailsRouteComponent to ensure proper rendering of fallback and detailed views.
- Refactored xtream-vod-details.interface.ts to include new utility functions for metadata extraction.
This commit is contained in:
4gray committed 2026-04-11 22:32:50 +02:00
1 parent 7d4d9a280a
commit 4175fc57b1
11 files changed
+990 -98

No files matched your search

@@ -1,4 +1,4 @@
import { XtreamVodDetails } from './xtream-vod-details.interface';
import { XtreamVodDetails, getXtreamVodInfo } from './xtream-vod-details.interface';
import { StalkerVodDetails } from './stalker-vod-details.interface';
import {
NormalizedVodMeta,
@@ -12,7 +12,7 @@ import {
* Handles the various field name variations in Xtream API responses.
*/
export function normalizeXtreamVod(item: XtreamVodDetails): NormalizedVodMeta {
const info = item?.info;
const info = getXtreamVodInfo(item);
const movieData = item?.movie_data;
return {
@@ -1,41 +1,64 @@
export interface XtreamVodDetails {
info: {
kinopoisk_url: string;
tmdb_id: number;
name: string;
o_name: string;
cover_big: string;
movie_image: string;
releasedate: string;
episode_run_time: number;
youtube_trailer: string;
director: string;
actors: string;
cast: string;
description: string;
plot: string;
age: string;
mpaa_rating: string;
rating_count_kinopoisk: number;
country: string;
genre: string;
backdrop_path: string[];
duration_secs: number;
duration: string;
video: string[];
audio: string[];
bitrate: number;
rating: number;
rating_kinopoisk?: string;
rating_imdb?: string;
};
movie_data: {
stream_id: number;
name: string;
added: string;
category_id: string;
container_extension: string;
custom_sid: string;
direct_source: string;
};
export interface XtreamVodInfo {
kinopoisk_url: string;
tmdb_id: number | string;
name: string;
o_name: string;
cover_big: string;
movie_image: string;
releasedate: string;
episode_run_time: number;
youtube_trailer: string;
director: string;
actors: string;
cast: string;
description: string;
plot: string;
age: string;
mpaa_rating: string;
rating_count_kinopoisk: number;
country: string;
genre: string;
backdrop_path: string[];
duration_secs: number;
duration: string;
video: string[];
audio: string[];
bitrate: number;
rating: number | string;
runtime?: string;
status?: string;
rating_kinopoisk?: string;
rating_imdb?: string;
}
export interface XtreamVodMovieData {
stream_id: number;
name: string;
added: string;
category_id: string;
container_extension: string;
custom_sid: string | null;
direct_source: string;
category_ids?: number[];
}
export interface XtreamVodDetails {
info?: XtreamVodInfo | [] | null;
movie_data?: XtreamVodMovieData;
}
export function getXtreamVodInfo(
details: Pick<XtreamVodDetails, 'info'> | null | undefined
): XtreamVodInfo | null {
const info = details?.info;
if (!info || Array.isArray(info) || typeof info !== 'object') {
return null;
}
return info;
}
export function hasXtreamVodInfo(
details: Pick<XtreamVodDetails, 'info'> | null | undefined
): details is XtreamVodDetails & { info: XtreamVodInfo } {
return getXtreamVodInfo(details) !== null;
}