Civitai Ultra Fast Auto Clicker

스크롤 최적화된 Civitai 자동 클릭 스크립트 (10초 이내 완료)

  1. // ==UserScript==
  2. // @name Civitai Ultra Fast Auto Clicker
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.8
  5. // @description 스크롤 최적화된 Civitai 자동 클릭 스크립트 (10초 이내 완료)
  6. // @author YuAru
  7. // @match https://civitai.com/images
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. let cachedButtons = new Set();
  16. let isProcessing = false;
  17.  
  18. const createButton = () => {
  19. const button = document.createElement('button');
  20. button.innerText = '터보 클릭';
  21. button.style.cssText = `
  22. padding: 5px 10px;
  23. background-color: #ff0000;
  24. color: white;
  25. border: none;
  26. border-radius: 4px;
  27. cursor: pointer;
  28. font-size: 12px;
  29. font-weight: bold;
  30. `;
  31. return button;
  32. };
  33.  
  34. const rapidClickAllButtons = async () => {
  35. const currentButtons = Array.from(document.querySelectorAll('button'));
  36. let clickCount = 0;
  37.  
  38. for (let i = 0; i < currentButtons.length; i += 15) {
  39. for (let j = 0; j < 15; j++) {
  40. const button = currentButtons[i + j];
  41. if (button && button.closest('div.flex.items-center.justify-center.gap-1.justify-between.p-2')
  42. && !cachedButtons.has(button)) {
  43. try {
  44. button.click();
  45. cachedButtons.add(button);
  46. clickCount++;
  47. } catch (error) {
  48. console.error('Button click error:', error);
  49. }
  50. }
  51. }
  52. await new Promise(resolve => setTimeout(resolve, 4)); // 각 열다섯 번의 버튼 클릭 후 대기 시간 0.004초
  53. }
  54.  
  55. return clickCount;
  56. };
  57.  
  58. const performScroll = async () => {
  59. const scrollElement = document.querySelector("#main > div > div > div");
  60. if (!scrollElement) return false;
  61.  
  62. const currentPosition = scrollElement.scrollTop;
  63. const maxScroll = scrollElement.scrollHeight - scrollElement.clientHeight;
  64.  
  65. if (currentPosition >= maxScroll) return false;
  66.  
  67. scrollElement.scrollTo({
  68. top: currentPosition + (scrollElement.clientHeight / 1.5),
  69. behavior: 'smooth'
  70. });
  71.  
  72. await new Promise(resolve => setTimeout(resolve, 100));
  73.  
  74. return true;
  75. };
  76.  
  77. const turboScrollAndClick = async () => {
  78. const totalDuration = 9000;
  79. const startTime = Date.now();
  80. let totalClicks = 0;
  81.  
  82. const processFrame = async () => {
  83. if (Date.now() - startTime < totalDuration) {
  84. const clicks = await rapidClickAllButtons();
  85. totalClicks += clicks;
  86.  
  87. if (clicks > 0) {
  88. console.log(`현재까지 클릭한 버튼 수: ${totalClicks}`);
  89. }
  90.  
  91. if (!await performScroll()) {
  92. await new Promise(resolve => setTimeout(resolve, 100));
  93. }
  94.  
  95. requestAnimationFrame(processFrame);
  96. } else {
  97. console.log(`총 실행 시간: ${Date.now() - startTime}ms`);
  98. console.log(`총 클릭한 버튼 수: ${totalClicks}`);
  99. cleanup();
  100. location.reload();
  101. }
  102. };
  103.  
  104. requestAnimationFrame(processFrame);
  105. };
  106.  
  107. const cleanup = () => {
  108. cachedButtons.clear();
  109.  
  110. // 캐시 삭제 코드 추가
  111. if ('caches' in window) {
  112. caches.keys().then(names => {
  113. for (let name of names) caches.delete(name);
  114. });
  115. }
  116.  
  117. if (window.gc) window.gc();
  118. };
  119.  
  120. window.addEventListener('load', function() {
  121. const panel = document.querySelector("#main > div > div > div > footer > div.relative.flex.h-\\[var\\(--footer-height\\)\\].w-full.items-center.gap-2.overflow-x-auto.bg-gray-0.p-1.px-2.\\@sm\\:gap-3.dark\\:bg-dark-7.border-t.border-gray-3.dark\\:border-dark-4");
  122.  
  123. if (!panel) return;
  124.  
  125. const newButton = createButton();
  126.  
  127. newButton.addEventListener('click', async function() {
  128. if (isProcessing) return;
  129. isProcessing = true;
  130.  
  131. try {
  132. await turboScrollAndClick();
  133. } catch (error) {
  134. console.error('Error:', error);
  135. cleanup();
  136. } finally {
  137. isProcessing = false;
  138. }
  139. });
  140.  
  141. panel.style.display = 'flex';
  142. panel.style.justifyContent = 'center';
  143. panel.appendChild(newButton);
  144. });
  145. })();