您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Balances API key and URL pairs usage
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.org/scripts/528703/1546610/SimpleBalancer.js
// ==UserScript== // @name SimpleBalancer // @namespace http://tampermonkey.net/ // @version 0.1 // @description Balances API key and URL pairs usage // @author RoCry // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== class SimpleBalancer { /** * Balances API key and URL pairs usage */ constructor() { this.loadUsageData(); } loadUsageData() { try { // Use GM_getValue for Tampermonkey/Greasemonkey persistence this.pairUsage = GM_getValue('simpleBalancerUsage', {}); } catch (error) { console.error('Error loading balancer data:', error); this.pairUsage = {}; } } saveUsageData() { try { // Use GM_setValue for Tampermonkey/Greasemonkey persistence GM_setValue('simpleBalancerUsage', this.pairUsage); } catch (error) { console.error('Error saving balancer data:', error); } } parseItems(items) { return items.split(',').map(item => item.trim()).filter(item => item); } createPairKey(key, url) { return `${key}|||${url}`; } parsePairKey(pairKey) { const [key, url] = pairKey.split('|||'); return [key, url]; } /** * Choose a key-URL pair based on usage balancing. * Cases: * 1. 1 key, 1 url -> single pair * 2. 1 key, n urls -> key paired with each url * 3. n keys, n urls -> matching pairs * 4. n keys, 1 url -> each key paired with url * * @param {string} keys - Comma-separated list of API keys * @param {string} urls - Comma-separated list of URLs * @returns {Array} - [key, url] pair that was selected */ choosePair(keys, urls) { const keyList = this.parseItems(keys); const urlList = this.parseItems(urls); if (keyList.length === 0 || urlList.length === 0) { throw new Error("Keys and URLs cannot be empty"); } // Generate valid pairs based on the cases let pairs = []; if (urlList.length === 1) { pairs = keyList.map(key => [key, urlList[0]]); } else if (keyList.length === 1) { pairs = urlList.map(url => [keyList[0], url]); } else { if (keyList.length !== urlList.length) { throw new Error("When using multiple keys and URLs, their counts must match"); } pairs = keyList.map((key, index) => [key, urlList[index]]); } // Convert pairs to pairKeys and initialize usage count if needed const pairKeys = pairs.map(([key, url]) => { const pairKey = this.createPairKey(key, url); if (!(pairKey in this.pairUsage)) { this.pairUsage[pairKey] = 0; } return pairKey; }); // Find the minimum usage count const minUsage = Math.min(...pairKeys.map(key => this.pairUsage[key])); // Find all pairs with minimum usage const leastUsedPairKeys = pairKeys.filter(key => this.pairUsage[key] === minUsage); // Randomly select one of the least used pairs const randomIndex = Math.floor(Math.random() * leastUsedPairKeys.length); const chosenPairKey = leastUsedPairKeys[randomIndex]; // Increment usage for the chosen pair this.pairUsage[chosenPairKey]++; // Save updated usage data this.saveUsageData(); // Return the chosen pair return this.parsePairKey(chosenPairKey); } resetUsage() { this.pairUsage = {}; this.saveUsageData(); } getUsageStats() { const stats = {}; for (const pairKey in this.pairUsage) { const [key, url] = this.parsePairKey(pairKey); stats[`${key}, ${url}`] = this.pairUsage[pairKey]; } return stats; } } // Make it available globally for other scripts to use if (typeof module !== 'undefined') { module.exports = SimpleBalancer; } else { window.SimpleBalancer = SimpleBalancer; }