Torn Bazaar Filler

On "Fill" click autofills bazaar item price with lowest bazaar price currently minus $1 (can be customised), shows current price coefficient compared to 3rd lowest, fills max quantity for items, marks checkboxes for guns.

安装此脚本
作者推荐脚本

您可能也喜欢Torn Fast Slots

安装此脚本
  1. // ==UserScript==
  2. // @name Torn Bazaar Filler
  3. // @namespace https://github.com/SOLiNARY
  4. // @version 1.1
  5. // @description On "Fill" click autofills bazaar item price with lowest bazaar price currently minus $1 (can be customised), shows current price coefficient compared to 3rd lowest, fills max quantity for items, marks checkboxes for guns.
  6. // @author Ramin Quluzade, Silmaril [2665762]
  7. // @license MIT License
  8. // @match https://www.torn.com/bazaar.php*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com
  10. // @require https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
  11. // @run-at document-idle
  12. // @grant GM_addStyle
  13. // @grant GM_registerMenuCommand
  14. // ==/UserScript==
  15.  
  16. (function() {
  17. 'use strict';
  18.  
  19. const bazaarUrl = "https://api.torn.com/market/{itemId}?selections=bazaar&key={apiKey}&comment=BazaarFiller";
  20. const marketUrl = "https://api.torn.com/v2/market?id={itemId}&selections=itemMarket&key={apiKey}&comment=BazaarFiller";
  21. const itemUrl = "https://api.torn.com/torn/{itemId}?selections=items&key={apiKey}&comment=BazaarFiller";
  22. let priceDeltaRaw = localStorage.getItem("silmaril-torn-bazaar-filler-price-delta") ?? '-1';
  23. let apiKey = localStorage.getItem("silmaril-torn-bazaar-filler-apikey");
  24.  
  25. try {
  26. GM_registerMenuCommand('Set Price Delta', setPriceDelta);
  27. GM_registerMenuCommand('Set Api Key', function() { checkApiKey(false); });
  28. } catch (error) {
  29. console.log('[TornBazaarFiller] Tampermonkey not detected!');
  30. }
  31.  
  32. // TornPDA support for GM_addStyle
  33. let GM_addStyle = function (s) {
  34. let style = document.createElement("style");
  35. style.type = "text/css";
  36. style.innerHTML = s;
  37. document.head.appendChild(style);
  38. };
  39.  
  40. GM_addStyle(`.btn-wrap.torn-bazaar-fill-qty-price{float:right;margin-left:auto;z-index:99999}.btn-wrap.torn-bazaar-clear-qty-price{z-index:99999}div.title-wrap div.name-wrap{display:flex;justify-content:flex-end}.wave-animation{position:relative;overflow:hidden}.wave{pointer-events:none;position:absolute;width:100%;height:33px;background-color:transparent;opacity:0;transform:translateX(-100%);animation:waveAnimation 1s cubic-bezier(0, 0, 0, 1)}@keyframes waveAnimation{0%{opacity:1;transform:translateX(-100%)}100%{opacity:0;transform:translateX(100%)}}.overlay-percentage{position:absolute;top:0;background-color:rgba(0, 0, 0, 0.9);padding:0 5px;border-radius:15px;font-size:10px}.overlay-percentage-add{right:-30px}.overlay-percentage-manage{right:0}`);
  41.  
  42. const pages = { "AddItems": 10, "ManageItems": 20};
  43. const addItemsLabels = ["Fill", "Clear"];
  44. const updateItemsLabels = ["Update", "Clear"];
  45.  
  46. const viewPortWidthPx = window.innerWidth;
  47. const isMobileView = viewPortWidthPx <= 784;
  48.  
  49. const observerTarget = $(".content-wrapper")[0];
  50. const observerConfig = { attributes: false, childList: true, characterData: false, subtree: true };
  51.  
  52. const observer = new MutationObserver(function(mutations) {
  53. let mutation = mutations[0].target;
  54. if (mutation.classList.contains("items-cont") || mutation.className.indexOf("core-layout___") > -1 || mutation.classList.contains('ReactVirtualized__Grid__innerScrollContainer')) {
  55. $("ul.ui-tabs-nav").on("click", "li:not(.ui-state-active):not(.ui-state-disabled):not(.m-show)", function() {
  56. observer.observe(observerTarget, observerConfig);
  57. });
  58. $("div[class*=topSection___]").on("click", "div[class*=linksContainer___] a[aria-labelledby=add-items]", function(){
  59. observer.observe(observerTarget, observerConfig);
  60. });
  61. $("div[class*=topSection___]").on("click", "div[class*=listItem___] a[aria-labelledby=add-items]", function(){
  62. observer.observe(observerTarget, observerConfig);
  63. });
  64. $("div[class*=topSection___]").on("click", "div[class*=linksContainer___] a[aria-labelledby=manage-items]", function(){
  65. observer.observe(observerTarget, observerConfig);
  66. });
  67. $("div[class*=topSection___]").on("click", "div[class*=listItem___] a[aria-labelledby=manage-items]", function(){
  68. observer.observe(observerTarget, observerConfig);
  69. });
  70.  
  71. let containerItems = $("ul.items-cont li.clearfix");
  72. containerItems.find("div.title-wrap div.name-wrap").each(function(){
  73. let isParentRowDisabled = this.parentElement.parentElement.classList.contains("disabled");
  74. let alreadyHasFillBtn = this.querySelector(".btn-wrap.torn-bazaar-fill-qty-price") != null;
  75. if (!alreadyHasFillBtn && !isParentRowDisabled){
  76. insertFillAndWaveBtn(this, addItemsLabels, pages.AddItems);
  77. }
  78. });
  79.  
  80. let containerItemsManage = $("div[class*=row___]");
  81. containerItemsManage.find("div[class*=item___] div[class*=desc___]").each(function(){
  82. let alreadyHasUpdateBtn = this.querySelector(".btn-wrap.torn-bazaar-fill-qty-price") != null;
  83. if (!alreadyHasUpdateBtn) {
  84. insertFillAndWaveBtn(this, updateItemsLabels, pages.ManageItems);
  85. }
  86. });
  87. }
  88. });
  89. observer.observe(observerTarget, observerConfig);
  90.  
  91. function insertFillAndWaveBtn(element, buttonLabels, pageType){
  92. const waveDiv = document.createElement('div');
  93. waveDiv.className = 'wave';
  94.  
  95. const outerSpanFill = document.createElement('span');
  96. outerSpanFill.className = 'btn-wrap torn-bazaar-fill-qty-price';
  97. const outerSpanClear = document.createElement('span');
  98. outerSpanClear.className = 'btn-wrap torn-bazaar-clear-qty-price';
  99.  
  100. const innerSpanFill = document.createElement('span');
  101. innerSpanFill.className = 'btn';
  102. const innerSpanClear = document.createElement('span');
  103. innerSpanClear.className = 'btn';
  104. innerSpanClear.style.display = 'none';
  105.  
  106. const inputElementFill = document.createElement('input');
  107. inputElementFill.type = 'button';
  108. inputElementFill.value = buttonLabels[0];
  109. inputElementFill.className = 'torn-btn';
  110. const inputElementClear = document.createElement('input');
  111. inputElementClear.type = 'button';
  112. inputElementClear.value = buttonLabels[1];
  113. inputElementClear.className = 'torn-btn';
  114.  
  115. innerSpanFill.appendChild(inputElementFill);
  116. innerSpanClear.appendChild(inputElementClear);
  117. outerSpanFill.appendChild(innerSpanFill);
  118. outerSpanClear.appendChild(innerSpanClear);
  119.  
  120. element.append(outerSpanFill, outerSpanClear, waveDiv);
  121.  
  122. switch(pageType) {
  123. case pages.AddItems:
  124. $(outerSpanFill).on("click", "input", function(event) {
  125. checkApiKey();
  126. this.parentNode.style.display = "none";
  127. fillQuantityAndPrice(this, pageType);
  128. event.stopPropagation();
  129. });
  130.  
  131. $(outerSpanClear).on("click", "input", function(event) {
  132. this.parentNode.style.display = "none";
  133. clearQuantityAndPrice(this);
  134. event.stopPropagation();
  135. });
  136. break;
  137. case pages.ManageItems:
  138. $(outerSpanFill).on("click", "input", function(event) {
  139. checkApiKey();
  140. // this.parentNode.style.display = "none";
  141. updatePrice(this);
  142. event.stopPropagation();
  143. });
  144.  
  145. // $(outerSpanClear).on("click", "input", function(event) {
  146. // this.parentNode.style.display = "none";
  147. // clearQuantity(this, pageType);
  148. // event.stopPropagation();
  149. // });
  150. break;
  151. }
  152.  
  153. }
  154.  
  155. function insertPercentageSpan(element){
  156. let moneyGroupDiv = element.querySelector("div.price div.input-money-group");
  157.  
  158. if (moneyGroupDiv.querySelector("span.overlay-percentage") === null) {
  159. const percentageSpan = document.createElement('span');
  160. percentageSpan.className = 'overlay-percentage overlay-percentage-add';
  161. moneyGroupDiv.appendChild(percentageSpan);
  162. }
  163.  
  164. return moneyGroupDiv.querySelector("span.overlay-percentage");
  165. }
  166.  
  167. function insertPercentageManageSpan(element){
  168. let moneyGroupDiv = element.querySelector("div.input-money-group");
  169.  
  170. if (moneyGroupDiv.querySelector("span.overlay-percentage") === null) {
  171. const percentageSpan = document.createElement('span');
  172. percentageSpan.className = 'overlay-percentage overlay-percentage-manage';
  173. moneyGroupDiv.appendChild(percentageSpan);
  174. }
  175.  
  176. return moneyGroupDiv.querySelector("span.overlay-percentage");
  177. }
  178.  
  179. function fillQuantityAndPrice(element, pageType){
  180. let amountDiv = element.parentElement.parentElement.parentElement.parentElement.parentElement.querySelector("div.amount-main-wrap");
  181. let priceInputs = amountDiv.querySelectorAll("div.price div input");
  182. let keyupEvent = new Event("keyup", {bubbles: true});
  183. let inputEvent = new Event("input", {bubbles: true});
  184.  
  185. let image = element.parentElement.parentElement.parentElement.parentElement.querySelector("div.image-wrap img");
  186. let numberPattern = /\/(\d+)\//;
  187. let match = image.src.match(numberPattern);
  188. let extractedItemId = 0;
  189. if (match) {
  190. extractedItemId = parseInt(match[1], 10);
  191. } else {
  192. console.error("[TornBazaarFiller] ItemId not found!");
  193. }
  194.  
  195. let requestUrl = priceDeltaRaw.indexOf('[market]') != -1 ? itemUrl : marketUrl;
  196. requestUrl = requestUrl
  197. .replace("{itemId}", extractedItemId)
  198. .replace("{apiKey}", apiKey);
  199.  
  200. let wave = element.parentElement.parentElement.parentElement.querySelector("div.wave");
  201. fetch(requestUrl)
  202. .then(response => response.json())
  203. .then(data => {
  204. if (data.error != null && data.error.code === 2){
  205. apiKey = null;
  206. localStorage.setItem("silmaril-torn-bazaar-filler-apikey", null);
  207. wave.style.backgroundColor = "red";
  208. wave.style.animationDuration = "5s";
  209. console.error("[TornBazaarFiller] Incorrect Api Key:", data);
  210. return;
  211. }
  212. let lowBallPrice = Number.MAX_VALUE;
  213. if (priceDeltaRaw.indexOf('[market]') != -1) {
  214. let priceDelta = priceDeltaRaw.indexOf('[') == -1 ? priceDeltaRaw : priceDeltaRaw.substring(0, priceDeltaRaw.indexOf('['));
  215. let price = data.items[extractedItemId].market_value;
  216. lowBallPrice = Math.round(performOperation(price, priceDelta));
  217. } else {
  218. let price = 999_999_999;
  219. if (data.itemmarket.listings[0].price == null){
  220. console.warn("[TornBazaarFiller] The API is temporarily disabled, please try again later");
  221. }
  222. if (data.itemmarket.item.id != extractedItemId){
  223. console.warn("[TornBazaarFiller] The API is BROKEN!");
  224. }
  225. let priceListings = data.itemmarket.listings;
  226. let bazaarSlotOffset = priceDeltaRaw.indexOf('[') == -1 ? 0 : parseInt(priceDeltaRaw.substring(priceDeltaRaw.indexOf('[') + 1, priceDeltaRaw.indexOf(']')));
  227. let priceDeltaWithoutBazaarOffset = priceDeltaRaw.indexOf('[') == -1 ? priceDeltaRaw : priceDeltaRaw.substring(0, priceDeltaRaw.indexOf('['));
  228. lowBallPrice = Math.round(performOperation(priceListings[Math.min(bazaarSlotOffset, priceListings.length - 1)].price, priceDeltaWithoutBazaarOffset));
  229. let price3rd = priceListings[Math.min(2, priceListings.length - 1)].price;
  230. let priceCoefficient = ((lowBallPrice / price3rd) * 100).toFixed(0);
  231. let percentageOverlaySpan = insertPercentageSpan(amountDiv);
  232. if (priceCoefficient <= 95){
  233. percentageOverlaySpan.style.display = "block";
  234. if (priceCoefficient <= 50){
  235. percentageOverlaySpan.style.color = "red";
  236. wave.style.backgroundColor = "red";
  237. wave.style.animationDuration = "5s";
  238. } else if (priceCoefficient <= 75){
  239. percentageOverlaySpan.style.color = "yellow";
  240. wave.style.backgroundColor = "yellow";
  241. wave.style.animationDuration = "3s";
  242. } else {
  243. percentageOverlaySpan.style.color = "green";
  244. wave.style.backgroundColor = "green";
  245. }
  246. percentageOverlaySpan.innerText = priceCoefficient + "%";
  247. } else {
  248. percentageOverlaySpan.style.display = "none";
  249. wave.style.backgroundColor = "green";
  250. }
  251. }
  252.  
  253. priceInputs[0].value = lowBallPrice;
  254. priceInputs[1].value = lowBallPrice;
  255. priceInputs[0].dispatchEvent(inputEvent);
  256.  
  257. let isQuantityCheckbox = amountDiv.querySelector("div.amount.choice-container") !== null;
  258. if (isQuantityCheckbox){
  259. amountDiv.querySelector("div.amount.choice-container input").click();
  260. } else {
  261. let quantityInput = amountDiv.querySelector("div.amount input");
  262. quantityInput.value = getQuantity(element, pageType);
  263. quantityInput.dispatchEvent(keyupEvent);
  264. }
  265. })
  266. .catch(error => {
  267. wave.style.backgroundColor = "red";
  268. wave.style.animationDuration = "5s";
  269. console.error("[TornBazaarFiller] Error fetching data:", error);
  270. })
  271. .finally(() => {
  272. element.parentNode.parentNode.parentNode.querySelector("span.btn-wrap.torn-bazaar-clear-qty-price span.btn").style.display = "inline-block";
  273. });
  274. wave.style.animation = 'none';
  275. wave.offsetHeight;
  276. wave.style.animation = null;
  277. wave.style.backgroundColor = "transparent";
  278. wave.style.animationDuration = "1s";
  279. }
  280.  
  281. function updatePrice(element){
  282. let moneyGroupDiv;
  283. let parentNode4 = element.parentNode.parentNode.parentNode.parentNode;
  284. if (isMobileView){
  285. if (parentNode4.querySelector("[class*=menuActivators___] button[class*=iconContainer___][aria-label=Manage] span[class*=active___]") == null) {
  286. parentNode4.querySelector("[class*=menuActivators___] button[class*=iconContainer___][aria-label=Manage]").click();
  287. }
  288. moneyGroupDiv = parentNode4.parentNode.querySelector("[class*=bottomMobileMenu___] [class*=priceMobile___]");
  289. } else {
  290. moneyGroupDiv = element.parentNode.parentNode.parentNode.parentNode.querySelector("div[class*=price___]");
  291. }
  292. let priceInputs = moneyGroupDiv.querySelectorAll("div.input-money-group input");
  293. let inputEvent = new Event("input", {bubbles: true});
  294.  
  295. let image = element.parentElement.parentElement.parentElement.parentElement.querySelector("div[class*=imgContainer___] img");
  296. let extractedItemId = getItemIdFromImage(image);
  297.  
  298. let requestUrl = priceDeltaRaw.indexOf('[market]') != -1 ? itemUrl : marketUrl;
  299. requestUrl = requestUrl
  300. .replace("{itemId}", extractedItemId)
  301. .replace("{apiKey}", apiKey);
  302.  
  303. let wave = element.parentElement.parentElement.parentElement.querySelector("div.wave");
  304. fetch(requestUrl)
  305. .then(response => response.json())
  306. .then(data => {
  307. if (data.error != null && data.error.code === 2){
  308. apiKey = null;
  309. localStorage.setItem("silmaril-torn-bazaar-filler-apikey", null);
  310. wave.style.backgroundColor = "red";
  311. wave.style.animationDuration = "5s";
  312. console.error("[TornBazaarFiller] Incorrect Api Key:", data);
  313. return;
  314. }
  315. let lowBallPrice = Number.MAX_VALUE;
  316. if (priceDeltaRaw.indexOf('[market]') != -1) {
  317. let priceDelta = priceDeltaRaw.indexOf('[') == -1 ? priceDeltaRaw : priceDeltaRaw.substring(0, priceDeltaRaw.indexOf('['));
  318. let price = data.items[extractedItemId].market_value;
  319. lowBallPrice = Math.round(performOperation(price, priceDelta));
  320. } else {
  321. let price = 999_999_999;
  322. if (data.itemmarket.listings[0].price == null){
  323. console.warn("[TornBazaarFiller] The API is temporarily disabled, please try again later");
  324. }
  325. if (data.itemmarket.item.id != extractedItemId){
  326. console.warn("[TornBazaarFiller] The API is BROKEN!");
  327. }
  328. let priceListings = data.itemmarket.listings;
  329. let bazaarSlotOffset = priceDeltaRaw.indexOf('[') == -1 ? 0 : parseInt(priceDeltaRaw.substring(priceDeltaRaw.indexOf('[') + 1, priceDeltaRaw.indexOf(']')));
  330. let priceDeltaWithoutBazaarOffset = priceDeltaRaw.indexOf('[') == -1 ? priceDeltaRaw : priceDeltaRaw.substring(0, priceDeltaRaw.indexOf('['));
  331. lowBallPrice = Math.round(performOperation(priceListings[Math.min(bazaarSlotOffset, priceListings.length - 1)].price, priceDeltaWithoutBazaarOffset));
  332. let price3rd = priceListings[Math.min(2, priceListings.length - 1)].cost;
  333. let priceCoefficient = ((lowBallPrice / price3rd) * 100).toFixed(0);
  334. let percentageOverlaySpan = insertPercentageManageSpan(moneyGroupDiv);
  335. if (priceCoefficient <= 95){
  336. percentageOverlaySpan.style.display = "block";
  337. if (priceCoefficient <= 50){
  338. percentageOverlaySpan.style.color = "red";
  339. wave.style.backgroundColor = "red";
  340. wave.style.animationDuration = "5s";
  341. } else if (priceCoefficient <= 75){
  342. percentageOverlaySpan.style.color = "yellow";
  343. wave.style.backgroundColor = "yellow";
  344. wave.style.animationDuration = "3s";
  345. } else {
  346. percentageOverlaySpan.style.color = "green";
  347. wave.style.backgroundColor = "green";
  348. }
  349. percentageOverlaySpan.innerText = priceCoefficient + "%";
  350. } else {
  351. percentageOverlaySpan.style.display = "none";
  352. wave.style.backgroundColor = "green";
  353. }
  354. }
  355.  
  356. priceInputs[0].value = lowBallPrice;
  357. priceInputs[1].value = lowBallPrice;
  358. priceInputs[0].dispatchEvent(inputEvent);
  359. })
  360. .catch(error => {
  361. wave.style.backgroundColor = "red";
  362. wave.style.animationDuration = "5s";
  363. console.error("[TornBazaarFiller] Error fetching data:", error);
  364. })
  365. .finally(() => {
  366. // element.parentNode.parentNode.parentNode.querySelector("span.btn-wrap.torn-bazaar-clear-qty-price span.btn").style.display = "inline-block";
  367. });
  368. wave.style.animation = 'none';
  369. wave.offsetHeight;
  370. wave.style.animation = null;
  371. wave.style.backgroundColor = "transparent";
  372. wave.style.animationDuration = "1s";
  373. }
  374.  
  375. function clearQuantityAndPrice(element){
  376. let amountDiv = element.parentElement.parentElement.parentElement.parentElement.parentElement.querySelector("div.amount-main-wrap");
  377. let priceInputs = amountDiv.querySelectorAll("div.price div input");
  378. let keyupEvent = new Event("keyup", {bubbles: true});
  379. let inputEvent = new Event("input", {bubbles: true});
  380.  
  381. let wave = element.parentElement.parentElement.parentElement.querySelector("div.wave");
  382. wave.style.backgroundColor = "white";
  383.  
  384. let isQuantityCheckbox = amountDiv.querySelector("div.amount.choice-container") !== null;
  385. if (isQuantityCheckbox){
  386. amountDiv.querySelector("div.amount.choice-container input").click();
  387. } else {
  388. let quantityInput = amountDiv.querySelector("div.amount input");
  389. quantityInput.value = "";
  390. quantityInput.dispatchEvent(keyupEvent);
  391. }
  392.  
  393. priceInputs[0].value = "";
  394. priceInputs[1].value = "";
  395. priceInputs[0].dispatchEvent(inputEvent);
  396.  
  397. wave.style.animation = 'none';
  398. wave.offsetHeight;
  399. wave.style.animation = null;
  400.  
  401. element.parentNode.parentNode.parentNode.querySelector("span.btn-wrap.torn-bazaar-fill-qty-price span.btn").style.display = "inline-block";
  402. }
  403.  
  404. // function clearQuantity(element, pageType){
  405. // let itemRow = element.parentNode.parentNode.parentNode.parentNode;
  406. // let moneyGroupDiv = itemRow.querySelector("div.price___DoKP7");
  407. // let keyupEvent = new Event("keyup", {bubbles: true});
  408.  
  409. // let wave = element.parentElement.parentElement.parentElement.querySelector("div.wave");
  410. // wave.style.backgroundColor = "white";
  411.  
  412. // let quantityInput = itemRow.querySelector("div.remove___R4eVW input");
  413. // quantityInput.value = getQuantity(element, pageType);
  414. // quantityInput.dispatchEvent(keyupEvent);
  415.  
  416. // wave.style.animation = 'none';
  417. // wave.offsetHeight;
  418. // wave.style.animation = null;
  419.  
  420. // element.parentNode.parentNode.parentNode.querySelector("span.btn-wrap.torn-bazaar-fill-qty-price span.btn").style.display = "inline-block";
  421. // }
  422.  
  423. function getQuantity(element, pageType){
  424. let rgx = /x(\d+)$/;
  425. let rgxMobile = /^x(\d+)/
  426. let quantityText = 0;
  427. switch(pageType){
  428. case pages.AddItems:
  429. quantityText = element.parentNode.parentNode.parentNode.innerText;
  430. console.log('quantityText:', quantityText);
  431. break;
  432. case pages.ManageItems:
  433. quantityText = element.parentNode.parentNode.parentNode.querySelector("span").innerText;
  434. break;
  435. }
  436. let match = isMobileView ? rgxMobile.exec(quantityText) : rgx.exec(quantityText);
  437. let quantity = match === null ? 1 : match[1];
  438. return quantity;
  439. }
  440.  
  441. function getItemIdFromImage(image){
  442. let numberPattern = /\/(\d+)\//;
  443. let match = image.src.match(numberPattern);
  444. if (match) {
  445. return parseInt(match[1], 10);
  446. } else {
  447. console.error("[TornBazaarFiller] ItemId not found!");
  448. }
  449. }
  450.  
  451. function performOperation(number, operation) {
  452. // Parse the operation string to extract the operator and value
  453. const match = operation.match(/^([-+]?)(\d+(?:\.\d+)?)(%)?$/);
  454.  
  455. if (!match) {
  456. throw new Error('Invalid operation string');
  457. }
  458.  
  459. const [, operator, operand, isPercentage] = match;
  460. const operandValue = parseFloat(operand);
  461.  
  462. // Check for percentage and convert if necessary
  463. const adjustedOperand = isPercentage ? (number * operandValue) / 100 : operandValue;
  464.  
  465. // Perform the operation based on the operator
  466. switch (operator) {
  467. case '':
  468. case '+':
  469. return number + adjustedOperand;
  470. case '-':
  471. return number - adjustedOperand;
  472. default:
  473. throw new Error('Invalid operator');
  474. }
  475. }
  476.  
  477. function setPriceDelta() {
  478. let userInput = prompt('Enter price delta formula (default: -1):', priceDeltaRaw);
  479. if (userInput !== null) {
  480. priceDeltaRaw = userInput;
  481. localStorage.setItem("silmaril-torn-bazaar-filler-price-delta", userInput);
  482. } else {
  483. console.error("[TornBazaarFiller] User cancelled the Price Delta input.");
  484. }
  485. }
  486.  
  487. function checkApiKey(checkExisting = true) {
  488. if (!checkExisting || apiKey === null || apiKey.length != 16){
  489. let userInput = prompt("Please enter a PUBLIC Api Key, it will be used to get current bazaar prices:", apiKey ?? '');
  490. if (userInput !== null && userInput.length == 16) {
  491. apiKey = userInput;
  492. localStorage.setItem("silmaril-torn-bazaar-filler-apikey", userInput);
  493. } else {
  494. console.error("[TornBazaarFiller] User cancelled the Api Key input.");
  495. }
  496. }
  497. }
  498. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址