Subeta Searching

This script searches for shops.

此脚本不应直接安装,它是供其他脚本使用的外部库。如果你需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/30529/203734/Subeta%20Searching.js

  1. // ==UserScript==
  2. // @name Subeta Searching
  3. // @namespace http://artees.pw/
  4. // @description This script searches for shops.
  5. // @version 1.8
  6. // @author Artees
  7. // @match *://subeta.net/user_shops.php/mine/*
  8. // @match *://subeta.net/shop.php?shop*
  9. // @exclude *quick_stock*
  10. // @exclude *profits*
  11. // @exclude *history*
  12. // @exclude *edit_shop*
  13. // @exclude *delete_shop*
  14. // @grant none
  15. // @icon https://subeta.net/favicon.ico
  16. // @icon64 https://img.subeta.net/items/identifier_04_crystal.gif
  17. // ==/UserScript==
  18.  
  19. const CY = " sP",
  20. SPLITTER = " | ",
  21. XHR = new XMLHttpRequest(),
  22. KEY_ITEM_DELAY = "itemDelay";
  23.  
  24. var itemDelay = getFromStorage(localStorage, KEY_ITEM_DELAY, 5),
  25. itemCountdown = itemDelay,
  26. loadIntervalId,
  27. loadIntervalCount = 0;
  28.  
  29. function parseItems(itemDivs, getPriceField) {
  30. var prevItem = null,
  31. firstItem;
  32. for (var i = 0; i < itemDivs.length; i++) {
  33. var priceField = getPriceField(itemDivs[i]);
  34. if (priceField === null) {
  35. continue;
  36. }
  37. var curItem = new Item(itemDivs[i], priceField);
  38. if (curItem.priceField === null) {
  39. continue;
  40. }
  41. if (prevItem === null) {
  42. firstItem = curItem;
  43. } else {
  44. prevItem.next = curItem;
  45. }
  46. prevItem = curItem;
  47. }
  48. if (prevItem !== null) {
  49. prevItem.next = firstItem;
  50. }
  51. return firstItem;
  52. }
  53.  
  54. function getFromStorage(storage, key, defaultValue) {
  55. if (storage[key] === undefined) {
  56. return defaultValue;
  57. } else {
  58. return typeof defaultValue === "boolean" ? storage[key] === "true" : storage[key];
  59. }
  60. }
  61.  
  62. function forEachItem(action) {
  63. var f = curItem,
  64. i = f;
  65. do {
  66. if (!action(i)) {
  67. return;
  68. }
  69. i = i.next;
  70. } while (i !== f);
  71. }
  72.  
  73. function createSpace() {
  74. var space = document.createElement("SPAN");
  75. space.innerText = "|";
  76. space.style = "display: inline-block; width: 50px;";
  77. return space;
  78. }
  79.  
  80. function search() {
  81. var safeName = replaceAll(curItem.name, "%", "%25");
  82. XHR.open("GET", "https://subeta.net/user_shops.php/search/shops/" + safeName, true);
  83. XHR.send();
  84. curItem.priceField.value = curItem.resetPrice();
  85. curItem.priceField.value += SPLITTER;
  86. loadIntervalCount = 0;
  87. loadIntervalId = setInterval(updateSearchProgress, 100);
  88. }
  89.  
  90. function updateSearchProgress() {
  91. loadIntervalCount++;
  92. if (loadIntervalCount > 20) {
  93. clearInterval(loadIntervalId);
  94. XHR.abort();
  95. search();
  96. return;
  97. }
  98. curItem.priceField.value += ".";
  99. }
  100.  
  101. XHR.onreadystatechange = function setLowestPrice() {
  102. if (XHR.readyState !== XMLHttpRequest.DONE || XHR.status !== 200) return;
  103. clearInterval(loadIntervalId);
  104. var pricesText = XHR.responseText.split(CY),
  105. prices = [];
  106. for (var i = 0; i < pricesText.length; i++) {
  107. var priceWithCommas = pricesText[i].substring(pricesText[i].lastIndexOf(">") + 1),
  108. priceText = replaceAll(priceWithCommas, ",", ""),
  109. price = parseInt(priceText);
  110. if (isNaN(price)) continue;
  111. var isNPC = pricesText[i].indexOf("(NPC Shop)") !== -1,
  112. priceObject = new Price(price, isNPC);
  113. prices.push(priceObject);
  114. }
  115. if (prices.length > 0) {
  116. prices.sort(compareNumbers);
  117. }
  118. filterPrices(prices);
  119. curItem = curItem.next;
  120. if (curItem.onSelect()) {
  121. itemIntervalId = setInterval(updateItemCountdown, 1000);
  122. }
  123. };
  124.  
  125. function Price(value, isNPC) {
  126. this.isNPC = function () {
  127. return isNPC;
  128. };
  129. this.valueOf = function () {
  130. return value;
  131. };
  132. this.toString = function () {
  133. return value.toString();
  134. };
  135. }
  136.  
  137. function replaceAll(target, searchValue, replaceValue) {
  138. return target.replace(new RegExp(searchValue, 'g'), replaceValue);
  139. }
  140.  
  141. function compareNumbers(a, b)
  142. {
  143. return a - b;
  144. }
  145.  
  146. function updateItemCountdown() {
  147. curItem.priceField.value = curItem.resetPrice() + SPLITTER + itemCountdown;
  148. itemCountdown--;
  149. if (itemCountdown >= 0) return;
  150. curItem.priceField.value = curItem.resetPrice();
  151. itemCountdown = itemDelay;
  152. clearInterval(itemIntervalId);
  153. search();
  154. }