您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
B站原神激励活动自动领奖脚本,支持自动解锁按钮、可调节点击间隔、智能停止检测,提供一键控制和优雅的消息提示系统
当前为
// ==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(); } })();