/* Best-effort discovery for playback that never requests server streams. */ (function(root) { 'use strict'; function createReporter({ fetch: send = root.fetch?.bind(root), online = () => root.navigator?.onLine !== false, enabled = () => true } = {}) { const seen = new Set(), deferred = new Map(); function report(meta) { if (!enabled() || !send || !meta || !/^[A-Za-z0-9_-]{11}$/.test(meta.id) || meta.custom || meta.upload || !meta.title || meta.title === meta.id || seen.has(meta.id)) return; // Snapshot only the known metadata, never stream URLs or local blob art. let thumbnail; try { const url = new URL(meta.thumbnail); if (url.protocol === 'https:' && /^(?:i|i\d)\.ytimg\.com$/.test(url.hostname) && !url.port && !url.username && !url.password) thumbnail = url.href; } catch { /* server supplies canonical art */ } const card = { id: meta.id, title: String(meta.title).slice(0,300), channel: String(meta.channel || meta.artist || meta.uploader || '').slice(0,300), duration: Math.max(0, Math.min(86400, Number(meta.duration) || 0)), ...(thumbnail ? { thumbnail } : {}) }; if (!online()) { deferred.set(meta.id, card); if (deferred.size > 256) deferred.delete(deferred.keys().next().value); return; } seen.add(meta.id); deferred.delete(meta.id); // No synchronous/network failure can interrupt the player event handler. try { Promise.resolve(send(`/api/media/${encodeURIComponent(card.id)}/meta`, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(card), signal: root.AbortSignal?.timeout?.(10000), })).catch(() => {}); } catch { /* best effort; a later session can report again */ } } return { report, flush: () => { if (online()) for (const card of [...deferred.values()]) report(card); } }; } if (typeof module !== 'undefined') module.exports = { createReporter }; else { const reporter = createReporter(); root.ServerBackfill = reporter; root.addEventListener('online', reporter.flush); } })(typeof window !== 'undefined' ? window : globalThis);