您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Auto-start when offline; auto-extend
当前为
// ==UserScript== // @name Aternos Auto Start & Extend // @namespace https://aternos.org/ // @version 1.0.0 // @description Auto-start when offline; auto-extend // @match https://aternos.org/server // @match https://aternos.org/server/* // @run-at document-idle // @grant none // ==/UserScript== (function () { 'use strict'; const SELECTORS = { offlineContainer: 'div.status.offline', onlineContainer: 'div.status.online', startButton: '#start', players: '.live-status-box-value.js-players', countdown: '.server-end-countdown', extendButton: 'button.btn.btn-tiny.btn-success.server-extend-end', }; let lastStartClickMs = 0; let lastExtendClickMs = 0; function isVisible(el) { if (!el) return false; const style = window.getComputedStyle(el); return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'; } function queryText(selector) { const el = document.querySelector(selector); return el ? el.textContent.trim() : ''; } function isOffline() { return !!document.querySelector(SELECTORS.offlineContainer); } function isOnline() { return !!document.querySelector(SELECTORS.onlineContainer); } function playersAreZero() { const txt = queryText(SELECTORS.players); // e.g., "0/20" return /^0\s*\/\s*\d+$/i.test(txt); } function getCountdownSeconds() { const txt = queryText(SELECTORS.countdown); // e.g., "5:22" or "59s" if (!txt) return null; const trimmed = txt.replace(/\s+/g, ''); if (/^\d{1,2}:\d{2}$/.test(trimmed)) { const [m, s] = trimmed.split(':').map(Number); if (Number.isFinite(m) && Number.isFinite(s)) return m * 60 + s; } else if (/^\d{1,3}s$/i.test(trimmed)) { const s = Number(trimmed.slice(0, -1)); if (Number.isFinite(s)) return s; } return null; } function clickIfAvailable(selector, lastClickRef, minIntervalMs) { const now = Date.now(); if (now - lastClickRef.value < minIntervalMs) return false; const btn = document.querySelector(selector); if (!btn || !isVisible(btn) || btn.disabled) return false; btn.click(); lastClickRef.value = now; return true; } function tryStartIfOffline() { if (!isOffline()) return; clickIfAvailable(SELECTORS.startButton, { get value() { return lastStartClickMs; }, set value(v) { lastStartClickMs = v; } }, 10000); } function tryExtendIfEndingSoon() { if (!isOnline()) return; if (!playersAreZero()) return; const seconds = getCountdownSeconds(); if (seconds === null) return; // If <= 59 seconds remaining, extend if (seconds <= 59) { clickIfAvailable(SELECTORS.extendButton, { get value() { return lastExtendClickMs; }, set value(v) { lastExtendClickMs = v; } }, 5000); } } // Initial small delay to allow SPA content to render setTimeout(() => { // Poll for offline -> start setInterval(tryStartIfOffline, 5000); // Poll for extend condition every second setInterval(tryExtendIfEndingSoon, 1000); // React to dynamic DOM changes faster const observer = new MutationObserver(() => { tryStartIfOffline(); tryExtendIfEndingSoon(); }); observer.observe(document.documentElement, { childList: true, subtree: true }); }, 1500); })();