您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Manually set a price and highlight both item market and bazaar sellers accordingly in Torn.com.
// ==UserScript== // @name Bezas Bazaar // @namespace http://tampermonkey.net/ // @version 3.0.2 // @description Manually set a price and highlight both item market and bazaar sellers accordingly in Torn.com. // @author JeffBezas[3408347] // @match https://www.torn.com/page.php?sid=ItemMarket* // @match https://www.torn.com/bazaar.php?* // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @license MIT // ==/UserScript== (function () { 'use strict'; GM_addStyle(` .manual-highlight-good { background-color: #004d00 !important; color: white; } .manual-highlight-warning { background-color: #ffa500 !important; color: black; } .manual-highlight-bad { background-color: #8b0000 !important; color: white; } .manual-highlight-missing { background-color: #d3d3d3 !important; color: #000; } #manual-price-modal, #manual-price-manager { position: fixed; background: #1e1e1e; color: white; padding: 20px; border: 2px solid #888; border-radius: 10px; z-index: 9999; } #manual-price-modal { top: 30%; left: 50%; transform: translate(-50%, -30%); display: none; } #manual-price-modal input { width: 100px; padding: 5px; font-size: 14px; } #manual-price-modal button, #manual-price-manager button { margin-left: 10px; padding: 5px 10px; background: #444; color: white; border: none; border-radius: 5px; cursor: pointer; } `); const storage = typeof GM_getValue === 'function' ? { get: GM_getValue, set: GM_setValue } : { get: key => JSON.parse(localStorage.getItem(key)), set: (key, value) => localStorage.setItem(key, JSON.stringify(value)) }; const modal = document.createElement("div"); modal.id = "manual-price-modal"; modal.innerHTML = ` <label>Manual price: $<input type="number" id="manual-price-input" /></label> <button id="manual-price-save">Save</button> <button id="manual-price-cancel">Cancel</button> `; document.body.appendChild(modal); const priceInput = document.getElementById("manual-price-input"); const saveBtn = document.getElementById("manual-price-save"); const cancelBtn = document.getElementById("manual-price-cancel"); let currentItemId = null; const manager = document.createElement("div"); manager.id = "manual-price-manager"; manager.style.bottom = "10px"; manager.style.right = "10px"; manager.style.maxHeight = "300px"; manager.style.overflowY = "auto"; document.body.appendChild(manager); const refreshButton = document.createElement("button"); refreshButton.textContent = "📋 View Manual Prices"; refreshButton.style = "position: fixed; bottom: 10px; left: 10px; z-index: 10000;"; refreshButton.onclick = () => { manager.innerHTML = "<b>📋 Saved Prices:</b><br/><br/>"; let found = false; for (let key in localStorage) { if (key.startsWith("manual_price_")) { found = true; const itemId = key.split("_").pop(); const val = storage.get(key); if (val) { manager.innerHTML += `Item ID ${itemId}: $${Number(val).toLocaleString()} <button data-del="${key}" style="margin-left: 10px;">❌ Delete</button><br/>`; } } } if (!found) manager.innerHTML += "No saved prices."; }; document.body.appendChild(refreshButton); manager.addEventListener("click", (e) => { if (e.target.dataset.del) { storage.set(e.target.dataset.del, null); e.target.parentElement.remove(); } }); function getPageType() { const url = window.location.href; if (url.includes("page.php?sid=ItemMarket")) return "itemmarket"; if (url.includes("bazaar.php")) return "bazaar"; return null; } function makeDraggable(element) { let isDragging = false; let offsetX = 0; let offsetY = 0; element.addEventListener("mousedown", function (e) { // Prevent drag if interacting with input, textarea, or button if (["INPUT", "TEXTAREA", "BUTTON"].includes(e.target.tagName)) return; isDragging = true; offsetX = e.clientX - element.offsetLeft; offsetY = e.clientY - element.offsetTop; e.preventDefault(); }); document.addEventListener("mouseup", () => isDragging = false); document.addEventListener("mousemove", function (e) { if (isDragging) { element.style.left = e.clientX - offsetX + 'px'; element.style.top = e.clientY - offsetY + 'px'; element.style.right = 'auto'; element.style.bottom = 'auto'; } }); } makeDraggable(modal); makeDraggable(manager); saveBtn.onclick = () => { const value = parseInt(priceInput.value); if (value > 0 && currentItemId) { storage.set(`manual_price_${currentItemId}`, value); modal.style.display = "none"; const observer = new MutationObserver(() => { const sellerRows = document.querySelectorAll('li[class*="rowWrapper___"]'); if (sellerRows.length > 0) { observer.disconnect(); highlightSellerRows(currentItemId, value); } }); observer.observe(document.body, { childList: true, subtree: true }); waitForBazaarPrices(currentItemId, value); } }; cancelBtn.onclick = () => modal.style.display = "none"; function highlightSellerRows(itemId, manualPrice) { const rows = document.querySelectorAll('li[class*="rowWrapper___"]'); rows.forEach(row => { const priceEl = row.querySelector('div[class*="price___"]'); if (!priceEl) return; const match = priceEl.textContent.match(/\$([\d,]+)/); if (!match) return; const listed = parseInt(match[1].replace(/,/g, '')); const diffPercent = ((listed - manualPrice) / manualPrice) * 100; row.classList.remove('manual-highlight-good', 'manual-highlight-warning', 'manual-highlight-bad'); if (listed <= manualPrice) { row.classList.add('manual-highlight-good'); } else if (diffPercent <= 5) { row.classList.add('manual-highlight-warning'); } else { row.classList.add('manual-highlight-bad'); } addPercentIndicator(priceEl, diffPercent); }); } function addPercentIndicator(el, diffPercent) { if (el.querySelector('.manual-price-diff')) return; const span = document.createElement('span'); span.className = 'manual-price-diff'; span.style.marginLeft = '6px'; span.style.fontSize = '12px'; span.style.fontWeight = 'bold'; span.style.color = 'black'; span.style.backgroundColor = 'rgba(255,255,255,0.6)'; span.style.padding = '1px 4px'; span.style.borderRadius = '4px'; const sign = diffPercent > 0 ? '+' : ''; span.textContent = `(${sign}${diffPercent.toFixed(1)}%)`; el.appendChild(span); } function highlightBazaarPrices(priceLinks, manualPrice) { priceLinks.forEach(link => { if (link.dataset.manualChecked === "true") return; const match = link.textContent.match(/\$([\d,]+)/); if (!match) return; const listed = parseInt(match[1].replace(/,/g, '')); const diff = ((listed - manualPrice) / manualPrice) * 100; link.dataset.manualChecked = "true"; link.style.padding = "2px 4px"; link.style.borderRadius = "4px"; link.style.fontWeight = "bold"; if (listed <= manualPrice) { link.style.backgroundColor = "#004d00"; link.style.color = "#fff"; } else if (diff <= 5) { link.style.backgroundColor = "#ffa500"; link.style.color = "#000"; } else { link.style.backgroundColor = "#8b0000"; link.style.color = "#fff"; } addPercentIndicator(link, diff); }); } function waitForBazaarPrices(itemId, manualPrice) { const listingsView = document.querySelector('#fullListingsView'); if (!listingsView) return; const observer = new MutationObserver(() => { const noItem = listingsView.textContent.includes("No item selected"); const priceLinks = listingsView.querySelectorAll('a[href*="bazaar.php?userID="]:not([data-checked])'); if (!noItem && priceLinks.length > 0) { observer.disconnect(); highlightBazaarPrices(priceLinks, manualPrice); } }); observer.observe(listingsView, { childList: true, subtree: true, characterData: true }); } function extractItemIdFromButton(button) { const container = button.closest('.itemTile___cbw7w'); const img = container?.querySelector('img.torn-item'); const match = img?.src?.match(/\/items\/(\d+)\//); return match ? match[1] : null; } function setupBuyButtonListeners() { document.querySelectorAll('.actionButton___pb_Da').forEach(btn => { if (btn.dataset.boundManual === "true") return; btn.dataset.boundManual = "true"; btn.addEventListener('click', () => { const itemId = extractItemIdFromButton(btn); if (!itemId) return; currentItemId = itemId; const saved = storage.get(`manual_price_${itemId}`); priceInput.value = saved || ""; modal.style.display = "block"; if (saved) { const observer = new MutationObserver(() => { const sellerRows = document.querySelectorAll('li[class*="rowWrapper___"]'); if (sellerRows.length > 0) { observer.disconnect(); highlightSellerRows(itemId, parseInt(saved)); } }); observer.observe(document.body, { childList: true, subtree: true }); waitForBazaarPrices(itemId, parseInt(saved)); } }); }); } function highlightItemTilesFromSavedPrices() { document.querySelectorAll('.itemTile___cbw7w').forEach(tile => { if (tile.dataset.checkedManual === "true") return; tile.dataset.checkedManual = "true"; const img = tile.querySelector('img.torn-item'); const priceSpan = tile.querySelector('.priceAndTotal___eEVS7 span'); if (!img || !priceSpan) return; const match = img.src.match(/\/items\/(\d+)\//); if (!match) return; const itemId = match[1]; const priceText = priceSpan.textContent.trim(); const priceMatch = priceText.match(/\$([\d,]+)/); if (!priceMatch) return; const listedPrice = parseInt(priceMatch[1].replace(/,/g, '')); const savedPrice = storage.get(`manual_price_${itemId}`); tile.classList.remove('manual-highlight-good', 'manual-highlight-warning', 'manual-highlight-bad', 'manual-highlight-missing'); if (savedPrice) { const diffPercent = ((listedPrice - savedPrice) / savedPrice) * 100; if (listedPrice <= savedPrice) { tile.classList.add('manual-highlight-good'); } else if (diffPercent <= 5) { tile.classList.add('manual-highlight-warning'); } else { tile.classList.add('manual-highlight-bad'); } addPercentIndicator(priceSpan, diffPercent); } else { tile.classList.add('manual-highlight-missing'); } }); } setInterval(setupBuyButtonListeners, 1000); setInterval(highlightItemTilesFromSavedPrices, 1000); const pageType = getPageType(); console.log(`[ManualPrice] Detected page: ${pageType}`); alert(`ManualPrice] Detected page: ${pageType}`) if (pageType === "itemmarket") { // Run Item Market-specific logic } else if (pageType === "bazaar") { // Setup Bazaar-specific logic (next step) } window.addEventListener('keydown', (e) => { if (e.key === "Escape") modal.style.display = "none"; }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址