Fix : Stream Preview
All checks were successful
release / build (push) Successful in 27s
release / verify-windows (push) Successful in 1m26s

This commit is contained in:
jeanotx32
2026-08-12 16:37:04 +02:00
parent 58aadee97d
commit 8c82807368
3 changed files with 39 additions and 24 deletions

View File

@@ -1206,17 +1206,26 @@ export interface StripchatStatus {
*/
statusChangedAt: number | null;
/**
* Vignette du flux (`previewUrlThumbBig`) — une image, pas un flux vidéo :
* l'agent seul pilote un navigateur, le serveur n'a que cette API REST.
* Absente si le modèle n'a jamais diffusé.
* Image du flux — pas le flux lui-même : l'agent seul pilote un navigateur,
* le serveur n'a que cette API REST.
*
* Reconstruite depuis `img.doppiocdn.net/thumbs/{snapshotTimestamp}/{id}` et
* non lue telle quelle sur `previewUrlThumbBig` / `previewUrlThumbSmall` :
* ces deux champs, malgré leur nom, pointent vers la photo de couverture du
* profil — fixe, choisie par le modèle — et non vers une image de la
* diffusion en cours. `img.doppiocdn.net` est la vraie vignette caméra,
* confirmée en comparant les deux : contenu différent, cache CDN de 30 min
* au lieu de 30 jours, `Last-Modified` à quelques secondes de la requête.
*
* Absente si le modèle n'a jamais diffusé (pas d'identifiant numérique ou
* d'horodatage exploitable côté plateforme).
*/
previewUrl: string | null;
/**
* Horodatage de cette vignette côté plateforme, pour invalider le cache du
* navigateur : l'URL, elle, ne change pas d'une image à l'autre — le CDN la
* sert avec un `max-age` de 30 jours. Sans un paramètre qui varie à chaque
* rafraîchissement, le navigateur garderait indéfiniment la toute première
* image vue.
* Horodatage de cette vignette côté plateforme — déjà encodé dans
* `previewUrl`, donc sans utilité pour le cache : une nouvelle vignette porte
* de toute façon une URL différente. Exposé pour l'affichage seulement
* (« vignette vieille de X »).
*/
snapshotAt: number | null;
}
@@ -1254,10 +1263,10 @@ export async function fetchStripchatStatus(
const payload = (await response.json()) as {
user?: {
user?: {
id?: number;
status?: string;
avatarUrl?: string;
statusChangedAt?: string;
previewUrlThumbBig?: string;
snapshotTimestamp?: number;
};
};
@@ -1273,6 +1282,7 @@ export async function fetchStripchatStatus(
: Number.NaN;
// Secondes côté API, comme tous les timestamps Unix bruts de cette plateforme.
const snapshotAt = Number(profile?.snapshotTimestamp) * 1000;
const modelId = Number(profile?.id);
return {
raw,
@@ -1280,8 +1290,8 @@ export async function fetchStripchatStatus(
avatarUrl: typeof profile?.avatarUrl === 'string' && profile.avatarUrl ? profile.avatarUrl : null,
statusChangedAt: Number.isFinite(changedAt) ? changedAt : null,
previewUrl:
typeof profile?.previewUrlThumbBig === 'string' && profile.previewUrlThumbBig
? profile.previewUrlThumbBig
Number.isFinite(modelId) && modelId > 0 && Number.isFinite(snapshotAt) && snapshotAt > 0
? `https://img.doppiocdn.net/thumbs/${Math.round(snapshotAt / 1000)}/${modelId}`
: null,
snapshotAt: Number.isFinite(snapshotAt) && snapshotAt > 0 ? snapshotAt : null,
};

View File

@@ -122,16 +122,16 @@ export function autoRecordHint(
}
/**
* URL de la vignette du flux, invalidée par un paramètre de cache.
* URL de la vignette du flux.
*
* `previewUrl` ne change pas d'une image à l'autre — c'est le CDN qui la sert
* avec un `max-age` de 30 jours — donc sans `snapshotAt` en paramètre, le
* navigateur garderait indéfiniment la toute première image vue au lieu de la
* rafraîchir à chaque sonde.
* Un simple passe-plat aujourd'hui — `previewUrl` porte déjà l'horodatage de
* la vignette dans son chemin, donc chaque nouvelle image a naturellement sa
* propre URL, sans paramètre de cache à ajouter. Gardé comme fonction plutôt
* qu'un accès direct au champ : c'est le seul point à changer si la source
* de la vignette évolue encore une fois.
*/
export function previewSrc(target: Pick<WatchTarget, 'previewUrl' | 'snapshotAt'>): string | null {
if (!target.previewUrl) return null;
return target.snapshotAt ? `${target.previewUrl}?t=${target.snapshotAt}` : target.previewUrl;
export function previewSrc(target: Pick<WatchTarget, 'previewUrl'>): string | null {
return target.previewUrl;
}
/** Fenêtres proposées sous les frises. */