您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Shows TornZ bazaar listings on Torn's item market
// ==UserScript== // @name TornZ Market Helper // @namespace https://tornz.com // @version 0.1.1 // @description Shows TornZ bazaar listings on Torn's item market // @author ultrapro5000 // @match https://www.torn.com/page.php?sid=ItemMarket* // @grant GM.xmlHttpRequest // @connect tornz.com // @run-at document-idle // @license MIT // @homepageURL https://tornz.com // @supportURL https://www.torn.com/forums.php#/p=threads&f=67&t=16428643 // ==/UserScript== (function() { 'use strict'; const debug = (msg, ...args) => { console.log(`[TornZ] ${msg}`, ...args); }; let isProcessing = false; const injectStyles = () => { const style = document.createElement('style'); style.textContent = ` .tornz-container { margin: 10px 0; padding: 10px; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 4px; width: 100%; } .tornz-listings { display: flex; flex-wrap: wrap; gap: 10px; } .tornz-listing { flex: 1; min-width: 200px; padding: 8px; background: rgba(0, 0, 0, 0.2); border-radius: 4px; } .tornz-listing a { color: inherit; text-decoration: none; } .tornz-header { margin-bottom: 10px; padding-bottom: 5px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); font-weight: bold; } .tornz-seller { color: inherit; display: block; margin-bottom: 4px; } .tornz-price { color: #00a4ff; font-weight: bold; } `; document.head.appendChild(style); }; const getItemIdFromUrl = () => { const hash = window.location.hash; const match = hash.match(/itemID=(\d+)/); return match ? match[1] : null; }; const processPage = async () => { if (isProcessing) return; isProcessing = true; const itemId = getItemIdFromUrl(); if (!itemId) { isProcessing = false; return; } // Find the item market content area const marketArea = document.querySelector('[class*="appHeaderWrapper"]'); if (!marketArea) { debug('No market area found'); isProcessing = false; return; } // Remove any existing containers document.querySelectorAll('.tornz-container').forEach(el => el.remove()); // Create container const container = document.createElement('div'); container.className = 'tornz-container'; container.innerHTML = 'Loading listings...'; // Insert after the header marketArea.parentNode.insertBefore(container, marketArea.nextSibling); try { const response = await new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'GET', url: `https://tornz.com/api/three-listings/${itemId}`, headers: { 'Accept': 'application/json' }, onload: (response) => resolve(response), onerror: (error) => reject(error) }); }); const data = JSON.parse(response.responseText); if (data.data && data.data.length > 0) { container.innerHTML = ` <div class="tornz-header">Bazaar Listings:</div> <div class="tornz-listings"> ${data.data.map(listing => ` <div class="tornz-listing"> <a href="https://www.torn.com/bazaar.php?userId=${listing.seller_torn_id}"> <span class="tornz-seller"> ${listing.seller_torn_username} [${listing.seller_torn_id}] </span> <span class="tornz-price">$${listing.price.toLocaleString()} (${listing.quantity}x)</span> </a> </div> `).join('')} </div> `; } else { //container.innerHTML = '<div class="tornz-header">No bazaar listings found</div>'; } } catch (error) { debug('Error:', error); container.innerHTML = '<div class="tornz-header">Error loading listings</div>'; } isProcessing = false; }; const init = () => { debug('Initializing...'); injectStyles(); // Initial processing with longer delay for React setTimeout(processPage, 3000); // Watch for hash changes let lastHash = window.location.hash; setInterval(() => { const currentHash = window.location.hash; if (currentHash !== lastHash) { lastHash = currentHash; setTimeout(processPage, 1000); } }, 500); // Watch for DOM changes const observer = new MutationObserver((mutations) => { if (!document.querySelector('.tornz-container')) { setTimeout(processPage, 500); } }); observer.observe(document, { childList: true, subtree: true }); }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();