Auto Luarmor

Finds the elements on the page such as +12H, next, start, etc.. and clicks them at the appropriate times so you never have to do luarmor yourself again! (Code was written by ChatGPT)

当前为 2025-05-11 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Auto Luarmor
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.6
  5. // @description Finds the elements on the page such as +12H, next, start, etc.. and clicks them at the appropriate times so you never have to do luarmor yourself again! (Code was written by ChatGPT)
  6. // @author Chatgpt
  7. // @license MIT
  8. // @match https://ads.luarmor.net/get_key*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12.  
  13. (function () {
  14. 'use strict';
  15.  
  16. let scriptPaused = false;
  17.  
  18. const selectors = {
  19. nextButton: '#nextbtn',
  20. addTimeButton: '[id^="addtimebtn_"]',
  21. progressText: '#adprogressp',
  22. newKeyButton: '#newkeybtn',
  23. captchaCheckText: 'h1',
  24. keyTimeLeft: '[id^="_timeleft_"]',
  25. blacklistTitle: '#swal2-title',
  26. blacklistTimeText: 'p.text-sm',
  27. keyValue: 'h6.mb-0.text-sm'
  28. };
  29.  
  30. function isInPopupWindow() {
  31. return window.name === 'luarmor_popup';
  32. }
  33.  
  34. function parseTimeToMs(timeStr) {
  35. const parts = timeStr.split(':').map(Number);
  36. if (parts.length === 3) {
  37. const [h, m, s] = parts;
  38. return ((h * 60 + m) * 60 + s) * 1000;
  39. } else {
  40. const match = timeStr.match(/(\d+)\s*hours?\s*(\d+)\s*minutes?/i);
  41. if (match) {
  42. const [, h, m] = match.map(Number);
  43. return ((h * 60 + m) * 60) * 1000;
  44. }
  45. }
  46. return 0;
  47. }
  48.  
  49. function flashTitle(message, duration = 3000) {
  50. const originalTitle = document.title;
  51. let visible = true;
  52. const interval = 500;
  53. const flashCount = Math.floor(duration / interval);
  54. let i = 0;
  55. const flasher = setInterval(() => {
  56. document.title = visible ? message : originalTitle;
  57. visible = !visible;
  58. i++;
  59. if (i >= flashCount) {
  60. clearInterval(flasher);
  61. document.title = originalTitle;
  62. }
  63. }, interval);
  64. }
  65.  
  66. let lastStatusMessage = ''; // To track the last message logged
  67. let lastCooldownStatus = ''; // To keep track of the last cooldown status
  68. let lastCooldownTime = ''; // To keep track of the last cooldown time
  69.  
  70. function updateStatus(msg) {
  71. const statusText = document.getElementById('luarmor-status-text');
  72. if (statusText) statusText.textContent = msg;
  73.  
  74. // Extract the label from the message
  75. const labelMatch = msg.match(/^[\u{1F600}-\u{1F64F}]+|\D+/gu); // Match emojis and non-numeric characters at the start
  76. const label = labelMatch ? labelMatch[0] : msg;
  77.  
  78. // Check if the label has changed (log when label changes)
  79. if (label !== lastStatusMessage) {
  80. console.log(msg);
  81. lastStatusMessage = label;
  82. }
  83.  
  84. // Check if it's a cooldown message
  85. if (msg.includes("Cooldown")) {
  86. const timeMatch = msg.match(/\d{2}:\d{2}:\d{2}/);
  87. const currentCooldown = timeMatch ? timeMatch[0] : '';
  88.  
  89. // Log only when the cooldown status changes (not the time)
  90. if (currentCooldown !== lastCooldownTime) {
  91. // Log the first time the cooldown is detected
  92. if (lastCooldownStatus !== 'Cooldown') {
  93. console.log(msg); // Log once when the cooldown starts
  94. lastCooldownStatus = 'Cooldown';
  95. }
  96. lastCooldownTime = currentCooldown;
  97. }
  98. } else {
  99. // Reset cooldown status when it's no longer a cooldown message
  100. if (lastCooldownStatus === 'Cooldown') {
  101. lastCooldownStatus = ''; // Reset the cooldown log flag when it's no longer "Cooldown"
  102. }
  103. }
  104. }
  105.  
  106. function updateUITimers() {
  107. // Update active key time if available
  108. const timeLeftElem = document.querySelector(selectors.keyTimeLeft);
  109. if (timeLeftElem) {
  110. document.getElementById('luarmor-timeleft').textContent = timeLeftElem.textContent.trim();
  111. }
  112.  
  113. // Update key from the page
  114. const keyElem = document.querySelector(selectors.keyValue);
  115. if (keyElem) {
  116. document.getElementById('luarmor-key').textContent = keyElem.textContent.trim();
  117. }
  118. // Directly read cooldown time from DOM
  119. const nextBtn = document.querySelector(selectors.nextButton);
  120. const cooldownElem = document.getElementById('luarmor-cooldown');
  121.  
  122. if (nextBtn && cooldownElem) {
  123. if (nextBtn.style.cursor === 'not-allowed') {
  124. // Extract the visible time from the button's text
  125. const match = nextBtn.textContent.match(/\d{2}:\d{2}:\d{2}/);
  126. cooldownElem.textContent = match ? match[0] : 'Waiting...';
  127. } else {
  128. cooldownElem.textContent = 'None';
  129. }
  130. }
  131.  
  132. // Only update blacklist time and cooldown if blacklisted
  133. const isBlacklisted = document.querySelector(selectors.blacklistTitle)?.textContent.includes("Temporarily Blacklisted");
  134. if (isBlacklisted) {
  135. const blacklistTextElem = document.querySelector(selectors.blacklistTimeText);
  136. if (blacklistTextElem) {
  137. const blacklistTime = blacklistTextElem.textContent.replace("You can continue in:", '').trim();
  138. document.getElementById('luarmor-blacklist').textContent = blacklistTime;
  139.  
  140. const ms = parseTimeToMs(blacklistTime);
  141. const h = String(Math.floor(ms / 3600000)).padStart(2, '0');
  142. const m = String(Math.floor((ms % 3600000) / 60000)).padStart(2, '0');
  143. const s = String(Math.floor((ms % 60000) / 1000)).padStart(2, '0');
  144. document.getElementById('luarmor-cooldown').textContent = `${h}:${m}:${s}`;
  145. }
  146. } else {
  147. document.getElementById('luarmor-blacklist').textContent = 'None';
  148. document.getElementById('luarmor-cooldown').textContent = 'None';
  149. }
  150. }
  151.  
  152. function checkBlacklist() {
  153. const title = document.querySelector(selectors.blacklistTitle);
  154. if (title && title.textContent.includes("Temporarily Blacklisted")) {
  155. const timeText = document.querySelector(selectors.blacklistTimeText)?.textContent;
  156. if (timeText) {
  157. const ms = parseTimeToMs(timeText);
  158. updateStatus("⛔ Blacklisted. Waiting...");
  159. const blacklistTime = timeText.replace("You can continue in:", '').trim();
  160. document.getElementById('luarmor-blacklist').textContent = blacklistTime;
  161.  
  162. const h = String(Math.floor(ms / 3600000)).padStart(2, '0');
  163. const m = String(Math.floor((ms % 3600000) / 60000)).padStart(2, '0');
  164. const s = String(Math.floor((ms % 60000) / 1000)).padStart(2, '0');
  165. document.getElementById('luarmor-cooldown').textContent = `${h}:${m}:${s}`;
  166.  
  167. setTimeout(() => {
  168. location.reload();
  169. }, ms);
  170. return true;
  171. }
  172. }
  173. return false;
  174. }
  175.  
  176. let cooldownInterval;
  177.  
  178. function handleCooldownAndClickStart() {
  179. if (scriptPaused) return;
  180. updateUITimers();
  181.  
  182. const nextBtn = document.querySelector(selectors.nextButton);
  183. if (!nextBtn) return console.log("❌ Next button not found.");
  184.  
  185. if (nextBtn.style.cursor === 'not-allowed') {
  186. clearInterval(cooldownInterval); // prevent duplicates
  187.  
  188. cooldownInterval = setInterval(() => {
  189. if (scriptPaused) return;
  190. const btn = document.querySelector(selectors.nextButton);
  191. if (!btn || btn.style.cursor !== 'not-allowed') {
  192. clearInterval(cooldownInterval);
  193. return;
  194. }
  195. const match = btn.textContent.match(/\d{2}:\d{2}:\d{2}/);
  196. if (match) updateStatus(`⏳ Cooldown: ${match[0]}`);
  197. }, 1000);
  198.  
  199. const match = nextBtn.textContent.match(/\d{2}:\d{2}:\d{2}/);
  200. const ms = match ? parseTimeToMs(match[0]) : 0;
  201.  
  202. if (ms > 3000) {
  203. setTimeout(() => {
  204. if (scriptPaused) return;
  205. window.focus();
  206. flashTitle("⏰ Cooldown Ending!");
  207. }, ms - 3000);
  208. }
  209.  
  210. setTimeout(() => {
  211. if (scriptPaused) return;
  212. const btn = document.querySelector(selectors.nextButton);
  213. if (btn?.style.cursor !== 'not-allowed') {
  214. clearInterval(cooldownInterval);
  215. btn.click();
  216. updateStatus("🟢 Clicked Start.");
  217. setTimeout(() => window.close(), 1000);
  218. }
  219. }, ms + 1000);
  220. } else {
  221. nextBtn.click();
  222. updateStatus("🟢 Clicked Start.");
  223. setTimeout(() => window.close(), 1000);
  224. }
  225. }
  226.  
  227. function handleProgressCheck() {
  228. if (scriptPaused) return;
  229.  
  230. const progress = document.querySelector(selectors.progressText);
  231. if (!progress) return console.log("❌ Progress not found.");
  232.  
  233. const match = progress.textContent.match(/(\d+)\s*\/\s*(\d+)/);
  234. if (!match) return console.log("❌ Invalid progress format.");
  235.  
  236. const current = parseInt(match[1], 10);
  237. const total = parseInt(match[2], 10);
  238.  
  239. updateStatus(`🔄 Progress: ${current}/${total}`);
  240.  
  241. if (current >= total) {
  242. const addBtn = document.querySelector(selectors.addTimeButton);
  243. if (addBtn && !addBtn.classList.contains('disabled')) {
  244. addBtn.click();
  245. updateStatus("🟢 Clicked +12H.");
  246. return;
  247. }
  248.  
  249. const timeLeft = document.querySelector(selectors.keyTimeLeft);
  250. const ms = timeLeft ? parseTimeToMs(timeLeft.textContent.trim()) : 0;
  251. if (ms > 12 * 60 * 60 * 1000) {
  252. updateStatus("🕒 Max time. Retry in 12h.");
  253. setTimeout(handleProgressCheck, 12 * 60 * 60 * 1000 + 1000);
  254. return;
  255. }
  256.  
  257. const newKey = document.querySelector(selectors.newKeyButton);
  258. if (newKey && !newKey.disabled) {
  259. newKey.click();
  260. updateStatus("🟢 Clicked new key.");
  261. }
  262. } else {
  263. handleCooldownAndClickStart();
  264. }
  265. }
  266.  
  267.  
  268. function checkCaptchaAndProceed() {
  269. if (scriptPaused) return;
  270.  
  271. const check = document.querySelector(selectors.captchaCheckText);
  272. if (check?.textContent.includes("Checking Your Browser")) {
  273. updateStatus("⏳ CAPTCHA detected...");
  274. setTimeout(checkCaptchaAndProceed, 3000);
  275. } else {
  276. updateStatus("🟢 Proceeding.");
  277. setTimeout(handleProgressCheck, 1000);
  278. }
  279. }
  280.  
  281. function injectUI() {
  282. const style = document.createElement('style');
  283. style.textContent = `
  284. #luarmor-status-box {
  285. position: fixed;
  286. top: 10px;
  287. left: 10px;
  288. background: rgba(0,0,0,0.85);
  289. color: #0f0;
  290. padding: 12px 16px;
  291. border-radius: 10px;
  292. font-family: monospace;
  293. font-size: 14px;
  294. z-index: 9999;
  295. box-shadow: 0 0 12px rgba(0,255,0,0.5);
  296. transition: opacity 0.5s ease;
  297. max-width: 320px;
  298. }
  299. #luarmor-logo {
  300. position: fixed;
  301. bottom: 10px;
  302. right: 10px;
  303. width: 50px;
  304. height: 50px;
  305. background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Green_check.svg/1024px-Green_check.svg.png') no-repeat center;
  306. background-size: contain;
  307. opacity: 0.7;
  308. z-index: 9998;
  309. }
  310. #luarmor-status-box .extra {
  311. margin-top: 8px;
  312. font-size: 12px;
  313. color: #aaa;
  314. }
  315. #luarmor-status-box .extra strong {
  316. color: #0f0;
  317. }
  318. `;
  319. document.head.appendChild(style);
  320.  
  321. const box = document.createElement('div');
  322. box.id = 'luarmor-status-box';
  323. box.innerHTML = `
  324. <div id="luarmor-status-text">🚀 Script initialized</div>
  325. <button id="luarmor-pause-btn" style="margin-top: 8px; background:#222; color:#0f0; border:1px solid #0f0; padding:4px 8px; border-radius:6px; cursor:pointer;">
  326. ⏸️ Pause Script
  327. </button>
  328. <div class="extra">
  329. 🔐 Key: <strong id="luarmor-key">loading...</strong><br>
  330. ⏱️ Time Left: <strong id="luarmor-timeleft">loading...</strong><br>
  331. Blacklist: <strong id="luarmor-blacklist">None</strong><br>
  332. 🕒 Cooldown: <strong id="luarmor-cooldown">None</strong>
  333. </div>
  334. `;
  335.  
  336. document.body.appendChild(box);
  337.  
  338. const pauseBtn = document.getElementById('luarmor-pause-btn');
  339. pauseBtn.addEventListener('click', () => {
  340. scriptPaused = !scriptPaused;
  341. pauseBtn.textContent = scriptPaused ? '▶️ Resume Script' : '⏸️ Pause Script';
  342. updateStatus(scriptPaused ? '⏸️ Script paused by user.' : '▶️ Script resumed.');
  343. if (!scriptPaused) checkCaptchaAndProceed();
  344. });
  345.  
  346. const logo = document.createElement('div');
  347. logo.id = 'luarmor-logo';
  348. document.body.appendChild(logo);
  349. }
  350.  
  351. window.addEventListener("load", () => {
  352. if (isInPopupWindow()) {
  353. window.name = 'luarmor_popup';
  354. console.log("✅ Running in popup.");
  355. flashTitle("🚀 Script Started!");
  356. injectUI();
  357. if (!checkBlacklist()) checkCaptchaAndProceed();
  358. setInterval(updateUITimers, 1000);
  359. } else {
  360. if (!window.popupOpenedOnce) {
  361. const popup = window.open(window.location.href, '_blank', 'width=500,height=600');
  362. if (popup) {
  363. popup.name = 'luarmor_popup';
  364. window.popupOpenedOnce = true;
  365. setTimeout(() => window.close(), 500);
  366. } else {
  367. console.log("❌ Failed to open popup.");
  368. alert("Popup failed to open. Please try adding the following to your adblocker whitelist:\n\nads.luarmor.net/get_key\n\nOr try the rule:\n@@||ads.luarmor.net/get_key$popup,domain=ads.luarmor.net");
  369. }
  370. }
  371. }
  372. });
  373. })();