// ==UserScript== // @name 逆战活动工具箱 // @namespace https://gitee.com/ // @version 1.4.6 // @description 逆战活动一键领取助手 // @author 逆战-牢鹊 // @match *://nz.qq.com/* // @grant GM_log // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @run-at document-end // @icon https://nz.qq.com/favicon.ico // @license MIT // ==/UserScript== (() => { 'use strict'; const ACTIVITY_CONFIGS = [ { id: 'nz_january_login_202512', name: '1.1登录领5000', icon: '🎊', url: 'https://nz.qq.com/cp/a20251205knact/', urlRegex: /a20251205knact/, steps: [ { name: 'lijilq1', func: 'autoClick', param: '.btn_p1lq.sp.chakan1.isGray24', delay: 1000 }, { name: 'close_lijilq1', func: 'closePopup', param: 'lijilq1', delay: 1000 }, { name: 'lijilq2', func: 'autoClick', param: '.btn_p1lq.sp.chakan2.isGray25', delay: 1000 }, { name: 'close_lijilq2', func: 'closePopup', param: 'lijilq2', delay: 1000 }, { name: 'lijilq3', func: 'autoClick', param: '.btn_p1lq.sp.chakan3.isGray26', delay: 1000 }, { name: 'close_lijilq3', func: 'closePopup', param: 'lijilq3', delay: 1000 }, { name: 'lijilq4', func: 'autoClick', param: '.btn_p1lq.sp.chakan4.isGray27.gray', delay: 1000 }, { name: 'close_lijilq4', func: 'closePopup', param: 'lijilq4', delay: 1000 }, { name: 'lijilq5', func: 'autoClick', param: '.btn_p1lq.sp.chakan5.isGray28', delay: 1000 }, { name: 'close_lijilq5', func: 'closePopup', param: 'lijilq5', delay: 1000 }, { name: 'lijilq6', func: 'autoClick', param: '.btn_p1lq.sp.chakan6.isGray29', delay: 1000 }, { name: 'close_lijilq6', func: 'closePopup', param: 'lijilq6', delay: 1000 }, { name: 'bgGet1', func: 'autoClick', param: '.btn_p1lq.sp.isGray30', delay: 1000 }, { name: 'close_bgGet1', func: 'closePopup', param: 'bgGet1', delay: 1000 }, { name: 'bgGet2', func: 'autoClick', param: '.btn_p1lq.sp.isGray31', delay: 1000 }, { name: 'close_bgGet2', func: 'closePopup', param: 'bgGet2', delay: 1000 }, { name: 'bgGet3', func: 'autoClick', param: '.btn_p1lq.sp.isGray32', delay: 1000 }, { name: 'close_bgGet3', func: 'closePopup', param: 'bgGet3', delay: 1000 }, { name: 'bgGet4', func: 'autoClick', param: '.btn_p1lq.sp.isGray33', delay: 1000 }, { name: 'close_bgGet4', func: 'closePopup', param: 'bgGet4', delay: 1000 }, { name: 'bgGet5', func: 'autoClick', param: '.btn_p1lq.sp.isGray34', delay: 1000 }, { name: 'close_bgGet5', func: 'closePopup', param: 'bgGet5', delay: 1000 }, { name: 'bgGet6', func: 'autoClick', param: '.btn_p1lq.sp.isGray35', delay: 1000 }, { name: 'close_bgGet6', func: 'closePopup', param: 'bgGet6', delay: 1000 }, { name: 'yx30Get', func: 'autoClick', param: '.btn_p6open.sp.isGray36', delay: 1000 }, { name: 'close_yx30Get', func: 'closePopup', param: 'yx30Get', delay: 1000 }, { name: 'p4Choujiang1', func: 'autoClick', param: '.btn_p6open.sp.isGray18', delay: 1000 }, { name: 'close_p4c1', func: 'closePopup', param: 'p4Choujiang1', delay: 1000 }, { name: 'p4Choujiang2', func: 'autoClick', param: '.btn_p6open.sp.isGray19', delay: 1000 }, { name: 'close_p4c2', func: 'closePopup', param: 'p4Choujiang2', delay: 1000 }, { name: 'p4Choujiang3', func: 'autoClick', param: '.btn_p6open.sp.isGray20', delay: 1000 }, { name: 'close_p4c3', func: 'closePopup', param: 'p4Choujiang3', delay: 1000 }, { name: 'p4Choujiang4', func: 'autoClick', param: '.btn_p6open.sp.isGray21', delay: 1000 }, { name: 'close_p4c4', func: 'closePopup', param: 'p4Choujiang4', delay: 1000 }, { name: 'p4Choujiang1_1', func: 'autoClick', param: '.btn_p6open.sp.isGray22', delay: 1000 }, { name: 'close_p4c1_1', func: 'closePopup', param: 'p4Choujiang1_1', delay: 1000 }, { name: 'p4Choujiang1_2', func: 'autoClick', param: '.btn_p6open.sp.isGray23', delay: 1000 }, { name: 'close_p4c1_2', func: 'closePopup', param: 'p4Choujiang1_2', delay: 1000 }, { name: 'P1evDayGet', func: 'autoClick', param: '.sp.isGray1', delay: 1000 }, { name: 'close_p1d', func: 'closePopup', param: 'P1evDayGet', delay: 1000 }, { name: 'P1ydyxGet', func: 'autoClick', param: '.sp.isGray2', delay: 1000 }, { name: 'close_p1y', func: 'closePopup', param: 'P1ydyxGet', delay: 1000 }, { name: 'P1bgyxGet', func: 'autoClick', param: '.sp.isGray3', delay: 1000 }, { name: 'close_p1b', func: 'closePopup', param: 'P1bgyxGet', delay: 1000 }, { name: 'P1chongnGet', func: 'autoClick', param: '.btn_p1lq.sp.isGray4', delay: 1000 }, { name: 'close_p1c', func: 'closePopup', param: 'P1chongnGet', delay: 1000 }, { name: 'P2evDLoginget', func: 'autoClick', param: '.sp.isGray5', delay: 1000 }, { name: 'close_p2d', func: 'closePopup', param: 'P2evDLoginget', delay: 1000 }, { name: 'P2evDtgGet', func: 'autoClick', param: '.sp.isGray6', delay: 1000 }, { name: 'close_p2t', func: 'closePopup', param: 'P2evDtgGet', delay: 1000 }, { name: 'P2ydloginGet', func: 'autoClick', param: '.sp.btn_p4btn1.isGray7', delay: 1000 }, { name: 'close_p2yl', func: 'closePopup', param: 'P2ydloginGet', delay: 1000 }, { name: 'P2bgyxGet', func: 'autoClick', param: '.sp.btn_p4btn1.isGray8', delay: 1000 }, { name: 'close_p2bg', func: 'closePopup', param: 'P2bgyxGet', delay: 1000 }, { name: 'p2ljGet1', func: 'autoClick', param: '.sp.btn_p4lq.isGray12', delay: 1000 }, { name: 'close_p2l1', func: 'closePopup', param: 'p2ljGet1', delay: 1000 }, { name: 'p2ljGet2', func: 'autoClick', param: '.sp.btn_p4lq.isGray13', delay: 1000 }, { name: 'close_p2l2', func: 'closePopup', param: 'p2ljGet2', delay: 1000 }, { name: 'p2ljGet3', func: 'autoClick', param: '.sp.btn_p4lq.isGray14', delay: 1000 }, { name: 'close_p2l3', func: 'closePopup', param: 'p2ljGet3', delay: 1000 }, { name: 'p2ljGet4', func: 'autoClick', param: '.sp.btn_p4lq.isGray15', delay: 1000 }, { name: 'close_p2l4', func: 'closePopup', param: 'p2ljGet4', delay: 1000 }, { name: 'p2ljGet5', func: 'autoClick', param: '.sp.btn_p4lq.isGray16', delay: 1000 }, { name: 'close_p2l5', func: 'closePopup', param: 'p2ljGet5', delay: 1000 }, { name: 'P2jiasu', func: 'autoClick', param: '.btn_p4jsfh.sp.isGray11', delay: 1000 }, { name: 'close_p2j', func: 'closePopup', param: 'P2jiasu', delay: 1000 }, { name: 'P2leijiGet1', func: 'autoClick', param: '.sp.isGray9', delay: 1000 }, { name: 'close_p2l1', func: 'closePopup', param: 'P2leijiGet1', delay: 1000 }, { name: 'P2leijiGet2', func: 'autoClick', param: '.sp.isGray10', delay: 1000 }, { name: 'close_p2l2', func: 'closePopup', param: 'P2leijiGet2', delay: 1000 }, { name: 'P3chouQu', func: 'autoClick', param: '.sp.btn_p5btns.isGray17', delay: 1000 }, { name: 'close_p3c', func: 'closePopup', param: 'P3chouQu', delay: 1000 } ] }, { id: 'nz_artifact_20251215', name: '典藏神器免费领', icon: '🎁', url: 'https://nz.qq.com/cp/a20251215springact/', urlRegex: /a20251215springact/, steps: [ // 累计收集1/4把武器领取 { name: 'lingshouji13', func: 'autoClick', param: '.sp.btn_p1lq:contains', delay: 1000 }, { name: 'close_dz6', func: 'autoClick', param: '#pop1 .close.sp', delay: 1000 }, // 累计收集1/8把武器领取 { name: 'lingshouji14', func: 'autoClick', param: '.sp.btn_p1lq:contains', delay: 1000 }, { name: 'close_dz6', func: 'autoClick', param: '#pop1 .close.sp', delay: 1000 }, // 累计收集1/16把武器领取 { name: 'lingshouji15', func: 'autoClick', param: '.sp.btn_p1lq:contains', delay: 1000 }, { name: 'close_dz6', func: 'autoClick', param: '#pop1 .close.sp', delay: 1000 }, // 立即领取中奖码奖励 { name: 'lingqu1', func: 'autoClick', param: 'a.btn_p3lq.sp[href^="javascript:lingqujlzjm"]', delay: 1000 }, { name: 'close_dz6', func: 'autoClick', param: '#pop1 .close.sp', delay: 1000 }, // 领取中奖码 { name: 'lingquzhongjiang1', func: 'autoClick', param: 'a.btn_yaoq.sp[href^="javascript:lingchongzhongjiang"]', delay: 1000 }, { name: 'close_dz6', func: 'autoClick', param: '#pop1 .close.sp', delay: 1000 }, // 点赞 { name: 'dianzan1', func: 'autoClick', param: 'a.btn_p4dz.sp[href^="javascript:dianzan"]', delay: 1000 }, { name: 'close_dz1', func: 'autoClick', param: '#pop1 .close.sp', delay: 1000 }, // 立即抽取(renwuling('t1')) { name: 'renwuling_t1', func: 'autoClick', param: '.btn_p4lq.sp.cebianling:contains', delay: 1000 }, { name: 'close_dz6', func: 'autoClick', param: '#pop1 .close.sp', delay: 1000 }, // 累计点赞领取(chongzhizhongjiangma(renwuling('t2'))) { name: 'chongzhizhongjiangma_t2', func: 'autoClick', param: '.btn_p4lq.sp.leijidianzanling.cebianling', delay: 1000 }, { name: 'close_gb', func: 'autoClick', param: '#pop1 .close.sp', delay: 1000 }, // 立即领取(renwuling('t5')) { name: 'lingqu1', func: 'autoClick', param: 'a.btn_p4lq.sp.cebianling[href^="javascript:renwuling(\'t5\')"]', delay: 1000 }, { name: 'close_dz6', func: 'autoClick', param: '#pop1 .close.sp', delay: 1000 } ] }, { id: 'nz_return_202512', name: '1月新新老玩家回归', icon: '🎯', url: 'https://nz.qq.com/cp/a20251222qxtq/', urlRegex: /a20251222qxtq/, steps: [ { name: 'dayJian', func: 'autoClick', param: '.btnA.isGray24', delay: 1000 }, { name: 'close_dayJian', func: 'closePopup', param: 'dayJian', delay: 1000 }, { name: 'checkInJump', func: 'autoClick', param: '.btnA.isGray54', delay: 1000 }, { name: 'close_checkInJump', func: 'closePopup', param: 'checkInJump', delay: 1000 }, { name: 'part2_Jian1', func: 'autoClick', param: '.btnA[href*="part2_Jian(1)"]', delay: 1000 }, { name: 'close_part2_Jian1', func: 'closePopup', param: 'part2_Jian1', delay: 1000 }, { name: 'partInvCopy1', func: 'autoClick', param: '.btnA.isGray815', delay: 1000 }, { name: 'close_partInvCopy1', func: 'closePopup', param: 'partInvCopy1', delay: 1000 }, { name: 'invitePropVeteran', func: 'autoClick', param: '.btnA.isGray814', delay: 1000 }, { name: 'close_invitePropVeteran', func: 'closePopup', param: 'invitePropVeteran', delay: 1000 }, { name: 'part1_3_TotalDraw1', func: 'autoClick', param: '.btnA.isGray35', delay: 1000 }, { name: 'close_part1_3_TotalDraw1', func: 'closePopup', param: 'part1_3_TotalDraw1', delay: 1000 }, { name: 'part1_3_TotalDraw2', func: 'autoClick', param: '.btnA.isGray36', delay: 1000 }, { name: 'close_part1_3_TotalDraw2', func: 'closePopup', param: 'part1_3_TotalDraw2', delay: 1000 }, { name: 'part1_3_TotalDraw3', func: 'autoClick', param: '.btnA.isGray37', delay: 1000 }, { name: 'close_part1_3_TotalDraw3', func: 'closePopup', param: 'part1_3_TotalDraw3', delay: 1000 }, { name: 'part1_3_TotalDraw4', func: 'autoClick', param: '.btnA.isGray38', delay: 1000 }, { name: 'close_part1_3_TotalDraw4', func: 'closePopup', param: 'part1_3_TotalDraw4', delay: 1000 }, { name: 'part1_3_TotalDraw5', func: 'autoClick', param: '.btnA.isGray39', delay: 1000 }, { name: 'close_part1_3_TotalDraw5', func: 'closePopup', param: 'part1_3_TotalDraw5', delay: 1000 }, { name: 'part1_DayGame', func: 'autoClick', param: '.btnA.isGray106', delay: 1000 }, { name: 'close_part1_DayGame', func: 'closePopup', param: 'part1_DayGame', delay: 1000 }, { name: 'partInvCopy11', func: 'autoClick', param: '.btnA[href*="partInvCopy(11)"]', delay: 1000 }, { name: 'close_partInvCopy11', func: 'closePopup', param: 'partInvCopy11', delay: 1000 }, { name: 'part4_inviteLao', func: 'autoClick', param: '.btnB.isGray26', delay: 1000 }, { name: 'close_part4_inviteLao', func: 'closePopup', param: 'part4_inviteLao', delay: 1000 }, { name: 'part4_zyl_selReceive1', func: 'autoClick', param: '.btnA.isGray30', delay: 1000 }, { name: 'close_part4_zyl_selReceive1', func: 'closePopup', param: 'part4_zyl_selReceive1', delay: 1000 }, { name: 'part4_zyl_selReceive2', func: 'autoClick', param: '.btnA.isGray31', delay: 1000 }, { name: 'close_part4_zyl_selReceive2', func: 'closePopup', param: 'part4_zyl_selReceive2', delay: 1000 }, { name: 'part4_zyl_selReceive4', func: 'autoClick', param: '.btnB.isGray33', delay: 1000 }, { name: 'close_part4_zyl_selReceive4', func: 'closePopup', param: 'part4_zyl_selReceive4', delay: 1000 } ] }, { id: 'nz_bosaidong_20260109', name: '波塞冬女王活动打卡', icon: '🎉', url: 'https://nz.qq.com/cp/a20251128queenencore/', urlRegex: /a20251128queenencore/, steps: [ // 每日签到 { name: 'lingqu4', func: 'autoClick', param: 'a.sp.btn_lq[href^="javascript:callFlow"]', delay: 1000 }, { name: 'guanbi2', func: 'autoClick', param: 'a.dia-close.sp.db[href^="javascript:closeDialog"]', delay: 1000 }, // 每日打卡 { name: 'daka1', func: 'autoClick', param: 'a.sp.btn_dk[href^="javascript:callFlow"]', delay: 1000 }, { name: 'guanbi3', func: 'autoClick', param: 'a.dia-close.sp.db[href^="javascript:closeDialog"]', delay: 1000 }, // 第1个宝箱领取 + 关闭弹窗 { name: 'btn_lq1_1', func: 'autoClick', param: 'a.sp.btn_lq1', delay: 1000 }, { name: 'guanbi1', func: 'autoClick', param: 'a.dia-close.sp.db[href^="javascript:closeDialog"]', delay: 1000 }, // 第2个宝箱领取 + 关闭弹窗 { name: 'btn_lq1_2', func: 'autoClick', param: 'a.sp.btn_lq1', delay: 1000 }, { name: 'guanbi2', func: 'autoClick', param: 'a.dia-close.sp.db[href^="javascript:closeDialog"]', delay: 1000 }, // 第3个宝箱领取 + 关闭弹窗 { name: 'btn_lq1_3', func: 'autoClick', param: 'a.sp.btn_lq1', delay: 1000 }, { name: 'guanbi3', func: 'autoClick', param: 'a.dia-close.sp.db[href^="javascript:closeDialog"]', delay: 1000 }, // 第4个宝箱领取 + 关闭弹窗 { name: 'btn_lq1_4', func: 'autoClick', param: 'a.sp.btn_lq1', delay: 1000 }, { name: 'guanbi4', func: 'autoClick', param: 'a.dia-close.sp.db[href^="javascript:closeDialog"]', delay: 1000 }, // 第5个宝箱领取 + 关闭弹窗 { name: 'btn_lq1_5', func: 'autoClick', param: 'a.sp.btn_lq1', delay: 1000 }, { name: 'guanbi5', func: 'autoClick', param: 'a.dia-close.sp.db[href^="javascript:closeDialog"]', delay: 1000 }, // 第6个宝箱领取 + 关闭弹窗 { name: 'btn_lq1_6', func: 'autoClick', param: 'a.sp.btn_lq1', delay: 1000 }, { name: 'guanbi6', func: 'autoClick', param: 'a.dia-close.sp.db[href^="javascript:closeDialog"]', delay: 1000 } ] } ]; GM_addStyle(` #nz-toolbox { position: fixed; top: 50px; left: 20px; z-index: 99999999; width: 320px; background: #fff; border: 1px solid rgba(230, 57, 70, 0.3); border-radius: 20px; box-shadow: 0 12px 36px rgba(0, 0, 0, 0.15); font-family: 'Microsoft YaHei', 'PingFang SC', sans-serif; overflow: hidden; opacity: 1; visibility: visible; pointer-events: auto; } #nz-toolbox-header { background: linear-gradient(90deg, #e63946 0%, #ff6b6b 100%); color: #fff; padding: 20px 24px; display: flex; justify-content: space-between; align-items: center; cursor: move; user-select: none; border-top-left-radius: 20px; border-top-right-radius: 20px; position: relative; } #nz-toolbox-header::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.8), transparent); } .nz-toolbox-title { font-size: 18px; font-weight: 700; display: flex; align-items: center; gap: 12px; letter-spacing: 0.8px; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } .nz-toolbox-icon { width: 28px; height: 28px; object-fit: contain; border-radius: 8px; box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3); } .nz-toolbox-mini { background: rgba(255, 255, 255, 0.2); border: 1px solid rgba(255, 255, 255, 0.3); color: #fff; font-size: 20px; cursor: pointer; width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center; justify-content: center; transition: all 0.3s; } .nz-toolbox-mini:hover { background: rgba(255, 255, 255, 0.3); transform: translateY(-2px); box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2); } #nz-toolbox-body { padding: 24px; max-height: 600px; overflow-y: auto; } #nz-toolbox-body::-webkit-scrollbar { width: 8px; } #nz-toolbox-body::-webkit-scrollbar-track { background: rgba(230, 57, 70, 0.08); border-radius: 4px; } #nz-toolbox-body::-webkit-scrollbar-thumb { background: linear-gradient(180deg, #e63946 0%, #ff6b6b 100%); border-radius: 4px; } .nz-group-title { font-size: 14px; color: #e63946; margin: 24px 0 12px 0; padding-left: 10px; border-left: 3px solid #e63946; text-transform: uppercase; letter-spacing: 1.2px; font-weight: 600; } .nz-group-title:first-child { margin-top: 0; } .nz-toolbox-btn { width: 100%; background: #f8f9fa; border: 1px solid rgba(230, 57, 70, 0.2); color: #333; padding: 14px 20px; margin: 8px 0; border-radius: 14px; cursor: pointer; font-size: 15px; text-align: left; display: flex; align-items: center; gap: 14px; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); position: relative; overflow: hidden; } .nz-toolbox-btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(230, 57, 70, 0.1), transparent); transition: left 0.6s cubic-bezier(0.4, 0, 0.2, 1); } .nz-toolbox-btn:hover { background: linear-gradient(145deg, #e63946 0%, #ff6b6b 100%); color: #fff; transform: translateY(-3px); box-shadow: 0 8px 24px rgba(230, 57, 70, 0.3); border-color: rgba(230, 57, 70, 0.5); } .nz-toolbox-btn:hover::before { left: 100%; } .nz-toolbox-btn:active { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(230, 57, 70, 0.2); } .nz-btn-icon { width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 20px; } #nz-toolbox.mini { width: 70px; height: 70px; border-radius: 22px; overflow: hidden; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } #nz-toolbox.mini #nz-toolbox-body, #nz-toolbox.mini .nz-toolbox-title span { display: none; } #nz-toolbox.mini #nz-toolbox-header { width: 100%; height: 100%; justify-content: center; border-radius: 22px; padding: 0; } .nz-toast { position: fixed; bottom: 60px; left: 50%; transform: translateX(-50%); background: #fff; color: #333; padding: 16px 28px; border-radius: 14px; font-size: 15px; z-index: 99999999; box-shadow: 0 12px 36px rgba(0, 0, 0, 0.15); border: 1px solid rgba(230, 57, 70, 0.3); animation: nzSlideUp 0.4s ease-out; } @keyframes nzSlideUp { from { transform: translate(-50%, 30px); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } } `); class StorageManager { static get(key) { try { return GM_getValue(`nz_${key}`, null); } catch (e) { return null; } } static set(key, val) { try { GM_setValue(`nz_${key}`, val); } catch (e) { console.log(e); } } } class UIHelper { static toast(msg, duration = 2000) { const existing = document.querySelector('.nz-toast'); if (existing) existing.remove(); const el = document.createElement('div'); el.className = 'nz-toast'; el.textContent = msg; document.body.appendChild(el); setTimeout(() => el.parentNode && el.remove(), duration); } static confirm(title, msg) { return new Promise(resolve => { const overlay = document.createElement('div'); overlay.style.cssText = `position: fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.6);z-index:99999998;`; const dialog = document.createElement('div'); dialog.style.cssText = `position: fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;border-radius:20px;padding:28px;width:360px;box-shadow:0 20px 60px rgba(0,0,0,0.15);border:1px solid rgba(230,57,70,0.3);z-index:99999999;`; dialog.innerHTML = `

${title}

${msg}

`; document.body.appendChild(overlay); document.body.appendChild(dialog); const cleanup = () => { overlay.parentNode && overlay.remove(); dialog.parentNode && dialog.remove(); }; dialog.querySelector('#nz-dialog-cancel').addEventListener('click', () => { resolve(false); cleanup(); }); dialog.querySelector('#nz-dialog-confirm').addEventListener('click', () => { resolve(true); cleanup(); }); overlay.addEventListener('click', () => { resolve(false); cleanup(); }); }); } } class Executor { static closePopup(popupType = "default") { const selectors = [ '.sp.btn_qr', '.close.sp', '.pop_btn1.sp', '.pop-btn2', '.pop1btn1', '.pop_close.pa', '.pop_close1' ]; try { for (const selector of selectors) { const btn = document.querySelector(selector); if (btn) { btn.click(); GM_log(`Close popup ${popupType}: ${selector} success`); return true; } } if (typeof closeDialog === 'function') { closeDialog(); GM_log(`Close popup ${popupType}: closeDialog() success`); return true; } GM_log(`Close popup ${popupType}: no element found`); return false; } catch (e) { GM_log(`Close popup ${popupType} error: ${e.message}`); return false; } } static autoClick(selector, actionName = "button") { try { let btn = null; if (selector.includes(':contains')) { const [baseSelector, textPart] = selector.split(':contains'); const text = textPart.replace(/[()"]/g, '').split(':nth-of-type')[0]; const nthMatch = textPart.match(/:nth-of-type\((\d+)\)/); const nth = nthMatch ? parseInt(nthMatch[1]) - 1 : 0; const allBtns = document.querySelectorAll(baseSelector.trim()); const matchedBtns = Array.from(allBtns).filter(btn => btn.textContent.includes(text)); if (matchedBtns.length > nth) { btn = matchedBtns[nth]; } } else { btn = document.querySelector(selector); } if (!btn) { GM_log(`${actionName}: selector ${selector} not found`); return false; } btn.click(); if (btn.dispatchEvent) { const event = new MouseEvent('click', { bubbles: true, cancelable: true, view: window }); btn.dispatchEvent(event); } GM_log(`${actionName}: selector ${selector} click success`); return true; } catch (e) { GM_log(`${actionName}: selector ${selector} click error: ${e.message}`); return false; } } static delayExecution(param = null, actionName = "delay") { const delay = param ? parseInt(param) : 1000; GM_log(`${actionName}: delay ${delay}ms`); return new Promise(resolve => setTimeout(resolve, delay)); } } class Toolbox { static quickPages = { activity: { icon: '🎮', name: '活动中心', url: 'https://nz.qq.com/web202403/activity-list.shtml' } }; static create() { const oldBox = document.getElementById('nz-toolbox'); if (oldBox) oldBox.remove(); const box = document.createElement('div'); box.id = 'nz-toolbox'; const pos = StorageManager.get('toolbox_pos'); if (pos) { box.style.top = `${pos.top}px`; box.style.left = `${pos.left}px`; } if (StorageManager.get('toolbox_mini')) { box.classList.add('mini'); } box.innerHTML = `
逆战活动助手
-
快速访问
${Object.values(this.quickPages).map(page => ` `).join('')}
活动列表
${ACTIVITY_CONFIGS.map(activity => ` `).join('')}
活动助手
`; document.body.appendChild(box); this.setupEvents(box); return box; } static setupEvents(box) { box.querySelector('.nz-toolbox-mini').addEventListener('click', (e) => { e.stopPropagation(); box.classList.toggle('mini'); StorageManager.set('toolbox_mini', box.classList.contains('mini')); }); let isDragging = false; let offsetX, offsetY; const header = box.querySelector('#nz-toolbox-header'); header.addEventListener('mousedown', (e) => { isDragging = true; const rect = box.getBoundingClientRect(); offsetX = e.clientX - rect.left; offsetY = e.clientY - rect.top; header.style.cursor = 'grabbing'; }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; box.style.left = `${e.clientX - offsetX}px`; box.style.top = `${e.clientY - offsetY}px`; }); document.addEventListener('mouseup', () => { if (isDragging) { isDragging = false; header.style.cursor = 'move'; StorageManager.set('toolbox_pos', { top: parseInt(box.style.top), left: parseInt(box.style.left) }); } }); box.addEventListener('click', (e) => { const btn = e.target.closest('.nz-toolbox-btn'); if (!btn) return; if (btn.dataset.action === 'openUrl' && btn.dataset.url) { window.open(btn.dataset.url, '_self'); return; } if (btn.id === 'execute-all') { this.executeCurrentActivity(); } }); } static async executeCurrentActivity() { const currentUrl = window.location.href; const currentActivity = ACTIVITY_CONFIGS.find(act => act.urlRegex.test(currentUrl)); if (!currentActivity) { UIHelper.toast('当前页面不是支持的活动页面'); return; } if (currentActivity.steps.length === 0) { UIHelper.toast(`【${currentActivity.name}】暂无可用领取步骤`); return; } const confirm = await UIHelper.confirm('执行操作', `确定要执行【${currentActivity.name}】一键领取吗?`); if (!confirm) return; UIHelper.toast('开始执行一键领取'); await this.executeSteps(currentActivity.steps); UIHelper.toast('一键领取执行完成(部分道具及任务,需手动领取)'); } static async executeSteps(steps) { if (!steps || steps.length === 0) return; for (const [index, step] of steps.entries()) { GM_log(`[${index + 1}/${steps.length}] Execute: ${step.name}`); try { if (Executor[step.func]) { await Executor[step.func](step.param, step.name); } else { GM_log(`Unknown function: ${step.func}`); } } catch (e) { GM_log(`Step error: ${e.message}`); } if (step.delay > 0) { await new Promise(resolve => setTimeout(resolve, step.delay)); } } } } window.addEventListener('load', () => { setTimeout(() => Toolbox.create(), 1000); }); })();