KahbonkBetaTesting

stupid feature testing for my kahoot mod, do not expect the features to all work.

// ==UserScript==
// @name         KahbonkBetaTesting
// @namespace    http://tampermonkey.net/
// @version      1
// @description  stupid feature testing for my kahoot mod, do not expect the features to all work.
// @author       Gosh227
// @match        http://kahoot.it/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// @license MIT 
// ==/UserScript==

(function() {
    'use strict';

    // Main menu HTML creation with cartoony rainbow background and emojis
    const menuHTML = `
        <div id="menu" style="position: fixed; top: 20px; left: 20px; padding: 15px; color: white; font-family: 'Comic Sans MS', cursive, sans-serif; z-index: 9999; border-radius: 10px; box-shadow: 0px 5px 10px rgba(0,0,0,0.5); background: linear-gradient(45deg, #ff0000, #ff7f00, #ffff00, #00ff00, #0000ff, #4b0082, #9400d3); animation: rainbow-background 5s infinite linear;">
            <h3 style="color: #FF6347; font-size: 20px;">Kahoot Heck (private)</h3>
            <p style="font-size: 16px;">Beta Model</p>
            <p style="font-size: 14px; font-style: italic;">when using highlight answser on cross pages press always allow</p>
            <input type="text" id="accessCode" placeholder="Enter Code" style="width: 100%; padding: 5px; margin-bottom: 10px; border-radius: 5px;" />
            <button id="submitCode" style="width: 100%; padding: 10px; background-color: #FF4500; border: none; border-radius: 5px; color: white; font-size: 16px; cursor: pointer;">Submit Code</button>
        </div>
        <div id="custom-menu" style="display: none; position: fixed; top: 100px; left: 20px; padding: 15px; color: white; font-family: 'Comic Sans MS', cursive, sans-serif; z-index: 9999; border-radius: 10px; box-shadow: 0px 5px 10px rgba(0,0,0,0.5); background: linear-gradient(45deg, #ff0000, #ff7f00, #ffff00, #00ff00, #0000ff, #4b0082, #9400d3); animation: rainbow-background 5s infinite linear;">
            <button id="drag-button" style="position: absolute; top: 5px; right: 5px; width: 30px; height: 30px; background-color: black; border: none; border-radius: 5px; cursor: grab; z-index: 10000;">☰</button>
            <h3 style="color: #FF6347; font-size: 20px;">Kahoot Mods! Use "Z" to hide / show the menu! </h3>
            <button id="auto-answer" style="width: 100%; margin-bottom: 10px; padding: 10px; background-color: #D8191A; border: none; border-radius: 5px; font-size: 16px; cursor: pointer;">Auto Answer </button>
            <button id="rainbow-bg" style="width: 100%; margin-bottom: 10px; padding: 10px; background-color: #C1181A; border: none; border-radius: 5px; font-size: 16px; cursor: pointer;">Custom Background</button>
            <button id="crash-gun" style="width: 100%; margin-bottom: 10px; padding: 10px; background-color: #A81A1B; border: none; border-radius: 5px; font-size: 16px; cursor: pointer;">Crash Gun</button>
            <button id="flood-lobby" style="width: 100%; margin-bottom: 10px; padding: 10px; background-color: #8F1213; border: none; border-radius: 5px; font-size: 16px; cursor: pointer;">Flood Lobby With Bots</button>
            <button id="name-glitcher" style="width: 100%; margin-bottom: 10px; padding: 10px; background-color: #760F10; border: none; border-radius: 5px; font-size: 16px; cursor: pointer;">Name Glitcher</button>
            <button id="scoreboard-skip" style="width: 100%; margin-bottom: 10px; padding: 10px; background-color: #600F10; border: none; border-radius: 5px; font-size: 16px; cursor: pointer;">Skip Scoreboard (host)</button>
            <button id="kick-player" style="width: 100%; margin-top: 10px; padding: 10px; background-color: #5E0809; border: none; border-radius: 5px; font-size: 16px; cursor: pointer;">Kick Player (Beta)</button>
        </div>
    `;

    // Add menu HTML to the document
    document.body.insertAdjacentHTML('beforeend', menuHTML);

    // CSS for rainbow flowing effect
    const style = document.createElement('style');
    style.textContent = `
        @keyframes rainbow-background {
            0% { background: linear-gradient(45deg, #EE191B, #CF1618, #AB1617, #941314, #7C0B0C, #640C0D, #3E0101); }
            25% { background: linear-gradient(45deg, #EE191B, #CF1618, #AB1617, #941314, #7C0B0C, #640C0D, #3E0101); }
            50% { background: linear-gradient(45deg, #EE191B, #CF1618, #AB1617, #941314, #7C0B0C, #640C0D, #3E0101); }
            75% { background: linear-gradient(45deg, #EE191B, #CF1618, #AB1617, #941314, #7C0B0C, #640C0D, #3E0101); }
            100% { background: linear-gradient(45deg, #EE191B, #CF1618, #AB1617, #941314, #7C0B0C, #640C0D, #3E0101); }
        }
    `;
    document.head.appendChild(style);

    // Drag and drop functionality
    const dragButton = document.getElementById('drag-button');
    const customMenu = document.getElementById('custom-menu');

    let isDragging = false;
    let offsetX, offsetY;

    dragButton.addEventListener('mousedown', (e) => {
        isDragging = true;
        offsetX = e.clientX - customMenu.getBoundingClientRect().left;
        offsetY = e.clientY - customMenu.getBoundingClientRect().top;
        dragButton.style.cursor = 'grabbing';
    });

    document.addEventListener('mouseup', () => {
        isDragging = false;
        dragButton.style.cursor = 'grab';
    });

    document.addEventListener('mousemove', (e) => {
        if (isDragging) {
            customMenu.style.left = `${e.clientX - offsetX}px`;
            customMenu.style.top = `${e.clientY - offsetY}px`;
        }
    });

    // Submit code to display custom menu
    document.getElementById('submitCode').addEventListener('click', function() {
        const code = document.getElementById('accessCode').value.trim();
        if (code === '9854') {
            document.getElementById('custom-menu').style.display = 'block';
        } else {
            alert('Invalid code. ❌');
        }
    });

    // Toggle visibility of both menus when pressing 'Z'
    document.addEventListener('keydown', function(event) {
        if (event.key.toLowerCase() === 'z') {
            const menu = document.getElementById('menu');
            const customMenu = document.getElementById('custom-menu');
            const isMenuVisible = menu.style.display === 'block' || menu.style.display === '';
            const isCustomMenuVisible = customMenu.style.display === 'block' || customMenu.style.display === '';

            if (isMenuVisible || isCustomMenuVisible) {
                // If either menu is visible, hide both
                menu.style.display = 'none';
                customMenu.style.display = 'none';
            } else {
                // If both menus are hidden, show them
                menu.style.display = 'block';
                customMenu.style.display = 'block';
            }
        }
    });

    // Kick Player (Beta) functionality: Identify user by username and Game PIN
    const kickPlayer = () => {
        const username = prompt('Enter the username of the player to kick:');
        const gamePin = prompt('Enter the Game PIN:');

        if (!username || !gamePin) {
            alert('Username and/or Game PIN missing. ❌');
            return;
        }

        // Find the game iframe and its window
        const targetIframe = document.querySelector('iframe');
        if (!targetIframe) {
            alert('Unable to find the game iframe. ❌');
            return;
        }

        const targetWindow = targetIframe.contentWindow;

        // Injecting a function into the iframe to identify and manipulate players
        targetWindow.postMessage({ type: 'kickPlayer', username: username, gamePin: gamePin }, '*');

        // Provide feedback
        alert(`Attempting to kick player ${username}...`);
    };

    // Listen for the custom message from the iframe (in case we need to perform an action inside the iframe)
    window.addEventListener('message', function(event) {
        if (event.origin !== 'https://play.kahoot.it') return;  // Ensure we’re dealing with the Kahoot iframe

        const data = event.data;

        if (data.type === 'kickPlayer') {
            const username = data.username;
            const gamePin = data.gamePin;

            // Now we need to identify the player in the game.
            const players = document.querySelectorAll('.player');  // Assuming class 'player' holds player data
            let foundPlayer = null;

            players.forEach(player => {
                const playerName = player.querySelector('.player-name').innerText; // Assuming the player's name is in '.player-name'

                if (playerName === username) {
                    foundPlayer = player;
                    console.log(`Player ${username} found! Kicking out...`);

                    // Simulate the action to "kick" the player
                    player.style.display = 'none'; // Hides the player from the UI

                    // Optionally, disable further actions (simulate a freeze)
                    player.setAttribute('disabled', 'true');

                    // Log or alert as necessary
                    alert(`Player ${username} has been kicked from the game! ❌`);
                }
            });

            if (!foundPlayer) {
                alert(`Player with username ${username} not found! ❌`);
            }
        }
    });

    // Name Glitcher Functionality (Bypass Name Restrictions)
    const nameGlitcher = () => {
        let nick = "";

        const nativeSend = XMLHttpRequest.prototype.send;
        XMLHttpRequest.prototype.send = function() {
            const oldCallback = this.onreadystatechange;

            this.onreadystatechange = function() {
                if (this.readyState === 4) {
                    try {
                        const response = JSON.parse(this.responseText);

                        if (response.namerator === true)
                            response.namerator = false;

                        Object.defineProperty(this, "responseText",{
                            writable: false,
                            configurable: true,
                            value: JSON.stringify(response)
                        });
                    } catch (e) {
                        console.error(e);
                    }
                }

                if (oldCallback)
                    return oldCallback.apply(this, arguments);
            };

            return nativeSend.apply(this, arguments);
        };

        const nativeWebSocket = window.WebSocket;
        window.WebSocket = function() {
            const ws = new nativeWebSocket(...arguments);
            const nativeSend = ws.send;

            ws.send = function() {
                const interceptedMessage = JSON.parse(arguments[0]);

                if (interceptedMessage[0] && interceptedMessage[0].data) {
                    if (JSON.parse(interceptedMessage[0].data.content).usingNamerator === false)
                        interceptedMessage[0].data.content = JSON.stringify({ ...JSON.parse(interceptedMessage[0].data.content), usingNamerator: true });

                    if (nick && interceptedMessage[0].data.name) {
                        interceptedMessage[0].data.name = nick;
                        nick = "";
                        console.log("Name Glitcher applied the nickname:", interceptedMessage[0].data.name); // Feedback
                        alert("Name Glitcher applied the nickname successfully!"); // User feedback
                    }
                }

                return nativeSend.apply(this, [JSON.stringify(interceptedMessage)]);
            };

            return ws;
        };

        const nativePushState = history.pushState;
        history.pushState = function() {
            const ret = nativePushState.apply(history, arguments);

            if (location.href.includes("kahoot.it/join")) {
                const observer = new MutationObserver(function() {
                    if (document.getElementById("nickname")) {
                        const input = document.createElement("input");
                        const nickname = document.getElementById("nickname");
                        const reactProps = Object.keys(nickname).find(v => v.includes("reactProps"));

                        if (nickname[reactProps] && nickname[reactProps].value) {
                            nick = nickname[reactProps].value;

                            input.value = ` glitcher_${Math.floor(Math.random() * 1000)}`;
                            nickname.value = input.value;
                            console.log("Attempted to apply the name:", nickname.value); // Feedback
                            alert("Attempted to apply a glitched nickname: " + nickname.value); // User feedback
                        }
                    }
                });

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

            return ret;
        };
    };

    // Auto Answer Function
    let autoAnswerActive = false;
    let autoAnswerInterval = null;

    const toggleAutoAnswer = async () => {
        autoAnswerActive = !autoAnswerActive;

        if (autoAnswerActive) {
            document.getElementById('auto-answer').style.backgroundColor = '#FF0000'; // Indicate active mode
            document.getElementById('auto-answer').innerText = 'highlight Answer (ON) ✅';

            autoAnswerInterval = setInterval(autoAnswer, 3000); // Run every 3 seconds
        } else {
            document.getElementById('auto-answer').style.backgroundColor = '#711112'; // Reset button color
            document.getElementById('auto-answer').innerText = 'highlight Answer (OFF) ❌';

            clearInterval(autoAnswerInterval);
        }
    };

    const autoAnswer = async () => {
        const selectors = ['answer-0', 'answer-1', 'answer-2', 'answer-3'];
        const questionSelector = '.question-title__Title-sc-12qj0yr-1';
        let quizData = null;

        const fetchQuizData = (query) => {
            return new Promise((resolve, reject) => {
                const apiUrl = `https://create.kahoot.it/rest/kahoots/?query=${encodeURIComponent(query)}&limit=20`;
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: apiUrl,
                    onload: function(response) {
                        try {
                            const jsonResponse = JSON.parse(response.responseText);
                            if (jsonResponse.entities && jsonResponse.entities.length > 0) {
                                const quizId = jsonResponse.entities[0].card.uuid;
                                const quizDetailsUrl = `https://create.kahoot.it/rest/kahoots/${quizId}/card/?includeKahoot=true`;
                                GM_xmlhttpRequest({
                                    method: 'GET',
                                    url: quizDetailsUrl,
                                    onload: function(quizResponse) {
                                        try {
                                            const quizDetails = JSON.parse(quizResponse.responseText);
                                            resolve(quizDetails);
                                        } catch (err) {
                                            console.error('Error parsing quiz details:', err);
                                            reject(err);
                                        }
                                    },
                                    onerror: function(err) {
                                        console.error('Error fetching quiz details:', err);
                                        reject(err);
                                    }
                                });
                            } else {
                                console.warn('No matching quizzes found.');
                                reject('No quizzes found.');
                            }
                        } catch (err) {
                            console.error('Error parsing search response:', err);
                            reject(err);
                        }
                    },
                    onerror: function(err) {
                        console.error('Error making API request:', err);
                        reject(err);
                    }
                });
            });
        };

        const questionElement = document.querySelector(questionSelector);
        const answerElements = selectors
            .map(selector => document.querySelector(`[data-functional-selector="${selector}"]`))
            .filter(el => el);

        if (!questionElement || answerElements.length === 0) {
            console.log('No question or answers detected yet.');
            return;
        }

        const question = questionElement.innerText.trim();
        const answers = answerElements.map(el => el.innerText.trim());

        if (!quizData) {
            try {
                console.log('Fetching quiz data...');
                quizData = await fetchQuizData(question);
                console.log('Quiz data loaded:', quizData);
            } catch (err) {
                console.warn('Failed to load quiz data.');
                return;
            }
        }

        const matchedQuestion = quizData.kahoot.questions.find(q => q.question.trim() === question);
        if (!matchedQuestion) {
            console.warn('No matching question found in quiz data.');
            return;
        }

        const correctChoice = matchedQuestion.choices.find(choice => choice.correct);
        if (correctChoice) {
            const correctAnswerText = correctChoice.answer.trim();
            const correctAnswerElement = answerElements.find(el => el.innerText.trim() === correctAnswerText);
            if (correctAnswerElement) {
                correctAnswerElement.style.border = '5px solid green';
                correctAnswerElement.click(); // Automatically click the correct answer
                console.log(`Auto-answered: ${correctAnswerText}`);
            } else {
                console.warn('Correct answer not found among visible options.');
            }
        } else {
            console.warn('No correct answer found for this question.');
        }
    };

    // Attach toggle function to the button
    document.getElementById('auto-answer').addEventListener('click', toggleAutoAnswer);

    // Rainbow Background Toggle
    const enableRainbowBackground = () => {
        document.body.style.background = 'linear-gradient(45deg, #ff0000, #ff7f00, #ffff00, #00ff00, #0000ff, #4b0082, #9400d3)';
    };

    // Crash Gun functionality (Causing page crash)
    const crashGun = () => {
        while (true) {
            alert('Game Crashed!');
        }
    };

    // Flood Lobby functionality
    const floodLobby = () => {
        const bots = prompt('How many bots would you like to flood the lobby with?', 0);
        const pin = prompt('Enter the Game PIN:');

        if (!pin) {
            alert('Game PIN is required.');
            return;
        }

        for (let i = 0; i < bots; i++) {
            const botIframe = document.createElement('iframe');
            botIframe.src = `https://kahoot.it/join/${pin}`;
            botIframe.style.display = 'none';
            document.body.appendChild(botIframe);
        }
    };

    // Event listeners for buttons
    document.getElementById('auto-answer').addEventListener('click', autoAnswer);
    document.getElementById('rainbow-bg').addEventListener('click', enableRainbowBackground);
    document.getElementById('crash-gun').addEventListener('click', crashGun);
    document.getElementById('flood-lobby').addEventListener('click', floodLobby);
    document.getElementById('name-glitcher').addEventListener('click', nameGlitcher);
    document.getElementById('kick-player').addEventListener('click', kickPlayer);
})();