您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
try to take over the world!
当前为
// ==UserScript== // @name Steam Bundle Sites Extension // @namespace http://tampermonkey.net/ // @version 1.2.1 // @description try to take over the world! // @icon http://store.steampowered.com/favicon.ico // @author Bisumaruko // @include http*://store.steampowered.com/* // @include https://www.indiegala.com/gift* // @include https://www.indiegala.com/profile* // @include http*://*bundlestars.com/* // @include https://www.humblebundle.com/downloads* // @include http*://*dailyindiegame.com/* // @include http*://bundle.ccyycn.com/order/* // @include https://groupees.com/purchases // @include http*://*agiso.com/* // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.6.6/sweetalert2.min.js // @resource SweetAlert2CSS https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.6.6/sweetalert2.min.css // @connect store.steampowered.com // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @grant GM_getResourceText // @run-at document-start // @noframes // ==/UserScript== /* global GM_xmlhttpRequest, GM_setValue, GM_getValue, GM_addStyle, GM_getResourceText, swal, g_AccountID, g_sessionID, g_oSuggestParams, window, document, location, fetch, localStorage, MutationObserver, Option */ // setup jQuery const $ = jQuery.noConflict(true); $.fn.pop = [].pop; $.fn.shift = [].shift; // inject swal css GM_addStyle( GM_getResourceText('SweetAlert2CSS'), ); // setup swal swal.setDefaults({ timer: 3000, useRejections: false, }); const config = JSON.parse(GM_getValue('SBSE_config') || '{}'); const activated = JSON.parse(GM_getValue('SBSE_activated') || '[]'); const owned = JSON.parse(localStorage.getItem('SBSE_owned') || '{}'); const regKey = /([A-Za-z0-9]{5}-){2,4}[A-Za-z0-9]{5}/g; const eol = "\n"; const has = Object.prototype.hasOwnProperty; const unique = a => [...new Set(a)]; // text const i18n = { tchinese: { name: '繁體中文', successStatus: '成功', successDetail: '無資料', activatedStatus: '已啟動', failStatus: '失敗', failTitle: '糟糕!', failDetailUnexpected: '發生未知錯誤,請稍後再試', failDetailInvalidKey: '序號錯誤', failDetailUsedKey: '序號已被使用', failDetailRateLimited: '啟動受限', failDetailCountryRestricted: '地區限制', failDetailAlreadyOwned: '產品已擁有', failDetailMissingBaseGame: '未擁有主程式', failDetailPS3Required: '需要PS3 啟動', failDetailGiftWallet: '偵測到禮物卡/錢包序號', failDetailParsingFailed: '處理資料發生錯誤,請稍後再試', failDetailRequestFailedNeedUpdate: '請求發生錯誤,請稍後再試<br>或者嘗試更新SessionID', noItemDetails: '無產品詳細資料', notLoggedInTitle: '未登入', notLoggedInMsg: '請登入Steam 以讓腳本紀錄SessionID', missingTitle: '未發現SessionID', missingMsg: '請問要更新SessionID 嗎?', emptyInput: '未發現Steam 序號', settingsTitle: '設定', settingsAutoUpdateSessionID: '自動更新SessionID', settingsSessionID: '我的SessionID', settingsLanguage: '語言', DIGEasyBuyPurchase: '購買', DIGEasyBuySelectAll: '全選', DIGEasyBuySelectCancel: '取消', DIGButtonPurchasing: '購買中', buttonReveal: '刮開', buttonRetrieve: '提取', buttonActivate: '啟動', buttonCopy: '複製', buttonReset: '清空', checkboxIncludeGameTitle: '遊戲名', checkboxJoinKeys: '合併', checkboxSkipUsed: '跳過已使用', BSselectConnector: '至', }, schinese: { name: '简体中文', successStatus: '成功', successDetail: '无信息', activatedStatus: '已激活', failStatus: '失败', failTitle: '糟糕!', failDetailUnexpected: '发生未知错误,请稍后再试', failDetailInvalidKey: '激活码错误', failDetailUsedKey: '激活码已被使用', failDetailRateLimited: '激活受限', failDetailCountryRestricted: '地区限制', failDetailAlreadyOwned: '产品已永有', failDetailMissingBaseGame: '未拥有基础游戏', failDetailPS3Required: '需要PS3 激活', failDetailGiftWallet: '侦测到礼物卡/钱包激活码', failDetailParsingFailed: '处理资料发生错误,请稍后再试', failDetailRequestFailedNeedUpdate: '请求发生错误,请稍后再试<br>或者尝试更新SessionID', noItemDetails: '无产品详细信息', notLoggedInTitle: '未登入', notLoggedInMsg: '请登入Steam 以让脚本记录SessionID', missingTitle: '未发现SessionID', missingMsg: '请问要更新SessionID 吗?', emptyInput: '未批配到Steam 激活码', settingsTitle: '設置', settingsAutoUpdateSessionID: '自动更新SessionID', settingsSessionID: '我的SessionID', settingsLanguage: '语言', DIGEasyBuyPurchase: '购买', DIGEasyBuySelectAll: '全选', DIGEasyBuySelectCancel: '取消', DIGButtonPurchasing: '购买中', buttonReveal: '刮开', buttonRetrieve: '提取', buttonActivate: '激活', buttonCopy: '复制', buttonReset: '清空', checkboxIncludeGameTitle: '游戏名', checkboxJoinKeys: '合并', checkboxSkipUsed: '跳过已使用', BSselectConnector: '至', }, english: { name: 'English', successStatus: 'Success', successDetail: 'No Detail', activatedStatus: 'Activated', failStatus: 'Fail', failTitle: 'Opps!', failDetailUnexpected: 'Unexpected Error', failDetailInvalidKey: 'Invalid Key', failDetailUsedKey: 'Used Key', failDetailRateLimited: 'Rate Limited', failDetailCountryRestricted: 'Country Restricted', failDetailAlreadyOwned: 'Product Already Owned', failDetailMissingBaseGame: 'Missing Base Game', failDetailPS3Required: 'PS3 Activation Required', failDetailGiftWallet: 'Gift Card/Wallet Code Detected', failDetailParsingFailed: 'Result parse failed', failDetailRequestFailedNeedUpdate: 'Request failed, please try again<br>or update sessionID', noItemDetails: 'No Item Details', notLoggedInTitle: 'Not Logged-In', notLoggedInMsg: 'Please login to Steam so sessionID can be saved', missingTitle: 'Missing SessionID', missingMsg: 'Do you want to update your Steam sessionID?', emptyInput: 'Could not find Steam code', settingsTitle: 'Settings', settingsAutoUpdateSessionID: 'Auto Update SessionID', settingsSessionID: 'Your sessionID', settingsLanguage: 'Language', DIGEasyBuyPurchase: 'Purchase', DIGEasyBuySelectAll: 'Select All', DIGEasyBuySelectCancel: 'Cancel', DIGButtonPurchasing: 'Purchassing', buttonReveal: 'Reveal', buttonRetrieve: 'Retrieve', buttonActivate: 'Activate', buttonCopy: 'Copy', buttonReset: 'Reset', checkboxIncludeGameTitle: 'Include Game Title', checkboxJoinKeys: 'Join Keys', checkboxSkipUsed: 'Skip Used', BSselectConnector: 'to', }, }; let text = has.call(i18n, config.language) ? i18n[config.language] : i18n.english; // inject settings panel css GM_addStyle(` .SBSE_settings .name { text-align: right; } .SBSE_settings .value { text-align: left; } .SBSE_settings .value > * { height: 30px; margin: 10px 20px; } .SBSE_settings .switch { position: relative; display: inline-block; width: 60px; } .SBSE_settings .switch input { display: none; } .SBSE_settings .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: 0.4s; } .SBSE_settings .slider:before { position: absolute; content: ""; height: 26px; width: 26px; left: 2px; bottom: 2px; background-color: white; transition: 0.4s; } .SBSE_settings input:checked + .slider { background-color: #2196F3; } .SBSE_settings input:focus + .slider { box-shadow: 0 0 1px #2196F3; } .SBSE_settings input:checked + .slider:before { transform: translateX(30px); } .SBSE_settings > span { display: inline-block; cursor: pointer; color: white; } `); // functions const settings = { construct() { const panelHTML = ` <div class="SBSE_settings"> <table> <tr> <td class="name">${text.settingsAutoUpdateSessionID}</td> <td class="value"> <label class="switch"> <input type="checkbox" class="autoUpdateSessionID"> <span class="slider"></span> </label> </td> </tr> <tr> <td class="name">${text.settingsSessionID}</td> <td class="value"> <input type="text" class="sessionID" value="${config.sessionID}" disabled> </td> </tr> <tr> <td class="name">${text.settingsLanguage}</td> <td class="value"> <select class="language"></select> </td> </tr> </table> </div> `; return panelHTML; }, display() { swal({ title: text.settingsTitle, html: this.construct(), timer: null, }); // apply settings const $panel = $(swal.getContent()); const $autoUpdateSessionID = $panel.find('.autoUpdateSessionID'); const $sessionID = $panel.find('.sessionID'); const $language = $panel.find('.language'); $autoUpdateSessionID.prop('checked', has.call(config, 'autoUpdateSessionID') ? config.autoUpdateSessionID : true); $autoUpdateSessionID.change(() => { swal.showLoading(); const state = $panel.find('.autoUpdateSessionID:checked').length || 0; config.autoUpdateSessionID = state; GM_setValue('SBSE_config', JSON.stringify(config)); $sessionID.attr('disabled', !!state); setTimeout(swal.hideLoading, 500); }); $sessionID.change(() => { swal.showLoading(); config.sessionID = $sessionID.val(); GM_setValue('SBSE_config', JSON.stringify(config)); setTimeout(swal.hideLoading, 500); }); Object.keys(i18n).forEach((language) => { $language.append(new Option(i18n[language].name, language)); }); $panel.find(`option[value=${config.language}]`).prop('selected', true); $language.change(() => { swal.showLoading(); config.language = $language.val(); GM_setValue('SBSE_config', JSON.stringify(config)); text = has.call(i18n, config.language) ? i18n[config.language] : i18n.english; setTimeout(swal.hideLoading, 500); }); }, }; const activateHandler = { keys: [], results: {}, updateResults(txt = null) { const $textarea = $('.SBSE_container > textarea'); if (txt) { $textarea.val(txt); } else { const results = this.results; const parsed = []; Object.values(results).forEach((result) => { parsed.push(result.join(' | ')); }); $textarea.val(parsed.join(eol)); } }, getResultStatus(result) { let status = text.failStatus; let statusMsg = text.failDetailUnexpected; const errors = { 14: text.failDetailInvalidKey, 15: text.failDetailUsedKey, 53: text.failDetailRateLimited, 13: text.failDetailCountryRestricted, 9: text.failDetailAlreadyOwned, 24: text.failDetailMissingBaseGame, 36: text.failDetailPS3Required, 50: text.failDetailGiftWallet, }; if (result.success === 1) { status = text.successStatus; statusMsg = text.successDetail; } else if (result.success === 2) { if (has.call(errors, result.purchase_result_details)) { statusMsg = errors[result.purchase_result_details]; } } return `${status}/${statusMsg}`; }, getResultItems(info) { const descriptions = []; if (info && info.line_items) { info.line_items.forEach((item) => { const description = []; if (item.packageid > 0) description.push(`sub: ${item.packageid}`); if (item.appid > 0) description.push(`app: ${item.appid}`); description.push(item.line_item_description); descriptions.push(description.join(' ')); }); } return descriptions.join(', '); }, activateKey(callback) { const self = this; const key = self.keys.shift(); if (key) { if (activated.includes(key)) { self.results[key].push(text.activatedStatus, text.noItemDetails); self.updateResults(); // next key self.activateKey(callback); } else { GM_xmlhttpRequest({ method: 'POST', url: 'https://store.steampowered.com/account/ajaxregisterkey/', headers: { Accept: 'text/javascript, text/html, application/xml, text/xml, */*', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', Origin: 'https://store.steampowered.com', Referer: 'https://store.steampowered.com/account/registerkey', }, data: `product_key=${key}&sessionid=${config.sessionID}`, onload: (res) => { if (res.status === 200) { let status = ''; let items = ''; try { const result = JSON.parse(res.response); status = self.getResultStatus(result); items = self.getResultItems(result.purchase_receipt_info); // update activated const failCode = result.purchase_result_details; if (result.success === 1 || [14, 15, 9].includes(failCode)) { activated.push(key); GM_setValue('SBSE_activated', JSON.stringify(activated)); } // dispatch activated event $(document).trigger('activated', [key, result]); } catch (e) { status = `${text.failStatus}/${text.failDetailParsingFailed}`; items = text.noItemDetails; } self.results[key].push(status, items); self.updateResults(); // next key setTimeout(self.activateKey.bind(self, callback), 2000); } else { swal({ title: text.failTitle, html: text.failDetailRequestFailedNeedUpdate, type: 'error', timer: null, showCancelButton: true, }).then(() => { window.open('https://store.steampowered.com/'); }); callback(); } }, }); } } else callback(); }, activateKeys(input, callback) { const self = this; const keys = unique(input.match(regKey)); if (keys.length > 0) { keys.forEach((key) => { self.results[key] = [key]; }); self.keys = Object.keys(self.results); self.updateResults(); self.activateKey(callback); } else { self.updateResults(text.emptyInput); callback(); } }, }; const bundleSitesBox = () => { GM_addStyle(` .SBSE_container { width: 100%; height: 200px; display: flex; flex-direction: column; box-sizing: border-box; } .SBSE_container > textarea { width: 100%; height: 150px; border: none; box-sizing: border-box; resize: none; outline: none; } .SBSE_container > div { width: 100%; padding-top: 5px; box-sizing: border-box; } .SBSE_container button { width: 120px; position: relative; margin-right: 10px; line-height: 28px; box-sizing: border-box; outline: none; cursor: pointer; } .SBSE_container label { margin-right: 10px; } #SBSE_BtnSettings { width: 20px; height: 20px; float: right; margin-right: 0; margin-left: 10px; background-color: transparent; background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGhlaWdodD0iMzJweCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzIgMzI7IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJMYXllcl8xIi8+PGcgaWQ9ImNvZyI+PHBhdGggZD0iTTMyLDE3Ljk2OXYtNGwtNC43ODEtMS45OTJjLTAuMTMzLTAuMzc1LTAuMjczLTAuNzM4LTAuNDQ1LTEuMDk0bDEuOTMtNC44MDVMMjUuODc1LDMuMjUgICBsLTQuNzYyLDEuOTYxYy0wLjM2My0wLjE3Ni0wLjczNC0wLjMyNC0xLjExNy0wLjQ2MUwxNy45NjksMGgtNGwtMS45NzcsNC43MzRjLTAuMzk4LDAuMTQxLTAuNzgxLDAuMjg5LTEuMTYsMC40NjlsLTQuNzU0LTEuOTEgICBMMy4yNSw2LjEyMWwxLjkzOCw0LjcxMUM1LDExLjIxOSw0Ljg0OCwxMS42MTMsNC43MDMsMTIuMDJMMCwxNC4wMzF2NGw0LjcwNywxLjk2MWMwLjE0NSwwLjQwNiwwLjMwMSwwLjgwMSwwLjQ4OCwxLjE4OCAgIGwtMS45MDIsNC43NDJsMi44MjgsMi44MjhsNC43MjMtMS45NDVjMC4zNzksMC4xOCwwLjc2NiwwLjMyNCwxLjE2NCwwLjQ2MUwxNC4wMzEsMzJoNGwxLjk4LTQuNzU4ICAgYzAuMzc5LTAuMTQxLDAuNzU0LTAuMjg5LDEuMTEzLTAuNDYxbDQuNzk3LDEuOTIybDIuODI4LTIuODI4bC0xLjk2OS00Ljc3M2MwLjE2OC0wLjM1OSwwLjMwNS0wLjcyMywwLjQzOC0xLjA5NEwzMiwxNy45Njl6ICAgIE0xNS45NjksMjJjLTMuMzEyLDAtNi0yLjY4OC02LTZzMi42ODgtNiw2LTZzNiwyLjY4OCw2LDZTMTkuMjgxLDIyLDE1Ljk2OSwyMnoiIHN0eWxlPSJmaWxsOiM0RTRFNTA7Ii8+PC9nPjwvc3ZnPg==); background-size: contain; background-repeat: no-repeat; background-origin: border-box; border: none; vertical-align: top; } `); // spinner button affect GM_addStyle(` .SBSE_container button:before { content: ''; position: absolute; right: 10px; margin-top: 5px; width: 20px; height: 20px; border: 3px solid; border-left-color: transparent; border-radius: 50%; box-sizing: border-box; opacity: 0; transition: opacity 0.5s; animation-duration: 1s; animation-iteration-count: infinite; animation-name: rotate; animation-timing-function: linear; } .SBSE_container button.working { padding-right: 20px; width: 120px; transition: padding-right 0.5s; transition: width 0.5s; } .SBSE_container button.working:before { transition-delay: 0.5s; transition-duration: 1s; opacity: 1; } @keyframes rotate { 0% { transform: rotate(0deg);} 100% { transform: rotate(360deg);} } `); const $container = $(` <div class="SBSE_container"> <textarea></textarea> <div> <button class="SBSE_BtnReveal">${text.buttonReveal}</button> <button class="SBSE_BtnRetrieve">${text.buttonRetrieve}</button> <button class="SBSE_BtnActivate">${text.buttonActivate}</button> <button class="SBSE_BtnCopy">${text.buttonCopy}</button> <button class="SBSE_BtnReset">${text.buttonReset}</button> <label><input type="checkbox" class="SBSE_ChkTitle">${text.checkboxIncludeGameTitle}</label> <label><input type="checkbox" class="SBSE_ChkJoin">${text.checkboxJoinKeys}</label> <button id="SBSE_BtnSettings"> </button> </div> </div> `); $container.find('.SBSE_BtnCopy').click(() => { $('.SBSE_container > textarea').select(); document.execCommand('copy'); }); $container.find('.SBSE_BtnReset').click(() => { $('.SBSE_container > textarea').val(''); }); $container.find('.SBSE_BtnActivate').click((e) => { const $self = $(e.delegateTarget); const $textarea = $('.SBSE_container > textarea'); let input = $textarea.val().trim(); if (input.length === 0) { $('.SBSE_container input:not(.keep)').prop('checked', false); $('.SBSE_BtnRetrieve').click(); input = $textarea.val(); } $self.prop('disabled', true).addClass('working'); $textarea.attr('disabled', ''); activateHandler.activateKeys(input, () => { $self.prop('disabled', false).removeClass('working'); $textarea.removeAttr('disabled'); }); }); $container.find('#SBSE_BtnSettings').click(() => { settings.display(); }); return $container; }; const siteCache = { bundlestars: { doms: [document], }, }; const siteHandlers = { indiegala() { // insert textarea $('#library-contain').eq(0).before(bundleSitesBox()); // inject css GM_addStyle(` .SBSE_container { margin-top: 10px; } .SBSE_container > textarea { border: 1px solid #CC001D; } .SBSE_container button { background-color: #CC001D; color: white; } `); // dom source const source = location.pathname === '/profile' ? 'div[id*="_sale_"].collapse.in' : document; // button click $('.SBSE_BtnReveal').click((e) => { const $self = $(e.delegateTarget); const $games = $(source).find('img[src*="steam-icon-tm-g.png"]').closest('a'); const handler = async () => { const game = $games.shift(); if (game) { const $game = $(game); const code = $game.attr('id').split('_').pop(); const appID = $game.attr('onclick').match(/steampowered\.com\/app\/(\d+)/)[1]; $(`#permbutton_${code}, #fetchlink_${code}, #info_key_${code}`).hide(); $(`#fetching_${code}`).fadeIn(); $(`#ajax_loader_${code}`).show(); $(`#container_activate_${code}`).html(''); const url = `https://www.indiegala.com/myserials/syncget?code=${code}&cache=false&productId=${appID}`; const res = await fetch(url, { method: 'GET', headers: { Accept: 'application/json, text/javascript, */*; q=0.01', }, mode: 'same-origin', credentials: 'same-origin', cache: 'no-store', referer: location.href, }); if (res.ok) { const data = await res.json(); $(`#ajax_loader_${code}, #fetching_${code}, #info_key_${code}`).hide(); $(`#serial_${code}`).fadeIn(); $(`#serial_n_${code}`).val(data.serial_number); $game.parent().prev().find('.btn-convert-to-trade').remove(); handler(); } } else { $self.removeClass('working'); $('.SBSE_BtnRetrieve').click(); } }; $self.addClass('working'); handler(); }); $('.SBSE_BtnRetrieve').click(() => { const includeTitle = $('.SBSE_ChkTitle:checked').length; const separator = $('.SBSE_ChkJoin:checked').length > 0 ? ',' : eol; const keys = []; $(source).find('.game-key-string').each((index, element) => { const $ele = $(element); const key = $ele.find('.keys').val(); if (key) { const title = includeTitle ? `${$ele.find('.title_game > a').text().trim()}, ` : ''; keys.push(title + key); } }); $('.SBSE_container > textarea').val(keys.join(separator)); }); }, bundlestars(firstCalled) { const cache = siteCache.bundlestars; const $anchor = $('h2:contains(Order Keys)'); const BSselect = (selector) => { let $results = $(); let from = parseInt($('.SBSE_container .selectFrom').val(), 10); let to = parseInt($('.SBSE_container .selectTo').val(), 10); if ($.isNumeric(from) && $.isNumeric(to)) { if (from === 0 && to > 0) from = 1; if (from > 0 && to === 0) to = cache.doms.length - 1; for (let i = Math.min(from, to); i <= Math.max(from, to); i += 1) { $results = $results.add( $(cache.doms[i]).find(selector), ); } } return $results; }; if ($('.SBSE_container').length === 0 && $anchor.length > 0) { // insert textarea $anchor.eq(0).before(bundleSitesBox()); // insert bundlestars select $('.SBSE_container > div').append(` <select class="selectTo"></select> <span>${text.BSselectConnector}</span> <select class="selectFrom"></select> `); // inject css GM_addStyle(` .SBSE_container { border: 1px solid #424242; color: #999999; } .SBSE_container > textarea { background-color: #303030; color: #DDD; } .SBSE_container button { width: 80px; } .SBSE_container button, .SBSE_container select { border: 1px solid transparent; background-color: #262626; color: #DEDEDE; } .SBSE_container button:hover, .SBSE_container select:hover { color: #A8A8A8; } .SBSE_container label { color: #DEDEDE; } .SBSE_container select { max-width:120px; height: 30px; } .SBSE_container select, .SBSE_container span { margin-right: 0; margin-left: 10px; float: right; } .SBSE_container span { margin-top: 5px; } `); // button click $('.SBSE_BtnReveal').click((e) => { const $self = $(e.delegateTarget); const $games = BSselect('.key-container a[ng-click^="redeemSerial"]'); const handler = () => { const game = $games.shift(); if (game) { if (!game.closest('.ng-hide')) { game.click(); setTimeout(handler, 300); } else handler(); } else { $self.removeClass('working'); $('.SBSE_BtnRetrieve').click(); } }; $self.addClass('working'); handler(); }); $('.SBSE_BtnRetrieve').click(() => { const includeTitle = $('.SBSE_ChkTitle:checked').length; const separator = $('.SBSE_ChkJoin:checked').length > 0 ? ',' : eol; const keys = []; BSselect('.key-container input').each((index, input) => { const $input = $(input); const title = includeTitle ? `${$input.closest('.key-container').prev().text().trim()}, ` : ''; const key = $input.val(); keys.push(title + key); }); $('.SBSE_container > textarea').val(keys.join(separator)); }); } // setup select const $selects = $('.SBSE_container select'); $selects.empty(); $selects.append(new Option('All', 0)); cache.doms = [document]; $('hr ~ div > div:not(.ng-hide)').each((index, block) => { const $block = $(block); const $bundle = $block.find('h3'); const $tiers = $block.find('h4'); if ($tiers.length > 1) { // bundles with multiple tiers $tiers.each((i, tier) => { const $tier = $(tier); $selects.append( new Option(`${$bundle.text()} ${$tier.text()}`, cache.doms.push($tier.parent()) - 1), ); }); } else if ($bundle.length > 0) { // bundles with single tier $selects.append( new Option($bundle.text(), cache.doms.push($bundle.next()) - 1), ); } else { // individual games $selects.append( new Option($block.find('.title').text(), cache.doms.push($block) - 1), ); } }); if (firstCalled) { new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.removedNodes.forEach((removedNode) => { if (removedNode.id === 'loading-bar-spinner') { siteHandlers.bundlestars(); } }); }); }).observe(document.body, { childList: true, }); } }, humblebundle() { // insert textarea $('#steam-tab').closest('.whitebox').eq(0).before(bundleSitesBox()); // inject css GM_addStyle(` .SBSE_container > textarea { border: 1px solid #AAAAAA; color: #4a4c45; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); border-radius: 5px; } .SBSE_container button { width: 80px; border: 1px solid #808080; border-radius: 3px; background-color: #c5c5c5; background: linear-gradient(to top, #cacaca, #e7e7e7); } `); // button click $('.SBSE_BtnReveal').click((e) => { const $self = $(e.delegateTarget); const $games = $('.sr-unredeemed-steam-button'); const handler = () => { const game = $games.shift(); if (game) { game.click(); setTimeout(handler, 300); } else { $self.removeClass('working'); $('.SBSE_BtnRetrieve').click(); } }; $self.addClass('working'); handler(); }); $('.SBSE_BtnRetrieve').click(() => { const includeTitle = $('.SBSE_ChkTitle:checked').length; const separator = $('.SBSE_ChkJoin:checked').length > 0 ? ',' : eol; const keys = []; $('.sr-redeemed-bubble').each((index, element) => { const $game = $(element); const key = $game.text().trim(); let title = ''; if (includeTitle) { const $heading = $game.closest('[class^=sr-key]').prev().children().eq(0); title = `${$heading.text().trim()}, `; } keys.push(title + key); }); $('.SBSE_container > textarea').val(keys.join(separator)); }); }, dailyindiegame() { const pathname = location.pathname; if (pathname.includes('/account_page')) { // insert textarea $('#TableKeys').eq(0).before(bundleSitesBox()); // inject css GM_addStyle(` .SBSE_container { padding: 5px; border: 1px solid #424242; } .SBSE_container > textarea { border: 1px solid #000; } .SBSE_container button { border: none; background-color: #FD5E0F; color: rgb(49, 49, 49); font-family: Ropa Sans; font-size: 15px; font-weight: 600; } `); // reveal button not neeeded $('.SBSE_BtnReveal').hide(); // button click $('.SBSE_BtnRetrieve').click(() => { const includeTitle = $('.SBSE_ChkTitle:checked').length; const separator = $('.SBSE_ChkJoin:checked').length > 0 ? ',' : eol; const keys = []; $('#TableKeys tr').each((i, tr) => { const $tds = $(tr).children(); const title = includeTitle ? `${$tds.eq(2).text().trim()}, ` : ''; const key = $tds.eq(4).text().trim(); if (key.includes('-')) keys.push(title + key); }); $('.SBSE_container > textarea').val(keys.join(separator)); }); } else if (pathname === '/account_digstore.html' || pathname === '/account_trades.html') { // DIG EasyBuy GM_addStyle(` .DIGEasyBuy button { padding: 4px 8px; outline: none; } .DIGEasyBuy_checked { background-color: #222; } `); const $target = $('#form3').closest('tr').children().eq(0); const $DIGEasyBuy = $(` <div class="DIGEasyBuy"> <button class="DIGButtonPurchase DIG3_Orange_15_Form">${text.DIGEasyBuyPurchase}</button> <button class="DIGButtonSelectAll DIG3_Orange_15_Form">${text.DIGEasyBuySelectAll}</button> </div> `); $target .empty() .append($DIGEasyBuy); // bind button event $('.DIGButtonPurchase').click((e) => { let bought = 0; let balance = parseInt($('a[href^="account_transac"]').closest('div').text().slice(12), 10) || 0; const $self = $(e.delegateTarget); const $checked = $('.DIGEasyBuy_checked'); const handler = async (callback) => { const item = $checked.shift(); if (item) { const $item = $(item); const id = $item.data('id'); const price = parseInt($item.data('price'), 10); if (id && price > 0 && (balance - price) > 0) { let url = `${location.origin}/account_buy.html`; const requestInit = { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `quantity=1&xgameid=${id}&xgameprice1=${price}&send=Purchase`, mode: 'same-origin', credentials: 'same-origin', cache: 'no-store', referrer: `${location.origin}/account_buy_${id}.html`, }; if (pathname === '/account_trades.html') { url = `${location.origin}/account_buytrade_${id}.html`; requestInit.body = `gameid=${id}&send=Purchase`; requestInit.referrer = url; } const res = await fetch(url, requestInit); if (res.ok) { $item.click(); bought += 1; balance -= price; } setTimeout(handler.bind(null, callback), 300); } } else callback(); }; $self.prop('disabled', true).text(text.DIGButtonPurchasing); handler(() => { if (bought) window.location = `${location.origin}/account_page.html`; else $self.prop('disabled', false).text(text.DIGButtonPurchase); }); }); $('.DIGButtonSelectAll').click((e) => { const $self = $(e.delegateTarget); const state = !$self.data('state'); $('.DIGEasyBuy_row').toggleClass('DIGEasyBuy_checked', state); $self.data('state', state); $self.text(state ? text.DIGEasyBuySelectCancel : text.DIGEasyBuySelectAll); }); // setup row data & event $('a[href^="account_buy"]').each((index, element) => { const $game = $(element); const $row = $game.closest('tr'); $row.data({ id: $game.attr('href').replace(/\D/g, ''), price: parseInt($game.closest('td').prev().text(), 10) || 0, }); $row.click(() => { $row.toggleClass('DIGEasyBuy_checked'); }); $row.addClass('DIGEasyBuy_row'); }); } }, ccyycn() { // insert textarea $('.featurette-divider').eq(0).after(bundleSitesBox()); // inject css GM_addStyle(` .SBSE_container { width: 80%; margin: 0 auto; color: #000; font-size: 16px; } .SBSE_container > textarea { background-color: #EEE; box-shadow: 0 0 1px 1px rgba(204,204,204,0.5); border-radius: 5px; } .SBSE_container > div { text-align: left; } .SBSE_container button { width: 80px; border: 1px solid transparent; border-radius: 5px; background-color: #EEE; box-shadow: 0 0 1px 1px rgba(204,204,204,0.5); } .SBSE_container label { color: #EEE; } `); // button click $('.SBSE_BtnReveal').click((e) => { const $self = $(e.delegateTarget); const $games = $('.deliver-btn'); const handler = () => { const game = $games.shift(); if (game) { game.click(); setTimeout(handler, 300); } else { $self.removeClass('working'); $('.SBSE_BtnRetrieve').click(); } }; $self.addClass('working'); handler(); }); $('.SBSE_BtnRetrieve').click(() => { const includeTitle = $('.SBSE_ChkTitle:checked').length; const separator = $('.SBSE_ChkJoin:checked').length > 0 ? ',' : eol; const keys = []; $('.deliver-gkey').each((index, element) => { const $game = $(element); const title = includeTitle ? `${$game.parent().prev().text().trim()}, ` : ''; const key = $game.text().trim(); keys.push(title + key); }); $('.SBSE_container > textarea').val(keys.join(separator)); }); }, groupees() { // insert textarea $('.container > div').eq(1).before(bundleSitesBox()); // inject css GM_addStyle(` .SBSE_container { } .SBSE_container > textarea { background-color: #EEE; border-radius: 3px; } .SBSE_container > div { } .SBSE_container button { font-weight: bold; background-color: #FFF; border: 1px solid #CCC; color: #333; } .SBSE_container button:hover { background-color: #e6e6e6; border-color: #adadad; } .SBSE_container label { } `); // append checkbox for used-key $('#SBSE_BtnSettings').before( $(`<label><input type="checkbox" class="SBSE_ChkSkipUsed keep" checked>${text.checkboxSkipUsed}</label>`), ); // button click $('.SBSE_BtnReveal').click((e) => { const $self = $(e.delegateTarget); const $games = $('.expanded .reveal'); const handler = () => { const game = $games.shift(); if (game) { game.click(); setTimeout(handler, 300); } else { $self.removeClass('working'); $('.SBSE_BtnRetrieve').click(); } }; $self.addClass('working'); // reveal products first const $reveals = $('.reveal-product'); if ($reveals.length > 0) { $reveals.click(); setTimeout(handler, 3000); } else handler(); }); $('.SBSE_BtnRetrieve').click(() => { const includeTitle = $('.SBSE_ChkTitle:checked').length; const separator = $('.SBSE_ChkJoin:checked').length > 0 ? ',' : eol; const skipUsed = $('.SBSE_ChkSkipUsed:checked').length; const keys = []; $('.expanded .code').each((index, element) => { const $game = $(element); const used = $game.prev('.key-meta').find('.usage').prop('checked'); if (!used || (used && !skipUsed)) { const title = includeTitle ? `${$game.closest('.details').find('h3').text().trim()}, ` : ''; const key = $game.val(); keys.push(title + key); } }); $('.SBSE_container > textarea').val(keys.join(separator)); }); // bind custom event $(document).on('activated', (e, key, result) => { if (result.success === 1 || result.purchase_result_details === 9) { const $game = $(`[value=${key}]`).eq(0); $game.prev('.key-meta').find('.usage').click(); } }); }, agiso() { const keys = unique($('body').text().match(regKey)); if (keys.length > 0) { // insert textarea $('#tabs').eq(0).prepend(bundleSitesBox()); // inject css GM_addStyle(` .SBSE_container > textarea { border: 1px solid #AAAAAA; } .SBSE_container button { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; color: #555555; } .SBSE_container button:hover { border-color: #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; color: #212121; } #SBSE_BtnSettings { width: 32px !important; height: 32px !important; } `); // remove event from agiso $('.SBSE_container button').click((e) => { e.preventDefault(); }); // hide reveal $('.SBSE_BtnReveal').hide(); // button click $('.SBSE_BtnRetrieve').click(() => { const separator = $('.SBSE_ChkJoin:checked').length > 0 ? ',' : eol; $('.SBSE_container > textarea').val(keys.join(separator)); }); } }, }; const init = () => { if (location.hostname === 'store.steampowered.com') { // save sessionID if (g_AccountID > 0) { if (!config.sessionID || config.autoUpdateSessionID) config.sessionID = g_sessionID; if (!config.language) config.language = g_oSuggestParams.l; GM_setValue('SBSE_config', JSON.stringify(config)); } else { swal(text.notLoggedInTitle, text.notLoggedInMsg, 'error'); } } else { const site = location.hostname.replace(/(www|alds|bundle)\./, '').split('.').shift(); // check sessionID if (!config.sessionID) { swal({ title: text.missingTitle, text: text.missingMsg, type: 'question', timer: null, showCancelButton: true, }).then(() => { window.open('https://store.steampowered.com/'); }); } if (has.call(siteHandlers, site)) { siteHandlers[site](true); // update owned every 10 min const updateTimer = 10 * 60 * 1000; if (!owned.lastUpdate || owned.lastUpdate < (Date.now() - updateTimer)) { GM_xmlhttpRequest({ method: 'GET', url: `http://store.steampowered.com/dynamicstore/userdata/t=${Math.random()}`, onload: (res) => { if (res.status === 200) { const data = JSON.parse(res.response); owned.app = data.rgOwnedApps; owned.sub = data.rgOwnedPackages; owned.lastUpdate = Date.now(); localStorage.setItem('SBSE_owned', JSON.stringify(owned)); } }, }); } } } }; $(init);