您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically does Luarmor for you with smart key/button handling + options menu (auto-copy, auto-next, delay changer)
// ==UserScript== // @name Auto Luarmor V2 (Remade!) // @namespace http://tampermonkey.net/ // @license MIT // @version 2.4 // @description Automatically does Luarmor for you with smart key/button handling + options menu (auto-copy, auto-next, delay changer) // @author Aro // @match https://ads.luarmor.net/get_key?* // @grant none // @run-at document-idle // ==/UserScript== (function() { let isPaused = false; let currentAction = "Idle"; let currentKey = "N/A"; let logHistory = []; const logCache = new Set(); let firstNextClick = true; // Flags let blacklistLogged = false; let loaderLogged = false; let captchaLogged = false; let discordLogged = false; let nextBtnNotClickableLogged = false; let blacklistUrlLogged = false; // Options with defaults let options = { autoCopy: localStorage.getItem("opt_autoCopy") === "true", nextDelay: parseInt(localStorage.getItem("opt_nextDelay") || "3000", 10), reloadOnResume: localStorage.getItem("opt_reloadOnResume") !== "false", // default true }; // Floating UI // Floating UI const ui = document.createElement("div"); ui.style.cssText = ` position: fixed; top: 20px; right: 20px; width: 250px; background: rgba(25,25,25,0.9); color: #fff; font-family: Arial,sans-serif; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.5); padding: 10px; z-index: 999999; font-size: 13px; `; ui.innerHTML = ` <div style="display: flex; justify-content: space-between; align-items: center;"> <strong>Script Status</strong> <div> <button id="optionsBtn" style=" background:#444;border:none;color:#fff;padding:4px 8px; border-radius:4px;cursor:pointer;margin-right:4px;">⚙</button> <button id="toggleBtn" style=" background:#444;border:none;color:#fff;padding:4px 8px; border-radius:4px;cursor:pointer;">Pause</button> </div> </div> <div style="margin-top: 5px;"> <b>Current Key:</b> <span id="keyDisplay" style="display:inline-block; max-width:220px; word-break:break-all;"> ${currentKey} </span> </div> <div style="margin-top: 5px;"> <b>Action:</b> <span id="actionDisplay">${currentAction}</span> </div> <div style="margin-top: 5px;"> <b style="cursor:pointer;" id="logToggle">Log ▼</b> <div id="logAreaContainer" style="display:none; max-height:100px; overflow-y:auto; background:rgba(0,0,0,0.3); padding:5px; border-radius:4px; margin-top:3px;"> <div id="logArea" style="font-size:12px;"></div> </div> </div> <div id="optionsMenu" style="display:none; margin-top:10px; padding:5px; background:rgba(0,0,0,0.4); border-radius:6px;"> <label><input type="checkbox" id="opt_autoCopy"> Auto-copy Key</label><br> <label><input type="checkbox" id="opt_reloadOnResume"> Reload on Resume</label><br> <label>Next Delay (ms): <input type="number" id="opt_nextDelay" style="width:80px;"> </label><br> <button id="saveOptions" style=" margin-top:5px; background:#555; color:#fff; border:none; border-radius:4px; padding:3px 6px; cursor:pointer;">Save</button> </div> `; document.body.appendChild(ui); // UI elements const toggleBtn = ui.querySelector("#toggleBtn"); const optionsBtn = ui.querySelector("#optionsBtn"); const optionsMenu = ui.querySelector("#optionsMenu"); const keyDisplay = ui.querySelector("#keyDisplay"); const actionDisplay = ui.querySelector("#actionDisplay"); const logArea = ui.querySelector("#logArea"); const logToggle = ui.querySelector("#logToggle"); const logAreaContainer = ui.querySelector("#logAreaContainer"); // Initialize options UI ui.querySelector("#opt_autoCopy").checked = options.autoCopy; ui.querySelector("#opt_nextDelay").value = options.nextDelay; ui.querySelector("#opt_reloadOnResume").checked = options.reloadOnResume; // Toggle pause/resume toggleBtn.addEventListener("click", () => { isPaused = !isPaused; toggleBtn.textContent = isPaused ? "Resume" : "Pause"; if (isPaused) { log("Script paused"); } else { log("Script resumed"); if (options.reloadOnResume) { log("Reloading page..."); location.reload(); } else { onLoad(); } } }); // Options open/close optionsBtn.addEventListener("click", () => { optionsMenu.style.display = optionsMenu.style.display === "none" ? "block" : "none"; }); // Save options ui.querySelector("#saveOptions").addEventListener("click", () => { options.autoCopy = ui.querySelector("#opt_autoCopy").checked; options.nextDelay = parseInt(ui.querySelector("#opt_nextDelay").value, 10) || 3000; options.reloadOnResume = ui.querySelector("#opt_reloadOnResume").checked; localStorage.setItem("opt_autoCopy", options.autoCopy); localStorage.setItem("opt_nextDelay", options.nextDelay); localStorage.setItem("opt_reloadOnResume", options.reloadOnResume); log("Options saved"); }); // Log toggle logToggle.addEventListener("click", () => { const isHidden = logAreaContainer.style.display === "none"; logAreaContainer.style.display = isHidden ? "block" : "none"; logToggle.textContent = isHidden ? "Log ▲" : "Log ▼"; }); // Logger function log(message) { if (logCache.has(message)) return; logCache.add(message); const timestamp = new Date().toLocaleTimeString(); logHistory.unshift(`[${timestamp}] ${message}`); if (logHistory.length > 100) logHistory.pop(); logArea.innerHTML = logHistory.join("<br>"); console.log(message); setTimeout(() => logCache.delete(message), 5000); } function setAction(action) { currentAction = action; actionDisplay.textContent = action; log(action); } function setKey(key) { currentKey = key; keyDisplay.textContent = key; if (options.autoCopy) { navigator.clipboard.writeText(key).then(() => log("Key copied to clipboard")); } } // Block detection function isBlocked() { const blacklist = document.querySelector('.swal2-x-mark'); const loader = document.querySelector('.loader'); const captcha = document.getElementById('captchafield'); const discord = document.querySelector('h2.swal2-title#swal2-title'); const blacklistVisible = blacklist && blacklist.offsetParent !== null; const loaderVisible = loader && loader.offsetParent !== null; const captchaVisible = captcha && captcha.offsetParent !== null; const discordVisible = discord && discord.textContent.includes("Log In with Discord"); const blacklistUrl = window.location.href.includes("ads.luarmor.net/Blacklisted"); if (blacklistUrl) { if (!blacklistUrlLogged) { setAction("Waiting (blacklisted URL)..."); blacklistUrlLogged = true; } return true; } else blacklistUrlLogged = false; if (blacklistVisible) { if (!blacklistLogged) { setAction("Waiting (blacklisted)..."); blacklistLogged = true; } return true; } else blacklistLogged = false; if (loaderVisible) { if (!loaderLogged) { setAction("Waiting for loader..."); loaderLogged = true; } return true; } else loaderLogged = false; if (captchaVisible) { if (!captchaLogged) { setAction("Waiting for captcha..."); captchaLogged = true; } return true; } else captchaLogged = false; if (discordVisible) { if (!discordLogged) { setAction("Waiting for Discord login..."); discordLogged = true; } return true; } else discordLogged = false; return false; } function grabKeyOnce() { if (currentKey !== "N/A") return; const keyElement = document.querySelector('h6.mb-0.text-sm'); if (keyElement) { const keyText = keyElement.textContent.trim(); if (keyText) { setKey(keyText); log(`Key grabbed: ${keyText}`); } } } function onLoad() { if (isPaused) return setAction("Paused"); if (isBlocked()) return setTimeout(onLoad, 500); grabKeyOnce(); checkProgress(); // ✅ only schedule first run if (!onLoad.started) { setTimeout(clickNextLoop, options.nextDelay); onLoad.started = true; // prevent double scheduling } } function checkProgress() { if (isPaused) return setAction("Paused"); if (isBlocked()) return; const progressElement = document.getElementById('adprogressp'); if (!progressElement) return; const progressText = progressElement.textContent; const progressParts = progressText.match(/(\d+)\/(\d+)/); if (!progressParts) return; const currentProgress = parseInt(progressParts[1], 10); const totalProgress = parseInt(progressParts[2], 10); const remainingProgress = totalProgress - currentProgress; setAction(`Remaining Progress: ${remainingProgress}`); if (remainingProgress === 0) { const keyElement = document.querySelector('h6.mb-0.text-sm'); const addTimeBtn = keyElement ? document.getElementById(`addtimebtn_${keyElement.textContent.trim()}`) : null; const newKeyBtn = document.getElementById('newkeybtn'); if (keyElement && addTimeBtn && addTimeBtn.offsetParent !== null && !addTimeBtn.disabled) { addTimeBtn.click(); setAction(`Clicked Add Time for key: ${keyElement.textContent.trim()}`); } else if (newKeyBtn && newKeyBtn.offsetParent !== null && !newKeyBtn.disabled) { newKeyBtn.click(); setAction("Clicked Get a New Key"); } } } function clickNextLoop() { if (isPaused) return setAction("Paused"); if (isBlocked()) return setTimeout(clickNextLoop, 500); const btn = document.getElementById('nextbtn'); if (btn && btn.offsetParent !== null && !(btn.style.cursor === 'not-allowed' || btn.disabled)) { if (firstNextClick) { btn.click(); setAction("Clicked Next button (first)"); // 🔎 Defer focus check to let browser update focus setTimeout(() => { if (!document.hasFocus()) { setAction("Focused Ad Tab"); return; } firstNextClick = false; setTimeout(clickNextLoop, options.nextDelay); }, 0); } else { if (!document.hasFocus()) { setAction("Focused Ad Tab"); return; } btn.click(); setAction("Clicked Next button"); setTimeout(clickNextLoop, options.nextDelay); } } else { if (!nextBtnNotClickableLogged) { setAction("Waiting to click button"); nextBtnNotClickableLogged = true; } setTimeout(clickNextLoop, 500); } } if (document.readyState === "complete") { onLoad(); } else { window.addEventListener("load", onLoad, { once: true }); } })();