您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Provides a button to purchase remaining cards needed for a badge in bulk
// ==UserScript== // @name Steam Trading Cards Bulk Buyer // @namespace https://alanyhq.com/ // @version 3.5.0 // @description Provides a button to purchase remaining cards needed for a badge in bulk // @match *://steamcommunity.com/*/gamecards/* // @require https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js // @copyright 2018 - 2023 Alanyhq // @license GPLv3 // ==/UserScript== $.ajaxSetup({ xhrFields: { withCredentials: true } }); var links = $('.gamecards_inventorylink'); // Current currency (numerical identifier used by Steam) var g_Currency = 1; // Initiatize currency information with default information first var g_CurrencyInfo = { symbol_prefix: "", symbol_suffix: "", separator: "." } // Function to format the string using the currency information function formatPrice(price, full) { if(full) { return g_CurrencyInfo.symbol_prefix + price.replace(".", g_CurrencyInfo.separator) + g_CurrencyInfo.symbol_suffix; } return price.replace(".", g_CurrencyInfo.separator); } $(document).ready(function() { // Ensure that the page is loaded in HTTPS (Issue #19) if(document.location.protocol != "https:") { var badgePageUrl = window.location.href; badgePageUrl = badgePageUrl.replace("http://", "https://"); window.location.href = badgePageUrl; } // Check if we need to craft a badge if(parseInt(localStorage.autoCraftBadge, 10)) { var button = $('.badge_craft_button'); if(button.length){ button.click(); setTimeout(function() {window.location.reload();}, 100); console.log("crafting..."); }else{ delete localStorage.autoCraftBadge; console.log("suessful craft..."); } } }); if(links && $('.badge_card_to_collect').length > 0) { links.append('<button type="button" class="btn_grey_grey btn_small_thin" id="buycards_1x"><span>自动购买剩余卡牌(Lv+1)</span></button'); links.append('<button type="button" class="btn_grey_grey btn_small_thin" id="buycards_4x"><span>自动购买剩余卡牌(Lv+4)</span></button'); $('#buycards_1x').click(function() { $('#buycards_1x').hide(); $('#buycards_4x').hide(); $('.gamecards_inventorylink').append('<div id="buycardspanel_1x" style="visibility: hidden; margin-top: 5px"></div>'); updatePrices_1x(); $('#buycardspanel_1x').css('display', 'none').css('visibility', 'visible').show('blind'); // We have to do this visibility/display thing in order for offsetWidth to work $('#buycardspanel_4x').css('display', 'none').css('visibility', 'visible').show('blind'); // We have to do this visibility/display thing in order for offsetWidth to work }); $('#buycards_4x').click(function() { $('#buycards_1x').hide(); $('#buycards_4x').hide(); $('.gamecards_inventorylink').append('<div id="buycardspanel_4x" style="visibility: hidden; margin-top: 5px"></div>'); updatePrices_4x(); $('#buycardspanel_1x').css('display', 'none').css('visibility', 'visible').show('blind'); // We have to do this visibility/display thing in order for offsetWidth to work $('#buycardspanel_4x').css('display', 'none').css('visibility', 'visible').show('blind'); // We have to do this visibility/display thing in order for offsetWidth to work }); } var g_SessionID; function updatePrices_1x() { $('#buycardspanel_1x').html(''); Array.prototype.slice.call($('.badge_card_to_collect')).forEach(function(card) { card = $(card); var name = card.find('.badge_card_set_text')[0].textContent; var row = $('<div class="cardrow"><span class="cardname" style="padding-right: 10px; text-align: right; display: inline-block; font-weight: bold">' + name + '</span><span class="cardprice" data-name="' + name.replace(/"/g, '"') + '">Loading...</span></div>'); $('#buycardspanel_1x').append(row); var url = card.find('.btn_grey_grey.btn_medium[href*=market]')[0].href; if (document.location.protocol == "https:") { url = url.replace("http://", "https://"); } $.get(url, function(html) { if(html.match(/There are no listings for this item\./)) { row.find('.cardprice').text('Error'); return; } var marketID = html.match(/Market_LoadOrderSpread\(\s*(\d+)\s*\);/); var sessionID = html.match(/g_sessionID = "(.+)";/); var countryCode = html.match(/g_strCountryCode = "([a-zA-Z0-9]+)";/); var currency = html.match(/"wallet_currency":(\d+)/); var hashName = html.match(/"market_hash_name":"([^"]+)"/); if(!marketID || !sessionID || !countryCode || !currency || !hashName) { row.find('.cardprice').text('Error'); return; } g_Currency = currency[1]; g_SessionID = sessionID[1]; $.get('/market/itemordershistogram', {"country": countryCode[1], language: 'english', "currency": g_Currency, "item_nameid": marketID[1]}, function(json) { if(!json.success) { row.find('.cardprice').text('Error'); return; } //console.info(json); var _lefts = 5 - parseInt(json.sell_order_graph[0][1]); var _level = 0; do { _lefts -= parseInt(json.sell_order_graph[_level++][1]); } while (_lefts > 0); var _price = parseInt(json.lowest_sell_order, 10) + _level; row.data('price', _price); row.data('hashname', hashName[1]); console.log("hashName : ["+ hashName[1] + "] price: [" + _price + "]"); // Get the currency symbol if(json.price_prefix) { g_CurrencyInfo.symbol_prefix = json.price_prefix; } else { g_CurrencyInfo.symbol_suffix = json.price_suffix; } // Get the separator of the price var regexString = g_CurrencyInfo.symbol_prefix.replace("$", "\\\$") + '\\s?\\S+(\\D+)\\d{2}\\s?' + g_CurrencyInfo.symbol_suffix.replace("$", "\\\$"); var regex = new RegExp(regexString, "g"); var match = regex.exec(json.sell_order_graph[0][2]); g_CurrencyInfo.separator = match[1]; row.find('.cardprice').text(formatPrice((_price / 100).toFixed(2), true)); row.addClass('ready'); if($('.cardrow:not(.ready)').length === 0) { var total = 0; var cards = $('.cardrow'); for(var i = 0; i < cards.length; i++) { total += parseInt($(cards[i]).data('price'), 10) * 1 / 100; } $('#buycardspanel_1x').append('<br /><span style="font-weight: bold; display: inline-block; width: ' + $('.cardname').css('width') + '; padding-right: 10px; text-align: right">Total</span><b>' + g_CurrencyInfo.symbol_prefix + '<span id="totalprice">' + formatPrice(total.toFixed(2)) + '</span>' + g_CurrencyInfo.symbol_suffix +'</b><br /><br /><button type="button" id="buycardsbutton_1x" class="btn_green_white_innerfade btn_medium_wide" style="padding: 10px 20px; margin-left: ' + ($('.cardname').css('width').replace('px', '') / 2) + 'px">PLACE ORDERS</button>'); $('#buycardspanel_1x').append('<br /><br /><label><input type="checkbox" id="auto-reload-and-craft" /> Automatically reload page and craft badge</label>'); $('#buycardsbutton_1x').click(function() { $('#buycardsbutton_1x').hide(); placeBuyOrder_1x(); }); if(parseInt(localStorage.autoReloadAndCraftBadge, 10)) { $('#auto-reload-and-craft').prop('checked', true); } $('#auto-reload-and-craft').change(function() { localStorage.autoReloadAndCraftBadge = $('#auto-reload-and-craft').prop('checked') ? 1 : 0; }); } }); }).fail(function() { row.find('.cardprice').text('Error'); }); }); var elements = $('.cardname'); var largestWidth = 0; for(var i = 1; i < elements.length; i++) { if(elements[i].offsetWidth > elements[largestWidth].offsetWidth) { largestWidth = i; } } $('.cardname').css('width', elements[largestWidth].offsetWidth + 'px'); } function updatePrices_4x() { $('#buycardspanel_4x').html(''); Array.prototype.slice.call($('.badge_card_to_collect')).forEach(function(card) { card = $(card); var name = card.find('.badge_card_set_text')[0].textContent; var row = $('<div class="cardrow"><span class="cardname" style="padding-right: 10px; text-align: right; display: inline-block; font-weight: bold">' + name + '</span><span class="cardprice" data-name="' + name.replace(/"/g, '"') + '">Loading...</span></div>'); $('#buycardspanel_4x').append(row); var url = card.find('.btn_grey_grey.btn_medium[href*=market]')[0].href; if (document.location.protocol == "https:") { url = url.replace("http://", "https://"); } $.get(url, function(html) { if(html.match(/There are no listings for this item\./)) { row.find('.cardprice').text('Error'); return; } var marketID = html.match(/Market_LoadOrderSpread\(\s*(\d+)\s*\);/); var sessionID = html.match(/g_sessionID = "(.+)";/); var countryCode = html.match(/g_strCountryCode = "([a-zA-Z0-9]+)";/); var currency = html.match(/"wallet_currency":(\d+)/); var hashName = html.match(/"market_hash_name":"([^"]+)"/); if(!marketID || !sessionID || !countryCode || !currency || !hashName) { row.find('.cardprice').text('Error'); return; } g_Currency = currency[1]; g_SessionID = sessionID[1]; $.get('/market/itemordershistogram', {"country": countryCode[1], language: 'english', "currency": g_Currency, "item_nameid": marketID[1]}, function(json) { if(!json.success) { row.find('.cardprice').text('Error'); return; } //console.info(json); var _lefts = 5 - parseInt(json.sell_order_graph[0][1]); var _level = 0; do { _lefts -= parseInt(json.sell_order_graph[_level++][1]); } while (_lefts > 0); var _price = parseInt(json.lowest_sell_order, 10) + _level; row.data('price', _price); row.data('hashname', hashName[1]); console.log("hashName : ["+ hashName[1] + "] price: [" + _price + "]"); // Get the currency symbol if(json.price_prefix) { g_CurrencyInfo.symbol_prefix = json.price_prefix; } else { g_CurrencyInfo.symbol_suffix = json.price_suffix; } // Get the separator of the price var regexString = g_CurrencyInfo.symbol_prefix.replace("$", "\\\$") + '\\s?\\S+(\\D+)\\d{2}\\s?' + g_CurrencyInfo.symbol_suffix.replace("$", "\\\$"); var regex = new RegExp(regexString, "g"); var match = regex.exec(json.sell_order_graph[0][2]); g_CurrencyInfo.separator = match[1]; row.find('.cardprice').text(formatPrice((_price / 100).toFixed(2), true)); row.addClass('ready'); if($('.cardrow:not(.ready)').length === 0) { var total = 0; var cards = $('.cardrow'); for(var i = 0; i < cards.length; i++) { total += parseInt($(cards[i]).data('price'), 10) * 1 / 100; } $('#buycardspanel_4x').append('<br /><span style="font-weight: bold; display: inline-block; width: ' + $('.cardname').css('width') + '; padding-right: 10px; text-align: right">Total (+Lv4) </span><b>' + g_CurrencyInfo.symbol_prefix + '<span id="totalprice">' + formatPrice(total.toFixed(2)) + '</span>' + g_CurrencyInfo.symbol_suffix +'</b><br /><br /><button type="button" id="buycardsbutton_4x" class="btn_green_white_innerfade btn_medium_wide" style="padding: 10px 20px; margin-left: ' + ($('.cardname').css('width').replace('px', '') / 2) + 'px">PLACE ORDERS</button>'); $('#buycardspanel_4x').append('<br /><br /><label><input type="checkbox" id="auto-reload-and-craft" /> Automatically reload page and craft badge</label>'); $('#buycardsbutton_4x').click(function() { $('#buycardsbutton_4x').hide(); placeBuyOrder_4x(); }); if(parseInt(localStorage.autoReloadAndCraftBadge, 10)) { $('#auto-reload-and-craft').prop('checked', true); } $('#auto-reload-and-craft').change(function() { localStorage.autoReloadAndCraftBadge = $('#auto-reload-and-craft').prop('checked') ? 1 : 0; }); } }); }).fail(function() { row.find('.cardprice').text('Error'); }); }); var elements = $('.cardname'); var largestWidth = 0; for(var i = 1; i < elements.length; i++) { if(elements[i].offsetWidth > elements[largestWidth].offsetWidth) { largestWidth = i; } } $('.cardname').css('width', elements[largestWidth].offsetWidth + 'px'); } function placeBuyOrder_1x() { var card = $('.cardrow:not(.buying)')[0]; if(!card) { return; } card = $(card); card.find('.cardprice')[0].innerHTML += ' - Placing buy order...'; card.addClass('buying'); $.post('https://steamcommunity.com/market/createbuyorder/', {"sessionid": g_SessionID, "currency": g_Currency, "appid": 753, "market_hash_name": card.data('hashname'), "price_total": card.data('price')*1, "quantity": 1}, function(json) { setTimeout(placeBuyOrder_1x, 500); if(json.success !== 1) { card.find('.cardprice').text(json.message); decrementTotal(card.data('price') / 100); return; } console.info(json); card.data('orderid', json.buy_orderid); card.data('checks', 0); card.find('.cardprice').text(card.find('.cardprice').text().replace('Placing buy order', 'Waiting')); checkOrderStatus(card); }); } function placeBuyOrder_4x() { var card = $('.cardrow:not(.buying)')[0]; if(!card) { return; } card = $(card); card.find('.cardprice')[0].innerHTML += ' - Placing buy order...'; card.addClass('buying'); $.post('https://steamcommunity.com/market/createbuyorder/', {"sessionid": g_SessionID, "currency": g_Currency, "appid": 753, "market_hash_name": card.data('hashname'), "price_total": card.data('price')*4, "quantity": 4}, function(json) { setTimeout(placeBuyOrder_4x, 500); if(json.success !== 1) { card.find('.cardprice').text(json.message); decrementTotal(card.data('price') / 100); return; } console.info(json); card.data('orderid', json.buy_orderid); card.data('checks', 0); card.find('.cardprice').text(card.find('.cardprice').text().replace('Placing buy order', 'Waiting')); checkOrderStatus(card); }); } function checkOrderStatus(card) { card.find('.cardprice')[0].innerHTML += '.'; $.get('/market/getbuyorderstatus/', {"sessionid": g_SessionID, "buy_orderid": card.data('orderid')}, function(json) { if(json.success !== 1) { setTimeout(function() { checkOrderStatus(card); }, 500); return; } if(json.purchases.length) { if(json.purchases[0].price_total < card.data('price')) { decrementTotal((card.data('price') - json.purchases[0].price_total) / 100); } card.find('.cardprice').text(formatPrice((json.purchases[0].price_total / 100).toFixed(2), true) + ' - Purchased'); checkAllPurchasesMade(); return; } if(!json.purchases.length) { card.data('checks', card.data('checks') + 1); if(card.data('checks') >= 10) { cancelBuyOrder(card.data('orderid')); card.find('.cardprice').text('Order unfulfilled'); decrementTotal(card.data('price') / 100); return; } } setTimeout(function() { checkOrderStatus(card); }, 500); }); } function cancelBuyOrder(orderid) { $.post('/market/cancelbuyorder/', {"sessionid": g_SessionID, "buy_orderid": orderid}, function(json) { if(!json.success) { setTimeout(function() { cancelBuyOrder(orderid); }, 500); } }); } function decrementTotal(total) { // Replace any commas to dots so we get a valid double $('#totalprice').text(formatPrice(($('#totalprice').text().replace(",", ".") - total).toFixed(2))); } function checkAllPurchasesMade() { var elements = $('.cardprice'); for(var i = 0; i < elements.length; i++) { if(elements[i].textContent.indexOf('Purchased') == -1) { return; } } // All cards bought if(parseInt(localStorage.autoReloadAndCraftBadge, 10)) { localStorage.autoCraftBadge = 1; window.location.reload(); } }