// Cloudflare Worker: IPTV Admin Panel & Xtream Proxy const COOKIE_NAME = "iptv_session"; export default { async fetch(request, env) { const url = new URL(request.url); const path = url.pathname; // 1. PUBLIC API ENDPOINTS (Xtream Codes / Player Compatibility) if (path.startsWith("/player_api.php")) return handleXtreamAPI(request, env); if (path.startsWith("/get.php")) return handleM3UDownload(request, env); if (path.startsWith("/xmltv.php")) return handleEPG(request, env); if (path.startsWith("/proxy/")) return handleStreamProxy(request, env); // 2. PUBLIC ADMIN AUTHS if (path === "/login" && request.method === "POST") return handleLoginSubmit(request, env); if (path === "/logout") return handleLogout(); // Session Verification for Protected Admin Spaces const authorized = await verifySession(request, env); if (!authorized) return loginPageResponse(); // Admin Actions (POST) if (request.method === "POST") { if (path === "/admin/update") return updateAdminCreds(request, env); if (path === "/user/add") return addUser(request, env); if (path === "/user/edit") return editUser(request, env); if (path === "/user/delete") return deleteUser(request, env); if (path === "/stream/add") return addStream(request, env); if (path === "/stream/edit") return editStream(request, env); if (path === "/stream/delete") return deleteStream(request, env); if (path === "/stream/import") return massImportStreams(request, env); } // Admin UI Routing (GET) if (path === "/admin/settings") return renderAdminSettingsPage(request, env); return renderDashboard(request, env); } }; // --- AUTHENTICATION FUNCTIONS --- async function verifySession(request, env) { const cookie = request.headers.get("Cookie") || ""; if (!cookie.includes(COOKIE_NAME)) return false; const match = cookie.match(new RegExp('(^| )' + COOKIE_NAME + '=([^;]+)')); if (!match) return false; try { const [user, pass] = atob(match[2]).split(":"); const admin = await env.DB.prepare("SELECT * FROM admins WHERE username = ? AND password = ?").bind(user, pass).first(); return !!admin; } catch (e) { return false; } } function loginPageResponse(error = "") { return new Response(` IPTV Login

IPTV Panel Access
TFMS IPTV Panel V3

${error ? `
${error}
` : ""}
`, { headers: { "Content-Type": "text/html" } }); } async function handleLoginSubmit(request, env) { const formData = await request.formData(); const user = formData.get("username"); const pass = formData.get("password"); const admin = await env.DB.prepare("SELECT * FROM admins WHERE username = ? AND password = ?").bind(user, pass).first(); if (admin) { const token = btoa(`${user}:${pass}`); return new Response("Redirecting...", { status: 302, headers: { "Location": "/", "Set-Cookie": `${COOKIE_NAME}=${token}; Path=/; HttpOnly; Max-Age=86400` } }); } return loginPageResponse("Invalid credentials."); } function handleLogout() { return new Response("Redirecting...", { status: 302, headers: { "Location": "/", "Set-Cookie": `${COOKIE_NAME}=; Path=/; Max-Age=0` } }); } // --- MASTER PANEL MANAGEMENT SETTINGS --- async function updateAdminCreds(request, env) { const cookie = request.headers.get("Cookie") || ""; const match = cookie.match(new RegExp('(^| )' + COOKIE_NAME + '=([^;]+)')); if (!match) return new Response("Session missing", { status: 401 }); const [oldUser] = atob(match[2]).split(":"); const f = await request.formData(); const newUsername = f.get("new_username"); const newPassword = f.get("new_password"); await env.DB.prepare("UPDATE admins SET username = ?, password = ? WHERE username = ?") .bind(newUsername, newPassword, oldUser).run(); return new Response("Password changed. Re-authenticating...", { status: 302, headers: { "Location": "/", "Set-Cookie": `${COOKIE_NAME}=; Path=/; Max-Age=0` } }); } // --- ADMIN CONTROL ACTIONS --- async function addUser(request, env) { const f = await request.formData(); await env.DB.prepare("INSERT INTO users (username, password, max_connections, exp_date) VALUES (?, ?, ?, ?)") .bind(f.get("username"), f.get("password"), parseInt(f.get("max_connections")), f.get("exp_date")).run(); return new Response(null, { status: 302, headers: { "Location": "/" } }); } async function editUser(request, env) { const f = await request.formData(); await env.DB.prepare("UPDATE users SET username = ?, password = ?, max_connections = ?, exp_date = ?, status = ? WHERE id = ?") .bind(f.get("username"), f.get("password"), parseInt(f.get("max_connections")), f.get("exp_date"), f.get("status"), f.get("id")).run(); return new Response(null, { status: 302, headers: { "Location": "/" } }); } async function deleteUser(request, env) { const f = await request.formData(); await env.DB.prepare("DELETE FROM users WHERE id = ?").bind(f.get("id")).run(); return new Response(null, { status: 302, headers: { "Location": "/" } }); } async function addStream(request, env) { const f = await request.formData(); await env.DB.prepare("INSERT INTO streams (name, url, category, type) VALUES (?, ?, ?, ?)") .bind(f.get("name"), f.get("url"), f.get("category"), f.get("type")).run(); return new Response(null, { status: 302, headers: { "Location": "/" } }); } async function editStream(request, env) { const f = await request.formData(); await env.DB.prepare("UPDATE streams SET name = ?, url = ?, category = ?, type = ? WHERE id = ?") .bind(f.get("name"), f.get("url"), f.get("category"), f.get("type"), f.get("id")).run(); return new Response(null, { status: 302, headers: { "Location": "/" } }); } async function deleteStream(request, env) { const f = await request.formData(); await env.DB.prepare("DELETE FROM streams WHERE id = ?").bind(f.get("id")).run(); return new Response(null, { status: 302, headers: { "Location": "/" } }); } async function massImportStreams(request, env) { const f = await request.formData(); const text = f.get("m3u_data") || ""; const lines = text.split("\n"); let currentName = ""; let currentCat = "Imported"; for (let line of lines) { line = line.trim(); if (line.startsWith("#EXTINF:")) { const nameMatch = line.match(/,(.*)$/); if (nameMatch) currentName = nameMatch[1].trim(); const catMatch = line.match(/group-title="([^"]+)"/); if (catMatch) currentCat = catMatch[1].trim(); } else if (line.startsWith("http")) { if (!currentName) currentName = "Untitled Stream"; await env.DB.prepare("INSERT INTO streams (name, url, category, type) VALUES (?, ?, ?, 'live')") .bind(currentName, line, currentCat).run(); currentName = ""; } } return new Response(null, { status: 302, headers: { "Location": "/" } }); } // --- SHARED NAVIGATION HEADER FRAGMENT --- function getNavHeaderHTML(activePath) { return `
TFMS IPTV Panel v3.0.0 Main Dashboard Admin Settings Get Streams
Logout
`; } // --- MAIN DATA DASHBOARD VIEW --- async function renderDashboard(request, env) { const users = (await env.DB.prepare("SELECT * FROM users").all()).results; const streams = (await env.DB.prepare("SELECT * FROM streams").all()).results; return new Response(` IPTV Core Engine Dashboard ${getNavHeaderHTML("/")}

Total Registered Lines

${users.length}

Active Managed Streams

${streams.length}

User Lines Management

Create New User Line

${users.map(u => ` `).join("")}
Line Configuration Details (Editable Fields)StatusPlaylistActions
Get M3U

Streams Base Management

Add Single Stream Route

Mass Import M3U Streams

${streams.map(s => ` `).join("")}
IDConfigurationCategoryActions
${s.id}
${s.category}
`, { headers: { "Content-Type": "text/html" } }); } // --- DEDICATED SEPARATE ADMIN SETTINGS PAGE VIEW --- async function renderAdminSettingsPage(request, env) { return new Response(` Admin Panel Settings
${getNavHeaderHTML("/admin/settings")}

Master Admin Credentials

Update your panel's root access credentials. Saving changes will terminate your current session and require logging back in.

`, { headers: { "Content-Type": "text/html" } }); } // --- PLAYLIST DOWNLOAD GENERATOR (.M3U) --- async function handleM3UDownload(request, env) { const url = new URL(request.url); let auth = url.searchParams.get("auth"); if (!auth) return new Response("Missing authorization token", { status: 401 }); const [username, password] = atob(auth).split(":"); const user = await env.DB.prepare("SELECT * FROM users WHERE username = ? AND password = ? AND status = 'active'").bind(username, password).first(); if (!user) return new Response("Unauthorized Line", { status: 403 }); const streams = (await env.DB.prepare("SELECT * FROM streams").all()).results; let playlist = "#EXTM3U\n"; const origin = url.origin; for (const s of streams) { playlist += `#EXTINF:-1 tvg-id="${s.id}" group-title="${s.category}",${s.name}\n`; playlist += `${origin}/proxy/${s.id}?u=${username}&p=${password}\n`; } return new Response(playlist, { headers: { "Content-Type": "application/x-mpegurl", "Content-Disposition": "attachment; filename=playlist.m3u" } }); } // --- STREAM PROXY ENGINE (Strict 20-Second Connection Lifespans) --- async function handleStreamProxy(request, env) { const url = new URL(request.url); const pathParts = url.pathname.split("/proxy/"); const streamId = pathParts[1]; const username = url.searchParams.get("u"); const password = url.searchParams.get("p"); const clientIp = request.headers.get("CF-Connecting-IP") || "0.0.0.0"; const now = Math.floor(Date.now() / 1000); const user = await env.DB.prepare("SELECT * FROM users WHERE username = ? AND password = ? AND status = 'active'").bind(username, password).first(); if (!user) return new Response("Access Forbidden: Invalid or Inactive Account", { status: 403 }); if (user.exp_date && new Date(user.exp_date) < new Date()) { return new Response("Access Forbidden: Line Playlist Expired", { status: 403 }); } // Strictly delete any session data link heartbeat records older than 20 seconds await env.DB.prepare("DELETE FROM connections WHERE last_active < ?").bind(now - 20).run(); await env.DB.prepare("INSERT OR REPLACE INTO connections (username, device_ip, last_active) VALUES (?, ?, ?)") .bind(username, clientIp, now).run(); const activeCount = await env.DB.prepare("SELECT COUNT(DISTINCT device_ip) as count FROM connections WHERE username = ?") .bind(username).first("count"); if (activeCount > user.max_connections) { return new Response(`Max Concurrent Multiroom Connections (${user.max_connections}) Reached`, { status: 429 }); } const stream = await env.DB.prepare("SELECT url FROM streams WHERE id = ?").bind(streamId).first(); if (!stream) return new Response("Target Stream Route ID Not Found", { status: 404 }); try { const response = await fetch(stream.url); const newHeaders = new Headers(response.headers); newHeaders.set("Access-Control-Allow-Origin", "*"); return new Response(response.body, { status: response.status, headers: newHeaders }); } catch (err) { return new Response("Stream Data Route Offline/Unreachable", { status: 502 }); } } // --- AUTOMATED EPG RENDERER (XMLTV) --- async function handleEPG(request, env) { const streams = (await env.DB.prepare("SELECT id, name FROM streams").all()).results; let xml = ``; for (const s of streams) { xml += `${s.name}`; xml += `Live BroadcastStreamed content from IPTV Matrix.`; } xml += ``; return new Response(xml, { headers: { "Content-Type": "application/xml" } }); } // --- XTREAM CODES API COMPATIBILITY ENGINE --- async function handleXtreamAPI(request, env) { const { searchParams } = new URL(request.url); const user = searchParams.get("user"); const pass = searchParams.get("password"); const action = searchParams.get("action"); const validUser = await env.DB.prepare("SELECT * FROM users WHERE username = ? AND password = ? AND status = 'active'").bind(user, pass).first(); if (!validUser) return new Response(JSON.stringify({ user_info: { auth: 0 } }), { headers: { "Content-Type": "application/json" } }); const baseResponse = { user_info: { auth: 1, status: "Active", exp_date: validUser.exp_date ? Math.floor(new Date(validUser.exp_date).getTime() / 1000).toString() : "null", max_connections: validUser.max_connections.toString(), active_cons: "0" }, server_info: { url: new URL(request.url).hostname, port: "80", https_port: "443" } }; if (!action) return new Response(JSON.stringify(baseResponse), { headers: { "Content-Type": "application/json" } }); if (action === "get_live_categories") { const categories = (await env.DB.prepare("SELECT DISTINCT category FROM streams").all()).results; return new Response(JSON.stringify(categories.map((c, i) => ({ category_id: (i + 1).toString(), category_name: c.category, parent_id: 0 }))), { headers: { "Content-Type": "application/json" } }); } if (action === "get_live_streams") { const streams = (await env.DB.prepare("SELECT * FROM streams WHERE type='live'").all()).results; const origin = new URL(request.url).origin; return new Response(JSON.stringify(streams.map(s => ({ num: s.id, name: s.name, stream_id: s.id, stream_icon: "", epg_channel_id: s.id.toString(), category_id: "1", direct_source: `${origin}/proxy/${s.id}?u=${user}&p=${pass}` }))), { headers: { "Content-Type": "application/json" } }); } return new Response(JSON.stringify([]), { headers: { "Content-Type": "application/json" } }); }