CSGO Market Tool(Fixed)

A script that displays float value and stickers of guns in market list.

  1. // ==UserScript==
  2. // @name CSGO Market Tool(Fixed)
  3. // @namespace https://coding.net/u/sffxzzp
  4. // @version 2.43
  5. // @description A script that displays float value and stickers of guns in market list.
  6. // @author sffxzzp/Cliencer Goge
  7. // @include /https?:\/\/steamcommunity\.com\/market\/listings\/730(%.{2})?\/*/
  8. // @icon https://store.steampowered.com/favicon.ico
  9. // @grant GM_xmlhttpRequest
  10. // @grant GM_openInTab
  11. // @connect api.csgofloat.com
  12. // @connect money.csgofloat.com
  13. // @grant unsafeWindow
  14. // ==/UserScript==
  15.  
  16. (function() {
  17. var util = (function () {
  18. function util() {}
  19. util.xhr = function (xhrData) {
  20. return new Promise(function(resolve, reject) {
  21. if (!xhrData.xhr) {
  22. GM_xmlhttpRequest({
  23. method: xhrData.method || "get",
  24. url: xhrData.url,
  25. data: xhrData.data,
  26. headers: xhrData.headers || {},
  27. responseType: xhrData.type || "",
  28. timeout: 3e5,
  29. onload: function onload(res) {
  30. return resolve({ response: res, body: res.response });
  31. },
  32. onerror: reject,
  33. ontimeout: reject
  34. });
  35. } else {
  36. var xhr = new XMLHttpRequest();
  37. xhr.open(xhrData.method || "get", xhrData.url, true);
  38. if (xhrData.method === "post") {xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded; charset=utf-8");}
  39. if (xhrData.cookie) {xhr.withCredentials = true;}
  40. xhr.responseType = xhrData.type || "";
  41. xhr.timeout = 3e5;
  42. if (xhrData.headers) {for (var k in xhrData.headers) {xhr.setRequestHeader(k, xhrData.headers[k]);}}
  43. xhr.onload = function(ev) {
  44. var evt = ev.target;
  45. resolve({ response: evt, body: evt.response });
  46. };
  47. xhr.onerror = reject;
  48. xhr.ontimeout = reject;
  49. xhr.send(xhrData.data);
  50. }
  51. });
  52. };
  53. util.createElement = function (data) {
  54. var node;
  55. if (data.node) {
  56. node = document.createElement(data.node);
  57. if (data.content) {this.setElement({node: node, content: data.content});}
  58. if (data.html) {node.innerHTML = data.html;}
  59. }
  60. return node;
  61. };
  62. util.setElement = function (data) {
  63. if (data.node) {
  64. for (let name in data.content) {data.node.setAttribute(name, data.content[name]);}
  65. if (data.html!=undefined) {data.node.innerHTML = data.html;}
  66. }
  67. };
  68. return util;
  69. })();
  70. var csgomt = (function () {
  71. function csgomt() {}
  72. csgomt.prototype.lsName = 'csgomt_data';
  73. csgomt.prototype.getItem = function (listingid) {
  74. let itemData = localStorage.getItem(this.lsName);
  75. let retData = null;
  76. if (itemData) {
  77. retData = JSON.parse(itemData)[listingid] || null;
  78. }
  79. else {
  80. this.initItem();
  81. }
  82. return retData;
  83. }
  84. csgomt.prototype.setItem = function (listingid, indata) {
  85. let itemData = localStorage.getItem(this.lsName);
  86. if (itemData) {
  87. itemData = JSON.parse(itemData);
  88. itemData[listingid] = indata;
  89. localStorage.setItem(this.lsName, JSON.stringify(itemData));
  90. }
  91. else {
  92. this.initItem();
  93. }
  94. }
  95. csgomt.prototype.initItem = function () {
  96. localStorage.setItem(this.lsName, '{}');
  97. }
  98. csgomt.prototype.parseResult = function (result) {
  99. let retResult = {"floatvalue": result.iteminfo.floatvalue.toFixed(14)};
  100. let stickerConts = result.iteminfo.stickers;
  101. if (stickerConts && stickerConts.length > 0) {
  102. let stickerText = "印花剩余:";
  103. for (let i=0;i<stickerConts.length;i++) {
  104. if (stickerConts[i].wear==null) {stickerText += "100% ";}
  105. else {let tmpNum = (1-stickerConts[i].wear)*100;stickerText += tmpNum.toFixed(2)+"% ";}
  106. }
  107. retResult.stickerText = stickerText;
  108. }
  109. if (result.iteminfo.imageurl.indexOf('phase')>=0) {
  110. let dopplerText = "多普勒:";
  111. let dopplerRe = /phase\d/gi;
  112. dopplerText += result.iteminfo.imageurl.match(dopplerRe)[0];
  113. retResult.dopplerText = dopplerText;
  114. }
  115. if (result.iteminfo.hasOwnProperty('paintseed')) {
  116. retResult.seedText = "图案模板:"+result.iteminfo.paintseed;
  117. }
  118. return retResult;
  119. }
  120. csgomt.prototype.getScreenShot = function (node) {
  121. var _this = this;
  122. node.className = "btn_darkred_white_innerfade btn_small";
  123. node.parentNode.parentNode.onclick = function () {};
  124. util.xhr({url: atob('aHR0cHM6Ly9tb25leS5jc2dvZmxvYXQuY29tL21vZGVsP3VybD0')+node.getAttribute('link'), headers: {'Origin': atob('Y2hyb21lLWV4dGVuc2lvbjovL2pqaWNiZWZwZW1ucGhpbmNjZ2lrcGRhYWdqZWJibmhn')}, type: 'json'}).then(function (res) {
  125. if (res.body.hasOwnProperty('screenshotLink')) {
  126. let preResult = JSON.parse(_this.getItem(node.id));
  127. preResult.screenshot = res.body.screenshotLink;
  128. _this.setItem(node.id, JSON.stringify(preResult));
  129. util.setElement({node: node, content: {class: "btn_green_white_innerfade btn_small", href: res.body.screenshotLink}});
  130. GM_openInTab(res.body.screenshotLink, false);
  131. }
  132. else {
  133. node.className = "btn_blue_white_innerfade btn_small";
  134. node.parentNode.parentNode.onclick = function () {_this.getScreenShot(node);};
  135. }
  136. });
  137. }
  138. csgomt.prototype.getFloatValue = function (node) {
  139. var _this = this;
  140. node.parentNode.parentNode.onclick = function () {};
  141. util.xhr({url: atob('aHR0cHM6Ly9hcGkuY3Nnb2Zsb2F0LmNvbS8/dXJsPQ')+node.getAttribute("link"), headers: {Origin: atob('Y2hyb21lLWV4dGVuc2lvbjovL2pqaWNiZWZwZW1ucGhpbmNjZ2lrcGRhYWdqZWJibmhn')}, type: 'json'}).then(function (result) {
  142. if (result.body.iteminfo) {
  143. console.log(result.body)
  144. node.parentNode.parentNode.onclick = function () {_this.getScreenShot(node);};
  145. let finalResult = _this.parseResult(result.body);
  146. util.setElement({node: node, content: {class: "btn_blue_white_innerfade btn_small"}, html: "<span>"+finalResult.floatvalue+"</span>"});
  147. let nameList = node.parentNode.parentNode.parentNode.getElementsByClassName('market_listing_item_name_block')[0];
  148. _this.addInfo(nameList, finalResult);
  149. _this.setItem(node.id, JSON.stringify(finalResult));
  150. }
  151. else {
  152. node.innerHTML = "<span>查询失败</span>";
  153. }
  154. });
  155. };
  156. csgomt.prototype.addInfo = function (nameList, result) {
  157. if (result.hasOwnProperty('seedText')) {
  158. let paintSeed = util.createElement({node: "span", content: {class: "market_listing_game_name", style: "display: block; color: silver;"}, html: result.seedText});
  159. nameList.appendChild(paintSeed);
  160. }
  161. if (result.hasOwnProperty('stickerText')) {
  162. let stickerWear = util.createElement({node: "span", content: {class: "market_listing_game_name", style: "display: block; color: silver;"}, html: result.stickerText});
  163. nameList.appendChild(stickerWear);
  164. }
  165. if (result.hasOwnProperty('dopplerText')) {
  166. let dopplerPhase = util.createElement({node: "span", content: {class: "market_listing_game_name", style: "display: block; color: silver;"}, html: result.dopplerText});
  167. nameList.appendChild(dopplerPhase);
  168. }
  169. }
  170. csgomt.prototype.addButton = function () {
  171. var _this = this;
  172. let oriButtonDiv = document.getElementById('market_buyorder_info').children[0];
  173. let oriButton = document.getElementById('market_commodity_buyrequests');
  174. let newButton = util.createElement({node: "div", content: {style: "float: right; padding-right: 10px;"}, html: "<a class=\"btn_blue_white_innerfade btn_medium market_noncommodity_buyorder_button\" href=\"javascript:void(0)\"><span>清除本地缓存</span></a>"});
  175. newButton.onclick = function () {
  176. _this.initItem();
  177. alert("清理完毕!");
  178. };
  179. oriButtonDiv.insertBefore(newButton, oriButton);
  180. };
  181. csgomt.prototype.addBanner = function () {
  182. let listBanner = document.getElementsByClassName('market_listing_table_header');
  183. listBanner = listBanner[listBanner.length-1];
  184. let nameBanner = listBanner.children[1];
  185. let childBanner = util.createElement({node: "span", content:{style: "padding-left: 4vw;"}});
  186. nameBanner.appendChild(childBanner);
  187. childBanner = util.createElement({node: "span", content: {style: "width: 20%;", class: "market_listing_right_cell market_listing_stickers_buttons market_listing_sticker"}, html: "印花"});
  188. listBanner.insertBefore(childBanner, nameBanner);
  189. childBanner = util.createElement({node: "span", content: {style: "width: 15%;", class: "market_listing_right_cell market_listing_action_buttons market_listing_wear"}, html: "磨损值"});
  190. listBanner.insertBefore(childBanner, nameBanner);
  191. };
  192. csgomt.prototype.addStyle = function () {
  193. let customstyle = util.createElement({node: "style", html: ".market_listing_item_name_block {margin-top: 0px !important;}.csgo-stickers-show img:hover{opacity:1;width:96px;margin:-16px -24px -24px -24px;z-index:4;-moz-transition:.2s;-o-transition:.2s;-webkit-transition:.2s;transition:.2s;} .csgo-sticker{width: 48px;opacity: 1;vertical-align: middle;z-index: 3;-moz-transition: .1s; -o-transition: .1s; -webkit-transition: .1s; transition: .1s;}"});
  194. document.head.appendChild(customstyle);
  195. };
  196. csgomt.prototype.addPageCtl = function () {
  197. let oriPageCtl = document.getElementsByClassName('market_paging_summary')[0];
  198. let oriPageDiv = document.getElementById('searchResults_ctn');
  199. let newPageCtl = util.createElement({node: "div", content: {style: "float: right; padding-right: 20px;"}});
  200. let newPageInput = util.createElement({node: "input", content: {class: "filter_search_box market_search_filter_search_box", style: "width: 20px;", type: "text", autocomplete: "off"}});
  201. newPageCtl.appendChild(newPageInput);
  202. let newPageGo = util.createElement({node: "span", content: {class: "btn_darkblue_white_innerfade btn_small"}, html: "&nbsp;Go!&nbsp;"});
  203. newPageGo.onclick = function () {
  204. unsafeWindow.g_oSearchResults.GoToPage( (newPageInput.value-1), true );
  205. newPageInput.value = "";
  206. };
  207. newPageCtl.appendChild(newPageGo);
  208. oriPageDiv.insertBefore(newPageCtl, oriPageCtl);
  209. let newPageSizeCtl = util.createElement({node: "div", content: {class: "market_pagesize_options", style: "margin: 0 0 2em 0; font-size: 12px;"}, html: "每页显示数: "});
  210. let newPageSizeInput = util.createElement({node: "input", content: {class: "filter_search_box market_search_filter_search_box", style: "width: 30px;", type: "text", autocomplete: "off"}});
  211. let newPageSizeGo = util.createElement({node: "span", content: {class: "btn_darkblue_white_innerfade btn_small"}, html: "&nbsp;修改&nbsp;"});
  212. newPageSizeGo.onclick = function () {
  213. if (unsafeWindow.g_oSearchResults.m_cPageSize != newPageSizeInput.value && newPageSizeInput.value < 101) {
  214. let oldPageSize = unsafeWindow.g_oSearchResults.m_cPageSize;
  215. unsafeWindow.g_oSearchResults.m_cPageSize = newPageSizeInput.value;
  216. unsafeWindow.g_oSearchResults.m_cMaxPages = Math.ceil(unsafeWindow.g_oSearchResults.m_cTotalCount / newPageSizeInput.value);
  217. unsafeWindow.g_oSearchResults.GoToPage(unsafeWindow.g_oSearchResults.m_iCurrentPage, true);
  218. }
  219. newPageSizeInput.value = "";
  220. };
  221. newPageSizeCtl.appendChild(newPageSizeInput);
  222. newPageSizeCtl.appendChild(newPageSizeGo);
  223. document.getElementById('searchResults_ctn').appendChild(newPageSizeCtl);
  224. };
  225. csgomt.prototype.addType = function () {
  226. var _this = this;
  227. var type = {
  228. "FN": {"name": "崭新出厂", "des": encodeURIComponent("Factory New"), "class": "btn_green_white_innerfade"},
  229. "MW": {"name": "略有磨损", "des": encodeURIComponent("Minimal Wear"), "class": "btn_blue_white_innerfade"},
  230. "FT": {"name": "久经沙场", "des": encodeURIComponent("Field-Tested"), "class": "btn_darkblue_white_innerfade"},
  231. "WW": {"name": "破损不堪", "des": encodeURIComponent("Well-Worn"), "class": "btn_grey_white_innerfade"},
  232. "BS": {"name": "战痕累累", "des": encodeURIComponent("Battle-Scarred"), "class": "btn_darkred_white_innerfade"}
  233. };
  234. let oriLink = location.href.split('/');
  235. oriLink = oriLink[oriLink.length-1];
  236. let curType = null;
  237. for (let i in type) {if (RegExp(type[i].des).test(oriLink)) {curType = i; break;}}
  238. let oriButton = document.getElementById('largeiteminfo_item_actions');
  239. if (curType != null) {
  240. oriButton.append(document.createElement('br'));
  241. for (let i in type) {
  242. if (i != curType) {
  243. let newBtn = util.createElement({node: "a", content: {class: "btn_small "+type[i].class, href: location.href.replace(type[curType].des, type[i].des), target: "_blank"}, html: "<span>"+type[i].name+"</span>"});
  244. oriButton.append(newBtn);
  245. }
  246. }
  247. }
  248. }
  249. csgomt.prototype.addVolume = function () {
  250. let oriLink = location.href.split('/');
  251. oriLink = oriLink[oriLink.length-1];
  252. util.xhr({url: `https://steamcommunity.com/market/priceoverview/?appid=730&market_hash_name=${oriLink}`, type: 'json'}).then(function (result) {
  253. var volume = '';
  254. if (result.body.success) {volume = `在 <span class="market_commodity_orders_header_promote">24</span> 小时内卖出了 <span class="market_commodity_orders_header_promote">${parseInt(result.body.volume.replace(/\, ?/gi, ''))}</span> 个`;}
  255. let oriDesc = document.getElementById('largeiteminfo_item_descriptors');
  256. let newDesc = util.createElement({node: "div", content: {class: "descriptor"}, html: volume});
  257. oriDesc.appendChild(newDesc);
  258. });
  259. }
  260. csgomt.prototype.load = function () {
  261. var _this = this;
  262. let isHandled = document.getElementsByClassName("market_listing_table_header");
  263. isHandled = isHandled[isHandled.length-1].children.length;
  264. if (isHandled > 3) {return false;}
  265. this.addBanner();
  266. this.addStyle();
  267. let itemDetails = unsafeWindow.g_rgAssets[730][2];
  268. let itemListInfo = unsafeWindow.g_rgListingInfo;
  269. let itemInfo = {};
  270. let reStickers = /(https+:\/\/.+?\.png)/gi;
  271. let reStickerDes = /<br>.{2,4}\: (.+?)<\/center>/;
  272. for (var listingid in itemListInfo) {
  273. itemInfo[itemListInfo[listingid].asset.id] = {};
  274. }
  275. for (var assetid in itemDetails) {
  276. itemInfo[assetid].link = itemDetails[assetid].actions[0].link.replace("%assetid%", assetid);
  277. itemInfo[assetid].nametag = itemDetails[assetid].hasOwnProperty('fraudwarnings')?itemDetails[assetid].fraudwarnings[0]:'';
  278. let sticker = '<div class="market_listing_right_cell market_listing_stickers_buttons"><div class="csgo-stickers-show" style="top: 12px;right: 300px;z-index: 3;">';
  279. let stickerInfo = itemDetails[assetid].descriptions[itemDetails[assetid].descriptions.length-1].value.replace(/\r/gi, '').replace(/\n/gi, '');
  280. if (stickerInfo.length > 1) {
  281. let stickerImgs = stickerInfo.match(reStickers);
  282. let stickerDes = stickerInfo.match(reStickerDes)[1].split(', ');
  283. for (let i=0;i<stickerImgs.length;i++) {
  284. sticker += '<img class="csgo-sticker" src="'+stickerImgs[i]+'" title="'+stickerDes[i]+'">';
  285. }
  286. }
  287. else {
  288. sticker += '<img class="csgo-sticker">';
  289. }
  290. itemInfo[assetid].sticker = sticker + '</div></div>';
  291. }
  292. let itemList = document.getElementsByClassName('market_recent_listing_row');
  293. for (let i=0;i<itemList.length;i++) {
  294. if (itemList[i].id.substring(0,7) != 'listing') {
  295. continue;
  296. }
  297. let listingid = itemList[i].id.substring(8);
  298. let assetid = itemListInfo[listingid].asset.id;
  299. let floatButton;
  300. let nameList = itemList[i].children[3];
  301. let namePlace = nameList.children[2];
  302. util.setElement({node: namePlace, content: {style: "color: yellow;"}, html: itemInfo[assetid].nametag});
  303. let itemSticker = util.createElement({node: "span", content: {style: "width: 20%;", class: "market_listing_right_cell market_listing_sticker"}, html: itemInfo[assetid].sticker});
  304. itemList[i].insertBefore(itemSticker, nameList);
  305. let savedItem = this.getItem(listingid);
  306. if (savedItem) {
  307. savedItem = JSON.parse(savedItem);
  308. if (savedItem.hasOwnProperty('screenshot')) {
  309. floatButton = util.createElement({node: "span", content: {style: "width: 15%;", class: "market_listing_right_cell market_listing_action_buttons market_listing_wear"}, html: '<div class="market_listing_right_cell market_listing_action_buttons" style="float:left;"><a target="_blank" href="'+savedItem.screenshot+'" id="'+listingid+'" class="btn_green_white_innerfade btn_small"><span>'+savedItem.floatvalue+'</span></a></div>'});
  310. }
  311. else {
  312. floatButton = util.createElement({node: "span", content: {style: "width: 15%;", class: "market_listing_right_cell market_listing_action_buttons market_listing_wear"}, html: '<div class="market_listing_right_cell market_listing_action_buttons" style="float:left;"><a link="'+itemInfo[assetid].link+'" target="_blank" id="'+listingid+'" class="btn_blue_white_innerfade btn_small"><span>'+savedItem.floatvalue+'</span></a></div>'});
  313. floatButton.onclick = function () {_this.getScreenShot(this.children[0].children[0]);};
  314. }
  315. _this.addInfo(nameList, savedItem);
  316. }
  317. else {
  318. floatButton = util.createElement({node: "span", content: {style: "width: 15%;", class: "market_listing_right_cell market_listing_action_buttons market_listing_wear"}, html: '<div class="market_listing_right_cell market_listing_action_buttons" style="float:left;"><a link="'+itemInfo[assetid].link+'" target="_blank" id="'+listingid+'" class="floatvalue_button btn_darkblue_white_innerfade btn_small"><span>点击查询磨损</span></a></div>'});
  319. floatButton.onclick = function () {
  320. let clickedButton = this.children[0].children[0];
  321. util.setElement({node: clickedButton, html: "<span>磨损查询中…</span>"});
  322. _this.getFloatValue(clickedButton);
  323. };
  324. }
  325. itemList[i].insertBefore(floatButton, nameList);
  326. }
  327. };
  328. csgomt.prototype.run = function () {
  329. var _this = this;
  330. this.load();
  331. this.addButton();
  332. this.addPageCtl();
  333. this.addType();
  334. this.addVolume();
  335. var csgoinv = document.getElementById("searchResultsRows");
  336. var observer = new MutationObserver(function (recs) {
  337. for (let i=0;i<recs.length;i++) {
  338. let rec = recs[i];
  339. if (rec.target.classList.contains('market_listing_item_img_container')) {
  340. _this.load();
  341. break;
  342. }
  343. }
  344. });
  345. observer.observe(csgoinv, { childList: true, subtree: true });
  346. };
  347. return csgomt;
  348. })();
  349. var script = new csgomt();
  350. script.run();
  351. })();

QingJ © 2025

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