View Bazaar Anytime

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

Versión del día 13/02/2024. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==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);

})();