ZeroAd: Poki

Instant, zero-delay Poki SDK bypass with global object scanning

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         ZeroAd: Poki
// @namespace    https://greasyfork.org/en/users/1483567-vujohn123
// @version      4.0.5
// @description  Instant, zero-delay Poki SDK bypass with global object scanning
// @author       ZeroAd Team
// @match        *://*.poki.com/*
// @match        *://poki.com/*
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    if (window.__zaPokiLoaded) return;
    window.__zaPokiLoaded = true;

    const CONFIG = { DEBUG: true };  // Set false to disable logs
    const METRICS = {
        hooksInstalled: 0,
        interceptedCalls: 0,
        failedHooks: 0,
        rewardsGranted: 0
    };

    const log = (...args) => CONFIG.DEBUG && console.log('[ZeroAd:Poki]', ...args);
    const warn = (...args) => CONFIG.DEBUG && console.warn('[ZeroAd:Poki]', ...args);
    const error = (...args) => console.error('[ZeroAd:Poki]', ...args);

    // --- Core hook functions (mutates the passed object) ---
    function safeDispatchEvent(target, eventName) {
        try { target.dispatchEvent(new CustomEvent(eventName, { bubbles: true })); } catch (e) {}
    }
    function safeCallback(fn, ...args) {
        if (typeof fn === 'function') {
            try { fn(...args); } catch (e) { warn('Callback error:', e); }
        }
    }

    function hookPokiSDK(sdk) {
        if (!sdk || sdk.__zaHooked) return false;
        log('Hooking SDK object...');

        try {
            sdk.__zaHooked = true;

            // --- commercialBreak ---
            if (typeof sdk.commercialBreak === 'function') {
                sdk.commercialBreak = function(...args) {
                    log('🚫 commercialBreak skipped');
                    METRICS.interceptedCalls++;
                    if (args.length && typeof args[0] === 'function') try { args[0](); } catch(e) {}
                    return Promise.resolve();
                };
                log('✅ commercialBreak hooked');
            }

            // --- rewardedBreak ---
            if (typeof sdk.rewardedBreak === 'function') {
                sdk.rewardedBreak = function(callbacks) {
                    log('🎁 rewardedBreak → instant reward');
                    METRICS.interceptedCalls++;
                    let onStart = null, onReward = null, onError = null;
                    if (typeof callbacks === 'function') {
                        onReward = callbacks;
                    } else if (callbacks && typeof callbacks === 'object') {
                        onStart = callbacks.onStart || callbacks.start;
                        onReward = callbacks.adFinished || callbacks.onComplete || callbacks.onReward || callbacks.complete;
                        onError = callbacks.onError || callbacks.error;
                    }
                    safeCallback(onStart);
                    safeCallback(onReward);
                    safeCallback(onError, null);
                    METRICS.rewardsGranted++;
                    safeDispatchEvent(window, 'rewardedComplete');
                    safeDispatchEvent(window, 'rewardGranted');
                    safeDispatchEvent(window, 'adComplete');
                    log('✅ Reward granted instantly');
                    return Promise.resolve(true);
                };
                log('✅ rewardedBreak hooked');
            }

            // --- display ads ---
            if (typeof sdk.hoistDisplayAd === 'function') {
                sdk.hoistDisplayAd = () => { METRICS.interceptedCalls++; return false; };
            }
            if (typeof sdk.destroyDisplayAd === 'function') {
                sdk.destroyDisplayAd = () => { METRICS.interceptedCalls++; };
            }
            if (typeof sdk.displayAd === 'function') {
                sdk.displayAd = (e, t, o, i) => {
                    METRICS.interceptedCalls++;
                    if (i) safeCallback(i, true);
                    if (o) safeCallback(o);
                    return false;
                };
            }
            if (typeof sdk.destroyAd === 'function') {
                sdk.destroyAd = () => { METRICS.interceptedCalls++; };
            }

            // --- playground / platform breaks ---
            ['playgroundCommercialBreak', 'platformCommercialBreak'].forEach(m => {
                if (typeof sdk[m] === 'function') {
                    sdk[m] = () => { log(m + ' skipped'); METRICS.interceptedCalls++; return Promise.resolve(); };
                }
            });

            // --- monetization internals ---
            if (sdk.__monetization) {
                if (typeof sdk.__monetization.requestAd === 'function') sdk.__monetization.requestAd = () => Promise.resolve();
                if (typeof sdk.__monetization.displayAd === 'function') sdk.__monetization.displayAd = () => false;
                if (typeof sdk.__monetization.init === 'function') sdk.__monetization.init = () => Promise.resolve();
            }

            // --- no-op tracking ---
            ['happyTime','gameLoading','gameplayStart','gameplayStop','captureError','sendEvent','track','setDebug','measure','gameLoadingFinished','gameLoadingProgress','gameInteractive','logError','muteAd','roundEnd','roundStart','sendHighscore','setLogging','setPlayerAge','enableEventTracking','openExternalLink'].forEach(m => {
                if (typeof sdk[m] === 'function') {
                    sdk[m] = (...args) => {
                        if (m === 'gameplayStart' || m === 'gameplayStop') log(m + ' tracked (no-op)');
                        else log(m + ' no-op');
                    };
                }
            });

            METRICS.hooksInstalled++;
            log('✅ SDK object fully hooked!');
            return true;
        } catch (e) {
            error('Hook failed:', e);
            METRICS.failedHooks++;
            return false;
        }
    }

    // --- Trap for window.PokiSDK (non-configurable) ---
    function installTrap() {
        let _pokiSDK = window.PokiSDK;
        if (_pokiSDK && !_pokiSDK.__zaHooked) {
            hookPokiSDK(_pokiSDK);
        }
        Object.defineProperty(window, 'PokiSDK', {
            configurable: false,
            enumerable: true,
            get: function() {
                // log('PokiSDK GET'); // optional, can be noisy
                return _pokiSDK;
            },
            set: function(newValue) {
                log('PokiSDK SET (new SDK)');
                _pokiSDK = newValue;
                if (newValue && !newValue.__zaHooked) {
                    hookPokiSDK(newValue);
                }
            }
        });
        log('✅ Non‑configurable trap installed');
    }

    // --- Global scanner: find and hook any object with SDK methods ---
    function scanAndHookAllSDKObjects() {
        let found = 0;
        // Check all properties of window
        for (let key in window) {
            try {
                const val = window[key];
                if (val && typeof val === 'object' && val !== window && !val.__zaHooked) {
                    // Check if it has the typical SDK methods
                    if (typeof val.commercialBreak === 'function' && typeof val.rewardedBreak === 'function') {
                        log('Found SDK object at window.' + key + ' – hooking its methods');
                        hookPokiSDK(val);
                        found++;
                    }
                }
            } catch(e) {}
        }
        // Also check common aliases
        const aliases = ['Poki', 'PokiUnitySDK', 'PokiSDK', 'poki'];
        for (let alias of aliases) {
            try {
                const val = window[alias];
                if (val && typeof val === 'object' && !val.__zaHooked && typeof val.commercialBreak === 'function') {
                    log('Found SDK object at window.' + alias + ' – hooking');
                    hookPokiSDK(val);
                    found++;
                }
            } catch(e) {}
        }
        if (found > 0) {
            log(`✅ Hooked ${found} additional SDK object(s)`);
        }
        return found;
    }

    // --- Observer for script loads (fallback) ---
    function setupObserver() {
        const observer = new MutationObserver(mutations => {
            for (const mutation of mutations) {
                for (const node of mutation.addedNodes) {
                    if (node.tagName === 'SCRIPT') {
                        const src = (node.src || '').toLowerCase();
                        if (src.includes('poki') && (src.includes('sdk') || src.includes('hoist') || src.includes('playground') || src.includes('v2') || src.includes('ay'))) {
                            log('SDK script detected:', src.substring(0, 80));
                            if (node.readyState === 'complete' || node.readyState === 'loaded') {
                                setTimeout(() => { scanAndHookAllSDKObjects(); }, 0);
                            } else {
                                node.addEventListener('load', () => {
                                    setTimeout(() => { scanAndHookAllSDKObjects(); }, 0);
                                });
                            }
                        }
                    }
                }
            }
        });
        if (document.documentElement) {
            observer.observe(document.documentElement, { childList: true, subtree: true });
        }
        log('✅ MutationObserver active');
    }

    // --- Initialization ---
    function initialize() {
        log('🚀 ZeroAd: Poki SDK v4.0.5 – Global scanner');
        installTrap();
        setupObserver();

        // Initial scan after a short delay
        setTimeout(scanAndHookAllSDKObjects, 100);

        // Keep scanning for a few seconds to catch late objects
        let attempts = 0;
        const maxAttempts = 20; // 10 seconds
        const interval = setInterval(() => {
            attempts++;
            const found = scanAndHookAllSDKObjects();
            if (attempts >= maxAttempts || found > 0) {
                // If we found something, we can slow down or stop, but we'll keep going a bit more.
                if (found > 0) {
                    log('Found objects, continuing scan...');
                }
                if (attempts >= maxAttempts) {
                    clearInterval(interval);
                    log('🔍 Scan finished');
                }
            }
        }, 500);

        window._zaMetrics = window._zaMetrics || {};
        window._zaMetrics.poki = METRICS;

        // Status report after 5 seconds
        setTimeout(() => {
            log('📊 Status:', {
                hooksInstalled: METRICS.hooksInstalled,
                interceptedCalls: METRICS.interceptedCalls,
                rewardsGranted: METRICS.rewardsGranted
            });
        }, 5000);
    }

    initialize();

    // Also scan on DOMContentLoaded as a safety net
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => {
            setTimeout(scanAndHookAllSDKObjects, 0);
        });
    }
})();