Bazaar Item Search powered by IronNerd

View items you are searching for in bazaars!

当前为 2025-03-04 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Bazaar Item Search powered by IronNerd
// @namespace    [email protected]
// @version      0.5
// @description  View items you are searching for in bazaars!
// @author       Nurv [669537]
// @match        https://www.torn.com/page.php?sid=ItemMarket*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-end
// @license      Copyright IronNerd.me
// @connect      ironnerd.me
// ==/UserScript==

(function () {
    'use strict';

    const BACKEND_URL = 'https://www.ironnerd.me';
    const ongoingRequests = new Set();
    let allBazaarItems = [];
    const VISITED_DURATION = 10 * 60 * 1000;
    let currentItemData = null;
    let lastUrl = location.href;
    let sortKey = 'price';
    let sortOrder = 'asc';

    function init() {
        injectAdditionalStyles();
        ensureBazaarEnhancerContainer().then(container => {
            initTabbedInterface(container);
            observeDarkMode();
            const info = getItemInfoFromURL();
            if (info.itemID) {
                currentItemData = info;
                fetchBazaarItems(info.itemID);
            } else {
                clearListingsData();
            }
            adjustBazaarEnhancerContainerTheme();
        });
    }

    function getItemInfoFromURL() {
        const url = new URL(window.location.href);
        let itemID = null;
        let itemName = '';
        if (url.hash) {
            let hash = url.hash.startsWith("#/") ? url.hash.substring(2) : url.hash.substring(1);
            let params = new URLSearchParams(hash);
            itemID = params.get("itemID");
            itemName = decodeURIComponent(params.get("itemName") ?? "");

        }
        if (!itemID) {
            let params = url.searchParams;
            itemID = params.get("itemID");
            itemName = decodeURIComponent(params.get("itemName") ?? "");
        }
        return {
            itemID: itemID ? parseInt(itemID, 10) : null,
            itemName: itemName
        };
    }

    function clearListingsData() {
        const topCheapestView = document.getElementById('topCheapestView');
        const fullListingsView = document.getElementById('fullListingsView');
        if (topCheapestView) {
            topCheapestView.innerHTML = `<p>No item selected.</p>`;
        }
        if (fullListingsView) {
            fullListingsView.innerHTML = `<p>No item selected.</p>`;
        }
    }

    function recordVisitedLink(link) {
        const key = 'visited_' + link.href;
        const now = Date.now();
        localStorage.setItem(key, now);
        link.classList.add('visited-link');
        scheduleVisitedRemoval(link, VISITED_DURATION);
    }

    function scheduleVisitedRemoval(link, delay) {
        if (link._visitedTimer) {
            clearTimeout(link._visitedTimer);
        }
        link._visitedTimer = setTimeout(() => {
            link.classList.remove('visited-link');
            localStorage.removeItem('visited_' + link.href);
            delete link._visitedTimer;
        }, delay);
    }

    function checkAndScheduleVisited(link) {
        const key = 'visited_' + link.href;
        const visitedTime = parseInt(localStorage.getItem(key), 10);
        if (visitedTime) {
            const elapsed = Date.now() - visitedTime;
            if (elapsed < VISITED_DURATION) {
                link.classList.add('visited-link');
                scheduleVisitedRemoval(link, VISITED_DURATION - elapsed);
            } else {
                link.classList.remove('visited-link');
                localStorage.removeItem(key);
            }
        }
    }

    function createCellWithLink(url, text) {
        const td = document.createElement('td');
        const a = document.createElement('a');
        a.href = url;
        a.innerText = text;
        a.target = '_blank';
        a.style.color = '#007bff';
        a.style.textDecoration = 'none';
        a.addEventListener('click', () => { recordVisitedLink(a); });
        checkAndScheduleVisited(a);
        a.addEventListener('mouseover', () => { a.style.textDecoration = 'underline'; });
        a.addEventListener('mouseout', () => { a.style.textDecoration = 'none'; });
        td.appendChild(a);
        return td;
    }

    function createCell(content) {
        const td = document.createElement('td');
        td.innerText = content;
        return td;
    }

    function createCellWithImage(src, alt) {
        const td = document.createElement('td');
        const img = document.createElement('img');
        img.src = src;
        img.alt = alt;
        img.style.height = '30px';
        img.setAttribute('loading', 'lazy');
        td.appendChild(img);
        return td;
    }

    function formatTimestamp(unixTime) {
        if (unixTime.toString().length === 10) {
            unixTime = unixTime * 1000;
        }
        const date = new Date(unixTime);
        const now = new Date();
        const diff = Math.floor((now - date) / 1000);

        if (diff < 60) {
            return diff + 's ago';
        }
        const minutes = Math.floor(diff / 60);
        if (minutes < 60) {
            return minutes + 'm ago';
        }
        const hours = Math.floor(minutes / 60);
        if (hours < 24) {
            return hours + 'h ago';
        }
        const days = Math.floor(hours / 24);
        return days + 'd ago';
    }

    function ensureBazaarEnhancerContainer() {
        return new Promise(resolve => {
            if (document.querySelector('.captcha-container')) {
                return;
            }
            let container = document.getElementById('bazaar-enhancer-container');
            if (container) {
                return resolve(container);
            }
            container = document.createElement('div');
            container.id = 'bazaar-enhancer-container';
            container.style.overflow = 'hidden';

            let target = document.querySelector('.delimiter___zFh2E');
            if (target && target.parentNode) {
                target.parentNode.insertBefore(container, target.nextSibling);
                return resolve(container);
            }
            const observer = new MutationObserver((mutations, obs) => {
                if (document.querySelector('.captcha-container')) {
                    obs.disconnect();
                    return;
                }
                target = document.querySelector('.delimiter___zFh2E');
                if (target && target.parentNode) {
                    target.parentNode.insertBefore(container, target.nextSibling);
                    obs.disconnect();
                    return resolve(container);
                }
            });
            observer.observe(document.body, { childList: true, subtree: true });

        });
    }

    function initTabbedInterface(container) {
        container.innerHTML = '';

        const nav = document.createElement('div');
        nav.id = 'bazaar-nav';
        nav.style.display = 'flex';
        nav.style.justifyContent = 'center';
        nav.style.marginBottom = '10px';

        const btnTopCheapest = document.createElement('button');
        btnTopCheapest.innerText = 'Top 3';
        btnTopCheapest.addEventListener('click', () => { setActiveTab(0); });

        const btnFullListings = document.createElement('button');
        btnFullListings.innerText = 'All Bazaars';
        btnFullListings.addEventListener('click', () => { setActiveTab(1); });

        nav.appendChild(btnTopCheapest);
        nav.appendChild(btnFullListings);
        container.appendChild(nav);

        const topCheapestView = document.createElement('div');
        topCheapestView.id = 'topCheapestView';
        topCheapestView.style.padding = '10px';
        topCheapestView.innerHTML = '<p>Loading top cheapest listings...</p>';

        const fullListingsView = document.createElement('div');
        fullListingsView.id = 'fullListingsView';
        fullListingsView.style.padding = '10px';
        fullListingsView.style.maxHeight = '350px';
        fullListingsView.style.height = 'auto';
        fullListingsView.style.overflowY = 'auto';
        fullListingsView.innerHTML = '<p>Loading full listings...</p>';

        container.appendChild(topCheapestView);
        container.appendChild(fullListingsView);

        setActiveTab(0);
    }

    function setActiveTab(tabIndex) {
        const topCheapestView = document.getElementById('topCheapestView');
        const fullListingsView = document.getElementById('fullListingsView');
        if (tabIndex === 0) {
            topCheapestView.style.display = 'block';
            fullListingsView.style.display = 'none';
        } else {
            topCheapestView.style.display = 'none';
            fullListingsView.style.display = 'block';
        }
    }

    function sortItems(items) {
        return items.slice().sort((a, b) => {
            let valA = a[sortKey], valB = b[sortKey];
            if (valA < valB) return sortOrder === 'asc' ? -1 : 1;
            if (valA > valB) return sortOrder === 'asc' ? 1 : -1;
            return 0;
        });
    }

    function renderListings() {
        if (currentItemData && allBazaarItems.length > 0) {
            const sortedItems = sortItems(allBazaarItems);
            const fullListingsView = document.getElementById('fullListingsView');
            const topCheapestView = document.getElementById('topCheapestView');
            displayFullListings(sortedItems, fullListingsView);
            displayTopCheapestItems(sortedItems.slice(0, 3), currentItemData.itemName, topCheapestView);
        }
    }

    function createSortableHeader(text, key) {
        const th = document.createElement('th');
        th.innerText = text;
        th.style.border = '1px solid #ccc';
        th.style.padding = '8px';
        th.style.backgroundColor = '#e0e0e0';
        th.style.textAlign = 'center';
        th.style.fontSize = '14px';
        th.style.cursor = 'pointer';
        th.addEventListener('click', () => {
            if (sortKey === key) {
                sortOrder = sortOrder === 'asc' ? 'desc' : 'asc';
            } else {
                sortKey = key;
                sortOrder = 'asc';
            }
            renderListings();
        });
        return th;
    }

    function fetchBazaarItems(itemID) {
        if (!itemID) {
            return;
        }
        const fullListingsView = document.getElementById('fullListingsView');
        const topCheapestView = document.getElementById('topCheapestView');
        if (ongoingRequests.has(`bazaar_items_${itemID}`)) return;
        ongoingRequests.add(`bazaar_items_${itemID}`);
        fullListingsView.innerHTML = `<p>Loading full listings...</p><div class="loading-spinner"></div>`;
        topCheapestView.innerHTML = `<p>Loading top 3 cheapest items...</p><div class="loading-spinner"></div>`;
        GM_xmlhttpRequest({
            method: 'GET',
            url: `${BACKEND_URL}/get_bazaar_items/${itemID}`,
            headers: { 'Accept': 'application/json' },
            onload: function(response) {
                ongoingRequests.delete(`bazaar_items_${itemID}`);
                if (response.status === 200) {
                    try {
                        const data = JSON.parse(response.responseText);
                        if (data.bazaar_items) {
                            allBazaarItems = data.bazaar_items;
                            const sortedItems = sortItems(allBazaarItems);
                            displayFullListings(sortedItems, fullListingsView);
                            displayTopCheapestItems(sortedItems.slice(0, 3), currentItemData ? currentItemData.itemName : "", topCheapestView);
                        } else {
                            fullListingsView.innerHTML = `<p>No items found.</p>`;
                            topCheapestView.innerHTML = `<p>No items found.</p>`;
                        }
                    } catch(e) {
                        fullListingsView.innerHTML = `<p>Error parsing server response.</p>`;
                        topCheapestView.innerHTML = `<p>Error parsing server response.</p>`;
                        console.error("Error parsing bazaar items response:", e);
                    }
                } else {
                    fullListingsView.innerHTML = `<p>Error: ${response.status} - ${response.statusText}</p>`;
                    topCheapestView.innerHTML = `<p>Error: ${response.status} - ${response.statusText}</p>`;
                }
            },
            onerror: function(error) {
                ongoingRequests.delete(`bazaar_items_${itemID}`);
                fullListingsView.innerHTML = `<p>Network error occurred. Please try again later.</p>`;
                topCheapestView.innerHTML = `<p>Network error occurred. Please try again later.</p>`;
                console.error("Network error (bazaar items):", error);
            }
        });
    }

    function displayFullListings(items, targetElement) {
        targetElement.innerHTML = '';
        if (items.length === 0) {
            targetElement.innerHTML = `<p>No items found.</p>`;
            return;
        }
        const title = document.createElement('h3');
        title.innerText = `Full Listings`;
        title.style.textAlign = 'center';
        title.style.marginTop = '2px';
        title.style.marginBottom = '10px';
        targetElement.appendChild(title);
        const tableContainer = document.createElement('div');
        tableContainer.style.overflowX = 'auto';
        tableContainer.style.width = '100%';
        const table = document.createElement('table');
        table.className = 'top-cheapest-table';
        table.style.width = '100%';
        table.style.borderCollapse = 'collapse';
        const thead = document.createElement('thead');
        const headerRow = document.createElement('tr');
        headerRow.appendChild(createSortableHeader("Price ($) ↑↓", "price"));
        headerRow.appendChild(createSortableHeader("Quantity ↑↓", "quantity"));
        headerRow.appendChild(createSortableHeader("Updated ↑↓", "last_updated"));
        headerRow.appendChild(createCell("Visit Bazaar"));
        thead.appendChild(headerRow);
        table.appendChild(thead);
        const tbody = document.createElement('tbody');
        items.forEach((item, index) => {
            const tr = document.createElement('tr');
            const rankTd = document.createElement('td');
            rankTd.innerText = index + 1;
            rankTd.style.border = '1px solid #ccc';
            rankTd.style.padding = '6px';
            rankTd.style.textAlign = 'center';
            rankTd.style.fontSize = '14px';
            tr.appendChild(createCell(`$${item.price.toLocaleString()}`));
            tr.appendChild(createCell(item.quantity));
            tr.appendChild(createCell(formatTimestamp(item.last_updated)));
            tr.appendChild(createCellWithLink(`https://www.torn.com/bazaar.php?userID=${item.user_id}`, 'Visit'));
            tbody.appendChild(tr);
        });
        table.appendChild(tbody);
        tableContainer.appendChild(table);
        targetElement.appendChild(tableContainer);
        adjustUnifiedTableTheme();
    }

    function displayTopCheapestItems(items, itemName, targetElement) {
        targetElement.innerHTML = '';
        if (!items || items.length === 0) {
            targetElement.innerHTML = `<p>No items found.</p>`;
            return;
        }
        const title = document.createElement('h3');
        title.innerText = `Top 3 Cheapest ${itemName} Bazaar Items`;
        title.style.textAlign = 'center';
        title.style.marginTop = '2px';
        title.style.marginBottom = '10px';
        targetElement.appendChild(title);
        const tableContainer = document.createElement('div');
        tableContainer.style.overflowX = 'auto';
        tableContainer.style.width = '100%';
        const table = document.createElement('table');
        table.className = 'top-cheapest-table';
        table.style.width = '100%';
        table.style.borderCollapse = 'collapse';
        const thead = document.createElement('thead');
        const headerRow = document.createElement('tr');
        headerRow.appendChild(createSortableHeader("Price ($) ↑↓", "price"));
        headerRow.appendChild(createSortableHeader("Quantity ↑↓", "quantity"));
        headerRow.appendChild(createSortableHeader("Updated ↑↓", "last_updated"));
        headerRow.appendChild(createCell("Visit Bazaar"));
        thead.appendChild(headerRow);
        table.appendChild(thead);
        const tbody = document.createElement('tbody');
        items.forEach((item, index) => {
            const tr = document.createElement('tr');
            const priceTd = document.createElement('td');
            priceTd.innerText = `$${item.price.toLocaleString()}`;
            priceTd.style.border = '1px solid #ccc';
            priceTd.style.padding = '6px';
            priceTd.style.textAlign = 'center';
            priceTd.style.fontSize = '14px';
            tr.appendChild(priceTd);
            const quantityTd = document.createElement('td');
            quantityTd.innerText = item.quantity;
            quantityTd.style.border = '1px solid #ccc';
            quantityTd.style.padding = '6px';
            quantityTd.style.textAlign = 'center';
            quantityTd.style.fontSize = '14px';
            tr.appendChild(quantityTd);
            const updatedTd = document.createElement('td');
            updatedTd.innerText = formatTimestamp(item.last_updated);
            updatedTd.style.border = '1px solid #ccc';
            updatedTd.style.padding = '6px';
            updatedTd.style.textAlign = 'center';
            updatedTd.style.fontSize = '14px';
            tr.appendChild(updatedTd);
            const bazaarTd = document.createElement('td');
            bazaarTd.style.border = '1px solid #ccc';
            bazaarTd.style.padding = '6px';
            bazaarTd.style.textAlign = 'center';
            bazaarTd.style.fontSize = '14px';
            const bazaarLink = createCellWithLink(`https://www.torn.com/bazaar.php?userID=${item.user_id}`, 'Visit');
            bazaarTd.appendChild(bazaarLink.firstChild);
            tr.appendChild(bazaarTd);
            tbody.appendChild(tr);
        });
        table.appendChild(tbody);
        tableContainer.appendChild(table);
        targetElement.appendChild(tableContainer);
        adjustUnifiedTableTheme();
    }

    function adjustUnifiedTableTheme() {
        const isDarkMode = document.body.classList.contains('dark-mode');
        const tables = document.querySelectorAll('.top-cheapest-table');
        tables.forEach(table => {
            if (isDarkMode) {
                table.style.backgroundColor = '#1c1c1c';
                table.style.color = '#f0f0f0';
                table.querySelectorAll('th').forEach(th => {
                    th.style.backgroundColor = '#444';
                    th.style.color = '#ffffff';
                });
                table.querySelectorAll('tr:nth-child(even)').forEach(tr => {
                    tr.style.backgroundColor = '#2a2a2a';
                });
                table.querySelectorAll('tr:nth-child(odd)').forEach(tr => {
                    tr.style.backgroundColor = '#1e1e1e';
                });
                table.querySelectorAll('td a').forEach(a => {
                    a.style.color = '#4ea8de';
                });
            } else {
                table.style.backgroundColor = '#fff';
                table.style.color = '#000';
                table.querySelectorAll('th').forEach(th => {
                    th.style.backgroundColor = '#f2f2f2';
                    th.style.color = '#000';
                });
                table.querySelectorAll('tr:nth-child(even)').forEach(tr => {
                    tr.style.backgroundColor = '#f9f9f9';
                });
                table.querySelectorAll('tr:nth-child(odd)').forEach(tr => {
                    tr.style.backgroundColor = '#fff';
                });
                table.querySelectorAll('td a').forEach(a => {
                    a.style.color = '#007bff';
                });
            }
        });
    }

    function adjustBazaarEnhancerContainerTheme() {
        const container = document.getElementById('bazaar-enhancer-container');
        const isDarkMode = document.body.classList.contains('dark-mode');
        if (container) {
            if (isDarkMode) {
                container.style.backgroundColor = 'rgba(0,0,0,0.6)';
                container.style.color = '#f0f0f0';
                container.style.border = '1px solid rgba(255,255,255,0.1)';
                container.style.boxShadow = '0 4px 8px rgba(0,0,0,0.4)';
            } else {
                container.style.backgroundColor = '#ffffff';
                container.style.color = '#000000';
                container.style.border = '1px solid #ddd';
                container.style.boxShadow = '0 4px 8px rgba(0,0,0,0.1)';
            }
        }
    }

    function observeDarkMode() {
        const observer = new MutationObserver(() => {
            adjustUnifiedTableTheme();
            adjustBazaarEnhancerContainerTheme();
        });
        observer.observe(document.body, { attributes: true, attributeFilter: ['class'] });
    }

    function injectAdditionalStyles() {
        const style = document.createElement('style');
        style.type = 'text/css';
        style.innerHTML = `
    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
    #bazaar-enhancer-container {
        background-color: #ffffff;
        color: #000000;
        border: 1px solid #ddd;
        box-shadow: 0 4px 8px rgba(0,0,0,0.1);
        border-radius: 8px;
        padding: 10px;
        margin: 10px 0;
        transition: background-color 0.3s, color 0.3s;
    }
    .dark-mode #bazaar-enhancer-container {
        background-color: rgba(0,0,0,0.6);
        color: #f0f0f0;
        border: 1px solid rgba(255,255,255,0.1);
        box-shadow: 0 4px 8px rgba(0,0,0,0.4);
    }
    #showBazaarModal table.bazaar-table,
    #bazaar-enhancer-container table.top-cheapest-table {
        width: 100%;
        border-collapse: collapse;
        margin-top: 10px;
        table-layout: auto;
    }
    #showBazaarModal table.bazaar-table th,
    #showBazaarModal table.bazaar-table td,
    #bazaar-enhancer-container table.top-cheapest-table th,
    #bazaar-enhancer-container table.top-cheapest-table td {
        text-align: center;
        padding: 8px;
        border: 1px solid #ccc;
    }
    #showBazaarModal table.bazaar-table th,
    #bazaar-enhancer-container table.top-cheapest-table th {
        background-color: #f2f2f2;
    }
    .dark-mode #showBazaarModal table.bazaar-table th,
    .dark-mode #showBazaarModal table.bazaar-table td,
    .dark-mode #bazaar-enhancer-container table.top-cheapest-table th,
    .dark-mode #bazaar-enhancer-container table.top-cheapest-table td {
        background-color: #2a2a2a;
        color: #f0f0f0;
    }
    .dark-mode #showBazaarModal table.bazaar-table th,
    .dark-mode #bazaar-enhancer-container table.top-cheapest-table th {
        background-color: #333;
    }
    #showBazaarModal .loading-spinner,
    #bazaar-enhancer-container .loading-spinner {
        border: 4px solid #f3f3f3;
        border-top: 4px solid #3498db;
        border-radius: 50%;
        width: 24px;
        height: 24px;
        animation: spin 2s linear infinite;
        display: inline-block;
        margin-left: 10px;
    }
    #bazaar-enhancer-container a.visited-link,
    #bazaar-enhancer-container table a.visited-link,
    #showBazaarModal a.visited-link,
    #showBazaarModal table a.visited-link {
        color: purple !important;
    }
    #bazaar-nav {
        display: flex;
        justify-content: center;
        margin-bottom: 10px;
    }
    #bazaar-nav button {
        margin: 0 5px;
        padding: 5px 10px;
        cursor: pointer;
        background-color: #f2f2f2;
        color: #000;
        border: 1px solid #ccc;
    }
    .dark-mode #bazaar-nav button {
        background-color: #444;
        color: #fff;
        border: 1px solid #666;
    }
    #topCheapestView, #fullListingsView {
        width: 100%;
        box-sizing: border-box;
        padding: 10px;
    }
    #fullListingsView {
        height: 500px;
        overflow-y: auto;
    }
    `;
        document.head.appendChild(style);
    }


    function checkForItems(wrapper) {
        if (!wrapper || wrapper.id === 'bazaar-enhancer-container') return;
        let itemTile = wrapper.previousElementSibling;
        if (itemTile && itemTile.id === 'bazaar-enhancer-container') {
            itemTile = itemTile.previousElementSibling;
        }
        if (!itemTile) return;
        const nameEl = itemTile.querySelector('.name___ukdHN');
        const btn = itemTile.querySelector('button[aria-controls^="wai-itemInfo-"]');
        if (nameEl && btn) {
            const itemName = nameEl.textContent.trim();
            const idParts = btn.getAttribute('aria-controls').split('-');
            const itemId = idParts[idParts.length - 1];
            currentItemData = {
                itemID: parseInt(itemId, 10),
                itemName: itemName
            };
            fetchBazaarItems(currentItemData.itemID);
        }
    }

    function checkForItemsMobile() {
        if (window.innerWidth >= 784) return;
        const sellerList = document.querySelector('ul.sellerList___e4C9_');

        const headerEl = document.querySelector('.itemsHeader___ZTO9r .title___ruNCT');
        const itemName = headerEl ? headerEl.textContent.trim() : "Unknown";
        const btn = document.querySelector('.itemsHeader___ZTO9r button[aria-controls^="wai-itemInfo-"]');
        let itemId = null;
        if (btn) {
            const parts = btn.getAttribute('aria-controls').split('-');
            itemId = parts.length > 2 ? parts[parts.length - 2] : parts[parts.length - 1];
        }
        if (!itemId) return;
        currentItemData = {
            itemID: parseInt(itemId, 10),
            itemName: itemName
        };
        fetchBazaarItems(currentItemData.itemID);
    }

    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            mutation.addedNodes.forEach(node => {
                if (node.nodeType !== Node.ELEMENT_NODE) return;
                if (window.innerWidth < 784 && node.classList.contains('sellerList___e4C9_')) {
                    checkForItemsMobile();
                } else if (window.innerWidth >= 784 && node.className.includes("sellerListWrapper")) {
                    checkForItems(node);
                }
            });
        });
    });
    observer.observe(document.body, { childList: true, subtree: true });

    setInterval(() => {
        if (location.href !== lastUrl) {
            lastUrl = location.href;
            setTimeout(() => {
                let info = getItemInfoFromURL();
                if (info.itemID) {
                    currentItemData = info;
                    fetchBazaarItems(info.itemID);
                } else {
                    if (window.innerWidth < 784) {
                        checkForItemsMobile();
                    } else {
                        const wrapper = document.querySelector('[class*="sellerListWrapper"]');
                        if (wrapper) checkForItems(wrapper);
                        else {
                            clearListingsData();
                            currentItemData = null;
                        }
                    }
                }
            }, 100);
        }
    }, 500);
    init()
})();