您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Display today's script installations, update checks, and feedback.
当前为
// ==UserScript== // @name Greasyfork/Sleazyfork Update Checks Display // @description Display today's script installations, update checks, and feedback. // @icon https://greasyfork.org/vite/assets/blacklogo96-CxYTSM_T.png // @version 1.3 // @author afkarxyz // @namespace https://github.com/afkarxyz/misc-scripts/ // @supportURL https://github.com/afkarxyz/misc-scripts/issues // @license MIT // @match https://greasyfork.org/* // @match https://sleazyfork.org/* // @grant none // ==/UserScript== (function() { 'use strict'; function formatNumber(num) { return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } function displayScriptStats() { document.head.appendChild(Object.assign(document.createElement('style'), { textContent: '.script-list-installs, .script-list-update-checks, .script-list-feedback { opacity: 1; }' })); function addStat(element, label, className) { const list = element.querySelector('.inline-script-stats'); if (!list) return; const dt = document.createElement('dt'); const dd = document.createElement('dd'); dt.className = className; dd.className = className; dt.textContent = label; dd.textContent = '...'; list.lastElementChild.parentNode.insertBefore(dt, list.lastElementChild.nextSibling); dt.after(dd); return dd; } document.querySelectorAll('li[data-script-id]').forEach(script => { const feedbackElement = addStat(script, 'Feedback', 'script-list-feedback'); const installsElement = addStat(script, 'Installs', 'script-list-installs'); const checksElement = addStat(script, 'Checks', 'script-list-update-checks'); script.dataset.feedbackElement = feedbackElement.id = `feedback-${script.dataset.scriptId}`; script.dataset.installsElement = installsElement.id = `installs-${script.dataset.scriptId}`; script.dataset.checksElement = checksElement.id = `checks-${script.dataset.scriptId}`; }); } const collectScriptLinks = () => Array.from(document.querySelectorAll('li[data-script-id]')) .map(el => { const domain = window.location.hostname; const scriptId = el.getAttribute('data-script-id'); const scriptName = el.getAttribute('data-script-name') .toLowerCase() .replace(/[^a-z0-9]+/g, '-'); return { url: `${domain}/en/scripts/${scriptId}-${scriptName}`, element: el }; }); async function fetchStats(scriptInfo) { const apiUrl = `https://forksapis.vercel.app/${scriptInfo.url}`; try { const response = await fetch(apiUrl); if (!response.ok) { throw new Error('Network response was not ok'); } return await response.json(); } catch (error) { console.error('Error fetching stats:', error); return null; } } function updateStats(scriptInfo, stats) { if (!stats) return; const element = scriptInfo.element; const feedbackElement = document.getElementById(element.dataset.feedbackElement); const installsElement = document.getElementById(element.dataset.installsElement); const checksElement = document.getElementById(element.dataset.checksElement); if (feedbackElement) feedbackElement.textContent = formatNumber(stats.feedback); if (installsElement) installsElement.textContent = formatNumber(stats.installs); if (checksElement) checksElement.textContent = formatNumber(stats.checks); } async function init() { displayScriptStats(); const scriptInfos = collectScriptLinks(); console.log('Found URLs:', scriptInfos.map(info => info.url)); const fetchPromises = scriptInfos.map(async (scriptInfo) => { const stats = await fetchStats(scriptInfo); updateStats(scriptInfo, stats); }); await Promise.all(fetchPromises); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();