Page Roulette

Bored? Click the dice and discover a random interesting website

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Page Roulette
// @namespace    http://tampermonkey.net/
// @version      11.5
// @description  Bored? Click the dice and discover a random interesting website
// @author       Mustafa Hakan
// @icon https://img.icons8.com/fluency/48/maintenance.png
// @match        *://*/*
// @grant        GM_openInTab
// @grant        GM_addStyle
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    const SITES = [
        { n: 'This Is Sand', u: 'https://thisissand.com', d: 'Paint with sand' },
        { n: 'Silk', u: 'http://weavesilk.com', d: 'Interactive light drawing' },
        { n: 'Pointer Pointer', u: 'https://pointerpointer.com', d: 'Cursor tracking fun' },
        { n: 'Hacker Typer', u: 'https://hackertyper.com', d: 'Pretend to be a hacker' },
        { n: 'Scale of Universe', u: 'https://htwins.net/scale2/', d: 'Zoom from quarks to galaxies' },
        { n: 'Quick Draw', u: 'https://quickdraw.withgoogle.com', d: 'AI guesses your drawing' },
        { n: 'A Soft Murmur', u: 'https://asoftmurmur.com', d: 'Ambient sounds' },
        { n: 'Radio Garden', u: 'http://radio.garden', d: 'Explore world radios' },
        { n: 'Window Swap', u: 'https://window-swap.com', d: 'Peek through windows worldwide' },
        { n: 'Patatap', u: 'https://patatap.com', d: 'Visual sound toy' },
        { n: '2048', u: 'https://play2048.co', d: 'Merge number tiles' },
        { n: 'Little Alchemy', u: 'https://littlealchemy.com', d: 'Combine elements' },
        { n: 'Neal Fun', u: 'https://neal.fun', d: 'Oddly satisfying experiments' },
        { n: 'Rainy Mood', u: 'https://rainymood.com', d: 'Rain sounds' },
        { n: 'The Useless Web', u: 'https://theuselessweb.com', d: 'Random weird sites' },
        { n: 'Bored Panda', u: 'https://www.boredpanda.com', d: 'Funny & creative content' },
        { n: 'Zoom Quilt', u: 'https://zoomquilt.org', d: 'Infinite zoom illusion' },
        { n: 'Staggering Beauty', u: 'https://staggeringbeauty.com', d: 'Wiggle it!' },
        { n: 'Cat Bounce', u: 'https://cat-bounce.com', d: 'Bouncing cats' },
        { n: 'Remove BG', u: 'https://www.remove.bg', d: 'Remove image backgrounds' },
        { n: 'Photopea', u: 'https://www.photopea.com', d: 'Online Photoshop' },
        { n: 'Every Noise', u: 'https://everynoise.com', d: 'All music genres' },
        { n: 'Flight Radar', u: 'https://www.flightradar24.com', d: 'Live air traffic' },
        { n: 'NASA APOD', u: 'https://apod.nasa.gov/apod/', d: 'Daily astronomy picture' },
        { n: 'GeoGuessr', u: 'https://www.geoguessr.com/free', d: 'Guess the location' },
        { n: 'Coolors', u: 'https://coolors.co', d: 'Color palette generator' },
        { n: 'Poolside FM', u: 'https://poolside.fm', d: 'Retro summer radio' },
        { n: 'This Person Does Not Exist', u: 'https://thispersondoesnotexist.com', d: 'AI‑generated faces' },
        { n: 'Spend Elon Money', u: 'https://neal.fun/spend/', d: 'Spend billions' },
        { n: 'Internet Archive', u: 'https://archive.org', d: 'Digital library' }
    ];

    let spinning = false;

    GM_addStyle(`
        #r-trigger {
            position: fixed;
            bottom: 24px;
            right: 24px;
            width: 48px;
            height: 48px;
            background-color: #2a2a2a;
            background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect x='5' y='5' width='90' height='90' rx='20' fill='%23ffffff'/%3E%3Ccircle cx='30' cy='30' r='10' fill='%23000'/%3E%3Ccircle cx='70' cy='70' r='10' fill='%23000'/%3E%3C/svg%3E");
            background-size: 36px;
            background-repeat: no-repeat;
            background-position: center;
            border: 1px solid #555;
            border-radius: 12px;
            cursor: pointer;
            z-index: 2147483644;
            box-shadow: 0 4px 12px rgba(0,0,0,0.5);
            transition: transform 0.2s ease, border-color 0.2s, box-shadow 0.2s;
        }
        #r-trigger:hover {
            transform: scale(1.08);
            border-color: #888;
            box-shadow: 0 6px 18px rgba(0,0,0,0.6);
        }
        #r-trigger:active {
            transform: scale(0.96);
            transition: transform 0.1s;
        }
        #r-panel {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: #1e1e1e;
            border: 1px solid #444;
            border-radius: 16px;
            padding: 24px;
            z-index: 2147483646;
            font-family: system-ui, -apple-system, sans-serif;
            color: #ddd;
            min-width: 320px;
            text-align: center;
            box-shadow: 0 20px 50px rgba(0,0,0,0.8);
            animation: rFadeIn 0.25s ease;
            user-select: none;
        }
        @keyframes rFadeIn {
            from { opacity: 0; transform: translate(-50%, -48%); }
            to { opacity: 1; transform: translate(-50%, -50%); }
        }
        @keyframes rPop {
            0%,100% { transform: scale(1); }
            50% { transform: scale(1.04); }
        }
        #r-panel .panel-title {
            font-weight: 600;
            font-size: 17px;
            margin-bottom: 12px;
            color: #ccc;
        }
        #r-display {
            min-height: 60px;
            padding: 12px;
            background: rgba(255,255,255,0.03);
            border-radius: 12px;
            margin: 10px 0;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            transition: background 0.2s;
        }
        #r-display .placeholder {
            color: #888;
        }
        #r-spin, #r-go, #r-close {
            width: 100%;
            padding: 12px;
            border-radius: 10px;
            border: 1px solid #555;
            background: #333;
            color: #eee;
            font-size: 15px;
            cursor: pointer;
            margin: 6px 0;
            transition: background 0.2s, border-color 0.2s, color 0.2s;
        }
        #r-spin:hover, #r-go:hover, #r-close:hover {
            background: #444;
            border-color: #777;
        }
        #r-spin:active, #r-go:active, #r-close:active {
            background: #2a2a2a;
        }
        #r-go {
            background: #444;
            display: none;
        }
        #r-close {
            background: transparent;
            border-color: #444;
            color: #888;
        }
        #r-close:hover {
            color: #ccc;
            background: rgba(255,255,255,0.05);
        }
    `);

    function spin() {
        if (spinning) return;
        spinning = true;
        const display = document.getElementById('r-display');
        const goBtn = document.getElementById('r-go');

        let count = 0;
        const interval = setInterval(() => {
            const s = SITES[Math.floor(Math.random() * SITES.length)];
            display.innerHTML = `<div style="font-size:28px;">${s.n}</div><div style="color:#aaa;font-size:12px;">${s.d}</div>`;
            count++;
            if (count >= 25) {
                clearInterval(interval);
                const final = SITES[Math.floor(Math.random() * SITES.length)];
                display.innerHTML = `<div style="font-size:32px;">${final.n}</div><div style="color:#aaa;font-size:12px;">${final.d}</div>`;
                display.style.animation = 'rPop 0.4s';
                setTimeout(() => display.style.animation = '', 400);
                goBtn.style.display = 'block';
                goBtn.onclick = () => GM_openInTab(final.u, { active: true });
                spinning = false;
            }
        }, 70);
    }

    function createPanel() {
        const existing = document.getElementById('r-panel');
        if (existing) existing.remove();

        const panel = document.createElement('div');
        panel.id = 'r-panel';
        panel.innerHTML = `
            <div class="panel-title">🎲 Page Roulette</div>
            <div id="r-display"><div class="placeholder">Ready to spin</div></div>
            <button id="r-spin">Spin</button>
            <button id="r-go">Go!</button>
            <button id="r-close">Close</button>
        `;
        document.body.appendChild(panel);

        document.getElementById('r-spin').onclick = spin;
        document.getElementById('r-close').onclick = () => panel.remove();
    }

    function createTrigger() {
        if (document.getElementById('r-trigger')) return;
        const trigger = document.createElement('div');
        trigger.id = 'r-trigger';
        trigger.title = 'Page Roulette (Ctrl+Shift+R)';
        trigger.addEventListener('click', () => {
            if (document.getElementById('r-panel')) {
                document.getElementById('r-panel').remove();
            } else {
                createPanel();
            }
        });
        document.body.appendChild(trigger);
    }

    document.addEventListener('keydown', e => {
        if (e.ctrlKey && e.shiftKey && e.key === 'R') {
            e.preventDefault();
            if (document.getElementById('r-panel')) {
                document.getElementById('r-panel').remove();
            } else {
                createPanel();
            }
        }
    });

    setTimeout(createTrigger, 800);
})();