View Bazaar Anytime

View Torn's bazaar from hospital, jail or travelling!

Version au 13/02/2024. Voir la dernière version.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         View Bazaar Anytime
// @namespace    heartflower.torn.com
// @version      1.0
// @description  View Torn'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';

    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();
                } 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}/[email protected] 2x, /images/items/${itemID}/[email protected] 3x, /images/items/${itemID}/[email protected] 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);

})();