mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 20:16:15 -08:00
* feat(tmdb): clickable director/creator chips and directing credits on person pages Directors were plain merged text — no photos, no navigation — while the data was already sitting in the cached TMDB payloads (credits.crew and created_by both carry id + profile_path; they just were not typed or parsed). - tmdb-merge: enrichedDirectors (crew, job === 'Director', deduped by person id) and enrichedCreators (created_by) produce the same chip shape as the cast (TmdbEnrichedCastMember) into a new tmdb_directors field on all three merges (Xtream VOD, Xtream series, Stalker); types widened (crew id/profile_path, created_by id/profile_path). - Detail views (shared VodDetailsComponent, Xtream vod/serial routes, Stalker series view) render the Director row as clickable avatar chips when tmdb_directors is present — same markup and openActor handler as the cast strip — falling back to the plain text otherwise. Stalker re-normalization allowlist preserves the new field. - Person pages: mapPersonFilmography now merges combined_credits.crew (jobs Director/Creator) into the filmography — acting wins the per-title dedup, directing-only titles show the job in the character slot. Everything else (library matching, All-portals scope, filters, search fallback, back button) works unchanged because the person page is role-agnostic. Existing caches work as-is: crew/created_by were always part of the stored payloads. Tests: merge spec (director/creator chips + crew-row dedup ×3 merges), person spec (crew credits, Producer excluded, acting-wins dedup), stalker-vod.utils passthrough. Docs updated (CLAUDE.md + architecture). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(tmdb): address director-pages review — split oversized spec, stable track keys, translated crew roles - tmdb-merge.spec.ts grew past the 400-line lint ceiling — the Stalker merge suite moved to tmdb-merge-stalker.spec.ts (fixes the CI Lint job). - All cast/director chip loops now track by TMDB person id with an index fallback ('p<id>' / 'i<index>') instead of member.name — distinct people can share a name and creator payloads carry no dedup (greptile). - Directing-only filmography credits carry the role in a new crewJob field ('Director' | 'Creator') instead of stuffing TMDB's raw English job into character; ActorViewComponent renders it through translated labels (XTREAM.CREW_JOB_DIRECTOR/CREATOR, added to all 18 locales via the i18n patch workflow, matching each locale's existing glossary — pt "Diretor", de "Regisseur") (Codex). Tests: person spec asserts character/crewJob separation; merge suites green after the split (15 + stalker file). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
76 lines
2.0 KiB
TypeScript
76 lines
2.0 KiB
TypeScript
import {
|
|
TmdbEnrichedCastMember,
|
|
TmdbRecommendation,
|
|
} from './tmdb.interface';
|
|
|
|
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;
|
|
/** Populated by TMDB enrichment; absent in raw provider responses */
|
|
tmdb_cast?: TmdbEnrichedCastMember[];
|
|
/** Directors (movies) / creators (series) as clickable person chips */
|
|
tmdb_directors?: TmdbEnrichedCastMember[];
|
|
/** Populated by TMDB enrichment; matched against the catalog in views */
|
|
tmdb_recommendations?: TmdbRecommendation[];
|
|
}
|
|
|
|
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;
|
|
}
|