Display case market value

Display the total market value of items in a display case

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        Display case market value
// @namespace   Violentmonkey Scripts
// @match       https://www.torn.com/displaycase.php*
// @grant       GM_xmlhttpRequest
// @version     1.0
// @license     MIT
// @author      BillyBourbon/Bilbosaggings[2323763]
// @description Display the total market value of items in a display case
// ==/UserScript==

// ================================
// Input your apikey in between the quote marks ""
const apikey = "";
// ================================

(async () => {
	// Function to format numbers to currency format (USD)
	function formatToCurrency(n) {
		n = Number(n);
		return new Intl.NumberFormat("en-US", {
			style: "currency",
			currency: "USD",
			minimumFractionDigits: 0,
			maximumFractionDigits: 0
		}).format(n);
	}

	// Function to load Torn items with caching
	async function loadTornItems() {
		const cacheKey = "tornItemsCache";
		const cacheExpiryKey = "tornItemsCacheExpiry";
		const cacheDuration = 60 * 60 * 1000; // 1 hour in milliseconds

		// Check for cached data
		const cachedData = localStorage.getItem(cacheKey);
		const cachedExpiry = localStorage.getItem(cacheExpiryKey);

		if (cachedData && cachedExpiry && Date.now() < cachedExpiry) {
			console.log("Using cached data");
			return JSON.parse(cachedData);
		}

		let attempt = 0;
		let jsonResponse = null;

		// Retry logic for API request
		while (attempt < 3) {
			try {
				jsonResponse = await new Promise((resolve, reject) => {
					GM_xmlhttpRequest({
						method: "GET",
						url: `https://api.torn.com/v2/torn/items`,
						headers: {
							"Authorization": `ApiKey ${apikey}`,
						},
						onload: function (response) {
							if (response.status >= 200 && response.status < 300) {
								try {
									const responseData = JSON.parse(response.responseText);
									resolve(responseData);
								} catch (error) {
									reject(new Error("Failed to parse JSON"));
								}
							} else {
								reject(new Error(`API request failed with status: ${response.status}`));
							}
						},
						onerror: function (error) {
							reject(new Error(`API request failed with error: ${error}`));
						}
					});
				});

				console.log(jsonResponse);

				// Cache the API response
				localStorage.setItem(cacheKey, JSON.stringify(jsonResponse));
				localStorage.setItem(cacheExpiryKey, Date.now() + cacheDuration);

				return jsonResponse;
			} catch (error) {
				attempt++;
				console.error(`Attempt ${attempt} failed: ${error.message}`);

				if (attempt < 3) {
					await new Promise(resolve => setTimeout(resolve, 2000)); // Delay before retrying
				}
			}
		}
	}

	// Function to find a Torn item by its ID
	function findTornItem(itemId, tornItems) {
		const item = tornItems.find(o => o.id.toString() === itemId.toString());

		// Return null if item is not found
		return item || null;
	}

	// Wait for the display case container to load
	while (document.querySelector(".display-cabinet") === null) {
		await new Promise(resolve => setTimeout(resolve, 500)); // Delay before retrying
	}

	// Select the display case container
	const displayCaseContainer = document.querySelector(".display-cabinet");

	// Load the Torn items
	const { items: tornItems } = await loadTornItems();

	// Iterate through each item in the display case
	displayCaseContainer.querySelectorAll("li").forEach(li => {
		const temp = li.querySelector(".item-hover");

		if (temp === null) return; // Skip if there's no item

		const itemId = temp.getAttribute("itemId");

		const ammountField = li.querySelector(".b-item-amount");

		const ammount = ammountField.innerHTML.trim().substring(1);

		// Find the item from the loaded Torn items
		const item = findTornItem(itemId, tornItems);

		// Check if item was found
		if (item && item.value && item.value.market_price) {
			const marketPrice = item.value.market_price;

			// Calculate total market value
			ammountField.innerHTML += `(${formatToCurrency(ammount * marketPrice)})`;
		} else {
			console.error(`Item with ID ${itemId} not found or missing market price.`);
		}
	});
})();