您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
The new bazaar directory feature doesn't tell you anything about what is in each bazaar. This replaces the (largely) useless counter showing how many favorites a bazaar has with a button to show their bazaar's contents instead.
- // ==UserScript==
- // @name Bazaar Directory - WTF is in there?
- // @namespace Violentmonkey Scripts
- // @match https://www.torn.com/page.php*
- // @grant GM_xmlhttpRequest
- // @version 1.0.1
- // @author Titanic_
- // @license MIT
- // @description The new bazaar directory feature doesn't tell you anything about what is in each bazaar. This replaces the (largely) useless counter showing how many favorites a bazaar has with a button to show their bazaar's contents instead.
- // ==/UserScript==
- let userApiKey = getData("API_KEY") || "";
- const bazaarIconSVG = `<svg class="bazaar-icon" style="scale: 0.75;"></svg>`;
- window.MyCustomBazaarInterval = null;
- async function fetchApi(endpoint, selections = "basic", apiKeyToUse = userApiKey) {
- if (!apiKeyToUse) {
- console.warn("API Key not set. Cannot fetch API.");
- return Promise.resolve({ error: { code: 0, error: "API Key not set" } });
- }
- return new Promise((resolve) => {
- GM_xmlhttpRequest({
- method: "GET",
- url: `https://api.torn.com/${endpoint}?key=${apiKeyToUse}&selections=${selections}`,
- timeout: 15000,
- onload: function (response) {
- let parsedJson;
- try {
- parsedJson = JSON.parse(response.responseText);
- } catch (e) {
- console.error(`Error parsing JSON response:`, e, "Response:", response.responseText);
- resolve({ error: { error: "JSON Parse Error", details: e.message, responseText: response.responseText } });
- return;
- }
- if (parsedJson?.error) {
- const errorMessage = parsedJson.error.error || JSON.stringify(parsedJson.error);
- if (parsedJson.error.error !== "API Key not set") console.error(`API Error (Status: ${response.status}): ${errorMessage}`);
- resolve(parsedJson);
- return;
- }
- if (response.status >= 200 && response.status < 300) resolve(parsedJson);
- else {
- console.error(`HTTP Error ${response.status}: Non-success status without specific API error in JSON.`, "Response:", response.responseText);
- resolve({
- error: {
- error: `HTTP Error ${response.status}`,
- details: "Server returned non-2xx status without a Torn API error object in JSON.",
- responseText: response.responseText,
- },
- });
- }
- },
- onerror: function (response) {
- console.error("Network Error:", response.statusText || "Unknown network issue", response);
- resolve({ error: { error: "Network Error", details: response.statusText || "Unknown network issue" } });
- },
- ontimeout: function () {
- console.error("Request Timeout");
- resolve({ error: { error: "Request Timeout" } });
- },
- });
- });
- }
- function checkUrl() {
- if (!window.location.href.includes("page.php?sid=bazaar")) {
- if (window.MyCustomBazaarInterval) {
- clearInterval(window.MyCustomBazaarInterval);
- window.MyCustomBazaarInterval = null;
- }
- return;
- }
- addBazaarIcons();
- }
- function addBazaarIcons() {
- document.querySelectorAll("li[class^=bazaarWrap]").forEach((row) => {
- const linkEl = row.querySelector("a[href*='bazaar.php']");
- if (!linkEl) return;
- const statsWrap = linkEl.querySelector("div[class^=statsWrap]");
- if (statsWrap) statsWrap.remove();
- if (!linkEl.querySelector(".bazaar-icon-container")) {
- const bazaarIcon = Object.assign(document.createElement("div"), {
- className: "bazaar-icon-container",
- innerHTML: bazaarIconSVG,
- style: "cursor: pointer; float: right; padding-left: 8px;",
- });
- linkEl.append(bazaarIcon);
- if (!bazaarIcon.dataset.listenerAttached) {
- bazaarIcon.addEventListener("click", (e) => {
- e.preventDefault();
- e.stopPropagation();
- toggleExpand(row);
- });
- bazaarIcon.dataset.listenerAttached = "true";
- }
- }
- });
- }
- function toggleExpand(row) {
- const existingDetailsDiv = row.querySelector(".expanded-bazaar-details");
- document.querySelectorAll(".expanded-bazaar-details").forEach((div) => {
- if (div.parentElement !== row) div.style.display = "none";
- });
- if (existingDetailsDiv) existingDetailsDiv.style.display = existingDetailsDiv.style.display === "none" ? "block" : "none";
- else {
- const detailsDiv = Object.assign(document.createElement("div"), {
- className: "expanded-bazaar-details",
- style: "",
- });
- const filterInput = Object.assign(document.createElement("input"), {
- type: "text",
- placeholder: "Filter item name",
- style: "width: calc(100% + 10px); text-align: center; background-color: #333333; color: #e0e0e0 !important; border: 1px outset #4f4f4f; padding: 3px;",
- });
- filterInput.addEventListener("input", () => {
- filterTable(table, filterInput.value);
- });
- detailsDiv.appendChild(filterInput);
- const table = Object.assign(document.createElement("table"), {
- style: "width: 100%; border-collapse: collapse; background-color: #383838;",
- });
- const headerRow = table.createTHead().insertRow();
- const columnHeaders = ["Name", "#", "$"];
- columnHeaders.forEach((header) => {
- headerRow.appendChild(
- Object.assign(document.createElement("th"), {
- textContent: header,
- style: `border: 1px solid #4F4F4F; padding: 5px; text-align: ${header == "Name" ? "left" : "right"}; background-color: #454545; color: #e0e0e0;`,
- })
- );
- });
- const placeholderCell = table.createTBody().insertRow().insertCell();
- Object.assign(placeholderCell, {
- colSpan: columnHeaders.length,
- textContent: "Details will be loaded here.",
- style: "text-align: center; padding: 3px; font-style: italic; color: #a0a0a0; border: 1px solid #4F4F4F;",
- });
- detailsDiv.appendChild(table);
- row.appendChild(detailsDiv);
- detailsDiv.style.display = "block";
- populateBazaar(row, table);
- }
- }
- function filterTable(table, searchText) {
- Array.from(table.querySelector("tbody").querySelectorAll("tr")).forEach((row) => {
- const nameCell = row.querySelector("td:first-child");
- if (nameCell) {
- const name = nameCell.textContent.toLowerCase();
- if (name.includes(searchText.toLowerCase())) row.style.display = "";
- else row.style.display = "none";
- }
- });
- }
- async function populateBazaar(row, table) {
- const url = row.querySelector("a[href*='bazaar.php']").href;
- const userID = new URL(url).searchParams.get("userId");
- const data = await fetchApi(`user/${userID}`, "bazaar");
- const tbody = table.querySelector("tbody");
- tbody.innerHTML = "";
- if (data.error) {
- const errorRow = tbody.insertRow();
- const errorCell = errorRow.insertCell();
- errorCell.colSpan = 3;
- errorCell.style = "text-align: center; padding: 10px; font-style: italic; color: #a0a0a0; border: 1px solid #4F4F4F;";
- if (data.error.error === "API Key not set") {
- const setKeyLink = Object.assign(document.createElement("a"), {
- href: "#",
- textContent: "Click to set Public API",
- style: "color: #88C9F2; cursor: pointer;",
- });
- setKeyLink.onclick = async (e) => {
- e.preventDefault();
- const newApiKeyInput = prompt("Please enter your Torn API (Public) key:");
- if (newApiKeyInput) {
- const trimmedKey = newApiKeyInput.trim();
- if (trimmedKey !== "") {
- setData("API_KEY", trimmedKey);
- userApiKey = trimmedKey;
- tbody.innerHTML = "";
- const loadingRow = tbody.insertRow();
- const loadingCell = loadingRow.insertCell();
- loadingCell.colSpan = 3;
- loadingCell.textContent = "Reloading bazaar data...";
- loadingCell.style = "text-align: center; padding: 10px; font-style: italic; color: #a0a0a0; border: 1px solid #4F4F4F;";
- await populateBazaar(row, table);
- } else {
- alert("API Key cannot be empty.");
- }
- }
- };
- errorCell.innerHTML = "";
- errorCell.appendChild(setKeyLink);
- } else errorCell.textContent = `Error loading bazaar: ${data.error.error}`;
- return;
- }
- if (!data.bazaar || data.bazaar.length === 0) {
- const noItemsRow = tbody.insertRow();
- const noItemsCell = noItemsRow.insertCell();
- noItemsCell.colSpan = 3;
- noItemsCell.textContent = "No items available in this bazaar.";
- noItemsCell.style = "text-align: center; padding: 10px; font-style: italic; color: #a0a0a0; border: 1px solid #4F4F4F;";
- return;
- }
- const items = data.bazaar.map((item) => ({
- name: item.name,
- amount: item.quantity,
- price: item.price,
- }));
- const sortedItems = items.sort((a, b) => a.name.localeCompare(b.name));
- for (const item of sortedItems) {
- const itemRow = tbody.insertRow();
- itemRow.appendChild(
- Object.assign(document.createElement("td"), {
- textContent: item.name,
- style:
- "border: 1px solid #4F4F4F; padding: 5px; color: #E0E0E0 !important; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100px;",
- })
- );
- itemRow.appendChild(
- Object.assign(document.createElement("td"), {
- textContent: item.amount.toLocaleString(),
- style: "border: 1px solid #4F4F4F; padding: 5px; color: #E0E0E0 !important; text-align: right;",
- })
- );
- itemRow.appendChild(
- Object.assign(document.createElement("td"), {
- textContent: "$" + item.price.toLocaleString(),
- style: "border: 1px solid #4F4F4F; padding: 5px; color: #E0E0E0 !important; text-align: right;",
- })
- );
- }
- const filterInput = row.querySelector('.expanded-bazaar-details > input[type="text"]');
- if (filterInput) {
- filterTable(table, filterInput.value);
- }
- }
- function getData(key) {
- return localStorage.getItem(key);
- }
- function setData(key, value) {
- localStorage.setItem(key, value);
- }
- function addStyle(css) {
- const styleEl = Object.assign(document.createElement("style"), { type: "text/css" });
- styleEl.appendChild(document.createTextNode(css));
- document.head.appendChild(styleEl);
- }
- if (window.MyCustomBazaarInterval) clearInterval(window.MyCustomBazaarInterval);
- window.MyCustomBazaarInterval = setInterval(checkUrl, 1000);
- checkUrl();
- addStyle(`
- .bazaarWrap___XXYgz {
- flex-direction: column;
- height: fit-content !important;
- }
- .expanded-bazaar-details {
- display: block;
- max-width: 100%;
- width: 100%;
- max-height: 200px;
- overflow-y: scroll;
- overflow-x: hidden;
- background-color: #383838;
- border-top: 1px solid #222222;
- clear: both; color: #cccccc;
- padding-right: 10px;
- }
- `);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址