您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
When your bazaar is open, a banner warns when your bazaar items are undercut using data from weav3r.dev
// ==UserScript== // @name Bazaar Undercut Alert // @namespace https://torn.com/ // @version 1.0 // @author swervelord [3637232] // @description When your bazaar is open, a banner warns when your bazaar items are undercut using data from weav3r.dev // // @match https://www.torn.com/* // // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // @connect api.torn.com // @connect weav3r.dev // ==/UserScript== (() => { const KEY_STORE = 'torn_api_key'; const CHECK_EVERY_MS = 60_000; const MAX_TORN_CALLS_PER_MIN = 50; const PLACEHOLDER_PRICE = 1; let queue = []; let undercutNow = new Map(); let tornCallsThisMinute = 0; let bannerDismissed = false; let bazaarOpen = false; const banner = (() => { const wrap = document.createElement('div'); wrap.id = 'undercutBanner'; wrap.style.cssText = ` position:fixed;top:0;left:0;right:0; display:none; align-items:center; justify-content:center; padding:3px 8px; height:20px; background:#2c2c2c; color:#ffffff; font:600 11px/14px "Segoe UI", sans-serif; z-index:2147483647; box-shadow:0 1px 4px rgba(0,0,0,0.2); cursor:pointer; `; const textSpan = document.createElement('span'); textSpan.style.cssText = ` text-align:center; width:100%; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; `; wrap.appendChild(textSpan); const close = document.createElement('span'); close.textContent = '✕'; close.style.cssText = ` position:absolute; top:3px; right:8px; font-weight:bold; font-size:10px; background:#1a1a1a; color:white; border-radius:3px; padding:0 4px; cursor:pointer; line-height:14px; `; close.addEventListener('click', e => { e.stopPropagation(); wrap.style.display = 'none'; bannerDismissed = true; }); wrap.addEventListener('click', () => { if (!bannerDismissed) { window.open('https://www.torn.com/bazaar.php#/manage', '_blank'); } }); wrap.appendChild(close); document.body.prepend(wrap); return { wrap, textSpan }; })(); const updateBanner = () => { if (bannerDismissed || !bazaarOpen || !undercutNow.size) { banner.wrap.style.display = 'none'; return; } banner.wrap.style.display = 'flex'; const items = [...undercutNow.values()] .map(o => `<span style="color:#00c8d6">${o.name}</span>`).join(', '); banner.textSpan.innerHTML = `Your items have been undercut: ${items}`; }; const apiKey = () => { let k = GM_getValue(KEY_STORE, ''); if (!k) { k = prompt('Enter your Torn API key (MINIMAL access, stored only locally):', ''); if (k) GM_setValue(KEY_STORE, k.trim()); } return k; }; const httpJSON = url => new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url, headers: { accept: 'application/json' }, onload: r => { try { resolve(JSON.parse(r.responseText)); } catch (e) { reject(e); } }, onerror: reject, timeout: 15000 }); }); const resetTornThrottle = () => { tornCallsThisMinute = 0; }; const refreshBazaarData = async () => { if (queue.length || tornCallsThisMinute >= MAX_TORN_CALLS_PER_MIN) return; const key = apiKey(); if (!key) return; tornCallsThisMinute++; try { const data = await httpJSON(`https://api.torn.com/user/?selections=bazaar&key=${key}`); bazaarOpen = !!data.bazaar_is_open; if (!bazaarOpen) { updateBanner(); return; } const fresh = Object.values(data.bazaar || {}) .filter(i => i.price > PLACEHOLDER_PRICE) .map(i => ({ id: i.ID, name: i.name, price: i.price })); queue.push(...fresh); } catch (err) { console.error('Torn API error:', err); } }; const processQueueBatch = async () => { while (queue.length) { const { id, name, price } = queue.shift(); try { const res = await httpJSON(`https://weav3r.dev/api/marketplace/${id}`); const lowest = (res.listings || []).reduce((m, l) => Math.min(m, l.price), Infinity); if (Number.isFinite(lowest) && price > lowest) { undercutNow.set(id, { name, our: price, lowest }); } else { undercutNow.delete(id); } } catch (e) { console.error('weav3r error:', e); } } updateBanner(); }; setInterval(resetTornThrottle, CHECK_EVERY_MS); setInterval(refreshBazaarData, CHECK_EVERY_MS); setInterval(processQueueBatch, 2000); refreshBazaarData().then(processQueueBatch); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址