Files
NewTube/src/app/shared/models/video-item.model.ts
T
bruno 665a0f0ebd
CI / build-and-test (push) Successful in 14m43s
feat(providers): phases 7.3/7.4/7.6/8.1 — provenance, health, NDJSON, contrat unique
7.3: capturedAt/source au registre + 6 adaptateurs + module provenance.ts + ?debug=1 (search-transport.mjs). 7.4: ProviderHealthService + badge source degradee. 7.6: squelettes par provider + snapshots progressifs + transport NDJSON /api/search. 8.1: ProviderAdapter unifie (search enveloppe + channelContent/channelMeta/capabilities) via getProviderAdapter + test de contrat offline.
2026-09-30 07:57:11 -04:00

67 lines
2.4 KiB
TypeScript

import type { ChannelMeta } from './channel.model';
import type { ProviderLongId } from '../providers/provider-ids';
/**
* Vue « grille » d'une vidéo. Miroir du contrat `Suggestion` v2
* (server/providers/registry.mjs) — voir src/app/search/api.v1.ts.
*
* Règle structurante (phase 2.1) : une métadonnée absente reste `undefined`.
* `durationSec: 0` est interdit : les règles de classification s'appuient sur
* « pas de durée connue » pour distinguer une verticale d'un short.
*/
export interface VideoItem {
id: string; // id vidéo canonicalisé
provider: ProviderLongId;
title: string;
thumbnailUrl: string;
/** Secondes, > 0. `undefined` = inconnue. */
durationSec?: number;
channelName?: string;
channelExternalId?: string;
channelAvatarUrl?: string;
channelMeta?: ChannelMeta;
viewCount?: number;
/**
* Phase 7.3 — spectateurs EN DIRECT (Twitch `viewer_count`). Ce n'est pas un
* compteur de vues : à n'afficher que si `isLive === true`.
*/
viewers?: number;
/** ISO 8601. */
publishedAt?: string;
// Provider-specific routing hints
slug?: string; // Odysee slug when available
channel?: string; // Twitch channel when item represents a channel/live
// Live status (only providers exposing it, e.g. Twitch, set these)
type?: string; // e.g. 'live' | 'channel' | 'video'
isLive?: boolean; // true when actually broadcasting now
isShort?: boolean; // true when the provider flagged a Short/clip
kind?: string; // e.g. Twitch 'vod' | 'clip'
game?: string; // e.g. Twitch game/category name
width?: number; // video width in px (orientation signal, when exposed)
height?: number; // video height in px (orientation signal, when exposed)
// --- v2 (phase 1 + 2) ---
likes?: number;
dislikes?: number;
uploaderAvatar?: string;
description?: string;
tags?: string[];
/** BCP-47. */
language?: string;
hasSubtitles?: boolean;
embeddable?: boolean;
/** Libellés bruts : permettent d'afficher une valeur approchée plutôt qu'un vide. */
durationRaw?: string;
viewCountRaw?: string;
// --- Phase 7.3 : provenance ---
/**
* Epoch ms : instant RÉEL de la collecte. `undefined` = inconnu (jamais
* `Date.now()` côté front : une donnée vieille de 4 min ne doit pas passer
* pour fraîche).
*/
capturedAt?: number;
/** Voie de collecte : `innertube` / `api` / `scrape` / `cache`… */
source?: string;
}