gaianet

空投 - 实时重定向到chat页面

  1. // ==UserScript==
  2. // @name gaianet
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.6
  5. // @description 空投 - 实时重定向到chat页面
  6. // @author 开启数字空投财富的发掘之旅
  7. // @match https://www.gaianet.ai/*
  8. // ==/UserScript==
  9.  
  10. (function() {
  11. const targetUrl = 'https://www.gaianet.ai/chat';
  12.  
  13. // 日志函数
  14. function log(message) {
  15. console.log(`[GaiaNet Chat AutoClicker] ${message}`);
  16. }
  17.  
  18. // 实时监测 URL 变化并重定向
  19. function checkAndRedirect() {
  20. if (window.location.hostname === 'www.gaianet.ai') {
  21. if (window.location.href !== targetUrl) {
  22. log(`当前页面不是目标页面,正在重定向到: ${targetUrl}`);
  23. window.location.href = targetUrl;
  24. return false;
  25. }
  26. return true;
  27. } else {
  28. log('不在 www.gaianet.ai 域名下,脚本停止执行');
  29. return false;
  30. }
  31. }
  32.  
  33. // 使用 MutationObserver 实时监测页面变化
  34. function setupUrlWatcher() {
  35. let lastUrl = window.location.href;
  36.  
  37. // 检查 History API 变化
  38. window.addEventListener('popstate', () => {
  39. if (!checkAndRedirect()) {
  40. return;
  41. }
  42. });
  43.  
  44. // 监测页面 DOM 变化,可能包含 SPA 路由变化
  45. const observer = new MutationObserver(() => {
  46. if (window.location.href !== lastUrl) {
  47. lastUrl = window.location.href;
  48. if (!checkAndRedirect()) {
  49. return;
  50. }
  51. }
  52. });
  53.  
  54. observer.observe(document.body, {
  55. childList: true,
  56. subtree: true
  57. });
  58.  
  59. // 初始检查
  60. checkAndRedirect();
  61. }
  62.  
  63. // 以下是原有的工具函数,未作改动
  64. function getElementByXPath(path) {
  65. try {
  66. const element = document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  67. return element;
  68. } catch (error) {
  69. log(`[调试] XPath错误: ${path} - ${error.message}`);
  70. return null;
  71. }
  72. }
  73.  
  74. function isElementClickable(element) {
  75. if (!element) {
  76. log('[调试] 元素不存在');
  77. return false;
  78. }
  79. try {
  80. const style = window.getComputedStyle(element);
  81. const clickable = style.display !== 'none' &&
  82. style.visibility !== 'hidden' &&
  83. style.opacity !== '0' &&
  84. !element.disabled;
  85. log('[调试] 元素样式 - display:', style.display || '未知',
  86. 'visibility:', style.visibility || '未知',
  87. 'opacity:', style.opacity || '未知',
  88. 'disabled:', element.disabled || '未知');
  89. log('[调试] 元素可点击:', clickable);
  90. return clickable;
  91. } catch (error) {
  92. log('[调试] 检查元素可点击性时出错:', error.message);
  93. return false;
  94. }
  95. }
  96.  
  97. async function getRandomElementFromXPathRange(basePath, startIdx, endIdx, timeout = 30000) {
  98. const maxAttempts = 3;
  99. for (let attempt = 0; attempt < maxAttempts; attempt++) {
  100. const index = Math.floor(Math.random() * (endIdx - startIdx + 1)) + startIdx;
  101. const path = basePath.replace(/\[1~[0-9]+\]$/, `[${index}]`);
  102. log(`[调试] 尝试 ${attempt + 1}/${maxAttempts} - 选择元素,XPath: ${path}`);
  103. const startTime = Date.now();
  104. while (Date.now() - startTime < timeout) {
  105. const element = getElementByXPath(path);
  106. if (element && isElementClickable(element)) {
  107. log(`[调试] 找到可点击元素,XPath: ${path}`);
  108. return element;
  109. }
  110. await sleep(500);
  111. }
  112. log(`[调试] 未找到可点击元素,XPath: ${path}`);
  113. }
  114. return null;
  115. }
  116.  
  117. async function waitForElementWithText(identifier, text = '', isXPath = false, timeout = 30000, infiniteWait = false) {
  118. log(`[调试] 等待元素: ${identifier}${text ? ` 包含文本 "${text}"` : ''}${infiniteWait ? '(无限等待)' : ''}`);
  119. const startTime = Date.now();
  120. while (infiniteWait || (Date.now() - startTime < timeout)) {
  121. let element = isXPath ? getElementByXPath(identifier) : document.querySelector(identifier);
  122. if (element && isElementClickable(element)) {
  123. const elementText = element.textContent.trim().toUpperCase();
  124. if (!text || elementText === text.toUpperCase()) {
  125. log('[调试] 元素已找到:', element.outerHTML);
  126. return element;
  127. }
  128. }
  129. await sleep(500);
  130. }
  131. log('[调试] 等待超时,未找到匹配文本的可点击元素');
  132. return null;
  133. }
  134.  
  135. function simulateClick(element) {
  136. try {
  137. const event = new MouseEvent('click', {
  138. bubbles: true,
  139. cancelable: true,
  140. view: window
  141. });
  142. element.dispatchEvent(event);
  143. log('[调试] 已模拟点击事件');
  144. return true;
  145. } catch (error) {
  146. log('[调试] 模拟点击失败:', error.message);
  147. return false;
  148. }
  149. }
  150.  
  151. function getRandomDelay() {
  152. return Math.floor(Math.random() * (3000 - 1000 + 1)) + 1000;
  153. }
  154.  
  155. function sleep(ms) {
  156. return new Promise(resolve => setTimeout(resolve, ms));
  157. }
  158.  
  159. // 实时监测元素0并点击,统计点击次数,添加超时恢复
  160. let element0ClickCount = 0;
  161. let pauseMainLoop = false;
  162. async function monitorElement0() {
  163. const element0XPath = '/html/body/div[2]/div[3]/div/div[2]/div/button';
  164. log('[Element0] 开始实时监测元素0');
  165. while (true) {
  166. const element0 = getElementByXPath(element0XPath);
  167. if (element0 && isElementClickable(element0)) {
  168. element0.click();
  169. element0ClickCount++;
  170. log(`[Element0] 元素0已点击,第 ${element0ClickCount} 次:`, element0.outerHTML);
  171.  
  172. if (element0ClickCount > 20) {
  173. log('[Element0] 点击次数超过20次,暂停主循环并执行额外点击');
  174. pauseMainLoop = true;
  175.  
  176. const timeoutPromise = new Promise(resolve => setTimeout(() => {
  177. log('[Element0] 额外点击超时(10秒),强制恢复主循环');
  178. pauseMainLoop = false;
  179. element0ClickCount = 0;
  180. resolve(false);
  181. }, 10000));
  182.  
  183. const extraClickPromise = (async () => {
  184. const extraElement1 = await waitForElementWithText('#nav > div.hidden.lg\\:flex.flex-1.flex-crossCenter.justify-end.wow.animate__.animate__fadeIn > div.flex-crossCenter.gap-6.xl\\:gap-8 > a:nth-child(4)', '', false, 5000);
  185. if (extraElement1) {
  186. extraElement1.click();
  187. log('[Element0] 额外元素1已点击:', extraElement1.outerHTML);
  188. }
  189. await sleep(getRandomDelay());
  190.  
  191. const extraElement2 = await waitForElementWithText('#nav > div.hidden.lg\\:flex.flex-1.flex-crossCenter.justify-end.wow.animate__.animate__fadeIn.animated > div.flex-crossCenter.gap-6.xl\\:gap-8 > a:nth-child(6)', '', false, 5000);
  192. if (extraElement2) {
  193. extraElement2.click();
  194. log('[Element0] 额外元素2已点击:', extraElement2.outerHTML);
  195. }
  196.  
  197. element0ClickCount = 0;
  198. pauseMainLoop = false;
  199. log('[Element0] 额外点击完成,恢复主循环');
  200. return true;
  201. })();
  202.  
  203. await Promise.race([extraClickPromise, timeoutPromise]);
  204. }
  205. await sleep(1000);
  206. }
  207. await sleep(500);
  208. }
  209. }
  210.  
  211. let shouldJumpToNextCycle = false;
  212. function startElementCheck() {
  213. setInterval(async () => {
  214. try {
  215. const checkElementSelector = '#__next > div > div > div.gaia-container.pt-12.md\\:pt-20.pb-\\[96px\\].md\\:pb-\\[150px\\] > div > div.flex-1 > div.MuiTableContainer-root.min-h-\\[380px\\].overflow-auto.hiddenScrollBar.css-kge0eu > table > thead > tr > th:nth-child(3)';
  216. const checkElement = document.querySelector(checkElementSelector);
  217. if (checkElement) {
  218. log('[ElementCheck] 检测到特定元素:', checkElement.outerHTML);
  219. const extraElement2 = await waitForElementWithText('#nav > div.hidden.lg\\:flex.flex-1.flex-crossCenter.justify-end.wow.animate__.animate__fadeIn.animated > div.flex-crossCenter.gap-6.xl\\:gap-8 > a:nth-child(6)', '', false, 5000);
  220. if (extraElement2) {
  221. extraElement2.click();
  222. log('[ElementCheck] 额外元素2已点击,准备跳到下次循环:', extraElement2.outerHTML);
  223. shouldJumpToNextCycle = true;
  224. }
  225. }
  226. } catch (error) {
  227. log('[ElementCheck] 检测特定元素时出错:', error.message);
  228. }
  229. }, 20000);
  230. }
  231.  
  232. async function performClickSequence(cycle) {
  233. log(`[Cycle ${cycle}/300] 开始执行`);
  234.  
  235. while (pauseMainLoop) {
  236. log(`[Cycle ${cycle}/300] 主循环已暂停,等待恢复`);
  237. await sleep(1000);
  238. }
  239.  
  240. const element1XPath = '//*[@id="__next"]/div/div/div[2]/div[3]/div/div/div/div[1]/div/div[2]';
  241. const element1 = await waitForElementWithText(element1XPath, '', true);
  242. if (element1) {
  243. element1.click();
  244. log('元素1已点击');
  245. } else {
  246. log('未找到元素1或不可点击,跳过此循环');
  247. return false;
  248. }
  249. await sleep(getRandomDelay());
  250.  
  251. const element2BaseXPath = '/html/body/div[2]/div[3]/div/div/div[3]/div[2]/div/div/div[1~32]';
  252. const element2Initial = await waitForElementWithText(element2BaseXPath.replace(/\[1~32\]$/, '[1]'), '', true, 30000, true);
  253. if (element2Initial) {
  254. const randomElement2 = await getRandomElementFromXPathRange(element2BaseXPath, 1, 32, 30000);
  255. if (randomElement2) {
  256. randomElement2.click();
  257. log('随机选择的元素2已点击:', randomElement2.outerHTML);
  258. } else {
  259. log('未找到可点击的随机元素2,跳过此循环');
  260. return false;
  261. }
  262. } else {
  263. log('未找到元素2基础实例,跳过此循环');
  264. return false;
  265. }
  266. await sleep(getRandomDelay());
  267.  
  268. const element3XPath = '//*[@id="__next"]/div/div/div[2]/div[3]/div/div/div/div[2]/div/button';
  269. const element3 = await waitForElementWithText(element3XPath, '', true, 5000);
  270. if (element3) {
  271. element3.click();
  272. log('元素3已点击');
  273. } else {
  274. log('未找到元素3或5秒内不可点击,继续下一步');
  275. }
  276. await sleep(getRandomDelay());
  277.  
  278. const element4BaseXPath = '//*[@id="__next"]/div/div/div[2]/div[3]/div/div/div/div[2]/div/div[1]/div/div[1~4]';
  279. const element4 = await getRandomElementFromXPathRange(element4BaseXPath, 1, 4, 5000);
  280. if (element4) {
  281. if (isElementClickable(element4)) {
  282. element4.click();
  283. log('随机选择的元素4已点击:', element4.outerHTML);
  284. } else {
  285. log('元素4不可点击,跳过此循环');
  286. return false;
  287. }
  288. } else {
  289. log('未找到元素4或5秒内不可点击,执行元素6和7后跳到下个循环');
  290. const element6XPath = '//*[@id="__next"]/div/div/div[2]/div[1]/div/div[3]/button[1]';
  291. const element6 = await waitForElementWithText(element6XPath, '', true);
  292. if (element6) {
  293. element6.click();
  294. log('元素6已点击(元素4超时回退)');
  295. }
  296. await sleep(getRandomDelay());
  297.  
  298. const element7Selector = 'svg.tabler-icon.tabler-icon-check';
  299. const element7 = await waitForElementWithText(element7Selector, '');
  300. if (element7) {
  301. simulateClick(element7);
  302. log('元素7已点击(元素4超时回退):', element7.outerHTML);
  303. }
  304. return false;
  305. }
  306. await sleep(getRandomDelay());
  307.  
  308. const element5Selector = 'button.absolute.min-w-\\[94px\\].h-10.bg-primaryOnyx.rounded-\\[8px\\]';
  309. const element5 = await waitForElementWithText(element5Selector, 'SEND', false, 60000);
  310. if (element5) {
  311. log('元素5已出现且文本为"SEND"');
  312. } else {
  313. log('1分钟内未出现文本为"SEND"的元素5,尝试点击文本为"STOP"的元素');
  314. const element5Stop = await waitForElementWithText(element5Selector, 'STOP', false, 5000);
  315. if (element5Stop) {
  316. element5Stop.click();
  317. log('元素5(文本为"STOP")已点击(超时回退)');
  318. }
  319. }
  320. await sleep(getRandomDelay());
  321.  
  322. const element6XPath = '//*[@id="__next"]/div/div/div[2]/div[1]/div/div[3]/button[1]';
  323. const element6 = await waitForElementWithText(element6XPath, '', true);
  324. if (element6) {
  325. element6.click();
  326. log('元素6已点击');
  327. } else {
  328. log('未找到元素6或不可点击,跳过此循环');
  329. return false;
  330. }
  331. await sleep(getRandomDelay());
  332.  
  333. const element7Selector = 'svg.tabler-icon.tabler-icon-check';
  334. const element7 = await waitForElementWithText(element7Selector, '');
  335. if (element7) {
  336. simulateClick(element7);
  337. log('元素7已点击:', element7.outerHTML);
  338. } else {
  339. log('未找到元素7或不可点击,跳过此循环');
  340. return false;
  341. }
  342.  
  343. log(`[Cycle ${cycle}/300] 完成`);
  344. return true;
  345. }
  346.  
  347. // 主流程
  348. async function mainFlow() {
  349. log('脚本开始执行 - 当前页面: https://www.gaianet.ai/chat');
  350. const maxCycles = 300;
  351.  
  352. setTimeout(monitorElement0, 0);
  353. startElementCheck();
  354.  
  355. for (let cycle = 1; cycle <= maxCycles; cycle++) {
  356. try {
  357. const success = await performClickSequence(cycle);
  358. if (!success) {
  359. log(`循环 ${cycle} 未完成,继续下一个循环`);
  360. }
  361. if (shouldJumpToNextCycle) {
  362. log(`[Cycle ${cycle}/300] 因额外元素2点击,跳到下次循环`);
  363. shouldJumpToNextCycle = false;
  364. continue;
  365. }
  366. if (cycle < maxCycles) {
  367. log('等待3秒后开始下一次循环');
  368. await sleep(3000);
  369. }
  370. } catch (error) {
  371. log(`循环 ${cycle} 执行过程中发生错误: ${error.message}`);
  372. }
  373. }
  374. }
  375.  
  376. // 页面加载后启动
  377. window.addEventListener('load', async function() {
  378. setupUrlWatcher(); // 启动实时监测
  379. if (window.location.href === targetUrl) {
  380. log('页面加载完成,位于目标页面,启动主流程');
  381. await sleep(2000);
  382. mainFlow();
  383. }
  384. });
  385. })();
  386.  
  387.