您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
try to take over the world!
当前为
// ==UserScript== // @name Steam Key Helper // @namespace http://tampermonkey.net/ // @version 1.2.0 // @description try to take over the world! // @icon http://store.steampowered.com/favicon.ico // @author Bisumaruko // @include http*://* // @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 // @noframes // ==/UserScript== /* global GM_xmlhttpRequest, GM_setValue, GM_getValue, GM_addStyle, GM_getResourceText, swal, g_AccountID, g_sessionID, window, document, location */ // setup jQuery const $ = jQuery.noConflict(true); // inject swal css GM_addStyle(GM_getResourceText('SweetAlert2CSS')); // setup swal swal.setDefaults({ timer: 3000, useRejections: false }); // inject CSS GM_addStyle(` .SKH_link { color: #57bae8; cursor: pointer; } .SKH_link:hover { text-decoration: underline; } .SKH_activated { text-decoration: line-through; } `); // load config const config = JSON.parse(GM_getValue('SKH_config') || '{}'); const activated = JSON.parse(GM_getValue('SKH_activated') || '[]'); const excludedTag = ['SCRIPT', 'STYLE', 'IFRAME', 'CANVAS']; const regKey = /([A-Za-z0-9]{5}-){2,4}[A-Za-z0-9]{5}/g; const has = Object.prototype.hasOwnProperty; // text const i18n = { tchinese: { errorTitle: '糟糕!', errorUnexpected: '發生未知錯誤,請稍後再試', errorInvalidKey: '序號錯誤', errorUsedKey: '序號已被使用', errorRateLimited: '啟動受限', errorCountryRestricted: '地區限制', errorAlreadyOwned: '產品已擁有', errorMissingBaseGame: '未擁有主程式', errorPS3Required: '需要PS3 啟動', errorGiftWallet: '偵測到禮物卡/錢包序號', errorFailedRequest: '處理資料發生錯誤,請稍後再試', errorFailedRequestNeedUpdate: '請求發生錯誤,請稍後再試<br>或者嘗試更新SessionID', successTitle: '啟動成功!', processingTitle: '喵~', processingMsg: '啟動序號中,請稍後', notLoggedInTitle: '未登入', notLoggedInMsg: '請登入Steam 以讓腳本紀錄SessionID', missingTitle: '未發現SessionID', missingMsg: '請問要更新SessionID 嗎?' }, schinese: { errorTitle: '糟糕!', errorUnexpected: '发生未知错误,请稍后再试', errorInvalidKey: '激活码错误', errorUsedKey: '激活码已被使用', errorRateLimited: '激活受限', errorCountryRestricted: '地区限制', errorAlreadyOwned: '产品已永有', errorMissingBaseGame: '位永有基础游戏', errorPS3Required: '需要PS3 激活', errorGiftWallet: '侦测到礼物卡/钱包激活码', errorFailedRequest: '处理资料发生错误,请稍后再试', errorFailedRequestNeedUpdate: '请求发生错误,请稍后再试<br>或者尝试更新SessionID', successTitle: '激活成功!', processingTitle: '喵~', processingMsg: '激活中,请稍后', notLoggedInTitle: '未登入', notLoggedInMsg: '请登入Steam 以让脚本记录SessionID', missingTitle: '未发现SessionID', missingMsg: '请问要更新SessionID 吗?' }, english: { errorTitle: 'Opps!', errorUnexpected: 'An unexpected error has occured, please try again later', errorInvalidKey: 'Invalid Key', errorUsedKey: 'Used Key', errorRateLimited: 'Rate Limited', errorCountryRestricted: 'Country Restricted', errorAlreadyOwned: 'Product Already Owned', errorMissingBaseGame: 'Missing Base Game', errorPS3Required: 'PS3 Activation Required', errorGiftWallet: 'Gift Card/Wallet Code Detected', errorFailedRequest: 'Result parse failed, please try again', errorFailedRequestNeedUpdate: 'Request failed, please try again<br>or update sessionID', successTitle: 'Activation Successful!', processingTitle: 'Nyaa~', processingMsg: 'Activating key, please wait', 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?' } }; const text = has.call(i18n, config.language) ? i18n[config.language] : i18n.english; // functions const updateActivated = (key, result) => { if (!activated.includes(key)) { if (result.success === 1 || [14, 15, 9].includes(result.purchase_result_details)) { activated.push(key); GM_setValue('SKH_activated', JSON.stringify(activated)); $(`span:contains(${key})`).addClass('SKH_activated'); } } }; const getResultMsg = result => { const errMsg = { title: text.errorTitle, html: text.errorUnexpected, type: 'error' }; const errors = { 14: text.errorInvalidKey, 15: text.errorUsedKey, 53: text.errorRateLimited, 13: text.errorCountryRestricted, 9: text.errorAlreadyOwned, 24: text.errorMissingBaseGame, 36: text.errorPS3Required, 50: text.errorGiftWallet }; const getDetails = items => { const details = []; items.forEach(item => { const detail = [`<b>${item.line_item_description}</b>`]; if (item.packageid > 0) detail.push(`sub: ${item.packageid}`); if (item.appid > 0) detail.push(`app: ${item.appid}`); details.push(detail.join(', ')); }); return details.join('<br>'); }; if (result.success === 1) { return { title: text.successTitle, html: getDetails(result.purchase_receipt_info.line_items), type: 'success' }; } else if (result.success === 2) { if (has.call(errors, result.purchase_result_details)) { errMsg.html = errors[result.purchase_result_details]; } if (result.purchase_receipt_info.line_items.length > 0) { errMsg.html += `<br>${getDetails(result.purchase_receipt_info.line_items)}`; } } return errMsg; }; const activateKey = key => { swal({ title: text.processingTitle, text: text.processingMsg, timer: null }); swal.showLoading(); GM_xmlhttpRequest({ method: 'POST', url: 'https://store.steampowered.com/account/ajaxregisterkey/', headers: { Accept: 'text/javascript, text/html, application/xml, text/xml, */*', 'Accept-Encoding': 'gzip, deflate, br', '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 => { swal.close(); if (res.status === 200) { try { const result = JSON.parse(res.response); swal(getResultMsg(result)); updateActivated(key, result); } catch (e) { swal(text.errorTitle, text.errorFailedRequest, 'error'); } } else { swal({ title: text.errorTitle, html: text.errorFailedRequestNeedUpdate, type: 'error', timer: null, showCancelButton: true, preConfirm: () => { window.open('https://store.steampowered.com/'); } }); } } }); }; const generateLink = txt => { const link = $(`<span class="SKH_link">${txt}</span>`).click(() => { activateKey(txt); }); if (activated.includes(txt)) link.addClass('SKH_activated'); return link[0]; }; const scanText = txt => { let matched = true; const matches = []; while (matched) { matched = regKey.exec(txt.data); if (matched) matches.push(matched); } matches.reverse().forEach(match => { txt.splitText(match.index); txt.nextSibling.splitText(match[0].length); txt.parentNode.replaceChild(generateLink(match[0]), txt.nextSibling); }); }; const scanElement = element => { Array.from(element.childNodes).reverse().forEach(child => { if (child.nodeType === 1) { // element node if (child.type === 'text' && regKey.test(child.value)) { const $child = $(child); if (activated.includes(child.value)) $child.addClass('SKH_activated'); $child.click(() => { activateKey(child.value); }); } else if (!excludedTag.includes(child.tagName)) scanElement(child); } else if (child.nodeType === 3) { // text node scanText(child); } }); }; const init = () => { // save sessionID if (location.hostname === 'store.steampowered.com') { if (g_AccountID > 0) { if (config.sessionID !== g_sessionID) config.sessionID = g_sessionID; if (config.language !== g_oSuggestParams.l) config.language = g_oSuggestParams.l; GM_setValue('SKH_config', JSON.stringify(config)); } else { swal(text.notLoggedInTitle, text.notLoggedInMsg, 'error'); } } else { // check sessionID & language if (!config.sessionID || !config.language) { swal({ title: text.missingTitle, text: text.missingMsg, type: 'question', timer: null, showCancelButton: true, preConfirm: () => { window.open('https://store.steampowered.com/'); } }); } scanElement(document.body); } }; $(init);