feat: Add M3U8/TS proxy, fix mirror fallback, fix seasons/watch-order

New endpoints:
- GET /api/stream/proxy?url= — M3U8 playlist proxy with URL rewriting
  Rewrites relative .m3u8 and .ts URLs to proxy endpoints
  Adds CORS headers for cross-origin playback
  Validates allowed streaming domains
- GET /api/stream/ts-proxy?url= — TS video segment proxy
  Proxies .ts segments with proper Content-Type and caching

Fixes:
- seasons.extractor.js: Now extracts from watch page sidebar instead of broken AJAX endpoint
- watchOrder.extractor.js: Now extracts from watch page sidebar (trending/related)
- mirror.helper.js: 404 responses no longer mark mirrors as failed
  Only connection errors trigger mirror failover
  Endpoint-specific 404s break immediately without retry

38 total endpoints, 34/34 passing with 0 errors
This commit is contained in:
Shinei Nouzen
2026-07-28 20:52:49 +05:30
parent 21384dc30f
commit d391908467
4 changed files with 177 additions and 112 deletions
+14 -3
View File
@@ -199,8 +199,17 @@ async function fetchWithMirror(path, options = {}) {
mirror
};
}
// NOTE: 404 means endpoint doesn't exist, not mirror failure — don't retry
if (response.status === 404) {
throw new Error(`Endpoint not found: ${path}`);
}
} catch (error) {
lastError = error;
// NOTE: Don't retry on 404 — the endpoint simply doesn't exist on this mirror
if (error.message?.includes("Endpoint not found")) {
break;
}
if (attempt < retries) {
// Wait before retry
await new Promise(r => setTimeout(r, 500 * (attempt + 1)));
@@ -208,9 +217,11 @@ async function fetchWithMirror(path, options = {}) {
}
}
// Mark mirror as failed after all retries
failedMirrors.add(mirror);
console.log(`[MIRROR] Marked as failed: ${mirror}`);
// NOTE: Only mark mirror as failed for connection errors, not endpoint 404s
if (!lastError.message?.includes("Endpoint not found")) {
failedMirrors.add(mirror);
console.log(`[MIRROR] Marked as failed: ${mirror}`);
}
}
throw new Error(`All mirrors failed. Last error: ${lastError?.message}`);