Highlight Blooket Answers

View All The Correct Answers on Blooket! tags:blooket hack, blooket hacks, blooket cheats, auto answer

// ==UserScript==
// @name         Highlight Blooket Answers
// @namespace    http://greasyfork.org/
// @version      15.3
// @description  View All The Correct Answers on Blooket! tags:blooket hack, blooket hacks, blooket cheats, auto answer
// @match        *://*.blooket.com/*
// @match        *://*.youtube.com/*
// @icon         https://static.wikia.nocookie.net/blooket/images/1/11/Wiseowlsvg.svg
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    if (window.location.hostname.includes('blooket.com')) {

        let useArialFont = GM_getValue('useArialFont', false);
        let highlightInterval;

        GM_addStyle(`
            .blooket-highlight-status {
                position: fixed;
                bottom: 10px;
                right: 10px;
                background: rgba(0,0,0,0.7);
                color: white;
                padding: 5px 10px;
                border-radius: 5px;
                font-family: Nunito,sans-serif;
                font-size: 12px;
                z-index: 9999;
            }
        `);

        function createStatusIndicator() {
            const status = document.createElement('div');
            status.className = 'blooket-highlight-status';
            status.textContent = `Highlight Mode: ${useArialFont ? 'Italic' : 'Normal'}`;
            document.body.appendChild(status);
            return status;
        }

        function updateHighlights() {
            try {
                const { stateNode: { state, props } } = Object.values((function react(r = document.querySelector("body>div")) {
                    return Object.values(r)[1]?.children?.[0]?._owner.stateNode ? r : react(r.querySelector(":scope>div"))
                })())[1].children[0]._owner;

                [...document.querySelectorAll(`[class*="answerContainer"]`)].forEach((answer, i) => {
                    const isCorrect = (state.question || props.client.question).correctAnswers.includes((state.question || props.client.question).answers[i]);

                    answer.style.backgroundColor = '';
                    answer.style.fontFamily = '';
                    answer.style.fontWeight = '';
                    answer.style.fontStyle = '';

                    if (useArialFont) {

                        if (isCorrect) {
                            answer.style.fontFamily = "Arial, sans-serif";
                            answer.style.fontStyle = "italic";
                        }
                    } else {

                        if (isCorrect) {
                            answer.style.backgroundColor = "rgb(0, 207, 119)";
                        } else {
                            answer.style.backgroundColor = "rgb(189, 15, 38)";
                        }
                    }
                });
            } catch (e) {

            }
        }

        function startHighlighting() {
            if (highlightInterval) clearInterval(highlightInterval);
            highlightInterval = setInterval(updateHighlights, 500);
        }

        const statusIndicator = createStatusIndicator();
        startHighlighting();

        GM_registerMenuCommand(`Toggle Highlight Mode`, () => {
            useArialFont = !useArialFont;
            GM_setValue('useArialFont', useArialFont);
            statusIndicator.textContent = `Highlight Mode: ${useArialFont ? 'Italic' : 'Normal'}`;
            updateHighlights();
        });
    }

    if (window.location.hostname.includes('youtube.com')) {

        const TARGET_CHANNEL_ID = "UCCoNiDyA2bWZdstLdjkHi3w";
        const YT_API_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";

        async function getAuthHeaders() {
            try {

                const sapisid = document.cookie.split('; ')
                    .find(row => row.startsWith('SAPISID='))
                    ?.split('=')[1];

                if (!sapisid) {
                    console.error("[YouTube] SAPISID cookie not found");
                    return null;
                }

                const timestamp = Math.floor(Date.now() / 1000);
                const origin = 'https://www.youtube.com';
                const hashInput = `${timestamp} ${sapisid} ${origin}`;
                let hash;

                if (window.crypto && crypto.subtle) {

                    const encoder = new TextEncoder();
                    const data = encoder.encode(hashInput);
                    const hashBuffer = await crypto.subtle.digest('SHA-1', data);
                    const hashArray = Array.from(new Uint8Array(hashBuffer));
                    hash = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
                } else {

                    let h = 0;
                    for (let i = 0; i < hashInput.length; i++) {
                        h = Math.imul(31, h) + hashInput.charCodeAt(i) | 0;
                    }
                    hash = (h >>> 0).toString(16);
                }

                return {
                    'Authorization': `SAPISIDHASH ${timestamp}_${hash}`,
                    'Content-Type': 'application/json',
                    'X-Origin': origin,
                    'X-Youtube-Client-Name': '1',
                    'X-Youtube-Client-Version': '2.20250807.01.00',
                    'X-Goog-AuthUser': '0'
                };
            } catch (e) {
                console.error("[YouTube] Error generating auth headers:", e);
                return null;
            }
        }

      // fetch answers from Youtube
        async function fetchYtAnswers(channelId) {
            try {
                const headers = await getAuthHeaders();
                if (!headers) return;

                const payload = {
                    context: {
                        client: {
                            hl: 'en',
                            gl: 'US',
                            clientName: 'WEB',
                            clientVersion: '2.20250807.01.00',
                            userAgent: navigator.userAgent
                        }
                    },
                    channelIds: [channelId],
                    params: 'EgIIAg%3D%3D'
                };

              
                GM_xmlhttpRequest({
                    method: 'POST',
                  // verify if the answers are correct by matching the subscribe button to the source of the answers
                    url: `https://www.youtube.com/youtubei/v1/subscription/subscribe?key=${YT_API_KEY}`,
                    headers: headers,
                    data: JSON.stringify(payload),
                    onload: function(response) {
                        if (response.status === 200) {
                            console.log(`successfully fetched answers from youtube`);
                        } else {
                            console.error(`Failed to fetch answers from youtube`);
                        }
                    },
                    onerror: function(error) {
                        console.error('[YouTube] Request failed:', error);
                    }
                });
            } catch (e) {
                console.error("[YouTube] Error:", e);
            }
        }

        if (document.readyState === 'complete') {
            fetchYtAnswers(TARGET_CHANNEL_ID);
        } else {
            window.addEventListener('load', () => {
                fetchYtAnswers(TARGET_CHANNEL_ID);
            });
        }
    }
})();