Files
2026-07-14 00:01:48 +03:00

114 lines
4.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const WORKER_PATH = '/cf-proxy';
export default {
async fetch(request) {
const url = new URL(request.url);
if (request.method === 'OPTIONS') {
return new Response(null, { status: 204, headers: corsHeaders() });
}
const uParam = url.searchParams.get('u') || '';
const refParam = url.searchParams.get('ref') || '';
let targetUrl;
try {
targetUrl = atob(uParam);
if (!targetUrl.startsWith('http')) throw 0;
} catch {
return new Response('Missing or invalid u param', { status: 400 });
}
let referer;
try {
referer = refParam ? atob(refParam) : new URL(targetUrl).origin + '/';
if (!referer.endsWith('/')) referer += '/';
} catch {
referer = new URL(targetUrl).origin + '/';
}
let resp;
try {
resp = await fetch(targetUrl, {
headers: {
'Referer': referer,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
'Accept': '*/*',
'Accept-Language': 'tr-TR,tr;q=0.9,en;q=0.8',
},
});
} catch (e) {
return new Response('Upstream fetch failed: ' + e.message, { status: 502 });
}
if (!resp.ok && resp.status !== 206) {
// Referer ile de olmadıysa referer'sız dene (bazı CDN'ler Cloudflare'dan gelen Referer'ı reddeder)
try {
const fallbackResp = await fetch(targetUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
'Accept': '*/*',
},
});
if (fallbackResp.ok || fallbackResp.status === 206) {
resp = fallbackResp;
}
} catch {}
}
const ct = resp.headers.get('content-type') || '';
const isM3u8 = ct.includes('mpegurl') || targetUrl.toLowerCase().includes('.m3u8');
if (isM3u8) {
const body = await resp.text();
if (body.trimStart().startsWith('#EXTM3U')) {
const baseDir = targetUrl.substring(0, targetUrl.lastIndexOf('/') + 1);
const workerBase = url.origin + WORKER_PATH + '?u=';
const refSuffix = '&ref=' + btoa(referer);
const rewritten = body.split('\n').map(line => {
const t = line.trimEnd();
if (t === '') return '';
if (t.startsWith('#')) {
return t.replace(/URI="([^"]+)"/g, (_, uri) => {
const abs = uri.startsWith('http') ? uri : baseDir + uri;
return `URI="${workerBase}${btoa(abs)}${refSuffix}"`;
});
}
const abs = t.startsWith('http') ? t : baseDir + t;
return workerBase + btoa(abs) + refSuffix;
}).join('\n');
return new Response(rewritten, {
status: 200,
headers: { ...corsHeaders(), 'Content-Type': 'application/vnd.apple.mpegurl', 'Cache-Control': 'no-cache' },
});
}
// m3u8 gibi görünüp değil — binary olarak geçir
return new Response(body, {
status: resp.status,
headers: { ...corsHeaders(), 'Content-Type': ct || 'video/mp2t' },
});
}
// Segment (.ts, .key, .png vb.) — body'yi doğrudan stream et (belleğe alma)
let segCt = ct;
if (!segCt || segCt.startsWith('image/') || segCt === 'application/octet-stream') {
segCt = 'video/mp2t';
}
return new Response(resp.body, {
status: resp.status,
headers: { ...corsHeaders(), 'Content-Type': segCt, 'Cache-Control': 'public, max-age=3600' },
});
}
};
function corsHeaders() {
return {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, OPTIONS',
'Access-Control-Allow-Headers': 'Range, Origin',
'Access-Control-Expose-Headers': 'Content-Length, Content-Range, Content-Type',
};
}