Auto Click Enabled Button

探测并自动点击变为可用状态的按钮

目前为 2024-06-07 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Auto Click Enabled Button
  3. // @name:zh-CN 自动点击启用按钮
  4. // @name:en Auto Click Enabled Button
  5. // @name:hi ऑटो क्लिक सक्षम बटन
  6. // @name:fr Bouton de clic automatique activé
  7. // @name:ar زر النقر التلقائي عند التمكين
  8. // @name:bg Автоматично кликване на активиран бутон
  9. // @name:ru Автоматическое нажатие на активированные кнопки
  10. // @name:pt-BR Botão de Clique Automático Habilitado
  11. // @name:id Tombol Klik Otomatis yang Diaktifkan
  12. // @name:zh-TW 自動點擊啟用按鈕
  13. // @namespace http://tampermonkey.net/
  14. // @version 2.6
  15. // @description 探测并自动点击变为可用状态的按钮
  16. // @description:en This script detects and automatically clicks buttons that become enabled. It has been tested and works correctly on the https://app.runwayml.com/* page.
  17. // @description:zh-CN 这个脚本可以探测并自动点击变为可用状态的按钮。该脚本于 https://app.runwayml.com/* 页面测试正常运行。
  18. // @description:hi यह स्क्रिप्ट बटन को पहचानती है और स्वचालित रूप से क्लिक करती है जो सक्षम हो जाते हैं। इसका परीक्षण https://app.runwayml.com/* पृष्ठ पर किया गया है और यह सही ढंग से काम करता है।
  19. // @description:fr Ce script détecte et clique automatiquement sur les boutons qui deviennent activés. Il a été testé et fonctionne correctement sur la page https://app.runwayml.com/*.
  20. // @description:ar يكتشف هذا البرنامج النصي الأزرار التي تصبح ممكّنة وينقر عليها تلقائيًا. تم اختباره ويعمل بشكل صحيح على صفحة https://app.runwayml.com/*.
  21. // @description:bg Този скрипт открива и автоматично кликва върху бутони, които стават активни. Тестван е и работи правилно на страницата https://app.runwayml.com/*.
  22. // @description:ru Этот скрипт обнаруживает и автоматически нажимает кнопки, которые становятся активными. Он был протестирован и работает правильно на странице https://app.runwayml.com/*.
  23. // @description:pt-BR Este script detecta e clica automaticamente em botões que se tornam habilitados. Ele foi testado e funciona corretamente na página https://app.runwayml.com/*.
  24. // @description:id Skrip ini mendeteksi dan mengklik tombol yang menjadi aktif secara otomatis. Skrip ini telah diuji dan berfungsi dengan baik di halaman https://app.runwayml.com/*.
  25. // @description:zh-TW 此腳本可以檢測並自動點擊變為可用狀態的按鈕。經測試,該腳本在 https://app.runwayml.com/* 頁面上正常運行。
  26. // @author HDR10
  27. // @match https://*/*
  28. // @grant none
  29. // @license Apache License 2.0
  30. // ==/UserScript==
  31.  
  32. (function() {
  33. 'use strict';
  34.  
  35. // 多语言支持的按钮文本
  36. const texts = {
  37. en: {
  38. title: "Auto Click Enabled Button",
  39. statusStopped: "Auto-clicking stopped",
  40. statusStarted: "Auto-clicking enabled",
  41. start: "Enable",
  42. stop: "Stop",
  43. clickLimit: "Stop after clicking:",
  44. clearLog: "Clear log",
  45. minimize: "Minimize"
  46. },
  47. "zh-CN": {
  48. title: "自动点击启用按钮",
  49. statusStopped: "自动点击已停止",
  50. statusStarted: "自动点击已启用",
  51. start: "启用",
  52. stop: "停止",
  53. clickLimit: "点击几次后停止:",
  54. clearLog: "清除log",
  55. minimize: "最小化"
  56. },
  57. hi: {
  58. title: "ऑटो क्लिक सक्षम बटन",
  59. statusStopped: "स्वचालित क्लिक बंद हो गया",
  60. statusStarted: "स्वचालित क्लिक सक्षम",
  61. start: "सक्षम करें",
  62. stop: "रोकें",
  63. clickLimit: "क्लिक करने के बाद रोकें:",
  64. clearLog: "लॉग साफ़ करें",
  65. minimize: "छोटा करें"
  66. },
  67. fr: {
  68. title: "Bouton de clic automatique activé",
  69. statusStopped: "Clic automatique arrêté",
  70. statusStarted: "Clic automatique activé",
  71. start: "Activer",
  72. stop: "Arrêter",
  73. clickLimit: "Arrêter après avoir cliqué:",
  74. clearLog: "Effacer le journal",
  75. minimize: "Minimiser"
  76. },
  77. ar: {
  78. title: "زر النقر التلقائي عند التمكين",
  79. statusStopped: "توقف النقر التلقائي",
  80. statusStarted: "تمكين النقر التلقائي",
  81. start: "تمكين",
  82. stop: "إيقاف",
  83. clickLimit: "توقف بعد النقر:",
  84. clearLog: "مسح السجل",
  85. minimize: "تصغير"
  86. },
  87. bg: {
  88. title: "Автоматично кликване на активиран бутон",
  89. statusStopped: "Автоматичното кликване е спряно",
  90. statusStarted: "Автоматичното кликване е активирано",
  91. start: "Активирай",
  92. stop: "Спри",
  93. clickLimit: "Спри след кликване:",
  94. clearLog: "Изчисти дневника",
  95. minimize: "Минимизирай"
  96. },
  97. ru: {
  98. title: "Автоматическое нажатие на активированные кнопки",
  99. statusStopped: "Автоклик остановлен",
  100. statusStarted: "Автоклик активирован",
  101. start: "Активировать",
  102. stop: "Остановить",
  103. clickLimit: "Остановить после кликов:",
  104. clearLog: "Очистить журнал",
  105. minimize: "Свернуть"
  106. },
  107. "pt-BR": {
  108. title: "Botão de Clique Automático Habilitado",
  109. statusStopped: "Clique automático parado",
  110. statusStarted: "Clique automático habilitado",
  111. start: "Habilitar",
  112. stop: "Parar",
  113. clickLimit: "Parar após clicar:",
  114. clearLog: "Limpar log",
  115. minimize: "Minimizar"
  116. },
  117. id: {
  118. title: "Tombol Klik Otomatis yang Diaktifkan",
  119. statusStopped: "Klik otomatis dihentikan",
  120. statusStarted: "Klik otomatis diaktifkan",
  121. start: "Aktifkan",
  122. stop: "Hentikan",
  123. clickLimit: "Berhenti setelah mengklik:",
  124. clearLog: "Hapus log",
  125. minimize: "Minimalkan"
  126. },
  127. "zh-TW": {
  128. title: "自動點擊啟用按鈕",
  129. statusStopped: "自動點擊已停止",
  130. statusStarted: "自動點擊已啟用",
  131. start: "啟用",
  132. stop: "停止",
  133. clickLimit: "點擊幾次後停止:",
  134. clearLog: "清除log",
  135. minimize: "最小化"
  136. }
  137. };
  138.  
  139. // 获取浏览器语言,默认为英文
  140. const lang = navigator.language || navigator.userLanguage;
  141. const userLang = lang.startsWith('zh') ? (lang === 'zh-TW' ? 'zh-TW' : 'zh-CN') : (texts[lang] ? lang : 'en');
  142. const t = texts[userLang];
  143.  
  144. // 创建浮窗
  145. const floatWindow = document.createElement('div');
  146. floatWindow.style.position = 'fixed';
  147. floatWindow.style.bottom = '10px';
  148. floatWindow.style.right = '10px';
  149. floatWindow.style.width = '400px';
  150. floatWindow.style.height = '250px';
  151. floatWindow.style.backgroundColor = 'white';
  152. floatWindow.style.border = '1px solid black';
  153. floatWindow.style.color = 'black';
  154. floatWindow.style.padding = '10px';
  155. floatWindow.style.overflowY = 'auto';
  156. floatWindow.style.zIndex = '10000';
  157. floatWindow.style.display = 'none'; // 初始状态为最小化
  158. floatWindow.innerHTML = `
  159. <div>
  160. <div id="dragHandle" style="width: 20px; height: 20px; background-color: gray; position: absolute; top: 5px; right: 5px; cursor: move;"></div>
  161. <h3>${t.title}</h3>
  162. <p id="statusLabel">${t.statusStopped}</p>
  163. <button id="startBtn">${t.start}</button>
  164. <button id="stopBtn">${t.stop}</button>
  165. <label for="clickLimit">${t.clickLimit}</label>
  166. <input type="number" id="clickLimit" value="0" min="0" style="width: 50px;">
  167. <div id="logContainer" style="height: 100px; background-color: white; border: 1px solid black; overflow-y: auto;"></div>
  168. <button id="clearLogBtn">${t.clearLog}</button>
  169. <button id="minimizeBtn">${t.minimize}</button>
  170. </div>
  171. `;
  172. document.body.appendChild(floatWindow);
  173.  
  174. // 创建最小化图标
  175. const minimizeIcon = document.createElement('div');
  176. minimizeIcon.style.position = 'fixed';
  177. minimizeIcon.style.bottom = '10px';
  178. minimizeIcon.style.right = '10px';
  179. minimizeIcon.style.width = '40px';
  180. minimizeIcon.style.height = '40px';
  181. minimizeIcon.style.backgroundColor = 'white';
  182. minimizeIcon.style.border = '1px solid black';
  183. minimizeIcon.style.borderRadius = '50%';
  184. minimizeIcon.style.display = 'flex';
  185. minimizeIcon.style.alignItems = 'center';
  186. minimizeIcon.style.justifyContent = 'center';
  187. minimizeIcon.style.cursor = 'pointer';
  188. minimizeIcon.style.zIndex = '10000';
  189. minimizeIcon.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8 0-4.41 3.59-8 8-8 4.41 0 8 3.59 8 8 0 4.41-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z"/></svg>`;
  190. document.body.appendChild(minimizeIcon);
  191.  
  192. let observer;
  193. let autoClickEnabled = false;
  194. let clickCount = 0;
  195. let clickLimit = 0;
  196.  
  197. document.getElementById('startBtn').addEventListener('click', function() {
  198. autoClickEnabled = true;
  199. clickCount = 0;
  200. clickLimit = parseInt(document.getElementById('clickLimit').value, 10);
  201. document.getElementById('statusLabel').textContent = t.statusStarted;
  202. document.getElementById('statusLabel').style.color = 'green';
  203. minimizeIcon.style.backgroundColor = 'green';
  204. startObserving();
  205. });
  206.  
  207. document.getElementById('stopBtn').addEventListener('click', function() {
  208. autoClickEnabled = false;
  209. document.getElementById('statusLabel').textContent = t.statusStopped;
  210. document.getElementById('statusLabel').style.color = 'black';
  211. minimizeIcon.style.backgroundColor = 'white';
  212. stopObserving();
  213. });
  214.  
  215. document.getElementById('clearLogBtn').addEventListener('click', function() {
  216. document.getElementById('logContainer').innerHTML = '';
  217. });
  218.  
  219. document.getElementById('minimizeBtn').addEventListener('click', function() {
  220. floatWindow.style.display = 'none';
  221. minimizeIcon.style.display = 'flex';
  222. });
  223.  
  224. minimizeIcon.addEventListener('click', function() {
  225. floatWindow.style.display = 'block';
  226. minimizeIcon.style.display = 'none';
  227. });
  228.  
  229. function startObserving() {
  230. const config = { attributes: true, childList: true, subtree: true };
  231. observer = new MutationObserver(mutationsList => {
  232. for (let mutation of mutationsList) {
  233. if (mutation.type === 'attributes' && mutation.attributeName === 'disabled') {
  234. const target = mutation.target;
  235. if (target.tagName.toLowerCase() === 'button' && !target.disabled && autoClickEnabled) {
  236. target.click();
  237. clickCount++;
  238. logClick(target);
  239. if (clickLimit > 0 && clickCount >= clickLimit) {
  240. autoClickEnabled = false;
  241. document.getElementById('statusLabel').textContent = t.statusStopped;
  242. document.getElementById('statusLabel').style.color = 'black';
  243. minimizeIcon.style.backgroundColor = 'white';
  244. stopObserving();
  245. }
  246. }
  247. }
  248. }
  249. });
  250.  
  251. observer.observe(document.body, config);
  252. }
  253.  
  254. function stopObserving() {
  255. if (observer) {
  256. observer.disconnect();
  257. observer = null;
  258. }
  259. }
  260.  
  261. function logClick(target) {
  262. const logContainer = document.getElementById('logContainer');
  263. const timestamp = new Date().toLocaleTimeString();
  264. const logEntry = document.createElement('div');
  265. logEntry.textContent = `${timestamp} - 点击了按钮: ${target.innerText || target.id || 'Unknown'}`;
  266. logContainer.appendChild(logEntry);
  267.  
  268. // 保持日志最多显示10行
  269. while (logContainer.children.length > 10) {
  270. logContainer.removeChild(logContainer.firstChild);
  271. }
  272.  
  273. // 自动滚动到最新日志
  274. logContainer.scrollTop = logContainer.scrollHeight;
  275. }
  276.  
  277. // 拖动浮窗功能
  278. const dragHandle = document.getElementById('dragHandle');
  279. let isDragging = false;
  280. let startX, startY, initialX, initialY;
  281.  
  282. dragHandle.addEventListener('mousedown', function(e) {
  283. isDragging = true;
  284. startX = e.clientX;
  285. startY = e.clientY;
  286. initialX = floatWindow.offsetLeft;
  287. initialY = floatWindow.offsetTop;
  288. document.addEventListener('mousemove', onMouseMove);
  289. document.addEventListener('mouseup', onMouseUp);
  290. });
  291.  
  292. function onMouseMove(e) {
  293. if (isDragging) {
  294. const dx = e.clientX - startX;
  295. const dy = e.clientY - startY;
  296. floatWindow.style.left = initialX + dx + 'px';
  297. floatWindow.style.top = initialY + dy + 'px';
  298. }
  299. }
  300.  
  301. function onMouseUp() {
  302. isDragging = false;
  303. document.removeEventListener('mousemove', onMouseMove);
  304. document.removeEventListener('mouseup', onMouseUp);
  305. }
  306. })();