Steam Gems-to-Price Helper

处理垃圾库存的好帮手 ╰( ̄▽ ̄)╭

  1. // ==UserScript==
  2. // @name Steam Gems-to-Price Helper
  3. // @namespace http://nota.moe/
  4. // @version 0.5.1
  5. // @description 处理垃圾库存的好帮手 ╰( ̄▽ ̄)╭
  6. // @author NotaStudio
  7. // @match *://steamcommunity.com/*/inventory/*
  8. // @grant GM_info
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // @run-at document-end
  12. // @license GPLv3
  13. // ==/UserScript==
  14.  
  15. /*
  16. * ChangeLog
  17. * 20170113 0.5
  18. * 更加完善的多国货币支持
  19. * 更彻底地修复了同时显示多个价格的 bug
  20. * 性能优化
  21. * 20161224 0.4
  22. * 添加初始设置
  23. * 添加手动设置货币单位功能
  24. * 修复了快速点击物品时同时显示多个价格的 bug
  25. * 降低了请求宝珠价格的频率,可能会有微弱的性能提升(或性能下降 o(≧v≦)o~~ )
  26. * 圣诞快乐~
  27. * 20161217 0.3
  28. * 临时修复国区价格显示为美元的 bug
  29. * 20161217 0.2
  30. * 修复价格显示为"约为 undefined NaN" 的 bug
  31. * 20161216 0.1-alpha
  32. * 初次发布
  33. */
  34.  
  35. /* jshint ignore:start */
  36. /*!
  37. * accounting.js v0.4.2, copyright 2014 Open Exchange Rates, MIT license, http://openexchangerates.github.io/accounting.js
  38. */
  39. (function(p,z){function q(a){return!!(""===a||a&&a.charCodeAt&&a.substr)}function m(a){return u?u(a):"[object Array]"===v.call(a)}function r(a){return"[object Object]"===v.call(a)}function s(a,b){var d,a=a||{},b=b||{};for(d in b)b.hasOwnProperty(d)&&null==a[d]&&(a[d]=b[d]);return a}function j(a,b,d){var c=[],e,h;if(!a)return c;if(w&&a.map===w)return a.map(b,d);for(e=0,h=a.length;e<h;e++)c[e]=b.call(d,a[e],e,a);return c}function n(a,b){a=Math.round(Math.abs(a));return isNaN(a)?b:a}function x(a){var b=c.settings.currency.format;"function"===typeof a&&(a=a());return q(a)&&a.match("%v")?{pos:a,neg:a.replace("-","").replace("%v","-%v"),zero:a}:!a||!a.pos||!a.pos.match("%v")?!q(b)?b:c.settings.currency.format={pos:b,neg:b.replace("%v","-%v"),zero:b}:a}var c={version:"0.4.1",settings:{currency:{symbol:"$",format:"%s%v",decimal:".",thousand:",",precision:2,grouping:3},number:{precision:0,grouping:3,thousand:",",decimal:"."}}},w=Array.prototype.map,u=Array.isArray,v=Object.prototype.toString,o=c.unformat=c.parse=function(a,b){if(m(a))return j(a,function(a){return o(a,b)});a=a||0;if("number"===typeof a)return a;var b=b||".",c=RegExp("[^0-9-"+b+"]",["g"]),c=parseFloat((""+a).replace(/\((.*)\)/,"-$1").replace(c,"").replace(b,"."));return!isNaN(c)?c:0},y=c.toFixed=function(a,b){var b=n(b,c.settings.number.precision),d=Math.pow(10,b);return(Math.round(c.unformat(a)*d)/d).toFixed(b)},t=c.formatNumber=c.format=function(a,b,d,i){if(m(a))return j(a,function(a){return t(a,b,d,i)});var a=o(a),e=s(r(b)?b:{precision:b,thousand:d,decimal:i},c.settings.number),h=n(e.precision),f=0>a?"-":"",g=parseInt(y(Math.abs(a||0),h),10)+"",l=3<g.length?g.length%3:0;return f+(l?g.substr(0,l)+e.thousand:"")+g.substr(l).replace(/(\d{3})(?=\d)/g,"$1"+e.thousand)+(h?e.decimal+y(Math.abs(a),h).split(".")[1]:"")},A=c.formatMoney=function(a,b,d,i,e,h){if(m(a))return j(a,function(a){return A(a,b,d,i,e,h)});var a=o(a),f=s(r(b)?b:{symbol:b,precision:d,thousand:i,decimal:e,format:h},c.settings.currency),g=x(f.format);return(0<a?g.pos:0>a?g.neg:g.zero).replace("%s",f.symbol).replace("%v",t(Math.abs(a),n(f.precision),f.thousand,f.decimal))};c.formatColumn=function(a,b,d,i,e,h){if(!a)return[];var f=s(r(b)?b:{symbol:b,precision:d,thousand:i,decimal:e,format:h},c.settings.currency),g=x(f.format),l=g.pos.indexOf("%s")<g.pos.indexOf("%v")?!0:!1,k=0,a=j(a,function(a){if(m(a))return c.formatColumn(a,f);a=o(a);a=(0<a?g.pos:0>a?g.neg:g.zero).replace("%s",f.symbol).replace("%v",t(Math.abs(a),n(f.precision),f.thousand,f.decimal));if(a.length>k)k=a.length;return a});return j(a,function(a){return q(a)&&a.length<k?l?a.replace(f.symbol,f.symbol+Array(k-a.length+1).join(" ")):Array(k-a.length+1).join(" ")+a:a})};if("undefined"!==typeof exports){if("undefined"!==typeof module&&module.exports)exports=module.exports=c;exports.accounting=c}else"function"===typeof define&&define.amd?define([],function(){return c}):(c.noConflict=function(a){return function(){p.accounting=a;c.noConflict=z;return c}}(p.accounting),p.accounting=c)})(this);
  40. /* jshint ignore:end */
  41.  
  42. (function($) {
  43. const ver = GM_info.script.version,
  44. dateVer = '2017.01.13';
  45.  
  46. console.log(`Steam Gems-to-Price Helper ${ver}\nCreated by Nota\n${dateVer}`);
  47.  
  48. let gemsInfo = {};
  49.  
  50. let currency = {
  51. "USD": 1,
  52. "GBP": 2,
  53. "EUR": 3,
  54. "CHF": 4,
  55. "RUB": 5,
  56. "PLN": 6,
  57. "BRL": 7,
  58. "JPY": 8,
  59. "NOK": 9,
  60. "IDR": 10,
  61. "MYR": 11,
  62. "PHP": 12,
  63. "SGD": 13,
  64. "THB": 14,
  65. "VND": 15,
  66. "KRW": 16,
  67. "TRY": 17,
  68. "UAH": 18,
  69. "MXN": 19,
  70. "CAD": 20,
  71. "AUD": 21,
  72. "NZD": 22,
  73. "CNY": 23,
  74. "INR": 24,
  75. "CLP": 25,
  76. "PEN": 26,
  77. "COP": 27,
  78. "ZAR": 28,
  79. "HKD": 29,
  80. "TWD": 30,
  81. "SAR": 31,
  82. "AED": 32
  83. };
  84.  
  85. let setup = (init) => {
  86. let initTips = [`Steam Gems-to-Price Helper 已升级到 ${ver} 版本! 请进行初始设置.<br><br>`, `<br> 以后, 您可以随时按下 Alt+G 更改本页设置.`],
  87. form = `<form style="font-size: 16px;line-height: 25px;text-align: center;" class="currencyForm"><b>我的币种代码是</b><select class="sg2ph_select" style="font-weight: bold;"></select><br></form><br><br>若价格显示存在问题,请在<a href="https://gf.qytechs.cn/zh-CN/scripts/25735-steam-gems-to-price-helper/feedback" target="_blank"> Greasy Fork镜像 </a>或<a href="http://steamcn.com/forum.php?mod=viewthread&tid=235466" target="_blank"> SteamCN </a>向我反馈.`;
  88. if (init) form = initTips[0] + form + initTips[1];
  89. ShowAlertDialog('设置 Steam Gems-to-Price Helper 币种', form);
  90. let nowID = GM_getValue('currencyId',23);
  91. for (let c in currency) {
  92. let opt = $(`<option value="${currency[c]}">${c}</option>`);
  93. if (currency[c] == nowID) opt.attr('selected', 'selected');
  94. opt.appendTo($('.sg2ph_select'));
  95. }
  96. let realButton = $('.newmodal:not(#market_sell_dialog) .btn_grey_white_innerfade');
  97. realButton.css('visibility', 'hidden');
  98. let overrideButton = $(`<div class="btn_green_white_innerfade btn_medium sg2ph_button"><span>确定(将会刷新页面)</span></div>`);
  99. overrideButton.insertAfter(realButton);
  100. overrideButton.on('click', (() => {
  101. GM_setValue('currencyId',$('.sg2ph_select').val());
  102. GM_setValue('currentVersion',ver);
  103. realButton.click();
  104. location.reload();
  105. })); // Steam 提供的模态窗口不支持回调函数,所以小小地 hack 了一下,用自定义的确认按钮替换掉原来的
  106. };
  107.  
  108. if (GM_getValue('currentVersion') !== ver) setup(true); // 初始设置
  109.  
  110. let parseAmount = (data) => {
  111. let rawData = data.lowest_price;
  112. let hasSpace = rawData.includes(' '),
  113. localAmountSymbol = rawData.replace(/ |\d\.\d|\d|,/g, ''),
  114. isSymbolBeforeNumber = rawData.indexOf(localAmountSymbol) === 0;
  115. let symbolReplaceRule = new RegExp(localAmountSymbol.replace(/\//g,'\/').replace(/\./g,'\.')),
  116. rawPrice = rawData.replace(symbolReplaceRule,'').replace(/\s/g,'');
  117. let commaPos = rawPrice.indexOf(','),
  118. dotPos = rawPrice.indexOf('.'),
  119. decimalSeparator = (commaPos > dotPos) ? ',' : '.',
  120. thousandSeparator = (decimalSeparator == ',') ? '.' : ',';
  121. rawPrice = accounting.unformat(rawPrice, decimalSeparator);
  122.  
  123. gemsInfo = {hasSpace, localAmountSymbol, isSymbolBeforeNumber, rawPrice, decimalSeparator, thousandSeparator};
  124.  
  125. // 解释一下上边这些翔一样的代码是干嘛的
  126. // Steam 针对不同的币种有不同的价格显示格式,如 '$0.86' '0,83€' 'CLP$ 579,17' 'Rp 11 513.27' '52,10 pуб.' 'S/.2.92' 等等等等
  127. // hasSpace - 符号与数字间是否存在空格(尚不完善,使用空格做千位分隔符的币种可能会误判)
  128. // localAmountSymbol - 币种符号
  129. // isSymbolBeforeNumber - 符号在前还是数字在前
  130. // rawPrice - 处理为纯数字的价格
  131. // decimalSeparator - 小数分隔符(部分欧洲货币使用逗号作为小数分隔符)
  132. // thousandSeparator - 千位分隔符(部分欧洲货币使用小数点作为千位分隔符)
  133. // L111 为什么要写 .replace(/\//g,'\/').replace(/\./g,'\.') : 因为 S/. 这个货币单位里有两个正则表达式的保留字
  134. };
  135.  
  136. let showValue = (xhr) => {
  137. let {hasSpace, localAmountSymbol, isSymbolBeforeNumber, rawPrice, decimalSeparator, thousandSeparator} = gemsInfo,
  138. gemsCount = Number.parseFloat(xhr.responseJSON.goo_value), // 获取当前物品可分解的宝珠数量
  139. valueSpan = $('span.item_scrap_value:visible'), // span.item_scrap_value 会对应两个 SPAN 元素,其中可见者则为当前宝珠价值
  140. gemsValue = rawPrice / 1000 * gemsCount;
  141. let accountingFormat;
  142. accountingFormat = isSymbolBeforeNumber ? '%s %v' : '%v %s';
  143. if (!hasSpace) accountingFormat = accountingFormat.replace(/\s/g, '');
  144. gemsValue = accounting.formatMoney(gemsValue, {
  145. symbol: localAmountSymbol,
  146. precision: 2,
  147. thousand: thousandSeparator,
  148. decimal: decimalSeparator,
  149. format: accountingFormat
  150. }); // accounting.js 的文档: http://openexchangerates.github.io/accounting.js
  151. valueSpan.append($(`<span style="color: #FF0;cursor: help;" class="sg2ph_valueBox" title="价格显示错误?按 Alt+G 修改设置!">&nbsp;&nbsp;&nbsp;&nbsp;约为 ${gemsValue}</span>`));
  152. };
  153.  
  154. let ajaxHandler = (event, xhr, settings) => {
  155. if (settings.url.match(/ajaxgetgoovalueforitemtype/)) { // Steam 会在点击某一库存物品时进行 3 次 jQuery AJAX 请求.筛选出请求宝珠数量的那一次
  156. $('.sg2ph_valueBox').remove();
  157. setTimeout((() => (showValue(xhr))), 100);
  158. }
  159. };
  160.  
  161. let refreshPrice = () => {
  162. let apiUrl = `https://steamcommunity.com/market/priceoverview/?appid=753&currency=${GM_getValue('currencyId',1)}&market_hash_name=753-Sack%20of%20Gems`;
  163. $.get(apiUrl,((data) => parseAmount(data)));
  164. setTimeout(refreshPrice, 45000);
  165. };
  166.  
  167. let keyHandler = (e) => {
  168. if (e.keyCode == 71 && e.altKey) setup(false); // 同时按下 Alt+G
  169. };
  170.  
  171. refreshPrice();
  172. $(document).keydown(keyHandler);
  173. $(document).ajaxComplete(ajaxHandler);
  174.  
  175. })(jQuery);

QingJ © 2025

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