Avjb VIP Unlock

Unlock all VIP videos, nuke paywall, fix thumbnails. Raw Source Fetch API Bypass, CORS fix, and native Playerjs hooking.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         Avjb VIP Unlock
// @namespace    avjb_vip_unlock
// @version      2.11.0
// @description  Unlock all VIP videos, nuke paywall, fix thumbnails. Raw Source Fetch API Bypass, CORS fix, and native Playerjs hooking.
// @author       codegeasse
// @match        https://avjb.com/*
// @match        https://avjb.cc/*
// @grant        GM_addStyle
// @license      MIT
// @require      https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.1.5/hls.min.js
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // ==========================================
    // Server Fallbacks (Prioritized Legacy Servers)
    // ==========================================
    const SERVERS = [
        'https://99newline.jb-aiwei.cc',
        'https://88newline.jb-aiwei.cc',
        'https://7senver.jb-aiwei.cc',
        'https://newbox.jb-aiwei.cc',
        'https://r22.jb-aiwei.cc',
        'https://bmc2.imgclh.com',
        'https://cdn1.bmc2.imgclh.com',
        'https://cdn2.bmc2.imgclh.com',
        'https://v.bmc2.imgclh.com',
        'https://hls.bmc2.imgclh.com',
        'https://stream.bmc2.imgclh.com',
        'https://back.bbmmic2.com',
        'https://lvb.rsso2.com'
    ];

    let capturedMasterUrl = null;
    let my_timer;
    let videoLoaded = false;
    let isChecking = false;

    // ====== NATIVE PLAYER HOOK (CRASH PREVENTION & URL THEFT) ======
    if (!window.__avjb_hooked) {
        window.__avjb_hooked = true;
        window.Playerjs = function(config) {
            console.log('[Avjb Unlock] Intercepted native Playerjs config:', config);
            if (config && config.file && !videoLoaded) {
                console.log('[Avjb Unlock] 🚀 Stolen secure URL from native player:', config.file);
                if (my_timer) { clearInterval(my_timer); my_timer = null; }
                loadHlsStream(config.file);
            }

            // Provide dummy API methods so the native scripts don't crash
            this.api = function(cmd, val) {
                const vid = document.getElementById('videoElement');
                if (cmd === 'time' && vid) return vid.currentTime || 0;
                if (cmd === 'duration' && vid) return vid.duration || 0;
                return 0;
            };
        };
    }

    // Hook fetch/xhr to capture master URLs (IGNORING OUR OWN PROBES)
    const originalFetch = window.fetch;
    window.fetch = function(input, init) {
        try {
            if (init && init.method && init.method.toUpperCase() === 'HEAD') return originalFetch.apply(this, arguments);
            const url = typeof input === 'string' ? input : input?.url;
            if (url && /\.m3u8(\?|$)/i.test(url) && !capturedMasterUrl) {
                const isBasicProbe = SERVERS.some(s => url.startsWith(s)) && !url.includes('md5=') && !url.match(/[a-zA-Z0-9_-]{30,}/);
                if (!isBasicProbe) {
                    capturedMasterUrl = url;
                    console.log('[Avjb Unlock] Captured master via Fetch:', url);
                }
            }
        } catch (e) {}
        return originalFetch.apply(this, arguments);
    };

    const originalXHROpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function(method, url, ...rest) {
        try {
            if (method && method.toUpperCase() === 'HEAD') return originalXHROpen.call(this, method, url, ...rest);
            if (url && /\.m3u8(\?|$)/i.test(url) && !capturedMasterUrl) {
                const isBasicProbe = SERVERS.some(s => url.startsWith(s)) && !url.includes('md5=') && !url.match(/[a-zA-Z0-9_-]{30,}/);
                if (!isBasicProbe) {
                    capturedMasterUrl = url;
                    console.log('[Avjb Unlock] Captured master via XHR:', url);
                }
            }
        } catch (e) {}
        return originalXHROpen.call(this, method, url, ...rest);
    };

    // ====== VIDEO PLAYER DOM ======
    const playerDiv = document.createElement('div');
    playerDiv.id = 'hlsPlayer';
    playerDiv.innerHTML = `
        <div class="player-content">
            <video id="videoElement" controls preload="none" playsinline webkit-playsinline></video>
            <div class="player-footer">
                <span id="showTips">⌛️ Initializing...</span>
                <a id="download" href="" target="_blank">⏬ 1-Click Download</a>
            </div>
        </div>
    `;
    const video = playerDiv.querySelector('#videoElement');
    const downloadEl = playerDiv.querySelector('#download');
    const showTipsEl = playerDiv.querySelector('#showTips');
    let hls = null;

    // ====== DOUBLE CLICK SEEK ======
    const SEEK_SECONDS = 10;
    let lastClickTime = 0;
    video.addEventListener('click', handleDoubleClick);
    video.addEventListener('touchend', handleDoubleClick, { passive: false });
    function handleDoubleClick(e) {
        const now = Date.now();
        const t = now - lastClickTime;
        if (t < 300 && t > 30) {
            let cx, cy;
            if (e.type.startsWith('touch')) {
                cx = e.changedTouches[0].clientX; cy = e.changedTouches[0].clientY;
            } else { cx = e.clientX; cy = e.clientY; }
            const rect = video.getBoundingClientRect();
            const xp = (cx - rect.left) / rect.width;
            const yp = (cy - rect.top) / rect.height;
            if (yp > 0.9) { lastClickTime = 0; return; }
            e.preventDefault(); e.stopPropagation();
            if (xp < 0.5) {
                video.currentTime = Math.max(0, video.currentTime - SEEK_SECONDS);
                showIndicator(`⏪ -${SEEK_SECONDS}s`, '15%');
            } else {
                video.currentTime = Math.min(video.duration, video.currentTime + SEEK_SECONDS);
                showIndicator(`+${SEEK_SECONDS}s ⏩`, '65%');
            }
            lastClickTime = 0;
        } else { lastClickTime = now; }
    }
    function showIndicator(text, left) {
        const popup = document.createElement('div');
        popup.className = 'seek-indicator';
        popup.innerText = text;
        popup.style.left = left;
        video.parentElement.appendChild(popup);
        setTimeout(() => popup.remove(), 700);
    }

    // ====== HLS LOADER ======
    function loadHlsStream(url) {
        if (videoLoaded) { return; }

        console.log('[Avjb Unlock] Loading HLS stream:', url);
        downloadEl.href = `https://tools.thatwind.com/tool/m3u8downloader#m3u8=${url}&referer=${window.location.href}&filename=${encodeURIComponent(document.title)}`;

        if (Hls.isSupported()) {
            if (hls) hls.destroy();
            hls = new Hls({
                manifestLoadingTimeOut: 20000,
                manifestLoadingMaxRetry: 4,
                levelLoadingTimeOut: 20000,
                levelLoadingMaxRetry: 4,
                xhrSetup: (xhr) => {
                    xhr.withCredentials = false;
                },
                enableWorker: true,
                lowLatencyMode: false,
            });

            hls.on(Hls.Events.MANIFEST_LOADING, () => {
                showTipsEl.innerText = '⌛️ Loading manifest...';
            });

            hls.loadSource(url);
            hls.attachMedia(video);
            hls.on(Hls.Events.MANIFEST_PARSED, () => {
                videoLoaded = true;
                showTipsEl.innerText = '✅ Unlocked! Click to play';
                showTipsEl.style.color = '#2ed573';
                if (my_timer) { clearInterval(my_timer); my_timer = null; }
            });
            hls.on(Hls.Events.ERROR, (event, data) => {
                if (data.fatal) {
                    if (data.type === Hls.ErrorTypes.MEDIA_ERROR) {
                        hls.recoverMediaError();
                        return;
                    }
                    showTipsEl.innerText = '❌ Load failed: ' + (data.details || data.type);
                    showTipsEl.style.color = '#ff4757';
                }
            });
        } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
            video.src = url;
            video.addEventListener('loadedmetadata', () => {
                videoLoaded = true;
                showTipsEl.innerText = '✅ Unlocked! Click to play';
                showTipsEl.style.color = '#2ed573';
                if (my_timer) { clearInterval(my_timer); my_timer = null; }
            });
        }
    }

    // ====== TRY ALL SERVERS ======
    function tryAllServers(folder, videoID) {
        if (videoLoaded || isChecking) return;

        isChecking = true;
        console.log('[Avjb Unlock] Starting legacy server probe for video:', videoID, 'folder:', folder);
        if (!videoID || isNaN(videoID) || videoID <= 0) {
            showTipsEl.innerText = '❌ Invalid video ID';
            isChecking = false;
            return;
        }

        showTipsEl.innerText = '⌛️ Finding legacy server...';
        let resolved = false;
        const cacheKey = `bbmmic2_date_${videoID}`;
        const cachedDate = localStorage.getItem(cacheKey);

        const tasks = [];
        SERVERS.forEach(baseURL => {
            let urlsToTry = [];

            if (baseURL.includes('bbmmic2.com')) {
                if (cachedDate) urlsToTry.push(`${baseURL}/data/${cachedDate}/${videoID}/hls/index.m3u8`);
                const probeDates = ['20220101','20220301','20220530','20220615','20220801','20221001','20221201','20230201','20230501','20230801','20240101','20240601','20250101','20250501','20250901'];
                probeDates.forEach(d => { if (d !== cachedDate) urlsToTry.push(`${baseURL}/data/${d}/${videoID}/hls/index.m3u8`); });
            } else if (baseURL.includes('imgclh.com')) {
                urlsToTry.push(
                    `${baseURL}/contents/videos/${folder}/${videoID}/index.m3u8`,
                    `${baseURL}/contents/videos/${folder}/${videoID}/master.m3u8`,
                    `${baseURL}/contents/videos_hls/${folder}/${videoID}/index.m3u8`,
                    `${baseURL}/contents/hls/${folder}/${videoID}/index.m3u8`,
                    `${baseURL}/videos/${folder}/${videoID}/index.m3u8`,
                    `${baseURL}/hls/${folder}/${videoID}/index.m3u8`,
                    `${baseURL}/contents/videos/${folder}/${videoID}/playlist.m3u8`
                );
            } else {
                urlsToTry.push(`${baseURL}/videos/${folder}/${videoID}/index.m3u8`);
            }

            urlsToTry.forEach(url => {
                tasks.push(
                    fetch(url, { method: 'HEAD', cache: 'no-store' })
                        .then(res => {
                            if (res.ok && !resolved && !videoLoaded) {
                                resolved = true;
                                console.log('[Avjb Unlock] ✅ Found working legacy server:', url);
                                const match = url.match(/\/data\/(\d{8})\//);
                                if (match) try { localStorage.setItem(cacheKey, match[1]); } catch (e) {}
                                showTipsEl.innerText = '⌛️ Server found, loading...';
                                loadHlsStream(url);
                            }
                        }).catch(() => {})
                );
            });
        });

        Promise.all(tasks);
        setTimeout(() => {
            if (!resolved && !videoLoaded) {
                resolved = true;
                showTipsEl.innerText = '⚠️ Limit hit & no legacy fallback found. Use VPN.';
                if (capturedMasterUrl) loadHlsStream(capturedMasterUrl);
            }
            isChecking = false;
        }, 20000);
    }

    // ====== THUMBNAILS ======
    function fixThumbnails() {
        document.querySelectorAll('.thumb, .video-thumb, .videos-list a, .list-videos a, .card a').forEach(el => {
            if (el.dataset.thumbFixed) return;
            el.dataset.thumbFixed = 'true';
            el.dispatchEvent(new PointerEvent('pointerover', {bubbles: true, cancelable: true}));
            el.dispatchEvent(new TouchEvent('touchstart', {bubbles: true, cancelable: true}));
            el.dispatchEvent(new MouseEvent('mouseover', {bubbles: true, cancelable: true}));
            setTimeout(() => el.dispatchEvent(new PointerEvent('pointermove', {bubbles: true})), 50);
        });
        document.querySelectorAll('a[href^="/video/"] img').forEach(img => {
            if (img.src && !img.src.includes('placeholder') && !img.src.includes('blank') && !img.src.includes('lazy')) return;
            const link = img.closest('a[href^="/video/"]');
            if (!link) return;
            const videoId = link.href.split('/video/')[1].split('/')[0];
            if (!videoId) return;
            const folder = Math.floor(parseInt(videoId) / 1000) * 1000;
            img.src = `https://bmc2.imgclh.com/contents/videos_screenshots/${folder}/${videoId}/preview.jpg`;
        });
        document.querySelectorAll('img').forEach(img => {
            img.style.opacity = '1';
            img.style.visibility = 'visible';
            img.loading = 'eager';
            img.classList.remove('lazy', 'lazyload', 'b-lazy');
        });
    }

    function startThumbnailFixer() {
        fixThumbnails();
        setInterval(fixThumbnails, 700);
        let scrollTimeout;
        window.addEventListener('scroll', () => {
            clearTimeout(scrollTimeout);
            scrollTimeout = setTimeout(fixThumbnails, 150);
        }, { passive: true });
    }

    function safeObserve(callback) {
        if (document.body) {
            callback();
        } else {
            const wait = setInterval(() => {
                if (document.body) { clearInterval(wait); callback(); }
            }, 10);
        }
    }

    safeObserve(() => {
        new MutationObserver(() => setTimeout(fixThumbnails, 100))
            .observe(document.body, { childList: true, subtree: true });
    });

    startThumbnailFixer();

    // ====== PAYWALL KILLER ======
    function nukePaywallAggressive(context) {
        context = context || document;
        try {
            const layer2 = context.getElementById ? context.getElementById('layer2') : (context.querySelector && context.querySelector('#layer2'));
            if (layer2 && layer2.remove) layer2.remove();

            const classQuery = context.querySelectorAll ? context.querySelectorAll(
                '.paywall-guest, .paywall-v2, .no-player, .pw-headline, ' +
                '.pw-guest-actions, .pw-btn-primary, .pw-btn-secondary, .pw-title, .message'
            ) : [];
            classQuery.forEach(el => el.remove());

            const allEls = context.querySelectorAll ? context.querySelectorAll('*') : [];
            allEls.forEach(el => {
                if (el.id === 'hlsPlayer' || (el.closest && el.closest('#hlsPlayer'))) return;
                if (el.children.length === 0) {
                    const text = (el.textContent || '').trim();
                    if (text === 'Sign Up to Watch' || text === 'Register Free Now' ||
                        text === 'Already a member? Log In' || text === 'Full video' ||
                        text.includes('Get 5 Free Watches')) {
                        let target = el;
                        for (let i = 0; i < 6 && target.parentElement; i++) {
                            if (target.className && typeof target.className === 'string' &&
                                (target.className.includes('paywall') ||
                                 target.className.includes('no-player') ||
                                 target.className.includes('message'))) {
                                target.remove();
                                break;
                            }
                            target = target.parentElement;
                        }
                    }
                }
            });

            const iframes = context.querySelectorAll ? context.querySelectorAll('iframe') : [];
            iframes.forEach(f => {
                try {
                    const idoc = f.contentDocument || (f.contentWindow && f.contentWindow.document);
                    if (idoc) nukePaywallAggressive(idoc);
                } catch (e) {}
            });

            const allWithShadow = context.querySelectorAll ? context.querySelectorAll('*') : [];
            allWithShadow.forEach(el => {
                if (el.shadowRoot) nukePaywallAggressive(el.shadowRoot);
            });

        } catch (e) {}

        if (context === document) {
            const holder = document.querySelector('.player-holder');
            if (holder && !holder.querySelector('#hlsPlayer')) {
                playerDiv.className = 'inline-mode';
                holder.innerHTML = '';
                holder.style.cssText = 'padding:0;margin:0;overflow:visible;position:relative;background:#000;min-height:200px;';
                holder.appendChild(playerDiv);
            }
        }
    }

    function setupPaywallKiller() {
        if (window.__paywallKillerInstalled) return;
        window.__paywallKillerInstalled = true;

        new MutationObserver(() => nukePaywallAggressive(document)).observe(document.body, { childList: true, subtree: true });
        setInterval(() => nukePaywallAggressive(document), 500);

        document.addEventListener('click', (e) => {
            const t = e.target;
            if (t.closest && (t.closest('.paywall-v2') || t.closest('.paywall-guest') ||
                t.closest('.no-player') || t.closest('.pw-btn-primary') ||
                t.closest('.pw-btn-secondary') || t.closest('.pw-guest-actions'))) {
                e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
            }
        }, true);
    }

    // ====== STYLE ======
    GM_addStyle(`
        img { opacity: 1 !important; visibility: visible !important; }
        .thumb, .video-thumb { background: none !important; }

        .paywall-guest, .paywall-v2, .no-player, .pw-headline, .pw-guest-actions,
        .pw-btn-primary, .pw-btn-secondary, .pw-title, .message {
            display: none !important; visibility: hidden !important; opacity: 0 !important;
            pointer-events: none !important; height: 0 !important; width: 0 !important;
            position: absolute !important; left: -99999px !important; top: -99999px !important;
        }

        .seek-indicator {
            position: absolute; top: 50%; transform: translateY(-50%);
            font-size: 42px; font-weight: bold; color: white;
            background: rgba(0,0,0,0.6); padding: 16px 20px; border-radius: 50%;
            z-index: 999999; pointer-events: none; animation: seekFadeOut 0.7s ease-out forwards;
        }
        @keyframes seekFadeOut {
            0% { opacity: 1; transform: translateY(-50%) scale(0.7); }
            30% { opacity: 1; transform: translateY(-50%) scale(1.1); }
            100% { opacity: 0; transform: translateY(-50%) scale(1); }
        }

        #hlsPlayer.inline-mode {
            position: relative !important; width: 100% !important; max-width: 100vw !important;
            background: #000; border-radius: 0; box-shadow: none; border: none;
            padding: 0; margin: 0; z-index: 999999; display: block !important;
            visibility: visible !important; opacity: 1 !important;
        }
        #hlsPlayer.inline-mode .player-content { display: flex; flex-direction: column; width: 100%; position: relative; }
        #hlsPlayer.inline-mode #videoElement { width: 100%; max-height: 56.25vw; aspect-ratio: 16 / 9; background: #000; border-radius: 0; display: block; }
        #hlsPlayer.inline-mode .player-footer { display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; background: #1a1a1a; font-size: 13px; font-family: Arial, sans-serif; }

        #showTips { color: #ccc; }
        #download { color: #ff4757; text-decoration: none; font-weight: bold; font-size: 13px; white-space: nowrap; }
        #download:hover { color: #ff6b81; text-decoration: underline; }
    `);

    function getVideoIdFromUrl() {
        const m = window.location.pathname.match(/\/video\/(\d+)/);
        return m ? parseInt(m[1]) : null;
    }

    let savedImgSrc = null;
    function earlyGrab() {
        if (!savedImgSrc) {
            const img = document.querySelector('.player-holder img[src*="videos_screenshots"]');
            const meta = document.querySelector('meta[property="og:image"]');
            if (img) savedImgSrc = img.src;
            else if (meta) savedImgSrc = meta.content;
        }
    }

    // ====== SECURE API BYPASS ======
    async function fetchSecureVIPLink() {
        showTipsEl.innerText = '⌛️ Extracting API token...';

        let rawHTML = "";
        try {
            // Bulletproof method: Fetch the raw page source directly so site scripts can't hide the token
            const pageRes = await fetch(window.location.href);
            rawHTML = await pageRes.text();
        } catch (e) {
            // Fallback to DOM if fetch fails
            rawHTML = document.documentElement.innerHTML;
        }

        const scriptMatch = rawHTML.match(/var\s+PLAYER_CSRF\s*=\s*"([^"]+)"/);

        if (!scriptMatch || !scriptMatch[1]) {
            console.warn('[Avjb Unlock] ❌ No CSRF token found in raw source. Strict IP-Ban active.');
            return false;
        }

        const csrfToken = scriptMatch[1];
        console.log('[Avjb Unlock] ✅ Found CSRF Token in raw source, requesting secure links...');
        showTipsEl.innerText = '⌛️ Requesting secure links...';

        try {
            const apiUrl = `/player/spped.php?csrf=${encodeURIComponent(csrfToken)}`;
            const response = await fetch(apiUrl, { credentials: 'same-origin' });

            if (!response.ok) throw new Error("HTTP " + response.status);

            const data = await response.json();

            if (data && data.sources && data.sources.length > 0) {
                const bestSource = data.sources.find(s => s.key === data.defaultKey) || data.sources[0];
                if (bestSource && bestSource.url) {
                    console.log('[Avjb Unlock] 🚀 API Success! Authorized URL:', bestSource.url);
                    if (my_timer) { clearInterval(my_timer); my_timer = null; }
                    loadHlsStream(bestSource.url);
                    return true;
                }
            }

            if (data && data.direct) {
                 const mp4Match = rawHTML.match(/this\.currentVideoURL\s*=\s*"([^"]+)"/);
                 if (mp4Match && mp4Match[1]) {
                     // Clean up weird 'function/0/' prefixes if they exist
                     const cleanUrl = mp4Match[1].replace('function/0/', '');
                     console.log('[Avjb Unlock] ⚠️ Falling back to direct proxy:', cleanUrl);
                     if (my_timer) { clearInterval(my_timer); my_timer = null; }
                     loadHlsStream(cleanUrl);
                     return true;
                 }
            }
        } catch (error) {
            console.error('[Avjb Unlock] ❌ API fetch failed:', error);
        }

        return false;
    }

    async function check_circle_v2() {
        if (videoLoaded || isChecking) return;
        if (!document.body) return;

        const playerHolder = document.querySelector('.player-holder');
        if (!playerHolder) return;

        earlyGrab();
        setupPaywallKiller();

        if (!document.getElementById('hlsPlayer')) {
            playerDiv.className = 'inline-mode';
            playerHolder.innerHTML = '';
            playerHolder.style.cssText = 'padding:0;margin:0;overflow:visible;position:relative;background:#000;min-height:200px;';
            playerHolder.appendChild(playerDiv);
        }

        if (capturedMasterUrl) {
            console.log('[Avjb Unlock] Using captured URL:', capturedMasterUrl);
            showTipsEl.innerText = '⌛️ Using site request...';
            loadHlsStream(capturedMasterUrl);
            if (my_timer) { clearInterval(my_timer); my_timer = null; }
            return;
        }

        isChecking = true;
        const apiSuccess = await fetchSecureVIPLink();

        if (!apiSuccess && !videoLoaded) {
            let videoID = getVideoIdFromUrl();
            let folder = null;
            if (!videoID && savedImgSrc) {
                const tmp = savedImgSrc.split('/');
                for (let i = 0; i < tmp.length - 1; i++) {
                    if (/^\d+000$/.test(tmp[i]) && /^\d+$/.test(tmp[i + 1])) {
                        folder = tmp[i]; videoID = parseInt(tmp[i + 1]); break;
                    }
                }
            }
            if (!videoID) {
                const meta = document.querySelector('meta[property="og:image"]');
                if (meta) {
                    const tmp = meta.content.split('/');
                    for (let i = 0; i < tmp.length - 1; i++) {
                        if (/^\d+000$/.test(tmp[i]) && /^\d+$/.test(tmp[i + 1])) {
                            folder = tmp[i]; videoID = parseInt(tmp[i + 1]); break;
                        }
                    }
                }
            }
            if (videoID) {
                if (!folder) folder = Math.floor(videoID / 1000) * 1000;
                console.log('[Avjb Unlock] API Failed/Limit Hit. Checking Legacy Servers. Video ID:', videoID, 'Folder:', folder);
                isChecking = false;
                tryAllServers(folder, videoID);
            } else {
                isChecking = false;
            }
        }

        if (videoLoaded && my_timer) {
            clearInterval(my_timer);
            my_timer = null;
        }
    }

    safeObserve(() => {
        console.log('[Avjb Unlock] Body ready, setting up paywall killer');
        setupPaywallKiller();
        check_circle_v2();
    });

    my_timer = setInterval(check_circle_v2, 1500);
})();