- // ==UserScript==
- // @name View Bazaar Anytime
- // @namespace heartflower.torn.com
- // @version 1.1
- // @description View anyone's bazaar from hospital, jail or travelling!
- // @author Heartflower [2626587]
- // @match https://www.torn.com/bazaar.php*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- // Set to 'true' if you want to show a link to remove your API key
- let removeKeyLink = true;
-
- // Change maximum calls you want to do here. If it says 40, but those 40 items have an UID, it'll actually be 80 calls.
- let maximumCalls = 40;
- let apiCallCount = 0;
-
- let itemIDs = [];
- let itemUIDs = [];
-
- let userName = '';
- let userID = '';
-
- let apiKey = '';
- let storedAPIKey = localStorage.getItem('hf-public-apiKey');
-
- if (storedAPIKey) {
- apiKey = storedAPIKey;
- }
-
- function checkElement() {
- let contentWrapper = document.querySelector('.content-wrapper');
-
- if (contentWrapper) {
- let messageContent = document.querySelector('.msg.right-round');
- let originalText = messageContent.textContent;
-
- if (messageContent && messageContent.textContent.includes('This area is unavailable')) {
- if (userName == '') {
- userName = 'Unknown';
- }
-
- let newText = `${userName}'s bazaar is fetched by the "View Bazaar Anytime" script" with the help of the API!`;
- messageContent.textContent = newText;
-
- if (apiKey !== '') {
- fetchBazaarData();
-
- if (removeKeyLink === true) {
- let link = document.createElement('a');
- link.href = '#'; // Set a placeholder href
-
- link.textContent = ' Click here to remove your (public) API key!';
-
- // Add click event listener to the link
- link.addEventListener('click', function(event) {
- event.preventDefault(); // Prevent the default link behavior
-
- localStorage.removeItem('hf-public-apiKey');
- alert('API key successfully removed!');
- link.remove();
-
- let enterLink = document.createElement('a');
- enterLink.href = '#'; // Set a placeholder href
-
- enterLink.textContent = ' Click here to enter your (public) API key!';
-
-
- // Add click event listener to the link
- enterLink.addEventListener('click', function(event) {
- event.preventDefault(); // Prevent the default link behavior
- promptAPIKey();
- link.remove();
- });
-
- messageContent.appendChild(enterLink);
- });
-
- messageContent.appendChild(link);
- }
-
- } else {
- let link = document.createElement('a');
- link.href = '#'; // Set a placeholder href
- link.textContent = ' Click here to enter your (public) API key!';
-
- // Add click event listener to the link
- link.addEventListener('click', function(event) {
- event.preventDefault(); // Prevent the default link behavior
- promptAPIKey();
- });
-
- messageContent.appendChild(link);
- }
- }
- }
- }
-
- function promptAPIKey() {
- let enterAPIKey = prompt('Enter a public API key here:');
-
- if (enterAPIKey !== null && enterAPIKey.trim() !== '') {
- localStorage.setItem('hf-public-apiKey', enterAPIKey);
- alert('API key set succesfully');
-
- fetchBazaarData();
- } else {
- alert('No valid API key entered!');
- }
- }
-
- function checkUserID() {
- let url = new URL(window.location.href);
- userID = url.searchParams.get('userId');
-
- let apiUrl = `https://api.torn.com/user/${userID}?key=${apiKey}&selections=basic&comment=ViewBazaarAnytime`;
-
- fetch(apiUrl)
- .then(response => response.json())
- .then(data => {
- userName = data.name;
- console.log(userName);
- })
- .catch(error => console.error('Error fetching data: ' + error));
-
- }
-
- function createTable (data) {
- let contentWrapper = document.querySelector('.content-wrapper');
-
- let tableDiv = document.createElement('div');
- tableDiv.style.paddingTop = '16px';
-
- let table = document.createElement('table');
- table.style.margin = '0 auto';
- table.style.background = 'var(--default-bg-panel-color)';
- table.style.width = '100%';
-
- let thead = document.createElement('thead');
-
- let tbody = document.createElement('tbody');
- tbody.style.borderRadius = '5px';
-
-
- // Create table headers
- let headers = ['Image', 'Name', 'Bonus', 'Stock', 'Price each', 'Price total', 'Lowest price in other bazaars'];
- let headerRow = document.createElement('tr');
- headers.forEach(function(header) {
- let th = document.createElement('th');
- th.style.padding = '4px';
- th.textContent = header;
- th.style.background = 'var(--tabs-active-bg-gradient)';
- th.style.color = 'var(--default-color)';
- th.style.fontWeight = 'bold';
- th.style.textAlign = 'center';
- th.style.padding = '8px 4px';
- th.style.borderBottom = '1px solid grey';
- th.style.borderBottomColor = 'var(--default-panel-divider-outer-side-color)';
-
- headerRow.appendChild(th);
- });
- thead.appendChild(headerRow);
- table.appendChild(thead);
-
- // Create table body
- data.forEach(function(item, index) {
- let row = document.createElement('tr');
- row.style.borderBottom = '1px solid grey';
- row.style.borderBottomColor = 'var(--default-panel-divider-outer-side-color)';
-
- let itemID = item.ID;
-
- let itemUID = item.UID;
- let bonusText = '';
- if (itemUID) {
- itemUIDs.push({ uid: itemUID, index: index});
- bonusText = 'Loading...';
- }
-
- // Store itemID with index
- itemIDs.push({ id: itemID, index: index});
-
- createCell('Image', row, itemID);
- createCell(item.name, row);
- createCell(bonusText, row);
- createCell(item.quantity, row);
- createCell(item.price.toLocaleString('en-US', {style: 'currency', currency: 'USD', maximumFractiondigits: 0, minimumFractionDigits: 0}), row);
- createCell((item.quantity * item.price).toLocaleString('en-US', {style: 'currency', currency: 'USD', maximumFractiondigits: 0, minimumFractionDigits: 0}), row);
- createCell('Loading...', row);
-
- tbody.appendChild(row);
- });
-
- table.appendChild(tbody);
- tableDiv.appendChild(table);
- contentWrapper.appendChild(tableDiv);
-
- fetchMarketDataForItems();
- fetchItemDetailsForUIDs();
- }
-
- function createCell(text, row, itemID) {
- let cell = document.createElement('td');
-
- if (text == 'Image') {
- let img = document.createElement('img');
- img = document.createElement('img');
- img.src = `/images/items/${itemID}/large.png`;
- img.srcset = `/images/items/${itemID}/large.png 1x, /images/items/${itemID}/large@2x.png 2x, /images/items/${itemID}/large@3x.png 3x, /images/items/${itemID}/large@4x.png 4x`;
- img.alt = 'Item Image';
- img.style.height = '25px';
- cell.appendChild(img);
- } else {
- cell.textContent = text;
- }
-
- cell.style.color = 'var(--default-color)';
- cell.style.textAlign = 'center';
- cell.style.verticalAlign = 'middle';
- cell.style.padding = '4px';
-
- row.appendChild(cell);
- }
-
- function fetchBazaarData() {
- let apiUrl = `https://api.torn.com/user/${userID}?key=${apiKey}&selections=bazaar&comment=ViewBazaarAnytime`;
-
- fetch(apiUrl)
- .then(response => response.json())
- .then(data => {
- createTable(data.bazaar);
- apiCallCount++;
- })
- .catch(error => console.error('Error fetching data: ' + error));
- }
-
- function fetchMarketDataForItems() {
- let itemsToFetch = Math.min(maximumCalls, itemIDs.length);
-
- for (let i = 0; i < itemsToFetch; i++) {
- let { id, index } = itemIDs[i];
- fetchMarketData(id, index);
- }
-
- if (itemIDs.length > maximumCalls) {
- setTimeout(function () {
- fetchMarketDataForItems();
- }, 60000);
- }
- }
-
- function fetchMarketData(itemID, index) {
- let apiUrl = `https://api.torn.com/market/${itemID}?selections=bazaar&key=${apiKey}&comment=ViewBazaarAnytime`;
-
- // Make the API call
- fetch(apiUrl)
- .then(response => response.json())
- .then(data => {
- if (data.bazaar && data.bazaar.length > 0) {
- let lowestPrice = data.bazaar[0].cost;
-
- // Update table with lowest bazaar price
- let table = document.querySelector('table');
- let cell = table.rows[index + 1].cells[6];
- cell.textContent = lowestPrice.toLocaleString('en-US', {style: 'currency', currency: 'USD', maximumFractiondigits: 0, minimumFractionDigits: 0});
-
- // Remove from itemIDs
- itemIDs = itemIDs.filter(item => item.id !== itemID);
- } else {
- throw new Error('No items found in the bazaar');
- }
- })
- .catch(error => console.error('Error fetching data: ' + error));
- }
-
- function fetchItemDetailsForUIDs() {
- console.log('Fetching all item details');
- let itemsToFetch = Math.min(maximumCalls, itemUIDs.length);
-
- for (let i = 0; i < itemsToFetch; i++) {
- let { uid, index } = itemUIDs[i];
- fetchItemDetails(uid, index);
- }
-
- if (itemIDs.length > maximumCalls) {
- setTimeout(function () {
- fetchItemDetailsForUIDs();
- }, 60000);
- }
- }
-
- function fetchItemDetails(itemUID, index) {
- console.log('Fetching item details');
-
- let apiUrl = `https://api.torn.com/torn/${itemUID}?selections=itemdetails&key=${apiKey}&comment=ViewBazaarAnytime`;
-
- console.log(apiUrl);
-
- // Make the API call
- fetch(apiUrl)
- .then(response => response.json())
- .then(data => {
- if (data.itemdetails) {
- let rarity = data.itemdetails.rarity;
-
- if (rarity == 'None') {
- rarity = '';
- }
-
- let quality = data.itemdetails.quality;
- let bonuses = data.itemdetails.bonuses;
-
- let bonusText = '';
-
- if (bonuses) {
- if (Object.keys(bonuses).length === 1) {
- // If there is only one bonus
- let bonus = bonuses[Object.keys(bonuses)[0]];
- bonusText = `<p style="padding:4px">${bonus.value}% ${bonus.bonus}</p>`;
- } else if (Object.keys(bonuses).length === 2) {
- // If there are two bonuses
- Object.keys(bonuses).forEach(key => {
- let bonus = bonuses[key];
- bonusText += `<p style="padding:4px">${bonus.value}% ${bonus.bonus}</p>`;
- });
- }
- }
-
- // Update table with bonus text
- let table = document.querySelector('table');
- let cell = table.rows[index + 1].cells[2];
- cell.innerHTML = `<p style="padding:4px">${rarity}<p>${quality} Quality</p>${bonusText}`;
-
- // Remove from itemUIDs
- itemUIDs = itemUIDs.filter(item => item.uid !== itemUID);
- } else {
- throw new Error('No item details found');
- }
- })
- .catch(error => console.error('Error fetching data: ' + error));
- }
-
- checkUserID();
- setTimeout(checkElement, 300);
-
- })();