Blookedex Integration (Original Style)

An efficient theme selector with blookedex integrations (maintains original profile style)

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Blookedex Integration (Original Style)
// @namespace    http://tampermonkey.net/
// @version      2025-05-23
// @description  An efficient theme selector with blookedex integrations (maintains original profile style)
// @author       fsscooter
// @match        *://tri.pengpowers.xyz/*
// @match        *://coplic.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=blooket.com
// @grant        none
// @license GNU GPLv3
// ==/UserScript==

(function() {
    'use strict';

    const version = "2025-05-23";

    // Cookie management functions
    function setCookie(e,t,o){let i=new Date;i.setTime(i.getTime()+864e5*o);let n="expires="+i.toUTCString();document.cookie=`${e}=${encodeURIComponent(t)}; ${n}; path=/; secure; samesite=Lax`}
    function getCookie(e){let t=e+"=",o=decodeURIComponent(document.cookie),i=o.split(";");for(let n of i){for(;" "===n.charAt(0);)n=n.substring(1);if(0===n.indexOf(t))return n.substring(t.length,n.length)}return null}
    function deleteCookie(name) {
        document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
    }

    const themes = [
        { name: "blooket", primary: "#9A48AA", secondary: "#08C2D0", background: "#08C2D0",
          scrollbar: { track: "#083a3d", thumb: "#0b7075", hover: "#10a5ac" } },
        { name: "sunset", primary: "#E44C51", secondary: "#FFA41B", background: ["#5d87e3", "#ff3b8c"],
          scrollbar: { track: "#3a1a1c", thumb: "#7a3639", hover: "#b84d51" } },
        { name: "forest", primary: "#2E8B57", secondary: "#A3C586", background: ["#1B512D", "#A4DE02"],
          scrollbar: { track: "#183a06", thumb: "#2a630c", hover: "#4e9329" } },
        { name: "ocean", primary: "#0077B6", secondary: "#90E0EF", background: ["#00B4D8", "#03045E"],
          scrollbar: { track: "#002b3d", thumb: "#005073", hover: "#0077b6" } },
        { name: "midnight", primary: "#1C1C2E", secondary: "#3E3E55", background: ["#3A3A7C", "#0F0F2D"],
          scrollbar: { track: "#0a0a14", thumb: "#1c1c2e", hover: "#3e3e55" } },
        { name: "sunrise", primary: "#FFA07A", secondary: "#FFD700", background: ["#FFDEE9", "#B5FFFC"],
          scrollbar: { track: "#3a1a0c", thumb: "#7a3419", hover: "#b84d26" } },
        { name: "aurora", primary: "#7F00FF", secondary: "#00FF87", background: ["#00FFC3", "#3E1E68"],
          scrollbar: { track: "#1a003d", thumb: "#3d007a", hover: "#7f00ff" } },
        { name: "space", primary: "#4B0082", secondary: "#9370DB", background: ["#1F2833", "#0B0C10"],
          scrollbar: { track: "#0a0a14", thumb: "#1c1c2e", hover: "#3e3e55" } },
        { name: "peach", primary: "#FFADAD", secondary: "#FFD6A5", background: ["#FFEACD", "#FFDAC1"],
          scrollbar: { track: "#3a1a1c", thumb: "#7a3639", hover: "#b84d51" } },
        { name: "ice", primary: "#A0E9FD", secondary: "#CAF0F8", background: ["#B2EBF2", "#E0F7FA"],
          scrollbar: { track: "#083a3d", thumb: "#0b7075", hover: "#10a5ac" } },
        { name: "coral", primary: "#148cdf", secondary: "#ee7de9", background: ["#ef1284", "#00b898"],
          scrollbar: { track: "#1a003d", thumb: "#3d007a", hover: "#7f00ff" } },
        { name: "charcoal", primary: "#111a24", secondary: "#f8ee00", background: ["#aba400", "#1f3042"],
          scrollbar: { track: "#0a0a14", thumb: "#1c1c2e", hover: "#3e3e55" } },
        { name: "cotton candy", primary: "#ffcbcb", secondary: "#c9fdff", background: ["#9db1ea", "#e47e98"],
          scrollbar: { track: "#1a003d", thumb: "#3d007a", hover: "#7f00ff" } },
        { name: "minecraft", primary: "#61371f", secondary: "#70b237", background: ["#3c44aa", "#3ab3da"],
          customShopkeeper: ["https://hollowvr.github.io/onlineassets/steveblooket.png", "1"],
          customStore: "https://hollowvr.github.io/onlineassets/mcstoreblooket.svg",
          scrollbar: { track: "#1a2b06", thumb: "#2a630c", hover: "#4e9329" } },
        { name: "easter", primary: "#F8DC8A", secondary: "#F4A8CF", background: ["#B6E7B9", "#93DE8B"],
          scrollbar: { track: "#1a2b06", thumb: "#2a630c", hover: "#4e9329" } },
        { name: "halloween", primary: "#F86D01", secondary: "#18e810", background: ["#A805F7", "#DA03F6"],
          customShopkeeper: ["https://hollowvr.github.io/onlineassets/jackolanternblooket.png","1.3"],
          scrollbar: { track: "#3a1a0c", thumb: "#7a3419", hover: "#b84d26" } },
        { name: "usa", primary: "#424173", secondary: "#B52A3A", background: "repeating-linear-gradient(-5deg,#dbdbdb,#dbdbdb 60px,#B52A3A 60px,#B52A3A 120px);",
          customShopkeeper: ["https://upload.wikimedia.org/wikipedia/commons/5/5a/Donald_Trump_cutout.png", "1.5"],
          customStore: "https://hollowvr.github.io/onlineassets/usastoreblooket.svg",
          scrollbar: { track: "#1a003d", thumb: "#3d007a", hover: "#7f00ff" } },
        { name: "summer", primary: "#72D6E4", secondary: "#D8A93F", background: ["#89CDDA", "#FBDCA5"],
          scrollbar: { track: "#083a3d", thumb: "#0b7075", hover: "#10a5ac" } },
        { name: "autumn", primary: "#C16A19", secondary: "#DFA628", background: ["#AD3B2D", "#D8284D"],
          scrollbar: { track: "#3a1a0c", thumb: "#7a3419", hover: "#b84d26" } },
        { name: "winter", primary: "#96CEFE", secondary: "#6C80BE", background: ["#A4F4FF", "#75A5C3"],
          scrollbar: { track: "#002b3d", thumb: "#005073", hover: "#0077b6" } },
        { name: "christmas", primary: "#C9001C", secondary: "#1FB34F", background: "radial-gradient(ellipse at bottom, #4e9a51 0%, #3d7b42 40%, #2f5e34 100%);",
          customShopkeeper: ["https://ac.blooket.com/marketassets/blooks/santaclaus.svg", "1"],
          customStore: "https://ac.blooket.com/dashclassic/assets/StoreWinter-DOhqNDCZ.svg",
          scrollbar: { track: "#1a2b06", thumb: "#2a630c", hover: "#4e9329" } },
        { name: "mardi gras", primary: "#A016FC", secondary: "#27DA3B", background: "linear-gradient(45deg,rgba(47, 163, 75, 1) 0%, rgba(140, 71, 151, 1) 50%, rgba(255, 204, 40, 1) 100%);",
          scrollbar: { track: "#1a003d", thumb: "#3d007a", hover: "#7f00ff" } },
        { name: "haze", primary: "#4e4c29", customSidebar: "linear-gradient(to right, rgba(0,0,0,0) 40%, #4287f566 130%),repeating-linear-gradient(135deg,#535b1f 0%, rgba(83,91,31,0.8) 40%, #4b462c 70%, rgba(75,70,44,0.8) 100%)",
          secondary: "#f8de99", background: ["#fdbb35", "#ad1f25"],
          scrollbar: { track: "#3a1a0c", thumb: "#7a3419", hover: "#b84d26" } },
        { name: "midnight flare", primary: "rgba(0, 20, 80, 0.8)", secondary: "#6c757d",
          background: ["#1a2b99", "#141414"],
          scrollbar: { track: "#0a0a14", thumb: "#1c1c2e", hover: "#3e3e55" } },
        { name: "twilight", primary: "rgba(38, 50, 56, 0.8)", secondary: "#b0bec5", background: ["#1a2327", "#37474f"],
          scrollbar: { track: "#0a0a14", thumb: "#1c1c2e", hover: "#3e3e55" } },
        { name: "blood moon", primary: "rgba(102, 0, 0, 0.8)", secondary: "#2f2f2f", background: ["#3e1414", "#000000"],
          scrollbar: { track: "#0a0a14", thumb: "#1c1c2e", hover: "#3e3e55" } },
        { name: "kraken", primary: "rgba(0, 51, 102, 0.8)", secondary: "#1abc9c", background: "linear-gradient(to bottom, #7db9e8 -5%, #005073 10%, #003e58 25%, #002a3d 55%, #000022 80%)",
          customShopkeeper: ["https://ac.blooket.com/marketassets/blooks/kraken.svg","1"],
          scrollbar: { track: "#002b3d", thumb: "#005073", hover: "#0077b6" } },
        { name: "pittsburgh", primary: "#000000", secondary: "#E0B800", background: ["#FFD700 0%", "#D4AF37 40%", "#B8860B 80%", "#2F1C00 100%"],
          scrollbar: { track: "#0a0a14", thumb: "#1c1c2e", hover: "#3e3e55" } },
        { name: "USSR", primary: "#C60300", secondary: "#F9D700", background: "radial-gradient(#ff0000, #a60000)",
          customShopkeeper: ["https://hollowvr.github.io/onlineassets/karlmarxblooket.png", "1.7"],
          customStore: "https://hollowvr.github.io/onlineassets/ussrstoreblooket.png",
          scrollbar: { track: "#3a1a0c", thumb: "#7a3419", hover: "#b84d26" } }
    ];

    if (getCookie("blxdextheme") == null) {
        setCookie("blxdextheme", "5") // Default to sunrise theme
    }
    const theme = Number(getCookie("blxdextheme"))
    let background = "#fff"
    if (Array.isArray(themes[theme].background)) {
        background = 'linear-gradient('+themes[theme].background[0]+', '+themes[theme].background[1]+')';
    } else {
        background = themes[theme].background;
    }

    console.log("Blookedex extension initialized");

    // Add styles
    const style = document.createElement('style');
    style.innerHTML = `
    @import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;700&display=swap');

    .blookedex-btnClose {
        transition:all .2s ease;
    }

    .blookedex-btnCloseGrandparent:hover .blookedex-btnClose {
        fill:#fff;
    }
    @keyframes blookedex-packImgKeyframes {
        from {transform:translateY(-50%) rotateY(90deg) scale(.1)}
        to {transform:translateY(-50%) rotateY(20deg) scale(1)}
    }
    .blookedex-packImg {
        animation: .5s cubic-bezier(.08,.54,.55,1.07) blookedex-packImgKeyframes;
    }
    .blookedex-buyBtn {
        transition: filter .25s;
    }
    .blookedex-buyBtn:hover {
        filter:brightness(110%);
    }
    .blookedex-buyBtn:hover > :first-child {
        transform:translateY(-2px);
    }
    .blookedex-buyBtn:hover > :nth-child(3) {
        transform:translateY(2px);
    }

    /* Custom styles for your page */
    .styles__background___2J-JA-camelCase {
        background: ${background} !important;
    }

    .styles__sidebar___1XqWi-camelCase {
        background-color: ${themes[theme].primary} !important;
    }

    /* Original profile container styling */
    .styles__profileContainer___CSuIE-camelCase {
        background-color: ${themes[theme].primary} !important;
    }

    .styles__pageButton___1wFuu-camelCase {
        color: white !important;
    }

    .styles__pageButton___1wFuu-camelCase:hover {
        background-color: ${themes[theme].secondary} !important;
    }

    .styles__header___153FZ-camelCase {
        color: ${themes[theme].secondary} !important;
        text-shadow: 2px 2px 0 rgba(0,0,0,0.2) !important;
    }

    /* Scrollbar styles */
    ::-webkit-scrollbar {
        width: 10px;
    }

    ::-webkit-scrollbar-track {
        background: ${themes[theme].scrollbar.track};
    }

    ::-webkit-scrollbar-thumb {
        background: ${themes[theme].scrollbar.thumb};
    }

    ::-webkit-scrollbar-thumb:hover {
        background: ${themes[theme].scrollbar.hover};
    }

    /* Blookedex page styles */
    .blookedex-page {
        display: flex;
        flex-direction: column;
        gap: 20px;
        align-items: center;
        justify-content: center;
        padding: 20px;
    }

    .blookedex-theme-grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
        gap: 15px;
        width: 100%;
        max-width: 800px;
    }

    .blookedex-theme-card {
        border-radius: 10px;
        padding: 10px;
        cursor: pointer;
        transition: transform 0.2s;
        color: white;
        text-align: center;
        font-weight: bold;
        text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
        height: 120px;
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
    }

    .blookedex-theme-card:hover {
        transform: scale(1.03);
    }

    .blookedex-section {
        position: relative;
        background-color: rgba(239, 239, 239, 0.133);
        backdrop-filter: blur(10px);
        border: 1px solid rgb(108, 117, 125);
        border-radius: 20px;
        width: 50rem;
        padding: 20px;
    }

    .blookedex-title {
        font-family: Titan One;
        font-size: 44px;
        font-weight: 700;
        margin: 15px 5% 10px;
        color: #efefef;
        text-shadow: 0 0 10px rgba(0,0,0,0.2);
    }

    .blookedex-default-btn {
        background: ${themes[theme].secondary};
        color: white;
        border: none;
        border-radius: 5px;
        padding: 10px 20px;
        font-size: 1.2em;
        cursor: pointer;
        transition: filter 0.2s;
        margin-top: 10px;
        font-family: 'Nunito', sans-serif;
        font-weight: 700;
    }

    .blookedex-default-btn:hover {
        filter: brightness(1.1);
    }
    `;
    document.head.appendChild(style);

    // Apply theme to specific elements
    const applyTheme = () => {
        // Apply to background
        const bgElement = document.querySelector('.styles__background___2J-JA-camelCase');
        if (bgElement) {
            bgElement.style.background = background;
        }

        // Apply to sidebar (solid color, not gradient)
        const sidebar = document.querySelector('.styles__sidebar___1XqWi-camelCase');
        if (sidebar) {
            sidebar.style.background = Array.isArray(themes[theme].primary) ? themes[theme].primary[0] : themes[theme].primary;
            sidebar.style.backgroundImage = 'none';
        }

        // Apply to cashier if theme has custom shopkeeper
        if (themes[theme].customShopkeeper) {
            const cashier = document.getElementById('phill');
            if (cashier) {
                cashier.src = themes[theme].customShopkeeper[0];
                cashier.style.transform = `rotate(10deg) scale(${themes[theme].customShopkeeper[1]})`;
            }
        }

        // Apply to store if theme has custom store
        if (themes[theme].customStore) {
            const store = document.getElementById('market');
            if (store) {
                store.src = themes[theme].customStore;
                store.style.filter = "drop-shadow(0 0 5px #0004)";
            }
        }

        // Add Blookedex tab to sidebar
        insertTab();
    };

    const insertTab = () => {
        const sidebar = document.querySelector('.styles__sidebar___1XqWi-camelCase');
        if (!sidebar || sidebar.dataset.injected === "true") return;

        // Clone an existing tab
        const existingTab = document.querySelector('.styles__pageButton___1wFuu-camelCase');
        if (!existingTab) return;

        const newTab = existingTab.cloneNode(true);
        newTab.href = "/stats?blookedex=true";
        newTab.querySelector('.styles__pageIcon___3OSy9-camelCase').className = "styles__pageIcon___3OSy9-camelCase fas fa-adjust";
        newTab.querySelector('.styles__pageText___1eo7q-camelCase').textContent = "Blookedex";

        // Insert before the bottom row
        const bottomRow = document.querySelector('.styles__bottomRow___3OozA-camelCase');
        if (bottomRow) {
            sidebar.insertBefore(newTab, bottomRow);
            sidebar.dataset.injected = "true";
        }
    };

    const createBlookedexPage = () => {
        // Hide existing content
        const profileBody = document.querySelector('.arts__profileBody___eNPbH-camelCase');
        if (profileBody) profileBody.style.display = "none";

        // Create new page container
        const page = document.createElement('div');
        page.className = "blookedex-page";

        // Add background
        page.innerHTML = `
    <div class="styles__background___2J-JA-camelCase">
        <div class="styles__blooksBackground___3oQ7Y-camelCase"
             style="background-image: url(&quot;/media/misc/background.png&quot;);
                    animation: animatedBackground 9s linear infinite;
                    -moz-animation: animatedBackground 9s linear infinite;
                    -webkit-animation: animatedBackground 9s linear infinite;
                    -ms-animation: animatedBackground 9s linear infinite;
                    -o-animation: animatedBackground 9s linear infinite;
        ">
        </div>
    </div>
`;


        // Add version section
        const versionSection = document.createElement('div');
        versionSection.className = "blookedex-section";
        versionSection.innerHTML = `
            <div class="blookedex-title">Version Info</div>
            <div style="font-size: 2em;">Current Version: ${version}</div>
            <a href="https://greasyfork.org/en/scripts/536421-blookedex-integration" style="font-size: 2em;">Check Updates</a>
        `;
        page.appendChild(versionSection);

        // Add theme selection section
        const themeSection = document.createElement('div');
        themeSection.className = "blookedex-section";
        themeSection.innerHTML = `<div class="blookedex-title">Select a Theme</div>`;

        const themesContainer = document.createElement('div');
        themesContainer.style = "display: flex; flex-wrap: wrap; gap: 10px; width: 100%; justify-content: center;";

        themes.forEach((t, i) => {
            let bg = t.background;
            if (Array.isArray(bg)) {
                bg = `linear-gradient(${bg[0]}, ${bg[1]})`;
            }

            const themeCard = document.createElement('div');
            themeCard.style = `
                width: 120px;
                height: 100px;
                border: 2px solid ${theme === i ? themes[theme].secondary : 'rgba(228, 232, 236, 0.2)'};
                border-radius: 10px;
                background: rgba(239, 239, 239, 0.133);
                --primary: ${Array.isArray(t.primary) ? t.primary[0] : t.primary};
                --secondary: ${t.secondary};
                --bgGradient: ${bg};
            `;
            themeCard.onclick = () => {
                setCookie("blxdextheme", String(i));
                location.reload();
            };

            // Add preview bar
            themeCard.innerHTML = `
                <div style="width: 100%; height: 80%; background: var(--bgGradient); border-radius: 10px; cursor: pointer; overflow: hidden; position: relative;">
                    <div style="position: absolute; left: 0px; top: 0px; height: 100%; background: var(--primary); width: 20px; box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 10px, rgba(0, 0, 0, 0.05) -3px 0px 0px inset; display: flex; flex-direction: column; gap: 5px; padding: 5px; align-items: center;">
                        <div style="height:3px;width:15px;background:#efefefee;border-radius:10px;"></div>
                        <div style="height:8px;width:18px;background:${t.secondary};border-radius:2px;"></div>
                        <div style="height:2px;width:10px;background:#efefefee;border-radius:10px;"></div>
                        <div style="height:2px;width:13px;background:#efefefee;border-radius:10px;"></div>
                        <div style="height:2px;width:15px;background:#efefefee;border-radius:10px;"></div>
                        <div style="height:2px;width:10px;background:#efefefee;border-radius:10px;"></div>
                        <div style="height:2px;width:8px;background:#efefefee;border-radius:10px;"></div>
                        <div style="height:2px;width:13px;background:#efefefee;border-radius:10px;"></div>
                    </div>
                </div>
                <div style="margin-left: 7px;">${t.name}</div>
            `;

            themesContainer.appendChild(themeCard);
        });

        themeSection.appendChild(themesContainer);
        page.appendChild(themeSection);

        // Add default theme button section
        const defaultSection = document.createElement('div');
        defaultSection.className = "blookedex-section";
        defaultSection.innerHTML = `
            <div class="blookedex-title">Set to default</div>
            <button class="blookedex-default-btn" id="blookedex-default-btn">Reset to Default Theme</button>
        `;
        page.appendChild(defaultSection);

        // Add to body
        document.body.appendChild(page);

        // Add event listener for reset button
        document.getElementById('blookedex-default-btn').addEventListener('click', () => {
            deleteCookie("blxdextheme");
            location.reload();
        });
    };

    // Initialize
    applyTheme();

    // Check if we're on the blookedex page
    if (window.location.href.includes("stats?blookedex=true")) {
        createBlookedexPage();
    }

    // Watch for dynamic changes
    const observer = new MutationObserver(() => {
        applyTheme();

        // Re-check for blookedex page if needed
        if (window.location.href.includes("stats?blookedex=true")) {
            if (!document.querySelector('.blookedex-page')) {
                createBlookedexPage();
            }
        }
    });

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