diff options
Diffstat (limited to 'src/features/messages.js')
| -rw-r--r-- | src/features/messages.js | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index 4900c40..6122ade 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -6768,6 +6768,7 @@ export function messagesFeature(ctx) { const videoProbes = new Map(); let videoProbing = 0; const videoProbeQueue = []; + const clipGone = (url) => { const d = videoInfo.get(url); return !!d && typeof d.goneAt === 'number' && Date.now() - d.goneAt < 86_400_000; }; const probeFailedLately = (d) => !!d && typeof d.failedAt === 'number' && Date.now() - d.failedAt < 3_600_000; function probeVideo(url, layout = false) { const have = videoInfo.get(url); @@ -6801,7 +6802,7 @@ export function messagesFeature(ctx) { // player's plain load answers this request without them, and it fails. // Any clip that had played in the feed was "unmeasurable" that way. const r = await fetch(url, { headers: { Range: 'bytes=0-' + (VIDEO_PROBE_BYTES - 1) }, cache: 'no-store', signal: ctrl.signal }); - if (!r.ok) throw new Error('HTTP ' + r.status); + if (!r.ok) throw Object.assign(new Error('HTTP ' + r.status), { status: r.status }); const ranges = r.status === 206; const total = ranges ? +(/\/(\d+)\s*$/.exec(r.headers.get('content-range') || '') || [])[1] : +r.headers.get('content-length'); // never more than the first bytes, even from a server that ignored the range @@ -6818,7 +6819,7 @@ export function messagesFeature(ctx) { let o = 0; for (const p of parts) { if (o >= buf.length) break; buf.set(p.subarray(0, buf.length - o), o); o += p.length; } const head = readMp4Head(buf); - const d = { probed: true, ranges, faststart: head.faststart === true, failedAt: undefined, ...(head.moovEnd ? { moovEnd: head.moovEnd } : {}), ...(head.hevc ? { hevc: true } : {}), ...(head.dur && !(videoInfo.get(url) || {}).dur ? { dur: head.dur } : {}) }; + const d = { probed: true, ranges, faststart: head.faststart === true, failedAt: undefined, goneAt: undefined, ...(head.moovEnd ? { moovEnd: head.moovEnd } : {}), ...(head.hevc ? { hevc: true } : {}), ...(head.dur && !(videoInfo.get(url) || {}).dur ? { dur: head.dur } : {}) }; if (total > 0) d.size = total; else { // a server that hides Content-Range from scripts (Primal's) still @@ -6832,8 +6833,13 @@ export function messagesFeature(ctx) { if (head.w && !(videoInfo.get(url) || {}).w) { d.w = head.w; d.h = head.h; } if (head.w) rememberVideo(url, head.w, head.h); noteVideoInfo(url, d); - } catch { - noteVideoInfo(url, { failedAt: Date.now() }); // a host that won't say (no CORS, down, slow): asked again in an hour + } catch (e) { + // a host that won't say (no CORS, down, slow): asked again in an hour. + // One that says the file is gone (deleted: a 404 or 410) is believed + // for a day, and the grid leaves the clip out (clipGone). + const gone = e && (e.status === 404 || e.status === 410); + noteVideoInfo(url, { failedAt: Date.now(), ...(gone ? { goneAt: Date.now() } : {}) }); + if (gone && mediaMode === 'videos') scheduleRepaint(); } finally { clearTimeout(timer); } return videoInfo.get(url); } @@ -13965,7 +13971,8 @@ export function messagesFeature(ctx) { const again = saidAgain(ev); if (again && said.has(again) && said.get(again) !== ev.id) continue; if (kind === 'videos') learnVideoMeta(ev); - const urls = kind === 'videos' ? clipUrlsOf(ev).filter(fitClip) + // (a clip whose host says it's deleted has nothing to show: a blank tile) + const urls = kind === 'videos' ? clipUrlsOf(ev).filter((u) => !clipGone(u)).filter(fitClip) : noteMediaUrls(ev.content).filter((u) => !u.startsWith('https://i.ytimg.com/')); // (the words are taken by a post that shows: one whose clip doesn't fit // the screen leaves them to the next) |
