您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
每5分钟检测“无所事事”,若存在则自动执行:挤奶 → 奶牛 → 开始(每步1秒),并确认状态切换为“奶牛 [∞]”。
// ==UserScript== // @name MW Idle 无所事事自动挤奶 // @namespace mwidle-auto // @version 1.0.1 // @description 每5分钟检测“无所事事”,若存在则自动执行:挤奶 → 奶牛 → 开始(每步1秒),并确认状态切换为“奶牛 [∞]”。 // @match https://www.milkywayidle.com/* // @grant none // @run-at document-idle // @license MIT // ==/UserScript== (function () { 'use strict'; // 5分钟检查一次 const CHECK_INTERVAL_MS = 5 * 60 * 1000; const CLICK_DELAY_MS = 1000; const ENABLE_TEST_BUTTON = false; // 如需开启手动测试按钮,将此值改为 true const ENABLE_IDLE_OBSERVER = true; // 即时监听“无所事事”,检测到后立即尝试执行 const ENABLE_KEEPALIVE = false; // 保活(降低后台节流),如需开启改为 true // 你提供的 XPath const XPATHS = { idle_indicator: '//*[@id="root"]/div/div/div[1]/div/div[1]/div[2]/div[1]/div/div[1]/div[2]', nav_milk: '//*[@id="root"]/div/div/div[2]/div[1]/div/div[2]/div[2]/div[5]/div[1]/div/div[1]/span[1]', cow_name: '//*[@id="root"]/div/div/div[2]/div[2]/div[1]/div[1]/div/div[1]/div/div[1]/div/div/div/div/div/div/div[1]/div[1]', start_button: '//*[@id="root"]/div/div/div[2]/div[2]/div[1]/div[1]/div/div[1]/div/div[3]/div[2]/div[1]/div/div[3]/div[7]/button', header_cow: '//*[@id="root"]/div/div/div[1]/div/div[1]/div[2]/div[1]/div/div[1]/div[2]' }; function isVisible(element) { if (!element) return false; const rect = element.getBoundingClientRect(); const style = window.getComputedStyle(element); return rect.width > 0 && rect.height > 0 && style.visibility !== 'hidden' && style.display !== 'none'; } function evalXPath(xpath) { try { const res = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); return res.singleNodeValue || null; } catch (e) { return null; } } function safeClickElement(el) { if (!el || !isVisible(el)) return false; try { el.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); el.dispatchEvent(new MouseEvent('mouseup', { bubbles: true })); el.click(); return true; } catch (e) { return false; } } function clickByXPath(xpath) { const el = evalXPath(xpath); return safeClickElement(el); } function getTextByXPath(xpath) { const el = evalXPath(xpath); return (el && (el.textContent || '').trim()) || ''; } function isIdle() { const text = getTextByXPath(XPATHS.idle_indicator); return text.includes('无所事事'); } function isCowHeader() { const text = getTextByXPath(XPATHS.header_cow); return text.includes('奶牛'); } function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } async function startMilkingSequence() { // 1) 挤奶(导航) clickByXPath(XPATHS.nav_milk); await sleep(CLICK_DELAY_MS); // 2) 奶牛(名称元素) clickByXPath(XPATHS.cow_name); await sleep(CLICK_DELAY_MS); // 3) 开始(按钮) clickByXPath(XPATHS.start_button); await sleep(CLICK_DELAY_MS); } async function runOnce() { try { // 仅当“无所事事”时才启动挤奶流程 if (!isIdle()) return; await startMilkingSequence(); // 尝试确认状态切换为“奶牛 [∞]”,最多等待3秒(分3次,每次1秒) for (let i = 0; i < 3; i++) { if (isCowHeader()) break; await sleep(1000); } } catch (e) { // 忽略错误,避免影响页面 } } // 周期轮询 setInterval(runOnce, CHECK_INTERVAL_MS); // 初始化首次检查(避免刚好空闲时需等5分钟) setTimeout(runOnce, 3000); // 即时监听“无所事事”状态变更 function setupIdleObserver() { if (!ENABLE_IDLE_OBSERVER) return; let scheduled = false; const observer = new MutationObserver(() => { if (scheduled) return; scheduled = true; setTimeout(() => { scheduled = false; if (isIdle()) runOnce(); }, 250); }); try { observer.observe(document.documentElement, { childList: true, subtree: true, characterData: true }); } catch (e) { // 忽略 } // 标签页重新可见时也尝试一次 document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') { setTimeout(runOnce, 500); } }); } // 保活:使用 WebAudio 降低后台节流概率 function setupKeepAlive() { if (!ENABLE_KEEPALIVE) return; try { const AudioCtx = window.AudioContext || window.webkitAudioContext; if (!AudioCtx) return; const ctx = new AudioCtx(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); gain.gain.value = 0.00001; // 接近静音 osc.connect(gain).connect(ctx.destination); osc.start(); // 定期尝试恢复,防止被挂起 setInterval(() => { if (ctx.state !== 'running') ctx.resume().catch(() => {}); }, 15000); // 重新可见时恢复 document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible' && ctx.state !== 'running') { ctx.resume().catch(() => {}); } }); } catch (e) { // 忽略 } } // 可选:页面上的手动测试按钮 function createTestButton() { if (!ENABLE_TEST_BUTTON) return; if (document.getElementById('mwidle-milk-test')) return; if (!document.body) return; const btn = document.createElement('button'); btn.id = 'mwidle-milk-test'; btn.textContent = '测试挤奶'; Object.assign(btn.style, { position: 'fixed', right: '16px', bottom: '64px', // 避开其它按钮 zIndex: '99999', padding: '8px 12px', fontSize: '14px', borderRadius: '6px', border: '1px solid #888', background: '#2a5', color: '#fff', cursor: 'pointer', opacity: '0.9' }); btn.addEventListener('mouseenter', () => btn.style.opacity = '1'); btn.addEventListener('mouseleave', () => btn.style.opacity = '0.9'); btn.addEventListener('click', async () => { btn.disabled = true; btn.textContent = '测试中...'; try { await runOnce(); } finally { btn.disabled = false; btn.textContent = '测试挤奶'; } }); document.body.appendChild(btn); } if (document.readyState === 'loading') { window.addEventListener('DOMContentLoaded', () => { createTestButton(); setupIdleObserver(); setupKeepAlive(); }, { once: true }); } else { createTestButton(); setupIdleObserver(); setupKeepAlive(); } })();