Manually set a price and highlight both item market and bazaar sellers accordingly in Torn.com.
当前为
// ==UserScript==
// @name Torn Manual Price Highlighter (Item Market + Bazaar)
// @namespace http://tampermonkey.net/
// @version 0.5
// @description Manually set a price and highlight both item market and bazaar sellers accordingly in Torn.com.
// @license MIT
// @author JeffBezas[3408347]
// @match https://www.torn.com/page.php?sid=ItemMarket*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// ==/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-price-modal {
position: fixed;
top: 30%;
left: 50%;
transform: translate(-50%, -30%);
background: #1e1e1e;
color: white;
padding: 20px;
border: 2px solid #888;
border-radius: 10px;
z-index: 9999;
display: none;
}
#manual-price-modal input {
width: 100px;
padding: 5px;
font-size: 14px;
}
#manual-price-modal button {
margin-left: 10px;
padding: 5px 10px;
background: #444;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
`);
// ========== Modal Setup ==========
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;
// ========== Save Price ==========
saveBtn.onclick = () => {
const value = parseInt(priceInput.value);
if (value > 0 && currentItemId) {
GM_setValue(`manual_price_${currentItemId}`, value);
modal.style.display = "none";
// Highlight Item Market rows
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
});
// Highlight Bazaar prices
waitForBazaarPrices(currentItemId, value);
}
};
cancelBtn.onclick = () => {
modal.style.display = "none";
};
// ========== Item Market Highlight ==========
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;
console.log(`[ItemMarket] $${listed} vs $${manualPrice} (${diffPercent.toFixed(2)}%)`);
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');
}
});
}
// ========== Bazaar Enhancer Highlight ==========
function highlightBazaarPrices(priceLinks, manualPrice) {
console.log(`[Bazaar Debug] Highlighting ${priceLinks.length} links for item`, 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"; // Green
link.style.color = "#fff";
} else if (diff <= 5) {
link.style.backgroundColor = "#ffa500"; // Yellow
link.style.color = "#000";
} else {
link.style.backgroundColor = "#8b0000"; // Red
link.style.color = "#fff";
}
console.log(`[Bazaar] $${listed} vs $${manualPrice} (${diff.toFixed(2)}%)`);
});
}
// ========== Bazaar Wait Loop ==========
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])');
// Only trigger once it's no longer saying "No item selected"
if (!noItem && priceLinks.length > 0) {
observer.disconnect();
console.log(`[Bazaar Trigger] Detected new item listings... highlighting.`);
highlightBazaarPrices(priceLinks, manualPrice);
}
});
observer.observe(listingsView, {
childList: true,
subtree: true,
characterData: true
});
}
// ========== Buy Item Listener ==========
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 = GM_getValue(`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));
}
});
});
}
// ========== Init Loop ==========
setInterval(setupBuyButtonListeners, 1000);
window.addEventListener('keydown', (e) => {
if (e.key === "Escape") {
modal.style.display = "none";
}
});
})();