Edit: v211
Nama Worker
Kode Sumber
const GITHUB_USERNAME = 'brodatv1'; const GITHUB_REPO = 'jsonp'; const GITHUB_BRANCH = 'master'; const GITHUB_FOLDER = 'mio'; const JSON_FILES = [ 'AA.json', 'AU.json', 'BR.json', 'EV.json', 'GB.json', 'ID.json', 'JP.json', 'KD.json', 'KR.json', 'LO.json', 'MI.json', 'MY.json', 'RI.json', 'SA.json', 'SG.json', 'SP.json' ]; const BASE_URL = `https://raw.githubusercontent.com/${GITHUB_USERNAME}/${GITHUB_REPO}/${GITHUB_BRANCH}/${GITHUB_FOLDER}/`; const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36'; const DEFAULT_REFERRER = 'https://xl365.plcdn.xyz/'; const DEFAULT_ORIGIN = 'https://xl365.plcdn.xyz'; // Base64URL to Hex helper (for clearkey DASH) function b64urlToHex(b64url) { const base64 = b64url.replace(/-/g, '+').replace(/_/g, '/'); const raw = atob(base64); let hex = ''; for (let i = 0; i < raw.length; i++) { const byte = raw.charCodeAt(i); hex += ('0' + byte.toString(16)).slice(-2); } return hex; } addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); async function handleRequest(request) { try { const allJsonPromises = JSON_FILES.map(file => fetch(BASE_URL + file).then(res => res.ok ? res.json() : null) ); const allJsonData = await Promise.all(allJsonPromises); let m3uContent = '#EXTM3U\n'; allJsonData.forEach(jsonData => { if (jsonData && Array.isArray(jsonData.info)) { const groupName = jsonData.country_name || 'General'; const channels = jsonData.info; channels.forEach(channel => { const isChannelValid = channel && typeof channel === 'object' && channel.name && typeof channel.name === 'string' && channel.name.trim() !== '' && channel.hls && typeof channel.hls === 'string' && channel.hls.trim() !== ''; if (isChannelValid) { const logo = channel.image ? `tvg-logo="${channel.image}"` : ''; m3uContent += `#EXTINF:-1 ${logo} group-title="${groupName}",${channel.name}\n`; // --- Ambil header_iptv jika ada, fallback ke default manual --- let userAgent = DEFAULT_USER_AGENT; let referrer = DEFAULT_REFERRER; let origin = DEFAULT_ORIGIN; if (channel.header_iptv) { try { const headers = JSON.parse(channel.header_iptv); if (headers['User-Agent'] && headers['User-Agent'] !== 'none') userAgent = headers['User-Agent']; if (headers['Referer'] && headers['Referer'] !== 'none') referrer = headers['Referer']; if (headers['Origin'] && headers['Origin'] !== 'none') origin = headers['Origin']; } catch (e) { /* abaikan header error */ } } m3uContent += `#EXTVLCOPT:http-user-agent=${userAgent}\n`; m3uContent += `#EXTVLCOPT:http-referrer=${referrer}\n`; m3uContent += `#EXTVLCOPT:network-caching=1000\n`; m3uContent += `#EXTVLCOPT--http-reconnect=true\n`; m3uContent += `#EXTVLCOPT:http-origin=${origin}\n`; // -- Lisensi clearkey, kalau ada -- if (channel.jenis === 'dash-clearkey' && channel.url_license) { m3uContent += `#KODIPROP:inputstream.adaptive.license_type=clearkey\n`; let licenseKey = channel.url_license; try { const decodedLicense = atob(channel.url_license); const licenseJson = JSON.parse(decodedLicense); if (licenseJson.keys && licenseJson.keys[0]) { const kid = b64urlToHex(licenseJson.keys[0].kid); const key = b64urlToHex(licenseJson.keys[0].k); licenseKey = `${kid}:${key}`; } } catch (e) {/* skip */} m3uContent += `#KODIPROP:inputstream.adaptive.license_key=${licenseKey}\n`; } // Akhir: URL channel m3uContent += `${channel.hls}\n`; } }); } }); return new Response(m3uContent, { headers: { 'Content-Type': 'application/vnd.apple.mpegurl; charset=utf-8', 'Access-Control-Allow-Origin': '*' }, }); } catch (error) { return new Response(`Error: ${error.message}`, { status: 500 }); } }
Bindings
Tambah KV
Tambah R2
Tambah D1
← Kembali
Simpan & Deploy
Hapus Script Worker Ini