// ===================================================================== // FILE: engine.js (Core: Bộ lọc Link, Chặn Quảng Cáo & Mini Player) // ===================================================================== ajaxHooker.protect(); // Bắt trọn mọi file .m3u8 (cả file fetch lẫn XHR) ajaxHooker.filter([{ url: '.m3u8', method: 'GET' }]); ajaxHooker.hook(async request => { // Chỉ bắt những link .m3u8 chứa tham số (video thật) hoặc từ cloudfront (chống bắt nhầm m3u8 rác) if (request.url.includes('.m3u8') && (request.url.includes('?') || request.url.includes('.cloudfront.net'))) { const videoKey = request.url.split('?')[0]; const isTrialFormat = request.url.includes('_0001.m3u8') || request.url.includes('preview'); // TH1: NẾU LÀ VIDEO BỊ KHÓA VIP (DẠNG XEM THỬ) if (isTrialFormat) { // Tránh gọi server liên tục cho cùng 1 video if (currentVideoKey === videoKey) { if (window.real_m3u8_url && window.isMiniPlayerEnabled !== false) { request.url = window.real_m3u8_url; } return; } // Lấy token đăng nhập (nếu có) const { data: { session } } = await supabaseClient.auth.getSession(); const token = session ? session.access_token : null; // Lấy Device ID (fallback nếu gọi hàm bị thiếu do load thứ tự) const deviceId = typeof getDeviceId === 'function' ? getDeviceId() : localStorage.getItem('xv_device_id'); try { const response = await fetch(`${CONFIG.SB_URL}/functions/v1/get-vip-video`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': token ? `Bearer ${token}` : 'Bearer null' }, body: JSON.stringify({ trialUrl: request.url, deviceId: deviceId }) }); const data = await response.json(); if (response.ok && data.fullUrl) { currentVideoKey = videoKey; // LỆNH 1: Bơm link xịn vào luồng mạng của trình duyệt web (Mở khóa video gốc) request.url = data.fullUrl; // LỆNH 2: Chỉ đẩy dữ liệu ra Mini Player nếu người dùng BẬT công tắc if (window.isMiniPlayerEnabled !== false) { window.real_m3u8_url = data.fullUrl; } // Hiển thị thông báo nếu đang xài lượt miễn phí if (data.isFreeTrial && typeof showToast === 'function') { showToast(`🎁 Đã dùng ${data.viewsTaken}/5 lượt xem miễn phí thiết bị`); } else if (data.isVip) { console.log("✅ Đã cấp phát luồng video VIP chuẩn!"); } } else { // Server chặn -> Hết lượt hoặc hết VIP if (typeof showToast === 'function') { showToast("❌ Hết 5 lượt xem thử trên thiết bị này! Vui lòng nâng cấp VIP."); } // Tự động bật bảng hệ thống yêu cầu nạp tiền const authPanel = document.getElementById('auth-panel'); const floatBtn = document.getElementById('vip-floating-btn'); if (authPanel) authPanel.style.display = 'block'; if (floatBtn) floatBtn.style.display = 'none'; } } catch (e) { console.error("Lỗi giao tiếp máy chủ VIP", e); } } // TH2: NẾU LÀ VIDEO BÌNH THƯỜNG / MIỄN PHÍ else { if (currentVideoKey !== videoKey) { currentVideoKey = videoKey; // Cũng chỉ nạp vào Mini Player nếu người dùng đang BẬT công tắc if (window.isMiniPlayerEnabled !== false) { window.real_m3u8_url = request.url; } } } } }); // Vòng lặp dọn dẹp quảng cáo và kích hoạt Player function mainLoop() { // 1. Quét và xóa các banner/popup rác document.querySelectorAll("div.homeAdPop, div.vue-nice-modal-root, .exo-native-widget, div.preview-ui").forEach(s => s.remove()); // 2. Kích hoạt Mini Player nếu có link mới và công tắc đang BẬT if (window.real_m3u8_url && window.real_m3u8_url !== (window.his_m3u8_url || '')) { window.his_m3u8_url = window.real_m3u8_url; if (window.isMiniPlayerEnabled !== false) { startHls(window.real_m3u8_url); } } } // Khởi tạo và phát luồng video HLS function startHls(url) { const container = document.getElementById('mini-player-container'); const videoElement = document.getElementById('mini-video'); if (!container || !videoElement) return; // Hiển thị khung Player container.style.display = 'block'; // Đảm bảo nút gọi Player thu nhỏ (▶️) biến mất khi Player đang mở const playerBtn = document.getElementById('player-floating-btn'); if (playerBtn) playerBtn.style.display = 'none'; // Bơm luồng video if (Hls.isSupported()) { const hls = new Hls({ maxBufferLength: 30 }); hls.loadSource(url); hls.attachMedia(videoElement); hls.on(Hls.Events.MANIFEST_PARSED, () => { videoElement.play().catch(() => console.log("Trình duyệt chặn autoplay")); }); } else if (videoElement.canPlayType('application/vnd.apple.mpegurl')) { // Hỗ trợ riêng cho các thiết bị Apple (Safari/iOS) videoElement.src = url; videoElement.play().catch(() => console.log("Trình duyệt chặn autoplay")); } }