Greasy Fork

Greasy Fork is available in English.

原神激励领奖

B站原神激励活动自动领奖脚本,支持自动解锁按钮、可调节点击间隔、智能停止检测,提供一键控制和优雅的消息提示系统

当前为 2025-06-07 提交的版本,查看 最新版本

// ==UserScript==
// @name         原神激励领奖
// @namespace    http://tampermonkey.net/
// @version      2025-06-19
// @description  B站原神激励活动自动领奖脚本,支持自动解锁按钮、可调节点击间隔、智能停止检测,提供一键控制和优雅的消息提示系统
// @author       You
// @match        https://www.bilibili.com/blackboard/new-award-exchange.html*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    let clickInterval = null;
    let isAutoClicking = false;
    let clickIntervalMs = 500; // Default click interval
    let timeUpdateInterval = null;
    let errorCheckInterval = null;
    let autoTriggerInterval = null;
    let autoVerifyEnabled = true; // Default enabled for auto verification click
    let autoRefreshEnabled = false; // Default disabled for auto refresh
    let hasAutoVerifyClicked = false; // Track if auto verify click has been done

    // List of stop texts
    const stopTexts = ["查看奖励", "每日库存已达上限", "暂无领取资格"];

    // Message container for stacking notifications
    let messageContainer = null;

    // Load saved click interval from localStorage
    function loadClickInterval() {
        const saved = localStorage.getItem('auto-click-interval');
        if (saved && [100, 200, 500, 800, 1000].includes(parseInt(saved))) {
            clickIntervalMs = parseInt(saved);
        } else {
            // If no valid saved value, save the current default to localStorage
            saveClickInterval(clickIntervalMs);
        }
    }

    // Save click interval to localStorage
    function saveClickInterval(interval) {
        localStorage.setItem('auto-click-interval', interval.toString());
    }

    // Load saved settings from localStorage
    function loadSettings() {
        const autoVerify = localStorage.getItem('auto-verify-enabled');
        if (autoVerify !== null) {
            autoVerifyEnabled = autoVerify === 'true';
        }
        
        const autoRefresh = localStorage.getItem('auto-refresh-enabled');
        if (autoRefresh !== null) {
            autoRefreshEnabled = autoRefresh === 'true';
        }
    }

    // Save settings to localStorage
    function saveSettings() {
        localStorage.setItem('auto-verify-enabled', autoVerifyEnabled.toString());
        localStorage.setItem('auto-refresh-enabled', autoRefreshEnabled.toString());
    }

    // Check for page activity state and auto-click for verification
    function checkAutoVerifyClick() {
        if (!autoVerifyEnabled || hasAutoVerifyClicked) return;
        
        const button = document.querySelector("#app > div > div.home-wrap.select-disable > section.tool-wrap > div.button.exchange-button");
        if (button && !button.classList.contains('disable')) {
            // Skip auto verification if button already shows "查看奖励"
            if (button.textContent.trim() === "查看奖励") {
                console.log('Skipping auto verification: button shows "查看奖励"');
                hasAutoVerifyClicked = true; // Mark as done to prevent further checks
                return;
            }
            
            // Page seems to be in active state, do one verification click
            console.log('Auto verification click triggered');
            showMessage('自动点一次已执行', 'info');
            button.click();
            hasAutoVerifyClicked = true;
        }
    }

    // Check for auto refresh at 00:59:59
    function checkAutoRefresh() {
        if (!autoRefreshEnabled) return;
        
        const now = new Date();
        const hours = now.getHours();
        const minutes = now.getMinutes();
        const seconds = now.getSeconds();
        
        // Check if time is 00:59:59 (refresh before 1 AM)
        if (hours === 0 && minutes === 59 && seconds === 59) {
            console.log('Auto refresh triggered at 00:59:59 for 1 AM auto-clicking');
            showMessage('即将到达1点,正在刷新页面准备领奖...', 'info');
            
            // Stop all intervals before refresh
            if (errorCheckInterval) clearInterval(errorCheckInterval);
            if (timeUpdateInterval) clearInterval(timeUpdateInterval);
            if (clickInterval) clearInterval(clickInterval);
            if (autoTriggerInterval) clearInterval(autoTriggerInterval);
            
            setTimeout(() => {
                window.location.reload();
            }, 500);
        }
    }

    // Function to create real-time clock display
    function createRealTimeClock() {
        // Create hidden iframe to load bjtime.net
        const iframe = document.createElement('iframe');
        iframe.src = 'https://www.bjtime.net/';
        iframe.style.cssText = `
            position: absolute;
            top: -9999px;
            left: -9999px;
            width: 1px;
            height: 1px;
            border: none;
            opacity: 0;
            pointer-events: none;
        `;
        iframe.id = 'time-iframe';

        document.body.appendChild(iframe);

        // Handle iframe load
        iframe.onload = function() {
            try {
                startTimeUpdater(iframe);
            } catch (error) {
                console.log('Failed to access iframe content, using local time');
                startLocalTimeUpdater();
            }
        };

        // Fallback to local time if iframe fails to load
        iframe.onerror = function() {
            console.log('Failed to load bjtime.net, using local time');
            startLocalTimeUpdater();
        };

        // Timeout fallback
        setTimeout(() => {
            const timeDisplay = document.getElementById('time-display');
            if (timeDisplay && timeDisplay.textContent === '00:00:00.000') {
                console.log('Timeout loading bjtime.net, using local time');
                startLocalTimeUpdater();
            }
        }, 5000);
    }

    // Function to start time updater using iframe
    function startTimeUpdater(iframe) {
        timeUpdateInterval = setInterval(() => {
            try {
                const timeDisplay = document.getElementById('time-display');
                const dateDisplay = document.getElementById('date-display');
                
                if (!timeDisplay || !dateDisplay) return;
                
                const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                const timeElement = iframeDoc.querySelector('#cTime');
                
                if (timeElement && timeElement.textContent) {
                    const fullTime = timeElement.textContent;
                    updateTimeDisplay(fullTime, timeDisplay, dateDisplay);
                } else {
                    // Fallback to local time if can't find element
                    updateLocalTime(timeDisplay, dateDisplay);
                }
            } catch (error) {
                // Cross-origin error, fallback to local time
                const timeDisplay = document.getElementById('time-display');
                const dateDisplay = document.getElementById('date-display');
                if (timeDisplay && dateDisplay) {
                    updateLocalTime(timeDisplay, dateDisplay);
                }
            }
        }, 100); // Update every 100ms
    }

    // Function to start local time updater
    function startLocalTimeUpdater() {
        timeUpdateInterval = setInterval(() => {
            const timeDisplay = document.getElementById('time-display');
            const dateDisplay = document.getElementById('date-display');
            if (timeDisplay && dateDisplay) {
                updateLocalTime(timeDisplay, dateDisplay);
            }
        }, 100);
    }

    // Function to update time display with parsed time
    function updateTimeDisplay(fullTime, timeDisplay, dateDisplay) {
        // Parse time string like "2025-01-07 14:30:25.123"
        const parts = fullTime.split(' ');
        if (parts.length >= 2) {
            dateDisplay.textContent = parts[0]; // Date part
            timeDisplay.textContent = parts[1]; // Time part
        } else {
            // Fallback to local time if parsing fails
            updateLocalTime(timeDisplay, dateDisplay);
        }
    }

    // Function to update with local time
    function updateLocalTime(timeDisplay, dateDisplay) {
        const now = new Date();
        const dateString = now.getFullYear() + '-' + 
                          String(now.getMonth() + 1).padStart(2, '0') + '-' + 
                          String(now.getDate()).padStart(2, '0');
        const timeString = String(now.getHours()).padStart(2, '0') + ':' + 
                          String(now.getMinutes()).padStart(2, '0') + ':' + 
                          String(now.getSeconds()).padStart(2, '0') + '.' + 
                          String(now.getMilliseconds()).padStart(3, '0');
        
        dateDisplay.textContent = dateString;
        timeDisplay.textContent = timeString;
    }

    // Function to create message container
    function createMessageContainer() {
        if (!messageContainer) {
            messageContainer = document.createElement('div');
            messageContainer.id = 'message-container';
            messageContainer.style.cssText = `
                position: fixed;
                top: 20px;
                left: 220px;
                z-index: 10000;
                display: flex;
                flex-direction: column;
                gap: 10px;
                pointer-events: none;
            `;
            document.body.appendChild(messageContainer);
        }
        
        // Update message container position based on control panel position
        const controlPanel = document.getElementById('control-panel');
        if (controlPanel) {
            const rect = controlPanel.getBoundingClientRect();
            messageContainer.style.top = rect.top + 'px';
            messageContainer.style.left = (rect.left - 220) + 'px';
        }
        
        return messageContainer;
    }

    // Function to show non-blocking message notification
    function showMessage(message, type = 'info') {
        const container = createMessageContainer();
        
        const notification = document.createElement('div');
        notification.textContent = message;
        notification.style.cssText = `
            padding: 12px 20px;
            background-color: ${type === 'error' ? '#FF6B6B' : type === 'success' ? '#51CF66' : '#339AF0'};
            color: white;
            border-radius: 8px;
            font-size: 14px;
            font-weight: bold;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
            max-width: 300px;
            word-wrap: break-word;
            transform: translateX(-100%);
            opacity: 0;
            transition: all 0.3s ease-out;
            pointer-events: auto;
        `;
        
        container.appendChild(notification);
        
        // Trigger slide-in animation
        setTimeout(() => {
            notification.style.transform = 'translateX(0)';
            notification.style.opacity = '1';
        }, 10);
        
        // Auto remove after 3 seconds
        setTimeout(() => {
            notification.style.transform = 'translateX(-100%)';
            notification.style.opacity = '0';
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.remove();
                }
            }, 300);
        }, 3000);
    }

    // Function to remove disable class from button
    function removeDisableClass() {
        const button = document.querySelector("#app > div > div.home-wrap.select-disable > section.tool-wrap > div.button.exchange-button");
        if (button) {
            button.classList.remove("disable");
            console.log("Disable class removed from button");
        }
    }

    // Function to check if verification panel is present
    function isVerificationPanelPresent() {
        const verificationPanel = document.querySelector("body > div.geetest_panel.geetest_wind > div.geetest_panel_box.geetest_no_logo.geetest_panelshowclick > div.geetest_panel_next");
        return verificationPanel !== null;
    }

    // Function to start/stop auto clicking
    function toggleAutoClick() {
        const button = document.querySelector("#app > div > div.home-wrap.select-disable > section.tool-wrap > div.button.exchange-button");
        
        if (isAutoClicking) {
            // Stop clicking
            if (clickInterval) {
                clearInterval(clickInterval);
                clickInterval = null;
            }
            isAutoClicking = false;
            updateControlButton();
            showMessage("已停止自动领奖", "info");
            return;
        }

        if (!button) {
            showMessage("找不到领奖按钮!", "error");
            return;
        }

        // Start clicking
        isAutoClicking = true;
        updateControlButton();
        showMessage(`开始自动领奖 (${clickIntervalMs}ms间隔)`, "success");

        clickInterval = setInterval(() => {
            if (button) {
                // Check if verification panel is present
                if (isVerificationPanelPresent()) {
                    console.log('Verification panel detected, skipping click');
                    return; // Skip this click cycle
                }

                // Check if button text is in stopTexts
                if (stopTexts.includes(button.textContent.trim())) {
                    clearInterval(clickInterval);
                    clickInterval = null;
                    isAutoClicking = false;
                    updateControlButton();
                    showMessage(`已停止领奖!原因:${button.textContent.trim()}`, "info");
                    return;
                }
                button.click();
            } else {
                clearInterval(clickInterval);
                clickInterval = null;
                isAutoClicking = false;
                updateControlButton();
            }
        }, clickIntervalMs); // Use selected interval

        // Stop clicking after 30 seconds for safety
        setTimeout(() => {
            if (clickInterval) {
                clearInterval(clickInterval);
                clickInterval = null;
                isAutoClicking = false;
                updateControlButton();
                showMessage("自动领奖已超时停止", "info");
            }
        }, 30000);
    }

    // Function to create and add control button
    function createControlButton() {
        const controlButton = document.createElement("button");
        controlButton.id = "auto-click-control";
        controlButton.textContent = "开始自动领奖";
        controlButton.style.cssText = `
            width: 100%;
            padding: 10px 15px;
            background-color: #00A1D6;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
            margin: 0;
            outline: none;
            box-sizing: border-box;
            display: block;
        `;
        
        controlButton.addEventListener("click", toggleAutoClick);
        
        // Add hover effect
        controlButton.addEventListener("mouseenter", function() {
            this.style.backgroundColor = "#0088CC";
        });
        controlButton.addEventListener("mouseleave", function() {
            this.style.backgroundColor = isAutoClicking ? "#FF6B6B" : "#00A1D6";
        });

        return controlButton;
    }

    // Function to update control button text and style
    function updateControlButton() {
        const controlButton = document.getElementById("auto-click-control");
        if (controlButton) {
            if (isAutoClicking) {
                controlButton.textContent = "停止自动领奖";
                controlButton.style.backgroundColor = "#FF6B6B";
            } else {
                controlButton.textContent = "开始自动领奖";
                controlButton.style.backgroundColor = "#00A1D6";
            }
        }
    }

    // Function to create interval selector
    function createIntervalSelector() {
        const selectorContainer = document.createElement("div");
        selectorContainer.style.cssText = `
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 8px;
        `;

        const label = document.createElement("label");
        label.textContent = "间隔:";
        label.style.cssText = `
            color: #333;
            font-size: 12px;
            font-weight: bold;
            text-shadow: 1px 1px 2px rgba(255,255,255,0.8);
            min-width: 35px;
        `;

        const selector = document.createElement("select");
        selector.id = "interval-selector";
        selector.style.cssText = `
            padding: 4px 8px;
            border: 1px solid #ccc;
            border-radius: 4px;
            background-color: white;
            font-size: 12px;
            cursor: pointer;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            flex: 1;
        `;

        // Add options
        const options = [
            { value: 100, text: "100ms (极快)" },
            { value: 200, text: "200ms (快)" },
            { value: 500, text: "500ms (中)" },
            { value: 800, text: "800ms (慢)" },
            { value: 1000, text: "1000ms (很慢)" }
        ];

        options.forEach(option => {
            const optionElement = document.createElement("option");
            optionElement.value = option.value;
            optionElement.textContent = option.text;
            if (option.value === clickIntervalMs) {
                optionElement.selected = true;
            }
            selector.appendChild(optionElement);
        });

        // Handle selection change
        selector.addEventListener("change", function() {
            clickIntervalMs = parseInt(this.value);
            saveClickInterval(clickIntervalMs);
            showMessage(`点击间隔已设置为 ${clickIntervalMs}ms`, "info");
            
            // If currently auto clicking, restart with new interval
            if (isAutoClicking) {
                toggleAutoClick(); // Stop
                setTimeout(() => {
                    toggleAutoClick(); // Start with new interval
                }, 100);
            }
        });

        selectorContainer.appendChild(label);
        selectorContainer.appendChild(selector);
        return selectorContainer;
    }

    // Function to create tooltip
    function createTooltip(text) {
        const tooltip = document.createElement('div');
        tooltip.style.cssText = `
            position: absolute;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 8px 12px;
            border-radius: 4px;
            font-size: 11px;
            white-space: nowrap;
            z-index: 10001;
            pointer-events: none;
            opacity: 0;
            transition: opacity 0.3s ease;
            bottom: 100%;
            right: 0;
            margin-bottom: 5px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.3);
        `;
        tooltip.textContent = text;
        return tooltip;
    }

    // Function to create switch button control
    function createSwitchControl(id, labelText, isChecked, onChange, tooltipText) {
        const container = document.createElement("div");
        container.style.cssText = `
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 8px;
            user-select: none;
            position: relative;
        `;

        const label = document.createElement("span");
        label.textContent = labelText;
        label.style.cssText = `
            color: #333;
            font-size: 12px;
            font-weight: bold;
            text-shadow: 1px 1px 2px rgba(255,255,255,0.8);
        `;

        // Create switch button
        const switchButton = document.createElement("div");
        switchButton.id = id;
        switchButton.style.cssText = `
            position: relative;
            width: 44px;
            height: 24px;
            background-color: ${isChecked ? '#4CAF50' : '#ccc'};
            border-radius: 24px;
            cursor: pointer;
            transition: background-color 0.3s ease;
            box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
        `;

        // Create switch thumb
        const switchThumb = document.createElement("div");
        switchThumb.style.cssText = `
            position: absolute;
            top: 2px;
            left: ${isChecked ? '22px' : '2px'};
            width: 20px;
            height: 20px;
            background-color: white;
            border-radius: 50%;
            transition: left 0.3s ease;
            box-shadow: 0 2px 4px rgba(0,0,0,0.2);
        `;

        switchButton.appendChild(switchThumb);

        // Create tooltip if provided
        if (tooltipText) {
            const tooltip = createTooltip(tooltipText);
            container.appendChild(tooltip);

            // Add tooltip events
            switchButton.addEventListener("mouseenter", function() {
                this.style.transform = 'scale(1.05)';
                tooltip.style.opacity = '1';
            });
            switchButton.addEventListener("mouseleave", function() {
                this.style.transform = 'scale(1)';
                tooltip.style.opacity = '0';
            });
        } else {
            // Add hover effect without tooltip
            switchButton.addEventListener("mouseenter", function() {
                this.style.transform = 'scale(1.05)';
            });
            switchButton.addEventListener("mouseleave", function() {
                this.style.transform = 'scale(1)';
            });
        }

        // Add click handler
        let currentState = isChecked;
        switchButton.addEventListener("click", function() {
            currentState = !currentState;
            
            // Update visual state
            switchButton.style.backgroundColor = currentState ? '#4CAF50' : '#ccc';
            switchThumb.style.left = currentState ? '22px' : '2px';
            
            // Call onChange with new state
            onChange.call({ checked: currentState });
        });

        container.appendChild(label);
        container.appendChild(switchButton);
        return container;
    }

    // Function to create main control panel
    function createControlPanel() {
        const panel = document.createElement("div");
        panel.id = "control-panel";
        panel.style.cssText = `
            position: fixed;
            top: 2%;
            right: 2%;
            z-index: 9999;
            background: rgba(255, 255, 255, 0.95);
            padding: 0;
            border-radius: 8px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
            backdrop-filter: blur(10px);
            border: 1px solid rgba(255, 255, 255, 0.3);
            min-width: 180px;
            display: flex;
            flex-direction: column;
        `;

        // Create title bar with drag button
        const titleBar = document.createElement("div");
        titleBar.id = "title-bar";
        titleBar.style.cssText = `
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 6px 12px;
            background: rgba(0, 0, 0, 0.05);
            border-bottom: 1px solid rgba(0,0,0,0.1);
            border-radius: 8px 8px 0 0;
            cursor: grab;
            user-select: none;
            margin: 0;
            box-sizing: border-box;
        `;

        // Add title text
        const titleText = document.createElement("span");
        titleText.textContent = "自动领奖";
        titleText.style.cssText = `
            font-size: 12px;
            font-weight: bold;
            color: #333;
            text-shadow: 1px 1px 2px rgba(255,255,255,0.8);
        `;

        // Add drag button
        const dragButton = document.createElement("div");
        dragButton.id = "drag-button";
        dragButton.innerHTML = "⋮⋮";
        dragButton.style.cssText = `
            width: 20px;
            height: 16px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: rgba(0, 0, 0, 0.1);
            border-radius: 3px;
            font-size: 10px;
            color: #666;
            font-weight: bold;
            letter-spacing: -2px;
            user-select: none;
            transition: all 0.2s ease;
            pointer-events: none;
        `;

        // Add hover effect for title bar
        titleBar.addEventListener("mouseenter", function() {
            this.style.background = "rgba(0, 0, 0, 0.08)";
            dragButton.style.background = "rgba(0, 0, 0, 0.2)";
            dragButton.style.color = "#333";
        });
        titleBar.addEventListener("mouseleave", function() {
            this.style.background = "rgba(0, 0, 0, 0.05)";
            dragButton.style.background = "rgba(0, 0, 0, 0.1)";
            dragButton.style.color = "#666";
        });

        titleBar.appendChild(titleText);
        titleBar.appendChild(dragButton);

        // Create content area (previously headerArea)
        const contentArea = document.createElement("div");
        contentArea.id = "control-panel-content";
        contentArea.style.cssText = `
            padding: 0 12px 12px 12px;
            margin: 0;
            box-sizing: border-box;
            display: flex;
            flex-direction: column;
        `;

        // Add control button
        const controlButton = createControlButton();
        // Remove all margins to eliminate any blank space
        controlButton.style.margin = '0';
        controlButton.style.marginBottom = '8px'; // Only bottom margin for spacing
        contentArea.appendChild(controlButton);

        // Add interval selector
        const intervalSelector = createIntervalSelector();
        contentArea.appendChild(intervalSelector);

        // Add auto verify switch
        const autoVerifyControl = createSwitchControl(
            "auto-verify-switch",
            "自动点一次",
            autoVerifyEnabled,
            function() {
                autoVerifyEnabled = this.checked;
                saveSettings();
                showMessage(`自动点一次已${autoVerifyEnabled ? '开启' : '关闭'}`, "info");
                if (!autoVerifyEnabled) {
                    hasAutoVerifyClicked = false; // Reset if disabled
                }
            },
            "页面活跃后自动点击一次领奖按钮,用于通过验证码检测"
        );
        contentArea.appendChild(autoVerifyControl);

        // Add auto refresh switch
        const autoRefreshControl = createSwitchControl(
            "auto-refresh-switch",
            "1点自动领奖",
            autoRefreshEnabled,
            function() {
                autoRefreshEnabled = this.checked;
                saveSettings();
                showMessage(`1点自动领奖已${autoRefreshEnabled ? '开启' : '关闭'}`, "info");
            },
            "每天00:59:59刷新页面,1点准备就绪后自动开始领奖"
        );
        contentArea.appendChild(autoRefreshControl);

        panel.appendChild(titleBar);
        panel.appendChild(contentArea);

        // Create time display section
        const timeSection = createTimeSection();
        panel.appendChild(timeSection);

        // Create verification notice section
        const noticeSection = createNoticeSection();
        panel.appendChild(noticeSection);

        // Add drag functionality
        addDragFunctionality(panel, titleBar);

        document.body.appendChild(panel);
    }

    // Function to create time display section
    function createTimeSection() {
        const timeContainer = document.createElement('div');
        timeContainer.id = 'time-section';
        timeContainer.style.cssText = `
            background: linear-gradient(135deg, rgba(74, 144, 226, 0.9), rgba(126, 208, 255, 0.9));
            color: #FFFFFF;
            padding: 8px 12px;
            text-align: center;
            border-top: 1px solid rgba(255, 255, 255, 0.2);
        `;

        // Create time display element
        const timeDisplay = document.createElement('div');
        timeDisplay.id = 'time-display';
        timeDisplay.style.cssText = `
            font-size: 14px;
            font-weight: 600;
            line-height: 1.2;
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
            margin-bottom: 1px;
        `;
        timeDisplay.textContent = '00:00:00.000';

        // Create date display element
        const dateDisplay = document.createElement('div');
        dateDisplay.id = 'date-display';
        dateDisplay.style.cssText = `
            font-size: 11px;
            font-weight: 400;
            opacity: 0.9;
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
        `;
        dateDisplay.textContent = '2025-01-19';

        timeContainer.appendChild(timeDisplay);
        timeContainer.appendChild(dateDisplay);

        return timeContainer;
    }

    // Function to create notice section
    function createNoticeSection() {
        const noticeContainer = document.createElement('div');
        noticeContainer.id = 'notice-section';
        noticeContainer.style.cssText = `
            background: linear-gradient(135deg, rgba(116, 185, 255, 0.9), rgba(162, 210, 255, 0.9));
            color: #1a365d;
            padding: 6px 12px;
            text-align: center;
            border-radius: 0 0 8px 8px;
        `;

        const noticeText = document.createElement('div');
        noticeText.style.cssText = `
            font-size: 10px;
            font-weight: 500;
            line-height: 1.3;
            text-shadow: 0 1px 2px rgba(255, 255, 255, 0.5);
        `;
        noticeText.innerHTML = '💡 请先手动领奖一次通过验证码检测';

        noticeContainer.appendChild(noticeText);

        return noticeContainer;
    }

    // Function to convert pixel position to percentage
    function convertToPercentage(panel) {
        const rect = panel.getBoundingClientRect();
        const viewportWidth = window.innerWidth;
        const viewportHeight = window.innerHeight;
        
        const leftPercent = (rect.left / viewportWidth) * 100;
        const topPercent = (rect.top / viewportHeight) * 100;
        
        return { left: leftPercent, top: topPercent };
    }

    // Function to ensure panel stays within viewport bounds
    function keepPanelInBounds(panel) {
        const rect = panel.getBoundingClientRect();
        const viewportWidth = window.innerWidth;
        const viewportHeight = window.innerHeight;
        
        let leftPercent = (rect.left / viewportWidth) * 100;
        let topPercent = (rect.top / viewportHeight) * 100;
        
        // Calculate panel size in percentage
        const widthPercent = (rect.width / viewportWidth) * 100;
        const heightPercent = (rect.height / viewportHeight) * 100;
        
        // Keep within bounds
        leftPercent = Math.max(0, Math.min(leftPercent, 100 - widthPercent));
        topPercent = Math.max(0, Math.min(topPercent, 100 - heightPercent));
        
        panel.style.left = leftPercent + '%';
        panel.style.top = topPercent + '%';
        panel.style.right = 'auto';
    }

    // Function to add drag functionality
    function addDragFunctionality(panel, titleBar) {
        let isDragging = false;
        let startX, startY, startLeft, startTop;

        titleBar.addEventListener('mousedown', function(e) {
            isDragging = true;
            startX = e.clientX;
            startY = e.clientY;
            
            const rect = panel.getBoundingClientRect();
            startLeft = rect.left;
            startTop = rect.top;
            
            // Change cursor to grabbing for title bar and panel
            titleBar.style.cursor = 'grabbing';
            panel.style.cursor = 'grabbing';
            document.body.style.cursor = 'grabbing';
            
            e.preventDefault();
            e.stopPropagation();
        });

        document.addEventListener('mousemove', function(e) {
            if (isDragging) {
                const deltaX = e.clientX - startX;
                const deltaY = e.clientY - startY;
                
                let newLeft = startLeft + deltaX;
                let newTop = startTop + deltaY;
                
                // Keep panel within viewport bounds
                const maxLeft = window.innerWidth - panel.offsetWidth;
                const maxTop = window.innerHeight - panel.offsetHeight;
                
                newLeft = Math.max(0, Math.min(newLeft, maxLeft));
                newTop = Math.max(0, Math.min(newTop, maxTop));
                
                // Convert to percentage
                const leftPercent = (newLeft / window.innerWidth) * 100;
                const topPercent = (newTop / window.innerHeight) * 100;
                
                panel.style.left = leftPercent + '%';
                panel.style.top = topPercent + '%';
                panel.style.right = 'auto';
            }
        });

        document.addEventListener('mouseup', function() {
            if (isDragging) {
                isDragging = false;
                // Restore normal cursors
                titleBar.style.cursor = 'grab';
                panel.style.cursor = 'default';
                document.body.style.cursor = 'default';
                
                // Save final position in percentage
                convertToPercentage(panel);
            }
        });

        // Add window resize listener to keep panel in bounds
        window.addEventListener('resize', function() {
            keepPanelInBounds(panel);
        });
    }

    // Function to check for auto-trigger condition
    function checkAutoTrigger() {
        // Don't auto-trigger if already clicking
        if (isAutoClicking) return;
        
        const button = document.querySelector("#app > div > div.home-wrap.select-disable > section.tool-wrap > div.button.exchange-button");
        if (button && button.textContent.trim() === "领取奖励") {
            console.log('Auto-trigger detected: button text is "领取奖励"');
            showMessage('检测到"领取奖励",自动开始领奖', 'success');
            
            // Small delay to ensure message is visible
            setTimeout(() => {
                toggleAutoClick();
            }, 500);
        }
    }

    // Function to start auto-trigger monitoring
    function startAutoTriggerMonitoring() {
        // Check every 2 seconds for auto-trigger condition
        autoTriggerInterval = setInterval(() => {
            checkAutoTrigger();
            checkAutoVerifyClick(); // Also check for auto verify click
            checkAutoRefresh(); // Also check for auto refresh
        }, 2000);
    }

    // Function to check for page load error dialog
    function checkForErrorDialog() {
        const errorDialog = document.querySelector('body > div.v-dialog > div.v-dialog__wrap > div > div.v-dialog__body');
        if (errorDialog) {
            console.log('Error dialog detected, refreshing page...');
            showMessage('检测到页面错误,正在刷新...', 'info');
            
            // Stop all intervals before refresh
            if (errorCheckInterval) {
                clearInterval(errorCheckInterval);
            }
            if (timeUpdateInterval) {
                clearInterval(timeUpdateInterval);
            }
            if (clickInterval) {
                clearInterval(clickInterval);
            }
            if (autoTriggerInterval) {
                clearInterval(autoTriggerInterval);
            }
            
            // Refresh page after a short delay
            setTimeout(() => {
                window.location.reload();
            }, 1000);
            
            return true;
        }
        return false;
    }

    // Function to start error monitoring
    function startErrorMonitoring() {
        // Check immediately
        if (checkForErrorDialog()) return;
        
        // Check every 1 second permanently
        errorCheckInterval = setInterval(() => {
            checkForErrorDialog();
        }, 1000);
    }

    // Initialize when page loads
    function init() {
        // Wait for page to fully load
        setTimeout(() => {
            loadClickInterval(); // Load saved click interval
            loadSettings();
            removeDisableClass();
            createControlPanel();
            createRealTimeClock(); // Initialize time display iframe
            startErrorMonitoring();
            startAutoTriggerMonitoring();
            console.log("Auto-click userscript initialized");
        }, 100);
    }

    // Run initialization when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();