您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
擷取 MSU.io 物品價格與庫存
// ==UserScript== // @name MSU 包包小精靈 // @namespace http://tampermonkey.net/ // @version 0.64 // @author Alex from MyGOTW // @description 擷取 MSU.io 物品價格與庫存 // @match https://msu.io/* // @grant none // @run-at document-end // @license MIT // ==/UserScript== (function() { 'use strict'; function waitForElement(selector) { return new Promise(resolve => { // 如果元素已存在,直接返回 if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } // 建立 observer 監聽 DOM 變化 const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { observer.disconnect(); resolve(document.querySelector(selector)); } }); observer.observe(document.body, { childList: true, subtree: true }); }); } async function initialize() { console.log('Initialize being called with URL:', window.location.href); if (!window.location.href.includes('/marketplace/inventory/')) { return; } // 添加 API 監聽 const originalFetch = window.fetch; window.fetch = async function(...args) { const [resource, config] = args; // 檢查是否為目標 API if (typeof resource === 'string' && resource.includes('/marketplace/api/marketplace/inventory/') && resource.includes('/owned')) { try { const response = await originalFetch.apply(this, args); const clone = response.clone(); const jsonData = await clone.json(); // 將數據保存在全局變數中 window.inventoryData = jsonData; console.log('已保存背包資料:', jsonData); return response; } catch (error) { console.error('監聽 API 時發生錯誤:', error); return originalFetch.apply(this, args); } } return originalFetch.apply(this, args); }; try { // 等待目標元素出現 const targetNode = await waitForElement('div[class*="item-list"]'); const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length) { getNFTitem(); } }); }); observer.observe(targetNode, { childList: true, subtree: true }); // 初始執行一次 getNFTitem(); } catch (error) { console.error('Error initializing:', error); } } const getNFTitem = () => { addStyleToHead(); const articles = document.querySelectorAll('div[class*="item-list"] > article'); let currentActiveBtn = null; let isClickable = true; let allButtons = []; // 新增儲存所有按鈕的陣列 articles.forEach((article, index) => { if (article.querySelector('.click-btn')) return; const nameSpanElement = article.querySelector('.leave-box div div span:first-child'); if (nameSpanElement && nameSpanElement.innerText) { const fragment = document.createDocumentFragment(); let textDiv = document.createElement('div'); textDiv.textContent = '查看市場價格'; textDiv.className = 'click-btn'; allButtons.push(textDiv); // 將按鈕加入陣列 textDiv.onclick = async () => { if (!isClickable) return; isClickable = false; // 設定所有按鈕為禁用狀態 allButtons.forEach(btn => { btn.style.cursor = 'not-allowed'; }); const originalText = textDiv.textContent; textDiv.textContent = ''; textDiv.classList.add('loading'); const itemName = filterNFTitem(nameSpanElement.innerText); const itemCategoryNo = window.inventoryData.records[index].category.categoryNo const searchItem = { name:itemName, categoryNo:itemCategoryNo ? itemCategoryNo : null } const result = await fetchItme(searchItem); textDiv.classList.remove('loading'); textDiv.textContent = result; setTimeout(() => { isClickable = true; // 恢復所有按鈕的狀態 allButtons.forEach(btn => { btn.style.cursor = 'pointer'; }); textDiv.textContent = originalText; }, 3000); } fragment.appendChild(textDiv); article.insertBefore(fragment.firstChild, article.firstChild); article.addEventListener('mouseenter', () => { if (currentActiveBtn && currentActiveBtn !== textDiv) { currentActiveBtn.style.display = 'none'; } textDiv.style.display = 'block'; currentActiveBtn = textDiv; }); } }); } const filterNFTitem = (name) =>{ const match = name.match(/^(.*?)(?=#|$)/); if (match) { return match[1].trim(); // 保留中間的空格,但去除前後空格 } return name; } const addStyleToHead = () => { const style = document.createElement('style'); const css = ` .click-btn { width: 100%; background-color: rebeccapurple; border-radius: 5px; cursor: pointer; color: white; padding: 5px; text-align: center; margin-top: 5px; transition: background-color 0.3s, cursor 0.3s; display: none; z-index: 9999; } .click-btn:hover { background-color: #663399; } /* 新增載入動畫相關樣式 */ .loading { position: relative; min-height: 24px; } .loading::after { content: ''; position: absolute; width: 20px; height: 20px; top: 50%; left: 50%; margin-top: -10px; margin-left: -10px; border: 2px solid #ffffff; border-radius: 50%; border-top-color: transparent; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } `; style.textContent = css; document.head.appendChild(style); } const getLowestPriceItem = (priceData, exactName) => { console.log(exactName) if (!priceData?.items || priceData.items.length === 0) { return null; } // 只篩選完全符合名稱的物品 const exactMatches = priceData.items.filter(item => item.name === exactName); if (exactMatches.length === 0) { return null; } return exactMatches.reduce((lowest, current) => { const currentPrice = BigInt(current.salesInfo?.priceWei || '0'); const lowestPrice = BigInt(lowest.salesInfo?.priceWei || '0'); return currentPrice < lowestPrice ? current : lowest; }, exactMatches[0]); } const fetchItme = async(item) => { try { const searchResult = await fetch("https://msu.io/marketplace/api/marketplace/explore/items", { headers: { "accept": "*/*", "cache-control": "no-cache", "content-type": "application/json", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin" }, body: JSON.stringify({ filter: { name:item.name, categoryNo:item.categoryNo, level:{min:0, max: 250}, potential:{min:0, max: 4}, price:{min:0, max: 10000000000}, starforce:{min:0, max: 25} }, sorting: "ExploreSorting_LOWEST_PRICE", paginationParam: { pageNo: 1, pageSize: 135 } }), method: "POST", mode: "cors", credentials: "include" }); const priceData = await searchResult.json(); const lowestPriceItem = getLowestPriceItem(priceData, item.name); const fullPrice = lowestPriceItem ? (BigInt(lowestPriceItem.salesInfo.priceWei) / BigInt(1e18)) .toString() + '.' + (BigInt(lowestPriceItem.salesInfo.priceWei) % BigInt(1e18)) .toString() .padStart(18, '0') .slice(0, 6) .replace(/\.?0+$/, '') : null; return fullPrice ? `${fullPrice} Neso` : '無上架資料' } catch (error) { console.error(`查詢 ${itemName} 價格時發生錯誤:`, error); return '查詢錯誤,被鎖啦' } } initialize() // URL 變化監聽 const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function (...args) { originalPushState.apply(this, args); handleUrlChange('pushState'); }; history.replaceState = function (...args) { originalReplaceState.apply(this, args); handleUrlChange('replaceState'); }; window.addEventListener('popstate', function () { handleUrlChange('popstate'); }); function handleUrlChange(method) { console.log(`小精靈通知: [${method}] URL 已變化: ${window.location.href}`); initialize(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址