// ==UserScript== // @name 逆战抢领助手 // @namespace https://nz.qq.com/ // @version 1.4.6 // @description 道具抢领 + 挚友力抽奖 // @author 逆战-牢鹊 // @match https://nz.qq.com/cp/a20251222qxtq/* // @grant GM_log // @grant GM_addStyle // @run-at document-end // @icon https://nz.qq.com/favicon.ico // @license MIT // @unwrap // ==/UserScript== (function() { 'use strict'; const TIME_PAGE_URL = 'https://time.is/zh/Beijing'; const TIME_IFRAME_HEIGHT = '190px'; const clickDelay = 100; const elementTimeout = 5000; const DEFAULT_RUN_TIMES = 100; const DEFAULT_LOOP_INTERVAL = 1000; let exchangeRunning = false; let lotteryRunning = false; let exchangeStopFlag = false; let lotteryStopFlag = false; let exchangeCount = 0; let lotteryCount = 0; const exchangeTargets = [ { type: 'selector', value: 'a.btnA[href*="part1_2_limitConvertTip(1)"]', name: '兑换按钮' }, { type: 'selector', value: 'a.pop_btn1.sp.text114_query[href*="part1_2_limitConvert(1)"]', name: '确认按钮' } ]; const lotteryTargets = [ { type: 'selector', value: 'a.btn_cj1.y.zylChouOne[href*="part4_zylChou();"]', name: '抽奖按钮' }, { type: 'selector', value: 'a.pop_btn1.sp[href*="closeDialog();"]', name: '确认按钮' } ]; function waitForElement(selector) { return new Promise((resolve) => { const element = document.querySelector(selector); if (element) return resolve(element); const observer = new MutationObserver((mutations) => { const element = document.querySelector(selector); if (element) { observer.disconnect(); resolve(element); } }); observer.observe(document.body, { childList: true, subtree: true }); setTimeout(() => { observer.disconnect(); resolve(null); }, elementTimeout); }); } function clickElement(element, targetName = '操作按钮') { if (!element) { console.warn(`[${targetName}] 目标元素未找到,跳过点击`); return false; } const rect = element.getBoundingClientRect(); const mouseEvents = [ new MouseEvent('mouseover', { bubbles: true, clientX: rect.centerX, clientY: rect.centerY }), new MouseEvent('mousedown', { bubbles: true, clientX: rect.centerX, clientY: rect.centerY }), new MouseEvent('mouseup', { bubbles: true, clientX: rect.centerX, clientY: rect.centerY }), new MouseEvent('click', { bubbles: true, clientX: rect.centerX, clientY: rect.centerY }) ]; mouseEvents.forEach(evt => element.dispatchEvent(evt)); console.log(`[${targetName}] 已点击:`, element.innerText.trim() || targetName); return true; } async function executeSingleRun(targets, stopFlag) { if (stopFlag) return false; for (let i = 0; i < targets.length; i++) { if (stopFlag) return false; const target = targets[i]; await new Promise(resolve => setTimeout(resolve, clickDelay)); try { const element = await waitForElement(target.value); const clickResult = clickElement(element, target.name); if (!clickResult) return false; } catch (error) { console.error(`[${target.name}] 第${i+1}步点击出错:`, error); return false; } } return true; } function updateStatus(text) { const statusText = document.getElementById('status-text'); if (statusText) { statusText.textContent = text; } console.log('[操作工具]', text); } async function executeExchange() { const runTimes = DEFAULT_RUN_TIMES; const loopInterval = DEFAULT_LOOP_INTERVAL; if (exchangeRunning) { updateStatus('❌ 奖券兑换任务正在执行中,请勿重复点击'); return; } exchangeRunning = true; exchangeStopFlag = false; exchangeCount = 0; updateStatus(`📌 开始奖券兑换,共需运行${runTimes}次,循环间隔${loopInterval}ms`); for (let i = 0; i < runTimes; i++) { if (exchangeStopFlag) break; exchangeCount = i + 1; updateStatus(`🔄 奖券兑换:正在执行第${exchangeCount}/${runTimes}次`); const singleResult = await executeSingleRun(exchangeTargets, exchangeStopFlag); if (!singleResult && !exchangeStopFlag) { updateStatus(`❌ 奖券兑换:第${exchangeCount}次执行失败,终止任务`); break; } if (i < runTimes - 1 && !exchangeStopFlag) { await new Promise(resolve => setTimeout(resolve, loopInterval)); } } exchangeRunning = false; if (exchangeStopFlag) { updateStatus(`🛑 奖券兑换已停止,共完成${exchangeCount}次`); exchangeStopFlag = false; } else { updateStatus(`✅ 奖券兑换任务完成,共执行${exchangeCount}次`); } } function stopExchange() { if (!exchangeRunning) { updateStatus('❌ 当前无奖券兑换任务在执行'); return; } exchangeStopFlag = true; updateStatus('⚠️ 正在停止奖券兑换任务...'); } async function executeLottery() { const runTimes = DEFAULT_RUN_TIMES; const loopInterval = DEFAULT_LOOP_INTERVAL; if (lotteryRunning) { updateStatus('❌ 挚友力抽奖任务正在执行中,请勿重复点击'); return; } lotteryRunning = true; lotteryStopFlag = false; lotteryCount = 0; updateStatus(`📌 开始挚友力抽奖,共需运行${runTimes}次,循环间隔${loopInterval}ms`); for (let i = 0; i < runTimes; i++) { if (lotteryStopFlag) break; lotteryCount = i + 1; updateStatus(`🔄 挚友力抽奖:正在执行第${lotteryCount}/${runTimes}次`); const singleResult = await executeSingleRun(lotteryTargets, lotteryStopFlag); if (!singleResult && !lotteryStopFlag) { updateStatus(`❌ 挚友力抽奖:第${lotteryCount}次执行失败,终止任务`); break; } if (i < runTimes - 1 && !lotteryStopFlag) { await new Promise(resolve => setTimeout(resolve, loopInterval)); } } lotteryRunning = false; if (lotteryStopFlag) { updateStatus(`🛑 挚友力抽奖已停止,共完成${lotteryCount}次`); lotteryStopFlag = false; } else { updateStatus(`✅ 挚友力抽奖任务完成,共执行${lotteryCount}次`); } } function stopLottery() { if (!lotteryRunning) { updateStatus('❌ 当前无挚友力抽奖任务在执行'); return; } lotteryStopFlag = true; updateStatus('⚠️ 正在停止挚友力抽奖任务...'); } function createControlPanel() { if (document.getElementById('main-operation-panel')) return; const mainPanel = document.createElement('div'); mainPanel.id = 'main-operation-panel'; mainPanel.style.cssText = ` position: fixed; top: 20px; right: 20px; z-index: 999999; background: #fff; border: 1px solid #e5e7eb; border-radius: 12px; padding: 16px; box-shadow: 0 4px 12px rgba(0,0,0,0.08); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; width: 340px; `; mainPanel.innerHTML = `
🕒 精准北京时间
📥 奖券兑换(一万购物券兑换)
配置:100次执行 | 每次间隔1000ms
🎁 挚友力抽奖(单次抽奖)
配置:100次执行 | 每次间隔1000ms
🟢 就绪,等待执行操作
`; document.body.appendChild(mainPanel); const exchangeStart = document.getElementById('exchange-start'); const exchangeStop = document.getElementById('exchange-stop'); const lotteryStart = document.getElementById('lottery-start'); const lotteryStop = document.getElementById('lottery-stop'); exchangeStart.addEventListener('click', executeExchange); exchangeStop.addEventListener('click', stopExchange); lotteryStart.addEventListener('click', executeLottery); lotteryStop.addEventListener('click', stopLottery); const btnHoverEffect = (btn, normalBg, hoverBg) => { btn.addEventListener('mouseover', () => { btn.style.background = hoverBg; btn.style.transform = 'translateY(-1px)'; btn.style.boxShadow = '0 4px 8px rgba(0,0,0,0.12)'; }); btn.addEventListener('mouseout', () => { btn.style.background = normalBg; btn.style.transform = 'translateY(0)'; btn.style.boxShadow = `0 2px 4px ${normalBg === '#165dff' ? 'rgba(22, 93, 255, 0.1)' : normalBg === '#f59e0b' ? 'rgba(245, 158, 11, 0.1)' : 'rgba(239, 68, 68, 0.1)'}`; }); }; btnHoverEffect(exchangeStart, '#165dff', '#1451e0'); btnHoverEffect(exchangeStop, '#ef4444', '#dc2626'); btnHoverEffect(lotteryStart, '#f59e0b', '#d97706'); btnHoverEffect(lotteryStop, '#ef4444', '#dc2626'); } function initScript() { createControlPanel(); updateStatus(`✅ 操作工具已加载完成,可执行操作`); } if (document.readyState === 'complete' || document.readyState === 'interactive') { initScript(); } else { document.addEventListener('DOMContentLoaded', initScript); } })();