feat(providers): phases 7.3/7.4/7.6/8.1 — provenance, health, NDJSON, contrat unique
CI / build-and-test (push) Successful in 14m43s
CI / build-and-test (push) Successful in 14m43s
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.
This commit is contained in:
@@ -1,17 +1,33 @@
|
||||
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: 'youtube' | 'dailymotion' | 'twitch' | 'peertube' | 'odysee' | 'rumble';
|
||||
provider: ProviderLongId;
|
||||
title: string;
|
||||
thumbnailUrl: string;
|
||||
/** Secondes, > 0. `undefined` = inconnue. */
|
||||
durationSec?: number;
|
||||
channelName?: string;
|
||||
channelExternalId?: string;
|
||||
channelAvatarUrl?: string;
|
||||
channelMeta?: ChannelMeta;
|
||||
viewCount?: number;
|
||||
publishedAt?: string; // ISO
|
||||
/**
|
||||
* 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
|
||||
@@ -23,4 +39,28 @@ export interface VideoItem {
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user