币圈KOL劣迹标记 - X(Twitter)

在Twitter/X上标记有劣迹的加密货币KOL,并实时显示其劣迹指数(0-100分)和不良行为记录。整合公共数据和本地自定义功能,帮助用户识别高风险KOL,避免投资陷阱。支持证据查看、数据更新和自定义标记功能。

  1. // ==UserScript==
  2. // @name 币圈KOL劣迹标记 - X(Twitter)
  3. // @namespace http://tampermonkey.net/
  4. // @icon data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB7ElEQVR4Ae1XMZLCMAwUdw0ldJQ8ATpKnkBJByUd8ALyA/gBdJTQUtHS8QT4AaRM5ctmThmfogQ75CYNmhGTbGJr45Vk0yAiQzXaF9VsHwIZAofDgYwxqo9GI/K16/X6cqyxvdVqmdvtZh6PhwmCIHXcw7vdrpFj8ny9XhsYxhe8lwWHw2EycLFYpNh0Ok2w8/nsFHy1WrkE1wnAN5tNMkGv10ux3W6XIab5fD5P3ovldCGrP2Ap4LiW8uRJAcIwe1wpArYU0FJimhQgxaQ9cqX4BZYCgSVmS8HBfRP1JQEsY1xKGSmAcTC+l0QrIWDraicVMBBA4O1265ScpQnAMbkMwphjub1HAI7EkxoDK7n0/gQQGATsCmDMo+z++Hf8E5CjPZ9PiqKIZrMZhWFIl8slxcbjMTWbTTqdTuRrXoz5i2WXRIL+WxWw2+Uml13rnJUT4K9E9nMFaF3SxiojoO1u2rJzl4z3/+oIcHBMLiUp2rDe3ozg+BIYtNee87KjGzLGndPx7JD/0K7xog2Gl30ymaSY1jm9CPhsrXnnBK1zOhHgCWWtF7l2TtA6p3S1E+73exoMBrRcLul4PJKL3e93arfbSUeMA1O/36eYPHU6nWQu7pyaqRlfZnezV05anhSN34va7PPXrHYCP+VaTG3LBV1KAAAAAElFTkSuQmCC
  5. // @version 1.3
  6. // @description 在Twitter/X上标记有劣迹的加密货币KOL,并实时显示其劣迹指数(0-100分)和不良行为记录。整合公共数据和本地自定义功能,帮助用户识别高风险KOL,避免投资陷阱。支持证据查看、数据更新和自定义标记功能。
  7. // @author @mr96_0x0 (TG: @Mr96_me)
  8. // @license GNU General Public License v3.0 or later
  9. // @match https://twitter.com/*
  10. // @match https://x.com/*
  11. // @grant GM_xmlhttpRequest
  12. // @grant GM_setValue
  13. // @grant GM_getValue
  14. // @grant GM_registerMenuCommand
  15. // @connect *
  16. // ==/UserScript==
  17.  
  18. (function() {
  19. 'use strict';
  20.  
  21. const developerInfo = {
  22. twitter: "@mr96_0x0",
  23. telegram: "@Mr96_me"
  24. };
  25.  
  26. const PUBLIC_DATA_URL = "https://gist.githubusercontent.com/Mr96s/b05aa6971cea6407bcb00621b6c20197/raw/cae13b5bc4003a482133a74cee1ea034e4bbc253/kol-data.json";
  27.  
  28. const indexColors = {
  29. 0: { bg: "#e0e0e0", text: "#000000", emoji: "✅" }, // 0-9
  30. 10: { bg: "#ccffcc", text: "#000000", emoji: "🔍" }, // 10-19
  31. 20: { bg: "#99ff99", text: "#000000", emoji: "🔍" }, // 20-29
  32. 30: { bg: "#ffff99", text: "#000000", emoji: "⚠️" }, // 30-39
  33. 40: { bg: "#ffeb3b", text: "#000000", emoji: "⚠️" }, // 40-49
  34. 50: { bg: "#ffcc00", text: "#000000", emoji: "⚠️" }, // 50-59
  35. 60: { bg: "#ff9800", text: "#ffffff", emoji: "🚨" }, // 60-69
  36. 70: { bg: "#ff5722", text: "#ffffff", emoji: "🚨" }, // 70-79
  37. 80: { bg: "#f44336", text: "#ffffff", emoji: "☠️" }, // 80-89
  38. 90: { bg: "#d32f2f", text: "#ffffff", emoji: "☠️" } // 90-100
  39. };
  40.  
  41. function getColorConfig(index) {
  42. const tier = Math.min(Math.floor(index / 10) * 10, 90);
  43. return indexColors[tier] || indexColors[50];
  44. }
  45.  
  46. let badKOLs = {};
  47. let usePublicData = GM_getValue('usePublicData', true);
  48. let useLocalData = GM_getValue('useLocalData', true);
  49.  
  50. function loadData() {
  51. const publicData = GM_getValue('publicData', {});
  52. const localData = GM_getValue('localData', {});
  53.  
  54. badKOLs = {};
  55. if (usePublicData) Object.assign(badKOLs, publicData);
  56. if (useLocalData) Object.assign(badKOLs, localData);
  57.  
  58. checkForKOLs();
  59. }
  60.  
  61. function fetchPublicData() {
  62. if (!usePublicData) return;
  63.  
  64. GM_xmlhttpRequest({
  65. method: "GET",
  66. url: PUBLIC_DATA_URL,
  67. onload: function(response) {
  68. try {
  69. const data = JSON.parse(response.responseText);
  70. GM_setValue('publicData', data);
  71. loadData();
  72. } catch (e) {
  73. console.error("Failed to parse public data:", e);
  74. }
  75. },
  76. onerror: function(error) {
  77. console.error("Failed to fetch public data:", error);
  78. }
  79. });
  80. }
  81.  
  82. const observer = new MutationObserver(checkForKOLs);
  83. observer.observe(document.body, { childList: true, subtree: true });
  84.  
  85. function checkForKOLs() {
  86. const profileHeader = document.querySelector('[data-testid="UserName"]');
  87. if (profileHeader) {
  88. const screenName = document.querySelector('[data-testid="UserName"] div:nth-child(2) div span')?.textContent;
  89. if (screenName && badKOLs[screenName]) {
  90. addWarningBadge(profileHeader, badKOLs[screenName], true, screenName);
  91. }
  92. }
  93.  
  94. document.querySelectorAll('[data-testid="tweet"]').forEach(tweet => {
  95. const authorLink = tweet.querySelector('a[role="link"][tabindex="-1"]');
  96. if (authorLink) {
  97. const author = authorLink.getAttribute('href')?.slice(1);
  98. if (author && badKOLs[author]) {
  99. addWarningBadge(tweet, badKOLs[author], false, author);
  100. }
  101. }
  102. });
  103. }
  104.  
  105. function addWarningBadge(element, kolData, isProfile, accountName) {
  106. if (element.querySelector('.kol-warning-badge')) return;
  107.  
  108. const colorConfig = getColorConfig(kolData.index);
  109. const badgeSize = isProfile ? '16px' : '12px';
  110.  
  111. const badge = document.createElement('div');
  112. badge.className = 'kol-warning-badge';
  113. badge.innerHTML = `
  114. <div style="
  115. background: ${colorConfig.bg};
  116. color: ${colorConfig.text};
  117. padding: 4px 8px;
  118. border-radius: 4px;
  119. font-weight: bold;
  120. display: inline-flex;
  121. align-items: center;
  122. gap: 4px;
  123. margin-left: 8px;
  124. cursor: pointer;
  125. font-size: ${badgeSize};
  126. line-height: 1;
  127. white-space: nowrap;
  128. ">
  129. ${colorConfig.emoji}劣迹指数:${kolData.index}
  130. </div>
  131. `;
  132.  
  133. badge.onclick = (e) => {
  134. e.stopPropagation();
  135. showKolDetails(kolData, accountName, element);
  136. };
  137.  
  138. if (isProfile) {
  139. const nameElement = element.querySelector('div:nth-child(2) div span');
  140. if (nameElement) nameElement.parentNode.appendChild(badge);
  141. } else {
  142. const authorContainer = element.querySelector('[data-testid="User-Name"]');
  143. if (authorContainer) authorContainer.appendChild(badge);
  144. }
  145. }
  146.  
  147. function showKolDetails(kolData, accountName, badgeElement) {
  148. const modal = document.createElement('div');
  149. modal.style.cssText = `
  150. position: fixed; top: 0; left: 0; width: 100%; height: 100%;
  151. background-color: rgba(0,0,0,0.7); display: flex;
  152. justify-content: center; align-items: center; z-index: 9999;
  153. `;
  154.  
  155. const content = document.createElement('div');
  156. content.style.cssText = `
  157. background-color: #15202b; color: #ffffff; padding: 20px;
  158. border-radius: 12px; max-width: 500px; width: 90%;
  159. max-height: 80vh; overflow-y: auto;
  160. `;
  161.  
  162. const colorConfig = getColorConfig(kolData.index);
  163. let displayName = null;
  164.  
  165. const profileNameElement = document.querySelector('[data-testid="UserName"] div:first-child span');
  166. if (badgeElement.closest('[data-testid="UserName"]')) {
  167. displayName = profileNameElement ? profileNameElement.textContent : null;
  168. } else {
  169. const tweetElement = badgeElement.closest('[data-testid="tweet"]');
  170. if (tweetElement) {
  171. const tweetNameElement = tweetElement.querySelector('[data-testid="User-Name"] a div span');
  172. displayName = tweetNameElement ? tweetNameElement.textContent : null;
  173. } else {
  174. displayName = profileNameElement ? profileNameElement.textContent : null;
  175. }
  176. }
  177.  
  178. const finalName = displayName || `@${accountName}`;
  179.  
  180. const title = document.createElement('h2');
  181. title.textContent = `⚠️ ${finalName}】 劣迹指数 (${kolData.index})`;
  182. title.style.cssText = `margin-top: 0; color: ${colorConfig.bg};`;
  183. content.appendChild(title);
  184.  
  185. const recordsTitle = document.createElement('h3');
  186. recordsTitle.textContent = '劣迹记录:';
  187. recordsTitle.style.marginBottom = '8px';
  188. content.appendChild(recordsTitle);
  189.  
  190. const recordsList = document.createElement('ul');
  191. recordsList.style.cssText = 'padding-left: 20px; margin-top: 0;';
  192.  
  193. kolData.records.forEach(record => {
  194. const recordItem = document.createElement('li');
  195. recordItem.style.marginBottom = '12px';
  196.  
  197. const reason = document.createElement('div');
  198. reason.textContent = record.reason;
  199. reason.style.marginBottom = '4px';
  200. recordItem.appendChild(reason);
  201.  
  202. if (record.date && record.date.trim()) {
  203. const date = document.createElement('div');
  204. date.textContent = `时间: ${record.date}`;
  205. date.style.cssText = 'font-size: 0.9em; color: #8899a6; margin-bottom: 4px;';
  206. recordItem.appendChild(date);
  207. }
  208.  
  209. if (record.proof && record.proof.trim()) {
  210. const proofLink = document.createElement('a');
  211. proofLink.href = record.proof;
  212. proofLink.textContent = '查看详情 →';
  213. proofLink.target = '_blank';
  214. proofLink.style.cssText = 'color: #1da1f2; text-decoration: none; font-size: 0.9em;';
  215. recordItem.appendChild(proofLink);
  216. }
  217.  
  218. recordsList.appendChild(recordItem);
  219. });
  220. content.appendChild(recordsList);
  221.  
  222. const feedbackSection = document.createElement('div');
  223. feedbackSection.style.cssText = 'margin-top: 20px; padding-top: 15px; border-top: 1px solid #38444d;';
  224. feedbackSection.innerHTML = `
  225. <h4 style="margin-bottom: 8px;">📢 反馈与申诉</h4>
  226. <p style="margin-bottom: 8px; font-size: 0.9em;">1.🌟欢迎提交线索!共建币圈透明社区</p>
  227. <p style="margin-bottom: 8px; font-size: 0.9em;">2.🗃️数据来源由程序爬取公开信息或用户提交,如您认为标记信息有误,可提交申诉。</p>
  228. <h4 style="margin-bottom: 8px;">📬 请通过以下方式提交线索或申诉:</h4>
  229. <a href="https://twitter.com/${developerInfo.twitter}" target="_blank" style="display: block; color: #1da1f2; text-decoration: none; font-size: 0.9em; margin-bottom: 4px;">🐦 Twitter: ${developerInfo.twitter}</a>
  230. <a href="https://t.me/${developerInfo.telegram.replace('@', '')}" target="_blank" style="display: block; color: #1da1f2; text-decoration: none; font-size: 0.9em;">📨 Telegram: ${developerInfo.telegram}</a>
  231. `;
  232. content.appendChild(feedbackSection);
  233.  
  234. const closeButton = document.createElement('button');
  235. closeButton.textContent = '关闭';
  236. closeButton.style.cssText = 'margin-top: 15px; padding: 8px 16px; background-color: #1da1f2; color: white; border: none; border-radius: 4px; cursor: pointer;';
  237. closeButton.onclick = () => document.body.removeChild(modal);
  238. content.appendChild(closeButton);
  239.  
  240. modal.appendChild(content);
  241. document.body.appendChild(modal);
  242.  
  243. modal.onclick = (e) => {
  244. if (e.target === modal) document.body.removeChild(modal);
  245. };
  246. }
  247.  
  248. function showLocalDataEditor() {
  249. const modal = document.createElement('div');
  250. modal.style.cssText = `
  251. position: fixed; top: 0; left: 0; width: 100%; height: 100%;
  252. background-color: rgba(0,0,0,0.7); display: flex;
  253. justify-content: center; align-items: center; z-index: 9999;
  254. `;
  255.  
  256. const content = document.createElement('div');
  257. content.style.cssText = `
  258. background-color: #15202b; color: #ffffff; padding: 20px;
  259. border-radius: 12px; max-width: 600px; width: 90%;
  260. max-height: 80vh; overflow-y: auto;
  261. `;
  262.  
  263. const title = document.createElement('h2');
  264. title.textContent = '✏️ 编辑本地KOL记录';
  265. title.style.cssText = 'margin-top: 0; color: #1da1f2;';
  266. content.appendChild(title);
  267.  
  268. const localData = GM_getValue('localData', {});
  269. const form = document.createElement('div');
  270. form.innerHTML = `
  271. <div style="margin-bottom: 12px;">
  272. <label style="display: block; margin-bottom: 4px;">KOL用户名 (不含@):</label>
  273. <input id="username" type="text" style="width: 100%; padding: 6px; background-color: #253341; color: #ffffff; border: 1px solid #38444d; border-radius: 4px;">
  274. </div>
  275. <div style="margin-bottom: 12px;">
  276. <label style="display: block; margin-bottom: 4px;">劣迹指数 (0-100):</label>
  277. <input id="index" type="number" min="0" max="100" value="50" style="width: 100%; padding: 6px; background-color: #253341; color: #ffffff; border: 1px solid #38444d; border-radius: 4px;">
  278. </div>
  279. <div style="margin-bottom: 12px;">
  280. <label style="display: block; margin-bottom: 4px;">劣迹原因:</label>
  281. <input id="reason" type="text" style="width: 100%; padding: 6px; background-color: #253341; color: #ffffff; border: 1px solid #38444d; border-radius: 4px;">
  282. </div>
  283. <div style="margin-bottom: 12px;">
  284. <label style="display: block; margin-bottom: 4px;">证据链接 (可选):</label>
  285. <input id="proof" type="text" style="width: 100%; padding: 6px; background-color: #253341; color: #ffffff; border: 1px solid #38444d; border-radius: 4px;" placeholder="https://...">
  286. </div>
  287. <div style="margin-bottom: 12px;">
  288. <label style="display: block; margin-bottom: 4px;">日期 (可选):</label>
  289. <input id="date" type="date" style="width: 100%; padding: 6px; background-color: #253341; color: #ffffff; border: 1px solid #38444d; border-radius: 4px;" value="${new Date().toISOString().split('T')[0]}">
  290. </div>
  291. <button id="addRecord" style="padding: 6px 12px; background-color: #1da1f2; color: white; border: none; border-radius: 4px; cursor: pointer;">添加记录</button>
  292. `;
  293.  
  294. content.appendChild(form);
  295.  
  296. const usernameInput = form.querySelector('#username');
  297. const indexInput = form.querySelector('#index');
  298. const reasonInput = form.querySelector('#reason');
  299. const proofInput = form.querySelector('#proof');
  300. const dateInput = form.querySelector('#date');
  301. const addButton = form.querySelector('#addRecord');
  302.  
  303. addButton.onclick = () => {
  304. const username = usernameInput.value.trim();
  305. const index = parseInt(indexInput.value);
  306. const reason = reasonInput.value.trim();
  307.  
  308. if (!username || !reason) {
  309. alert('用户名和劣迹原因不能为空');
  310. return;
  311. }
  312. if (isNaN(index) || index < 0 || index > 100) {
  313. alert('劣迹指数必须在 0-100 之间');
  314. return;
  315. }
  316.  
  317. if (!localData[username]) {
  318. localData[username] = { index: index, records: [] };
  319. } else {
  320. localData[username].index = index;
  321. }
  322.  
  323. localData[username].records.push({
  324. reason: reason,
  325. proof: proofInput.value.trim() || '',
  326. date: dateInput.value.trim() || ''
  327. });
  328.  
  329. GM_setValue('localData', localData);
  330. loadData();
  331. alert(`已添加 ${username} 的记录`);
  332. usernameInput.value = '';
  333. reasonInput.value = '';
  334. proofInput.value = '';
  335. updateRecordsList(recordsList, localData);
  336. };
  337.  
  338. const recordsSection = document.createElement('div');
  339. recordsSection.style.marginTop = '20px';
  340. recordsSection.innerHTML = '<h3 style="margin-bottom: 8px;">已有本地记录</h3>';
  341. const recordsList = document.createElement('ul');
  342. recordsList.style.cssText = 'padding-left: 20px; margin-top: 0;';
  343. updateRecordsList(recordsList, localData);
  344. recordsSection.appendChild(recordsList);
  345. content.appendChild(recordsSection);
  346.  
  347. const closeButton = document.createElement('button');
  348. closeButton.textContent = '关闭';
  349. closeButton.style.cssText = 'margin-top: 15px; padding: 8px 16px; background-color: #1da1f2; color: white; border: none; border-radius: 4px; cursor: pointer;';
  350. closeButton.onclick = () => document.body.removeChild(modal);
  351. content.appendChild(closeButton);
  352.  
  353. modal.appendChild(content);
  354. document.body.appendChild(modal);
  355.  
  356. modal.onclick = (e) => {
  357. if (e.target === modal) document.body.removeChild(modal);
  358. };
  359. }
  360.  
  361. function updateRecordsList(recordsList, localData) {
  362. recordsList.innerHTML = '';
  363. for (const [username, data] of Object.entries(localData)) {
  364. data.records.forEach((record, index) => {
  365. const li = document.createElement('li');
  366. li.style.cssText = 'margin-bottom: 12px; display: flex; justify-content: space-between; align-items: center;';
  367. let recordText = `${username} (${data.index}): ${record.reason}`;
  368. if (record.date && record.date.trim()) recordText += ` - ${record.date}`;
  369. li.innerHTML = `
  370. <span>${recordText}</span>
  371. <button style="padding: 4px 8px; background-color: #ff3b30; color: white; border: none; border-radius: 4px; cursor: pointer;">删除</button>
  372. `;
  373. li.querySelector('button').onclick = () => {
  374. data.records.splice(index, 1);
  375. if (data.records.length === 0) delete localData[username];
  376. GM_setValue('localData', localData);
  377. loadData();
  378. updateRecordsList(recordsList, localData);
  379. };
  380. recordsList.appendChild(li);
  381. });
  382. }
  383. }
  384.  
  385. // 设置界面
  386. function showSettings() {
  387. const modal = document.createElement('div');
  388. modal.style.cssText = `
  389. position: fixed; top: 0; left: 0; width: 100%; height: 100%;
  390. background-color: rgba(0,0,0,0.7); display: flex;
  391. justify-content: center; align-items: center; z-index: 9999;
  392. `;
  393.  
  394. const content = document.createElement('div');
  395. content.style.cssText = `
  396. background-color: #15202b; color: #ffffff; padding: 20px;
  397. border-radius: 12px; max-width: 600px; width: 90%;
  398. max-height: 80vh; overflow-y: auto;
  399. `;
  400.  
  401. const title = document.createElement('h2');
  402. title.textContent = '⚙️ 设置';
  403. title.style.cssText = 'margin-top: 0; color: #1da1f2;';
  404. content.appendChild(title);
  405.  
  406. const dataSourceSection = document.createElement('div');
  407. dataSourceSection.innerHTML = `
  408. <h3 style="margin-bottom: 8px;">数据源设置</h3>
  409. <label style="display: block; margin-bottom: 8px;">
  410. <input type="checkbox" id="usePublicData" ${usePublicData ? 'checked' : ''}> 使用公共数据
  411. </label>
  412. <label style="display: block; margin-bottom: 8px;">
  413. <input type="checkbox" id="useLocalData" ${useLocalData ? 'checked' : ''}> 使用本地数据
  414. </label>
  415. <button id="saveDataSource" style="padding: 6px 12px; background-color: #1da1f2; color: white; border: none; border-radius: 4px; cursor: pointer;">保存</button>
  416. `;
  417. content.appendChild(dataSourceSection);
  418.  
  419. const publicCheckbox = dataSourceSection.querySelector('#usePublicData');
  420. const localCheckbox = dataSourceSection.querySelector('#useLocalData');
  421. const saveButton = dataSourceSection.querySelector('#saveDataSource');
  422. saveButton.onclick = () => {
  423. usePublicData = publicCheckbox.checked;
  424. useLocalData = localCheckbox.checked;
  425. GM_setValue('usePublicData', usePublicData);
  426. GM_setValue('useLocalData', useLocalData);
  427. loadData();
  428. alert('数据源设置已保存');
  429. };
  430.  
  431. const localDataSection = document.createElement('div');
  432. localDataSection.style.marginTop = '20px';
  433. localDataSection.innerHTML = `
  434. <h3 style="margin-bottom: 8px;">本地数据管理</h3>
  435. <button id="editLocalData" style="padding: 6px 12px; background-color: #1da1f2; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 8px;">编辑本地数据</button>
  436. <button id="clearLocalData" style="padding: 6px 12px; background-color: #ff3b30; color: white; border: none; border-radius: 4px; cursor: pointer;">清空本地数据</button>
  437. `;
  438. localDataSection.querySelector('#editLocalData').onclick = showLocalDataEditor;
  439. localDataSection.querySelector('#clearLocalData').onclick = () => {
  440. if (confirm('确定清空本地数据吗?')) {
  441. GM_setValue('localData', {});
  442. loadData();
  443. alert('本地数据已清空');
  444. }
  445. };
  446. content.appendChild(localDataSection);
  447.  
  448. const devInfoSection = document.createElement('div');
  449. devInfoSection.style.cssText = 'margin-top: 20px; padding-top: 15px; border-top: 1px solid #38444d;';
  450. devInfoSection.innerHTML = `
  451. <h3 style="margin-bottom: 8px;">开发者信息</h3>
  452. <p style="margin-bottom: 8px; font-size: 0.9em;">Twitter: <a href="https://twitter.com/${developerInfo.twitter}" target="_blank" style="color: #1da1f2; text-decoration: none;">${developerInfo.twitter}</a></p>
  453. <p style="margin-bottom: 8px; font-size: 0.9em;">Telegram: <a href="https://t.me/${developerInfo.telegram.replace('@', '')}" target="_blank" style="color: #1da1f2; text-decoration: none;">${developerInfo.telegram}</a></p>
  454. `;
  455. content.appendChild(devInfoSection);
  456.  
  457. const closeButton = document.createElement('button');
  458. closeButton.textContent = '关闭';
  459. closeButton.style.cssText = 'margin-top: 15px; padding: 8px 16px; background-color: #1da1f2; color: white; border: none; border-radius: 4px; cursor: pointer;';
  460. closeButton.onclick = () => document.body.removeChild(modal);
  461. content.appendChild(closeButton);
  462.  
  463. modal.appendChild(content);
  464. document.body.appendChild(modal);
  465.  
  466. modal.onclick = (e) => {
  467. if (e.target === modal) document.body.removeChild(modal);
  468. };
  469. }
  470.  
  471. // 初始化菜单命令
  472. GM_registerMenuCommand('⚙️ 打开设置', showSettings);
  473. GM_registerMenuCommand('🔄 更新公共数据', () => {
  474. fetchPublicData();
  475. alert('正在更新公共数据...');
  476. });
  477.  
  478. // 初始化
  479. loadData();
  480. fetchPublicData();
  481. setInterval(fetchPublicData, 24 * 60 * 60 * 1000); // 每24小时更新一次公共数据
  482. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址