ZeroAd: CrazyGames SDK

Ad bypass with singleton SDK instance, event, and Unity support

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         ZeroAd: CrazyGames SDK
// @namespace    https://greasyfork.org/users/YOUR_USER_ID
// @version      4.4.1
// @description  Ad bypass with singleton SDK instance, event, and Unity support
// @author       ZeroAd Team
// @match        *://*.crazygames.com/*
// @match        *://crazygames.com/*
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

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

    const CONFIG = {
        DEBUG: true,
        REWARD_DELAY_MS: 500,   // Half a second feels natural
        MAX_HOOK_ATTEMPTS: 100,
        HOOK_RETRY_INTERVAL_MS: 200,
        AD_PLAYING_DURATION_MS: 5,
        SIMULATE_AD_ERROR: false
    };

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

    const hookState = {
        crazyGamesSDK: false,
        constructSDK: false,
        crazygamesAds: false,
        unityGameInstance: false,
        genericCrazySDK: false,
        crazySDKInstance: false,
        interceptedCalls: 0
    };

    // Singleton fake instance (created once)
    let fakeCrazySDKInstance = null;

    // ═══════════════════════════════════════════════════════════════
    // Fake CrazySDK Instance (singleton)
    // ═══════════════════════════════════════════════════════════════
    function createFakeCrazySDKInstance() {
        const listeners = {};
        let initCalled = false;
        let requestInProgress = false;

        function fireEvent(eventName, data = {}) {
            if (listeners[eventName]) {
                listeners[eventName].forEach(cb => {
                    try { cb(data); } catch (e) { warn(`Error in ${eventName} listener:`, e); }
                });
            }
        }

        return {
            init() {
                log('CrazySDK instance: init()');
                initCalled = true;
                setTimeout(() => {
                    fireEvent('initialized', {
                        userInfo: {
                            countryCode: "US",
                            browser: { name: "Chrome", version: "120" },
                            os: { name: "Windows", version: "10" },
                            device: { type: "desktop" }
                        }
                    });
                }, 50);
            },

            addEventListener(event, callback) {
                if (!listeners[event]) listeners[event] = [];
                listeners[event].push(callback);
                log(`CrazySDK instance: added listener for "${event}"`);
                if (event === 'initialized' && initCalled) {
                    setTimeout(() => callback({
                        userInfo: {
                            countryCode: "US",
                            browser: { name: "Chrome", version: "120" },
                            os: { name: "Windows", version: "10" },
                            device: { type: "desktop" }
                        }
                    }), 10);
                }
            },
            removeEventListener(event, callback) {
                if (listeners[event]) {
                    listeners[event] = listeners[event].filter(cb => cb !== callback);
                }
            },

            async requestAd(type = "midgame") {
                hookState.interceptedCalls++;
                log(`✓ INTERCEPTED: CrazySDK.requestAd("${type}")`);

                if (CONFIG.SIMULATE_AD_ERROR) {
                    fireEvent('adError', { error: 'Simulated error' });
                    return;
                }

                requestInProgress = true;
                fireEvent('adStarted', { adType: type });
                log('  → adStarted fired');

                return new Promise(resolve => {
                    setTimeout(() => {
                        requestInProgress = false;
                        fireEvent('adFinished', { adType: type });
                        log('  → adFinished fired');
                        log(`  → ✅ Reward granted for "${type}"`);
                        resolve();
                    }, CONFIG.REWARD_DELAY_MS);
                });
            },

            gameplayStart() { log('CrazySDK instance: gameplayStart() (stub)'); },
            gameplayStop() { log('CrazySDK instance: gameplayStop() (stub)'); },
            happytime() { log('CrazySDK instance: happytime() (stub)'); },
            sdkGameLoadingStart() { log('CrazySDK instance: sdkGameLoadingStart() (stub)'); },
            sdkGameLoadingStop() { log('CrazySDK instance: sdkGameLoadingStop() (stub)'); },

            async requestBanner(containers) {
                log('CrazySDK instance: requestBanner() (stub)', containers);
                if (Array.isArray(containers)) {
                    containers.forEach(c => {
                        setTimeout(() => fireEvent('bannerRendered', { containerId: c.containerId }), 50);
                    });
                }
            },
            async requestResponsiveBanner(containers) {
                log('CrazySDK instance: requestResponsiveBanner() (stub)', containers);
                if (Array.isArray(containers)) {
                    containers.forEach(c => {
                        setTimeout(() => fireEvent('bannerRendered', { containerId: c.id || c.containerId }), 50);
                    });
                }
            },
            clearBanner(containerId) { log(`CrazySDK instance: clearBanner("${containerId}") (stub)`); },
            clearAllBanners() { log('CrazySDK instance: clearAllBanners() (stub)'); },

            get hasAdblock() { return false; },
            adblockDetectionExecuted: true,

            inviteLink(params = {}) {
                log('CrazySDK instance: inviteLink() (stub)');
                const baseUrl = window.location.href.split('?')[0];
                const queryParams = new URLSearchParams(params);
                return `${baseUrl}?czy_invite=true&utm_source=invite&${queryParams.toString()}`;
            },

            get requestInProgress() { return requestInProgress; },
            set requestInProgress(val) { requestInProgress = val; }
        };
    }

    // ═══════════════════════════════════════════════════════════════
    // HOOK: CrazyGames.CrazySDK.getInstance() – SINGLETON FIX
    // ═══════════════════════════════════════════════════════════════
    function hookCrazySDKInstance() {
        if (hookState.crazySDKInstance) return true;

        // Create the singleton instance immediately
        fakeCrazySDKInstance = createFakeCrazySDKInstance();

        try {
            if (window.CrazyGames?.CrazySDK?.getInstance) {
                const originalGetInstance = window.CrazyGames.CrazySDK.getInstance;
                window.CrazyGames.CrazySDK.getInstance = function() {
                    log('✓ INTERCEPTED: CrazyGames.CrazySDK.getInstance()');
                    return fakeCrazySDKInstance;
                };
                hookState.crazySDKInstance = true;
                log('✓✓ CrazySDK.getInstance() HOOKED (existing singleton)');
                return true;
            }

            let _crazyGames = window.CrazyGames;
            Object.defineProperty(window, 'CrazyGames', {
                configurable: true,
                enumerable: true,
                get() { return _crazyGames; },
                set(newValue) {
                    log('CrazyGames object assigned');
                    _crazyGames = newValue;
                    if (newValue?.CrazySDK?.getInstance && !hookState.crazySDKInstance) {
                        const originalGetInstance = newValue.CrazySDK.getInstance;
                        newValue.CrazySDK.getInstance = function() {
                            log('✓ INTERCEPTED: CrazyGames.CrazySDK.getInstance() (deferred)');
                            return fakeCrazySDKInstance;
                        };
                        hookState.crazySDKInstance = true;
                        log('✓✓ CrazySDK.getInstance() HOOKED (deferred singleton)');
                    }
                }
            });

            log('✓ CrazySDK.getInstance() singleton trap installed');
            return false;
        } catch (error) {
            warn('Failed to hook CrazySDK.getInstance():', error);
            return false;
        }
    }

    // ═══════════════════════════════════════════════════════════════
    // Legacy hooks (unchanged, kept for compatibility)
    // ═══════════════════════════════════════════════════════════════
    function createFakeAdModule() {
        let _adPlaying = false;
        let _playingTimer = null;

        function dispatchRewardEvents() {
            const events = [
                'rewardedComplete', 'rewardGranted', 'adComplete',
                'crazy_ad_finished', 'adReward', 'adFinished'
            ];
            events.forEach(ev => {
                try { window.dispatchEvent(new CustomEvent(ev)); } catch (e) {}
            });
        }

        return {
            get isAdPlaying() { log(`isAdPlaying checked → ${_adPlaying}`); return _adPlaying; },
            get requestInProgress() { log('requestInProgress checked → false'); return false; },
            get hasAdblock() { log('hasAdblock checked → false'); return false; },
            async prefetchAd(type) { hookState.interceptedCalls++; log(`✓ INTERCEPTED: prefetchAd("${type}")`); return Promise.resolve(); },
            async requestAd(type, callbacks = {}) {
                hookState.interceptedCalls++; log(`✓ INTERCEPTED: requestAd("${type}")`);
                _adPlaying = true;
                if (_playingTimer) clearTimeout(_playingTimer);
                _playingTimer = setTimeout(() => { _adPlaying = false; }, CONFIG.AD_PLAYING_DURATION_MS);

                if (CONFIG.SIMULATE_AD_ERROR && typeof callbacks.adError === 'function') {
                    try { callbacks.adError({ code: 'INTERNAL_ERROR', message: 'Simulated error' }); log('  → adError() called'); } catch(e) {}
                    _adPlaying = false; clearTimeout(_playingTimer); return;
                }
                if (typeof callbacks.adStarted === 'function') { try { callbacks.adStarted(); log('  → adStarted() called'); } catch(e) {} }
                return new Promise(resolve => {
                    setTimeout(() => {
                        _adPlaying = false; clearTimeout(_playingTimer);
                        if (typeof callbacks.adFinished === 'function') { try { callbacks.adFinished(); log('  → adFinished() called'); } catch(e) {} }
                        dispatchRewardEvents();
                        log(`  → ✅ Reward granted for "${type}"`);
                        resolve();
                    }, CONFIG.REWARD_DELAY_MS);
                });
            },
            async hasAdblockEnabled() { hookState.interceptedCalls++; log('✓ INTERCEPTED: hasAdblockEnabled() → false'); return false; },
            addAdblockPopupListener() { log('addAdblockPopupListener (stub)'); },
            removeAdblockPopupListener() { log('removeAdblockPopupListener (stub)'); }
        };
    }

    function hookCrazyGamesSDK() {
        if (hookState.crazyGamesSDK) return true;
        try {
            if (window.CrazyGames?.SDK) {
                const fakeAd = createFakeAdModule();
                Object.defineProperty(window.CrazyGames.SDK, 'ad', { configurable: true, enumerable: true, get: () => fakeAd });
                hookState.crazyGamesSDK = true; log('✓✓ CrazyGames.SDK.ad HOOKED (existing)'); return true;
            }
            let _crazyGames = window.CrazyGames;
            Object.defineProperty(window, 'CrazyGames', {
                configurable: true, enumerable: true, get() { return _crazyGames; },
                set(newValue) { _crazyGames = newValue; if (newValue?.SDK && !hookState.crazyGamesSDK) { const fakeAd = createFakeAdModule(); Object.defineProperty(newValue.SDK, 'ad', { configurable: true, enumerable: true, get: () => fakeAd }); hookState.crazyGamesSDK = true; log('✓✓ CrazyGames.SDK.ad HOOKED (deferred)'); } }
            });
            log('✓ CrazyGames trap installed'); return false;
        } catch (error) { warn('Failed to hook CrazyGames.SDK:', error); return false; }
    }

    function hookConstructSDK() {
        if (hookState.constructSDK) return true;
        try {
            if (window.ConstructCrazySDK) {
                const fakeAd = createFakeAdModule();
                Object.defineProperty(window.ConstructCrazySDK, 'ad', { configurable: true, enumerable: true, get: () => fakeAd });
                hookState.constructSDK = true; log('✓✓ ConstructCrazySDK.ad HOOKED (existing)'); return true;
            }
            let _construct = window.ConstructCrazySDK;
            Object.defineProperty(window, 'ConstructCrazySDK', {
                configurable: true, enumerable: true, get() { return _construct; },
                set(newValue) { _construct = newValue; if (newValue && !hookState.constructSDK) { const fakeAd = createFakeAdModule(); Object.defineProperty(newValue, 'ad', { configurable: true, enumerable: true, get: () => fakeAd }); hookState.constructSDK = true; log('✓✓ ConstructCrazySDK.ad HOOKED (deferred)'); } }
            });
            log('✓ ConstructCrazySDK trap installed'); return false;
        } catch (error) { warn('Failed to hook ConstructCrazySDK:', error); return false; }
    }

    function hookGenericCrazySDK() {
        if (hookState.genericCrazySDK) return true;
        const target = window.CrazySDK || window.crazysdk;
        if (target) {
            const fakeAd = createFakeAdModule();
            if (target.ad) { Object.defineProperty(target, 'ad', { configurable: true, enumerable: true, get: () => fakeAd }); log('✓✓ CrazySDK.ad HOOKED'); }
            if (target.Ad) { Object.defineProperty(target, 'Ad', { configurable: true, enumerable: true, get: () => fakeAd }); log('✓✓ CrazySDK.Ad HOOKED'); }
            hookState.genericCrazySDK = true; return true;
        }
        ['CrazySDK', 'crazysdk'].forEach(propName => {
            if (hookState.genericCrazySDK) return;
            let _val = window[propName];
            Object.defineProperty(window, propName, {
                configurable: true, enumerable: true, get() { return _val; },
                set(newValue) { _val = newValue; if (newValue && !hookState.genericCrazySDK) { const fakeAd = createFakeAdModule(); if (newValue.ad) Object.defineProperty(newValue, 'ad', { configurable: true, enumerable: true, get: () => fakeAd }); if (newValue.Ad) Object.defineProperty(newValue, 'Ad', { configurable: true, enumerable: true, get: () => fakeAd }); hookState.genericCrazySDK = true; log(`✓✓ ${propName} HOOKED (deferred)`); } }
            });
        });
        log('✓ Generic CrazySDK trap installed'); return false;
    }

    function hookUnitySendMessage() {
        if (hookState.unityGameInstance) return true;
        const candidates = Object.keys(window).filter(key => { try { const val = window[key]; return val && typeof val === 'object' && typeof val.SendMessage === 'function'; } catch(e) { return false; } });
        for (const key of candidates) {
            const instance = window[key]; if (instance.__zaHooked) continue;
            const originalSend = instance.SendMessage;
            instance.SendMessage = function(gameObject, method, param) {
                if (method === 'AdEvent' && (param === 'adStarted' || param === 'adFinished' || param === 'adError')) { log(`✓ INTERCEPTED: Unity SendMessage`); hookState.interceptedCalls++; if (param === 'adStarted') { setTimeout(() => { try { originalSend.call(this, gameObject, method, 'adFinished'); } catch(e) {} }, CONFIG.REWARD_DELAY_MS); } return; }
                return originalSend.apply(this, arguments);
            };
            instance.__zaHooked = true; hookState.unityGameInstance = true; log(`✓✓ Unity SendMessage HOOKED`); return true;
        }
        return false;
    }

    function hookCrazygamesAds() {
        if (hookState.crazygamesAds) return true;
        const AD_METHODS = [
            'requestAd', 'requestAds', 'showAd', 'showRewardedAd',
            'displayAd', 'displayRewardedAd', 'displayMidrollAd',
            'requestRewardedAd', 'showRewardedVideo', 'requestRewardedVideo',
            'showInterstitial', 'requestOnly', 'render', 'preloadAd'
        ];
        function isAdMethod(prop) { return AD_METHODS.includes(prop); }
        function isAdblockMethod(prop) {
            const lower = prop.toLowerCase();
            return lower === 'hasadblock' || lower === 'hasadblockenabled' || lower === 'isadblockactive';
        }
        function createAdsProxy(target) {
            if (!target || target.__zaProxied) return target;
            const handler = {
                get(obj, prop) {
                    const original = obj[prop];
                    if (isAdMethod(prop) && typeof original === 'function') {
                        return function(...args) {
                            hookState.interceptedCalls++;
                            log(`✓ INTERCEPTED: CrazygamesAds.${prop}()`);
                            let onStarted = null, onFinished = null;
                            for (const arg of args) {
                                if (arg && typeof arg === 'object') {
                                    onStarted = arg.adStarted || arg.onAdStarted || arg.onStart;
                                    onFinished = arg.adFinished || arg.onAdFinished || arg.onComplete || arg.onReward;
                                }
                            }
                            if (typeof onStarted === 'function') { try { onStarted(); } catch(e) { warn('onStarted error:', e); } }
                            if (prop === 'requestOnly' || prop === 'preloadAd') { return Promise.resolve({ success: true }); }
                            return new Promise(resolve => {
                                setTimeout(() => {
                                    if (typeof onFinished === 'function') { try { onFinished(); } catch(e) { warn('onFinished error:', e); } }
                                    const events = ['rewardedComplete', 'adComplete', 'crazy_ad_finished'];
                                    events.forEach(ev => { try { window.dispatchEvent(new CustomEvent(ev)); } catch(e) {} });
                                    resolve({ success: true, completed: true });
                                }, CONFIG.REWARD_DELAY_MS);
                            });
                        };
                    }
                    if (isAdblockMethod(prop) && typeof original === 'function') {
                        return async () => { log(`✓ INTERCEPTED: CrazygamesAds.${prop}() → false`); return false; };
                    }
                    return original;
                }
            };
            const proxied = new Proxy(target, handler);
            proxied.__zaProxied = true;
            return proxied;
        }
        try {
            if (window.CrazygamesAds) {
                window.CrazygamesAds = createAdsProxy(window.CrazygamesAds);
                hookState.crazygamesAds = true;
                log('✓✓ CrazygamesAds HOOKED (existing)');
                return true;
            }
            let _ads = window.CrazygamesAds;
            Object.defineProperty(window, 'CrazygamesAds', {
                configurable: true, enumerable: true,
                get() { return _ads; },
                set(newValue) {
                    log('CrazygamesAds object assigned');
                    _ads = newValue ? createAdsProxy(newValue) : newValue;
                    if (_ads && !hookState.crazygamesAds) {
                        hookState.crazygamesAds = true;
                        log('✓✓ CrazygamesAds HOOKED (deferred)');
                    }
                }
            });
            log('✓ CrazygamesAds trap installed');
            return false;
        } catch (error) {
            warn('Failed to hook CrazygamesAds:', error);
            return false;
        }
    }

    // ═══════════════════════════════════════════════════════════════
    // ORCHESTRATION
    // ═══════════════════════════════════════════════════════════════
    let hookAttempts = 0;
    let retryTimer = null;
    let observer = null;

    function allHooksInstalled() {
        return hookState.crazySDKInstance ||
               (hookState.crazyGamesSDK && hookState.constructSDK && hookState.crazygamesAds &&
                hookState.genericCrazySDK && hookState.unityGameInstance);
    }

    function attemptHooks() {
        hookAttempts++;

        // NEW: Primary hook for the event-listener pattern
        hookCrazySDKInstance();

        // Legacy hooks
        hookCrazyGamesSDK();
        hookConstructSDK();
        hookCrazygamesAds();
        hookGenericCrazySDK();
        hookUnitySendMessage();

        if (allHooksInstalled()) {
            log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
            log('✅ ALL HOOKS INSTALLED SUCCESSFULLY');
            log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
            cleanup();
            return true;
        }

        if (hookAttempts >= CONFIG.MAX_HOOK_ATTEMPTS) {
            warn('⚠️  Hook installation incomplete after max attempts');
            warn('Hooked:', hookState);
            cleanup();
            return false;
        }
        return false;
    }

    function cleanup() {
        if (retryTimer) { clearInterval(retryTimer); retryTimer = null; }
        if (observer) { observer.disconnect(); observer = null; log('✓ MutationObserver disconnected'); }
    }

    function setupMutationObserver() {
        if (!CONFIG.MUTATION_OBSERVER_ENABLED) return;
        observer = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                for (const node of mutation.addedNodes) {
                    if (node.tagName === 'SCRIPT') {
                        const src = node.src || '';
                        if (src.includes('crazygames') || src.includes('sdk')) {
                            log(`Script detected: ${src.substring(0, 80)}...`);
                            node.addEventListener('load', () => {
                                log('SDK script loaded, re-attempting hooks');
                                setTimeout(attemptHooks, 50);
                            });
                        }
                    }
                }
            }
        });
        observer.observe(document.documentElement, { childList: true, subtree: true });
        log('✓ MutationObserver watching for SDK scripts');
    }

    function initialize() {
        log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        log('ZeroAd v4.4.0 - Full CrazySDK Instance & Event Support');
        log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');

        attemptHooks();
        setupMutationObserver();

        retryTimer = setInterval(() => {
            if (!allHooksInstalled() && hookAttempts < CONFIG.MAX_HOOK_ATTEMPTS) {
                attemptHooks();
                log(`Hook attempt ${hookAttempts}/${CONFIG.MAX_HOOK_ATTEMPTS}`);
            } else {
                cleanup();
            }
        }, CONFIG.HOOK_RETRY_INTERVAL_MS);

        setTimeout(() => {
            log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
            log('Status Report:');
            log('  Hooks installed:', hookState);
            log('  Intercepted calls:', hookState.interceptedCalls);
            log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        }, 5000);
    }

    initialize();

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', attemptHooks);
    }

})();