View Bazaar Anytime

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

Verze ze dne 13. 02. 2024. Zobrazit nejnovější verzi.

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

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

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

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

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

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

})();