mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-28 08:22:24 +00:00
First piece of the "My Videos" management tab: classifyVideoHealth decides the maintenance status for one of the user's own videos from note-side data plus an optional URL probe result. Pure/synchronous so it's deterministic and testable; the controller will do the actual HEAD probe and pass the result in. Statuses: no-source (no url AND no magnet) -> error; hosted-URL-unreachable -> warning; deleted (tombstoned) -> info; otherwise ok. Key guardrail: only URLs under the user's storage publicBaseUrl can be flagged dead — external/CORS-opaque links are never cried wolf on. Deleted is checked before no-source since soft-delete scrubs url/magnet. Tests + mutation-verified: dropping the hosted guard (external false-alarm) and removing deleted-precedence each fail a scenario. Build + full lint green. Co-Authored-By: Claude Opus 4.8 <[email protected]>
72 lines
2.9 KiB
JavaScript
72 lines
2.9 KiB
JavaScript
// Pure health classification for the "My Videos" management tab.
|
|
//
|
|
// Given a parsed video note (and optionally a URL probe result), decide the
|
|
// maintenance status shown to the user. Deliberately no network/IO here so it
|
|
// stays deterministic and testable; the controller performs the actual HEAD
|
|
// probe and passes the result in. Phase 2 (bucket reconciliation) layers
|
|
// storage-side statuses on top of this note-side classification.
|
|
|
|
export const VIDEO_HEALTH_STATUS = Object.freeze({
|
|
DELETED: "deleted",
|
|
NO_SOURCE: "no-source",
|
|
DEAD_URL: "dead-url",
|
|
OK: "ok",
|
|
});
|
|
|
|
function trimStr(value) {
|
|
return typeof value === "string" ? value.trim() : "";
|
|
}
|
|
|
|
/**
|
|
* Does `url` live under the user's storage public base URL? Only hosted URLs are
|
|
* ones we can meaningfully probe / reconcile against the bucket; third-party
|
|
* links are out of our control (and CORS-opaque), so they must never be flagged
|
|
* red just because we can't verify them.
|
|
*/
|
|
export function isUrlUnderBase(url, publicBaseUrl) {
|
|
const u = trimStr(url);
|
|
const base = trimStr(publicBaseUrl).replace(/\/+$/, "");
|
|
if (!u || !base) {
|
|
return false;
|
|
}
|
|
return u === base || u.startsWith(`${base}/`);
|
|
}
|
|
|
|
/**
|
|
* Classify the maintenance health of one of the user's own videos.
|
|
*
|
|
* @param {object} video parsed video note ({ url, magnet, deleted, ... })
|
|
* @param {object} [opts]
|
|
* @param {string} [opts.publicBaseUrl] the user's storage public base URL
|
|
* @param {{ ok: boolean }|null} [opts.urlProbe] result of a HEAD probe on
|
|
* `video.url`, if one was performed (null = not probed / unverifiable)
|
|
* @returns {{ status: string, severity: "error"|"warning"|"info"|"ok",
|
|
* label: string, hosted: boolean }}
|
|
*/
|
|
export function classifyVideoHealth(video, { publicBaseUrl = "", urlProbe = null } = {}) {
|
|
const v = video && typeof video === "object" ? video : {};
|
|
const url = trimStr(v.url);
|
|
const magnet = trimStr(v.magnet);
|
|
const hosted = isUrlUnderBase(url, publicBaseUrl);
|
|
|
|
// A deleted (tombstoned) note is intentional, not a problem to fix here — it's
|
|
// a candidate for storage cleanup (Phase 2). Checked first because soft-delete
|
|
// scrubs url/magnet, which would otherwise read as "no source".
|
|
if (v.deleted === true) {
|
|
return { status: VIDEO_HEALTH_STATUS.DELETED, severity: "info", label: "Deleted on Nostr", hosted };
|
|
}
|
|
|
|
if (!url && !magnet) {
|
|
return { status: VIDEO_HEALTH_STATUS.NO_SOURCE, severity: "error", label: "No playable source", hosted };
|
|
}
|
|
|
|
// A dead URL is only a hard signal when it's a hosted URL we could actually
|
|
// probe. External links that fail (or can't be probed) stay "ok" so we don't
|
|
// cry wolf on CORS-opaque third-party hosts.
|
|
if (hosted && url && urlProbe && urlProbe.ok === false) {
|
|
return { status: VIDEO_HEALTH_STATUS.DEAD_URL, severity: "warning", label: "Hosted file unreachable", hosted };
|
|
}
|
|
|
|
return { status: VIDEO_HEALTH_STATUS.OK, severity: "ok", label: "OK", hosted };
|
|
}
|