AuTo Redeemer Steamkey

复制网页中的Steamkey后自动激活,3.0+版本为Beta版

目前為 2019-08-23 提交的版本,檢視 最新版本

// ==UserScript==
// @name        AuTo Redeemer Steamkey
// @namespace   HCLonely
// @author      HCLonely
// @description 复制网页中的Steamkey后自动激活,3.0+版本为Beta版
// @supportURL  https://steamcn.com/t344489-1-1
// @include     *://*/*
// @exclude     *store.steampowered.com/widget/*
// @version     3.0.10
// @grant       GM_setClipboard
// @grant       GM_addStyle
// @grant       GM_registerMenuCommand
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_xmlhttpRequest
// @run-at      document-end
// @require     https://greasyfork.org/scripts/376437-hclonely-function/code/HCLonely_function.js?version=660229
// @require     https://greasyfork.org/scripts/388035-$jQuery/code/$jQuery.js?version=721233
// @require     https://greasyfork.org/scripts/389177-static/code/static.js?version=727413
// @require     https://cdn.bootcss.com/sweetalert/2.1.2/sweetalert.min.js
// @connect     *
// ==/UserScript==

(function() {
    'use strict';

    try{

        const url = window.location.href;

        const defaultSetting={
            newTab:false,
            copyListen:true,
            selectListen:true,
            clickListen:true,
            asf:false,
            asfProtocol:'http',
            asfHost:'127.0.0.1',
            asfPort:1242,
            asfPassword:'',
            asfBot:'',
        }
        let sessionID="";
        try{
            sessionID=g_sessionID;
        }catch(e){
            sessionID="";
        }

        if(Object.prototype.toString.call(GM_getValue("setting")) != '[object Object]') GM_setValue("setting",defaultSetting);

        const asfCommands=$jQuery(arsStatic.html[0])[0];

        if(GM_getValue("setting").selectListen){
            //选中激活功能
            const iconSize = 24;
            const translationTestSize = 16;
            let icon = document.createElement('div');
            const style = '' +
                  'position:absolute;' +
                  'width:32px;' +
                  'height:32px;' +
                  'margin:0px!important;' +
                  '';
            icon.innerHTML = '' +
                '<img src="'+arsStatic.icon+'" href="javascript:void(0)" style="' + style + '">'
            '';
            icon.setAttribute('style', '' +
                              'width:32px!important;' +
                              'height:32px!important;' +
                              'display:none!important;' +
                              'background:#fff!important;' +
                              'border-radius:16px!important;' +
                              'box-shadow:4px 4px 8px #888!important;' +
                              'position:absolute!important;' +
                              'z-index:2147483647!important;' +
                              'cursor:pointer;'+
                              '');
            icon.setAttribute("title","激活");

            // 添加激活图标到 DOM
            document.documentElement.appendChild(icon);
            // 鼠标事件:防止选中的文本消失
            document.addEventListener('mousedown', function (e) {
                if (e.target == icon || (e.target.parentNode && e.target.parentNode == icon) || (e.target.parentNode.parentNode && e.target.parentNode.parentNode == icon)) {// 点击了激活图标
                    e.preventDefault();
                }
            });
            // 选中变化事件:当点击已经选中的文本的时候,隐藏激活图标和激活面板(此时浏览器动作是:选中的文本已经取消选中了)
            document.addEventListener("selectionchange", ()=> {
                if (!window.getSelection().toString().trim()) {
                    icon.style.display = 'none';
                }
            });
            // 鼠标事件:防止选中的文本消失;显示、隐藏激活图标
            document.addEventListener('mouseup', function (e) {
                if (e.target == icon || (e.target.parentNode && e.target.parentNode == icon) || (e.target.parentNode.parentNode && e.target.parentNode.parentNode == icon)) {// 点击了激活图标
                    e.preventDefault();
                    return;
                }
                let text = window.getSelection().toString().trim();
                let productKey = window.getSelection().toString().trim() || e.target.value;
                if (/^([\w\W]*)?([\d\w]{5}(\-[\d\w]{5}){2}(\r||,||,)?){1,}/.test(productKey) && text && icon.style.display == 'none') {
                    icon.style.top = e.pageY + 12 + 'px';
                    icon.style.left = e.pageX + 18 + 'px';
                    icon.style.display = 'block';
                } else if (!text) {
                    icon.style.display = 'none';
                }
            });
            // 激活图标点击事件
            icon.addEventListener('click', function (e) {
                let productKey = window.getSelection().toString().trim() || e.target.value;
                registerkey(productKey);
            });
        }

        //复制激活功能
        if (!/https?:\/\/store\.steampowered\.com\/account\/registerkey[\w\W]{0,}/.test(url)&&GM_getValue("setting").copyListen){//非激活页面
            let activateProduct = function(e) {
                let productKey = window.getSelection().toString().trim() || e.target.value;
                if (/^([\w\W]*)?([\d\w]{5}(\-[\d\w]{5}){2}(\r||,||,)?){1,}/.test(productKey)) {
                    if(!$jQuery("div.swal-overlay").hasClass("swal-overlay--show-modal")){
                        swal({
                            title:'检测到神秘key,是否激活?',
                            icon: 'success',
                            buttons:{
                                confirm:'激活',
                                cancel:'取消',
                            },
                        }).then((value) => {
                            if(value) registerkey(productKey);
                        });
                    }
                }else if(/^\!addlicense.*[\d]$/gi.test(productKey)){
                    if(Object.prototype.toString.call(GM_getValue("setting")) === '[object Object]'&&GM_getValue("setting").asf&&!$jQuery("div.swal-overlay").hasClass("swal-overlay--show-modal")){
                        swal({
                            closeOnClickOutside: false,
                            className:'swal-user',
                            title:'检测到您复制了以下ASF指令,是否执行?',
                            text:productKey,
                            buttons:{
                                confirm:'执行',
                                cancel:'取消',
                            },
                        }).then((value)=>{
                            if(value) asfRedeem(productKey);
                        });
                    }
                }
            };
            window.addEventListener("copy", activateProduct, false);
        }

        //激活页面自动激活
        const selecter=url.includes("/account/registerkey")?"":".hclonely ";
        const autoDivideNum = 9;
        const waitingSeconds = 20;
        const ajaxTimeout = 15;

        let keyCount = 0;
        let recvCount = 0;
        let timer;

        let allUnusedKeys = [];

        const failureDetail = {
            14: '无效激活码',
            15: '重复激活',
            53: '次数上限',
            13: '地区限制',
            9: '已拥有',
            24: '缺少主游戏',
            36: '需要PS3?',
            50: '这是充值码',
        };

        const myTexts = {
            fail: '失败',
            success: '成功',
            network: '网络错误或超时',
            line: '——',
            nothing: '',
            others: '其他错误',
            unknown: '未知错误',
            redeeming: '激活中',
            waiting: '等待中',
            showUnusedKey: '显示未使用的Key',
            hideUnusedKey: '隐藏未使用的Key',
        };

        const unusedKeyReasons = [
            '次数上限',
            '地区限制',
            '已拥有',
            '缺少主游戏',
            '其他错误',
            '未知错误',
            '网络错误或超时',
        ];

        function redeemKey(key) {
            GM_xmlhttpRequest({
                url: 'https://store.steampowered.com/account/ajaxregisterkey/',
                headers: {
                    '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=${sessionID}`,
                method: 'POST',
                responseType: 'json',
                timeout: 1000 * ajaxTimeout,
                onloadstart:function(){
                    if (jQuery(selecter+'table').is(':hidden')) {
                        jQuery(selecter+'table').fadeIn();
                    }
                },
                onload: function(response){
                    if(response.status==200&&response.response){
                        let data=response.response;
                        if (data.success == 1) {
                            tableUpdateKey(key, myTexts.success, myTexts.line,
                                           data.purchase_receipt_info.line_items[0].packageid,
                                           data.purchase_receipt_info.line_items[0].line_item_description);
                            return;
                        } else if (data.purchase_result_details !== undefined && data.purchase_receipt_info) {
                            if (!data.purchase_receipt_info.line_items[0]) {
                                tableUpdateKey(key, myTexts.fail,
                                               failureDetail[data.purchase_result_details] ? failureDetail[data.purchase_result_details] : myTexts.others,
                                               0, myTexts.nothing);
                            } else {
                                tableUpdateKey(key, myTexts.fail,
                                               failureDetail[data.purchase_result_details] ? failureDetail[data.purchase_result_details] : myTexts.others,
                                               data.purchase_receipt_info.line_items[0].packageid,
                                               data.purchase_receipt_info.line_items[0].line_item_description);
                            }
                            return;
                        }
                        tableUpdateKey(key, myTexts.fail, myTexts.nothing, 0, myTexts.nothing);
                    }else{
                        tableUpdateKey(key, myTexts.fail, myTexts.network, 0, myTexts.nothing);
                        return;
                    }

                },
            });
        }

        function setUnusedKeys(key, success, reason, subId, subName) {
            if (success && allUnusedKeys.includes(key)) {
                var listObject;
                allUnusedKeys = allUnusedKeys.filter(function(keyItem){
                    return keyItem != key;
                });

                $jQuery(selecter+'li').map((i,e)=>{
                    if($jQuery(e).innerHTML.includes(key)) {
                        listObject.remove();
                    }
                });
            } else if (!success && !allUnusedKeys.includes(key) && unusedKeyReasons.includes(reason)) {
                listObject = $jQuery('<li></li>');
                listObject.html(key + ' ( ' + reason +
                                (subId != 0 ? (': <code>' + subId + '</code> ' + subName) : '') +
                                ' )');
                $jQuery('#unusedKeys').append(listObject);

                allUnusedKeys.push(key);
            }
        }

        function tableInsertKey(key) {
            keyCount++;
            let row = $jQuery('<tr></tr>');
            // number
            row.append('<td class="nobr">' + keyCount + '</td>');
            //key
            row.append('<td class="nobr"><code>' + key + '</code></td>');
            //redeeming...
            row.append('<td colspan="3">' + myTexts.redeeming + '...</td>');

            $jQuery(selecter+'tbody').prepend(row);
        }

        function tableWaitKey(key) {
            keyCount++;
            let row = $jQuery('<tr></tr>');
            // number
            row.append('<td class="nobr">' + keyCount + '</td>');
            //key
            row.append('<td class="nobr"><code>' + key + '</code></td>');
            //waiting...
            row.append('<td colspan="3">' + myTexts.waiting +
                       ' (' + waitingSeconds + '秒)...</td>');

            $jQuery(selecter+'tbody').prepend(row);
        }

        function tableUpdateKey(key, result, detail, subId, subName) {
            setUnusedKeys(key, result === myTexts.success, detail, subId, subName);

            recvCount++;
            if (!selecter&&recvCount == keyCount) {
                $jQuery('#buttonRedeem').fadeIn();
                $jQuery('#inputKey').removeAttr('disabled');
            }

            var rowObjects = $jQuery(selecter+'tr');
            for (let i = 1; i < rowObjects.length; i++) {
                let rowElement = rowObjects[i];
                let rowObject = $jQuery(rowElement);

                if (rowObject.children()[1].innerHTML.includes(key)&&rowObject.children()[2].innerHTML.includes(myTexts.redeeming)) {

                    rowObject.children()[2].remove();

                    // result
                    if (result == myTexts.fail) rowObject.append('<td class="nobr" style="color:red">' + result + '</td>');
                    else rowObject.append('<td class="nobr" style="color:green">' + result + '</td>');
                    // detail
                    rowObject.append('<td class="nobr">' + detail + '</td>');
                    // sub
                    if (subId === 0) {
                        rowObject.append('<td>——</td>');
                    } else {
                        rowObject.append('<td><code>' + subId + '</code> <a href="https://steamdb.info/sub/' +
                                         subId + '/" target="_blank">' + subName + '</a></td>');
                    }
                    break;
                }
            }
        }

        function startTimer() {
            timer = setInterval(function() {
                let flag = false;
                let nowKey = 0;

                let rowObjects = $jQuery(selecter+'tr');
                for (let i = rowObjects.length - 1; i >= 1; i--) {
                    let rowElement = rowObjects[i];
                    let rowObject = $jQuery(rowElement);
                    if (rowObject.children()[2].innerHTML.includes(myTexts.waiting)) {
                        nowKey++;
                        if (nowKey <= autoDivideNum) {
                            let key = rowObject.children()[1].innerHTML.substring(6);
                            key = key.substring(0, key.indexOf('</code>'));
                            rowObject.children()[2].innerHTML = '<td colspan="3">' + myTexts.redeeming + '...</td>';
                            redeemKey(key);
                        } else {
                            flag = true;
                            break;
                        }
                    }
                }
                if (!flag) {
                    clearInterval(timer);
                }
            }, 1000 * waitingSeconds);
        }

        function redeem(keys){
            if (keys.length <= 0) {
                return;
            }

            if(!selecter){
                $jQuery('#buttonRedeem').hide();
                $jQuery('#inputKey').attr('disabled', 'disabled');
            }

            let nowKey = 0;
            keys.forEach(function (key) {
                nowKey++;
                if (nowKey <= autoDivideNum) {
                    tableInsertKey(key);
                    redeemKey(key);
                } else {
                    tableWaitKey(key);
                }
            });

            if (nowKey > autoDivideNum) {
                startTimer();
            }
        }
        function redeemKeys(key) {
            let keys = key||getKeysByRE($jQuery('#inputKey').val().trim());
            redeem(keys);
        }

        function toggleUnusedKeyArea() {
            if(!selecter){
                if ($jQuery('#unusedKeyArea').is(':hidden')) {
                    $jQuery('#unusedKeyArea').show();
                } else {
                    $jQuery('#unusedKeyArea').hide();
                }
            }
        }

        function setting(){
            let setting=Object.prototype.toString.call(GM_getValue("setting")) === '[object Object]'?GM_getValue("setting"):defaultSetting;
            let div=document.createElement("div");
            div.setAttribute("id","hclonely-asf");
            div.innerHTML=`
<input type="checkbox" name="newTab" ${setting.newTab?'checked=checked':''} title="开启ASF激活后此功能无效"/><span title="开启ASF激活后此功能无效">新标签页激活</span><br/>
<input type="checkbox" name="copyListen" ${setting.copyListen?'checked=checked':''} title="复制key时询问是否激活"/><span title="复制key时询问是否激活">开启复制捕捉</span>
<input type="checkbox" name="selectListen" ${setting.selectListen?'checked=checked':''} title="选中key时显示激活图标"/><span title="选中key时显示激活图标">开启选中捕捉</span>
<input type="checkbox" name="clickListen" ${setting.clickListen?'checked=checked':''} title="点击key时添加激活链接"/><span title="点击key时添加激活链接">开启点击捕捉</span>
<div class="swal-title">ASF IPC设置</div>
<span>ASF IPC协议</span><input type="text" name="asfProtocol" value='${setting.asfProtocol}' placeholder="http或https,默认为http"/><br/>
<span>ASF IPC地址</span><input type="text" name="asfHost" value='${setting.asfHost}' placeholder="ip地址或域名,默认为127.0.0.1"/><br/>
<span>ASF IPC端口</span><input type="text" name="asfPort" value='${setting.asfPort}' placeholder="默认1242"/><br/>
<span>ASF IPC密码</span><input type="text" name="asfPassword" value='${setting.asfPassword}' placeholder="ASF IPC密码"/><br/>
<span>ASF Bot名字</span><input type="text" name="asfBot" value='${setting.asfBot}' placeholder="ASF Bot name,可留空"/><br/>
<input type="checkbox" name="asf" ${setting.asf?'checked=checked':''} title="此功能默认关闭新标签页激活"/><span title="此功能默认关闭新标签页激活">开启ASF激活</span>`;

            swal({
                closeOnClickOutside: false,
                className:'asf-class',
                title:'全局设置',
                content: div,
                buttons:{
                    confirm:'保存',
                    cancel:'取消',
                },
            })
                .then((value) => {
                if(value){
                    let setting={};
                    let allSetting=$jQuery("#hclonely-asf input").map(function(){
                        setting[$jQuery(this).attr("name")]=this.value==="on"?this.checked:this.value;
                    });
                    GM_setValue("setting",setting);
                    swal({
                        closeOnClickOutside: false,
                        icon:"success",
                        title:'保存成功!',
                        text:'刷新页面后生效!',
                        buttons:{
                            confirm:'确定',
                        },
                    });
                }
            });
        }
        function asfSend(c=''){
            if(Object.prototype.toString.call(GM_getValue("setting")) === '[object Object]'&&GM_getValue("setting").asf){
                swal({
                    closeOnClickOutside: false,
                    className:'swal-user',
                    text:'请在下方输入要执行的ASF指令:',
                    content: 'input',
                    buttons:{
                        'test':'连接测试',
                        'redeem':'激活key',
                        'pause':'暂停挂卡',
                        'resume':'恢复挂卡',
                        '2fa':'获取令牌',
                        'more':'更多ASF指令',
                        confirm:'确定',
                        cancel:'取消',
                    },
                }).then((value) => {
                    switch(value){
                        case 'redeem':
                        case 'pause':
                        case 'resume':
                        case '2fa':
                            asfSend(value);
                            break;
                        case 'test':
                            asfTest();
                            break;
                        case 'more':
                            swal({
                                closeOnClickOutside: false,
                                className:'swal-user',
                                text:'ASF指令',
                                content: asfCommands,
                                buttons:{
                                    confirm:'返回',
                                    cancel:'关闭',
                                },
                            }).then((value)=>{
                                if(value) asfSend();
                            });
                            $jQuery('table.hclonely button.swal-button').click(function(){
                                let setting=Object.prototype.toString.call(GM_getValue("setting")) === '[object Object]'?GM_getValue("setting"):defaultSetting;
                                let command=setting.asfBot?$jQuery(this).parent().next().text().trim().replace(/\<Bots\>/gim,setting.asfBot):$jQuery(this).parent().next().text().trim();
                                asfSend(command);
                            });
                            break;
                        case null:
                            break;
                        default:
                            if(!$jQuery('.swal-content__input').val()){
                                swal({
                                    closeOnClickOutside: false,
                                    title:'ASF指令不能为空!',
                                    icon:'warning',
                                    buttons:{
                                        confirm:'确定',
                                    },
                                }).then(()=>{asfSend(c)});
                            }else{
                                let v=value||$jQuery('.swal-content__input').val();
                                if(v) asfRedeem(v);
                            }
                            break;
                            break;
                    }
                });
                if(c) $jQuery('.swal-content__input').val("!"+c);
            }else{
                swal({
                    closeOnClickOutside: false,
                    className:'swal-user',
                    icon:"warning",
                    title:'此功能需要在设置中配置ASF IPC并开启ASF功能!',
                    buttons:{
                        confirm:'确定',
                    },
                });
            }
        }

        function asfTest(){
            let setting=GM_getValue("setting")||{};
            if(setting.asf){
                swal({
                    closeOnClickOutside: false,
                    title:'ASF连接测试',
                    text:'正在尝试连接 `'+setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort+"/api/command/!stats`",
                    buttons:{
                        confirm:'确定',
                    },
                });
                GM_xmlhttpRequest({
                    method:"POST",
                    url:setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort+"/api/command/!stats",
                    responseType:"json",
                    headers:{
                        "Authentication": setting.asfPassword,
                        "Content-Length": 0,
                        "Host": setting.asfHost+":"+setting.asfPort,
                        "Origin": setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort,
                        "Referer": setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort+"/page/commands"
                    },
                    onload:function(data){
                        if(data.status==200){
                            if(data.response.Success==true&&data.response.Message=="OK"&&data.response.Result){
                                swal({
                                    closeOnClickOutside: false,
                                    title:'ASF连接成功!',
                                    icon:'success',
                                    text:'连接地址 `'+setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort+"/api/command/!stats` \n返回内容 `"+data.response.Result.trim()+"`",
                                    buttons:{
                                        confirm:'确定',
                                    },
                                });
                            }else if(data.response.Message){
                                swal({
                                    closeOnClickOutside: false,
                                    title:'ASF连接成功?',
                                    icon:'info',
                                    text:'连接地址 `'+setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort+"/api/command/!stats` \n返回内容 `"+data.response.Message.trim()+"`",
                                    buttons:{
                                        confirm:'确定',
                                    },
                                });
                            }else{
                                swal({
                                    closeOnClickOutside: false,
                                    title:'ASF连接失败!',
                                    icon:'error',
                                    text:'连接地址 `'+setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort+"/api/command/!stats` \n返回内容 `"+data.responseText+"`",
                                    buttons:{
                                        confirm:'确定',
                                    },
                                });
                            }
                        }else{
                            swal({
                                closeOnClickOutside: false,
                                title:'ASF连接失败:'+data.status,
                                icon:'error',
                                text:'连接地址 `'+setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort+'/api/command/!stats`',
                                buttons:{
                                    confirm:'确定',
                                },
                            });
                        }
                    }
                })
            }else{
                swal({
                    closeOnClickOutside: false,
                    title:'请先在设置中开启ASF功能',
                    icon:'warning',
                    buttons:{
                        confirm:'确定',
                    },
                });
            }
        }

        function showHistory(){
            let history=GM_getValue("history");
            if(Array.isArray(history)){
                swal({
                    closeOnClickOutside: false,
                    className:'swal-user',
                    title:'上次激活记录:',
                    content:$jQuery(history[0])[0],
                    buttons:{
                        confirm:'确定',
                    },
                });
                if(history[1]) $jQuery(".swal-content textarea").val(history[1]);
            }else{
                swal({
                    closeOnClickOutside: false,
                    title:'没有操作记录!',
                    icon:"error",
                    buttons:{
                        cancel:'关闭',
                    },
                });
            }
        }

        function showSwitchKey(){
            swal({
                closeOnClickOutside: false,
                title:'请选择要转换成什么格式:',
                buttons:{
                    confirm:"确定",
                    cancel:'关闭'
                },
                content:$jQuery(`<div class='switch-key'><div class='switch-key-left'><p>key</p><p>key</p><p>key</p><input name='keyType' type='radio' value='1'/></div><div class='switch-key-right'><p>&nbsp;</p><p>key,key,key</p><p>&nbsp;</p><input name='keyType' type='radio' value='2'/></div></div>`)[0],
            }).then((value)=>{
                if(value){
                    if($jQuery('input:radio:checked').val()){
                        showSwitchArea($jQuery('input:radio:checked').val());
                    }else{
                        swal({
                            closeOnClickOutside: false,
                            title:'请选择要将key转换成什么格式!',
                            icon:'warning',
                        }).then(showSwitchKey);
                    }
                }
            });
            function showSwitchArea(type){
                swal({
                    closeOnClickOutside: false,
                    title:'请输入要转换的key:',
                    content:$jQuery(`<textarea style='width: 80%;height: 100px;'></textarea>`)[0],
                    buttons:{
                        confirm:'转换',
                        'back':'返回',
                        cancel:'关闭',
                    }
                }).then((value)=>{
                    if(value==='back'){
                        showSwitchKey(type);
                    }else if(value){
                        switchKey($jQuery('.swal-content textarea').val(),type);
                    }
                });
            }
            function switchKey(key,type){
                switch(type){
                    case '1':
                        showKey(getKeysByRE(key).join("\n"),type);
                        break;
                    case '2':
                        showKey(getKeysByRE(key).join(','),type);
                        break;
                    default:
                        break;
                }
            }
            function showKey(key,type){
                swal({
                    closeOnClickOutside: false,
                    icon:'success',
                    title:'转换成功!',
                    content:$jQuery(`<textarea style='width: 80%;height: 100px;' value='${key}' readonly='readonly'>${key}</textarea>`)[0],
                    buttons:{
                        confirm:'返回',
                        cancel:'关闭',
                    }
                }).then((value)=>{
                    if(value){
                        showSwitchArea(type);
                    }
                });
                $jQuery('.swal-content textarea').click(function(){this.select()});
            }
            $jQuery('.switch-key div').map(function(){
                $jQuery(this).click(function(){
                    $jQuery(this).find('input')[0].click();
                });
            });
        }

        function getKeysByRE(text) {
            text = text.trim().toUpperCase();
            let reg = new RegExp('([0-9,A-Z]{5}-){2,4}[0-9,A-Z]{5}', 'g');
            let keys = [];

            let result = void 0;
            while (result = reg.exec(text)) {
                keys.push(result[0]);
            }

            return keys;
        }

        function registerkey(key){
            let setting=GM_getValue("setting");
            let keys=getKeysByRE(key);
            if(setting.asf) asfRedeem("!redeem "+setting.asfBot+" "+keys.join(","));
            else if(setting.newTab) window.open("https://store.steampowered.com/account/registerkey?key=" + keys.join(","), "_blank");
            else webRedeem(keys);
        }
        function asfRedeem(command){
            let setting=GM_getValue("setting");
            let textarea=document.createElement("textarea");
            textarea.setAttribute("class","asf-output");
            textarea.setAttribute("readonly","readonly");
            let btn=/\!redeem/gim.test(command)?{confirm:'提取未使用key',cancel:'关闭'}:{confirm:'确定'};
            swal({
                closeOnClickOutside: false,
                className:'swal-user',
                text:'正在执行ASF指令:'+command,
                content: textarea,
                buttons:btn,
            }).then((v)=>{
                if(/\!redeem/gim.test(command)){
                    let value="";
                    if($jQuery(".swal-content textarea").length>0){
                        value=$jQuery(".swal-content textarea").val();
                    }
                    GM_setValue("history",[$jQuery(".swal-content").html(),value]);
                    if(v){
                        let unUseKey=$jQuery(".swal-content textarea").val().split(/[(\r\n)\r\n]+/).map(function(e){
                            if(/未使用/gim.test(e)){
                                return e;
                            }
                        }).join(',');
                        GM_setClipboard(arr(getKeysByRE(unUseKey)).join(","));
                        swal({title:'复制成功!',icon:"success"});
                    }
                }
            });
            GM_xmlhttpRequest({
                method:"POST",
                url:setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort+"/api/command/"+command.replace(/ /g,"%20"),
                responseType:"json",
                headers:{
                    "Authentication": setting.asfPassword,
                    "Content-Length": 0,
                    "Host": setting.asfHost+":"+setting.asfPort,
                    "Origin": setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort,
                    "Referer": setting.asfProtocol+"://"+setting.asfHost+":"+setting.asfPort+"/page/commands"
                },
                onload:function(data){
                    if(data.status==200){
                        if(data.response.Success==true&&data.response.Message=="OK"&&data.response.Result){
                            textarea.value+=data.response.Result.trim()+" \n";
                        }else if(data.response.Message){
                            textarea.value+=data.response.Message.trim()+" \n";
                        }else{
                            textarea.value+=data.responseText;
                        }
                    }else{
                        swal({
                            closeOnClickOutside: false,
                            className:'swal-user',
                            title:'执行以下ASF指令失败!请检查ASF配置是否正确!',
                            text:command,
                            icon: 'error',
                            buttons:{
                                confirm:'关闭',
                            },
                        });
                    }
                }
            })
        }
        function webRedeem(key){
            let div=document.createElement("div");
            div.setAttribute("id","registerkey_examples_text");
            div.innerHTML=`
<div class="notice_box_content" id="unusedKeyArea"> <b>未使用的Key:</b>
    <br>
    <div>
        <ol id="unusedKeys" align="left"></ol>
    </div>
</div>
<div class="table-responsive table-condensed">
    <table class="table table-hover hclonely">
        <caption>
            <h2>激活记录</h2>
        </caption>
        <thead>
            <th>No.</th>
            <th>Key</th>
            <th>结果</th>
            <th>详情</th>
            <th>Sub</th>
        </thead>
        <tbody></tbody>
    </table>
</div>
<br>`;
            swal({
                closeOnClickOutside: false,
                className:'swal-user',
                title:'正在获取sessionID...',
                buttons:{
                    confirm:'关闭',
                },
            });
            if(sessionID){
                swal({
                    closeOnClickOutside: false,
                    className:'swal-user',
                    title:'正在激活steam key...',
                    content: div,
                    buttons:{
                        confirm:'提取未使用key',
                        cancel:'关闭',
                    },
                }).then((v)=>{
                    let value="";
                    if($jQuery(".swal-content textarea").length>0){
                        value=$jQuery(".swal-content textarea").val();
                    }
                    GM_setValue("history",[$jQuery(".swal-content").html(),value]);
                    if(v){
                        GM_setClipboard(arr(getKeysByRE($jQuery('#unusedKeys').text())).join(","));
                        swal({title:'复制成功!',icon:"success"});
                    }
                });
                redeemKeys(key);
            }else{
                GM_xmlhttpRequest({
                    method:"GET",
                    url:"https://store.steampowered.com/account/registerkey",
                    onload:function(data){
                        if(data.finalUrl.includes("login")){
                            swal({
                                closeOnClickOutside: false,
                                icon:"warning",
                                title:'请先登录steam!',
                                buttons:{
                                    confirm:'登录',
                                    cancel:'关闭',
                                },
                            }).then((value)=>{
                                if(value) window.open("https://store.steampowered.com/login/","_blank");
                            });
                        }else{
                            if(data.status==200){
                                let session_id = data.responseText.match(/g_sessionID = \"(.+?)\";/);
                                sessionID = session_id === null ? null : session_id[1];
                                swal({
                                    closeOnClickOutside: false,
                                    className:'swal-user',
                                    title:'正在激活steam key...',
                                    content: div,
                                    buttons:{
                                        confirm:'提取未使用key',
                                        cancel:'关闭',
                                    },
                                }).then((v)=>{
                                    let value="";
                                    if($jQuery(".swal-content textarea").length>0){
                                        value=$jQuery(".swal-content textarea").val();
                                    }
                                    GM_setValue("history",[$jQuery(".swal-content").html(),value]);
                                    if(v){
                                        GM_setClipboard(getKeysByRE($jQuery('#unusedKeys').text()).join(","));
                                        swal({title:'复制成功!',icon:"success"});
                                    }
                                });
                                redeemKeys(key);
                            }else{
                                swal({
                                    closeOnClickOutside: false,
                                    className:'swal-user',
                                    title:'获取sessionID失败!',
                                    icon: 'error',
                                    buttons:{
                                        confirm:'关闭',
                                    },
                                });
                            }
                        }
                    }
                })
            }
        }

        function redeemSub(e){
            let subText=e||document.getElementById("gameSub").value;
            if(subText){
                let ownedPackages = {};
                $jQuery( '.account_table a' ).each( function( i, el ){
                    let match = el.href.match( /javascript:RemoveFreeLicense\( ([0-9]+), '/ );
                    if( match !== null ){
                        ownedPackages[ +match[ 1 ] ] = true;
                    }
                } );
                let freePackages =subText.match(/[\d]{2,}/g);
                let i = 0,
                    loaded = 0,
                    packae = 0,
                    total = freePackages.length,
                    modal = swal( '正在执行…','请等待所有请求完成。 忽略所有错误,让它完成。' );
                for( ; i < total; i++ ){
                    packae = freePackages[ i ];
                    if( ownedPackages[ packae ] ){
                        loaded++;
                        continue;
                    }
                    $jQuery.post('//store.steampowered.com/checkout/addfreelicense',{
                            action: 'add_to_cart',
                            sessionid: g_sessionID,
                            subid: packae
                        }).always(function(){
                        loaded++;
                        if( loaded >= total ){
                           if(url.includes("licenses")){
                               window.open("https://store.steampowered.com/account/licenses/","_self");
                           }else{
                               swal("全部激活完成,是否前往账户页面查看结果?", {
                                   buttons: {
                                       cancel: "取消",
                                       "确定": true,
                                   },
                               })
                                   .then((value) => {
                                   if(value) window.open("https://store.steampowered.com/account/licenses/","_blank");
                               });
                           }
                        }else{
                            modal = swal( '正在激活…','进度:' + loaded + '/' + total + '.' );
                        }
                    });
                }
            }
        }
        function cc(){
            swal({
                closeOnClickOutside: false,
                icon:'info',
                title:`正在获取当前国家/地区...`,
            })
            $jQuery.ajax({
                url:"//store.steampowered.com/cart/",
                type:"get",
                success:function(data){
                    if(data.match(/id\=\"usercountrycurrency_trigger\"[\w\W]*?\>[w\W]*?\<\/a/gim)){
                        let c=data.match(/id\=\"usercountrycurrency_trigger\"[\w\W]*?\>[w\W]*?\<\/a/gim)[0].replace(/id\=\"usercountrycurrency_trigger\"[\w\W]*?\>|\<\/a/g,"");
                        let thisC=data.match(/id\=\"usercountrycurrency\"[\w\W]*?value=\".*?\"/gim)[0].match(/value=\".*?\"/gim)[0].replace(/value=\"|\"/g,"");
                        let div=data.match(/\<div class=\"currency_change_options\"\>[\w\W]*?\<p/gim)[0].replace(/[\s]*?\<p/gim,"")+"</div>";
                        //$jQuery("body").append(`<div id="nowCountry" class="ellipsis" data-country="${thisC}" style="font-size:20px;">转换商店和钱包&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当前国家/地区:${c}</div><div style="padding:20px">${div}</div></div>`);
                        swal({
                            closeOnClickOutside: false,
                            title:`当前国家/地区:${c}`,
                            content:$jQuery(`<div>${div}</div>`)[0],
                        })
                        $jQuery(".currency_change_option").click(function(){
                            changeCountry($jQuery(this).attr("data-country"));
                        });
                    }else{
                        swal("需要挂相应地区的梯子!","","warning");
                    }
                },
                error:()=>{
                    swal("获取当前国家/地区失败!","","error");
                }
            });
        }
        function changeCountry(country){
            swal({
                closeOnClickOutside: false,
                icon:'info',
                title:`正在更换国家/地区...`,
            })
            $jQuery.ajax({
                url:"//store.steampowered.com/account/setcountry",
                type:"post",
                data:{
                    sessionid:g_sessionID,
                    "cc":country
                },
                complete:function(){
                    $jQuery.ajax({
                        url:"//store.steampowered.com/cart/",
                        type:"get",
                        success:function(data){
                            let c=data.match(/id\=\"usercountrycurrency_trigger\"[\w\W]*?\>[w\W]*?\<\/a/gim)[0].replace(/id\=\"usercountrycurrency_trigger\"[\w\W]*?\>|\<\/a/g,"");
                            let thisC=data.match(/id\=\"usercountrycurrency\"[\w\W]*?value=\".*?\"/gim)[0].match(/value=\".*?\"/gim)[0].replace(/value=\"|\"/g,"");
                            let div=data.match(/\<div class=\"currency_change_options\"\>[\w\W]*?\<p/gim)[0].replace(/[\s]*?\<p/gim,"")+"</div>";

                            if(thisC===country){
                                swal("更换成功!","","success").then(()=>{
                                    swal({
                                        closeOnClickOutside: false,
                                        title:`当前国家/地区:${c}`,
                                        content:$jQuery(`<div>${div}</div>`)[0],
                                    })
                                    $jQuery(".currency_change_option").click(function(){
                                        changeCountry($jQuery(this).attr("data-country"));
                                    });
                                });
                            }else{
                                swal("更换失败!","","error");
                            }
                        },
                        error:()=>{
                            swal("获取当前国家/地区失败!","","error");
                        }
                    });
                }
            });
        }

        function arr(arr) {
            return [...new Set(arr)];
        }

        if (/^https?:\/\/store\.steampowered\.com\/account\/registerkey*/.test(url)){
            $jQuery('#registerkey_examples_text').html(
                '<div class="notice_box_content" id="unusedKeyArea" style="display: none">' +
                '<b>未使用的Key:</b><a tabindex="300" class="btnv6_blue_hoverfade btn_medium" id="copyUnuseKey"><span>提取未使用key</span></a><br>'+
                '<div><ol id="unusedKeys">' +
                '</ol></div>' +
                '</div>' +

                '<div class="table-responsive table-condensed">' +
                '<table class="table table-hover" style="display: none">' +
                '<caption><h2>激活记录</h2></caption><thead><th>No.</th><th>Key</th>' +
                '<th>结果</th><th>详情</th><th>Sub</th></thead><tbody></tbody>' +
                '</table></div><br>');

            $jQuery('#copyUnuseKey').click(()=>{
                GM_setClipboard(arr(getKeysByRE($jQuery('#unusedKeys').text())).join(","));
                swal({title:'复制成功!',icon:"success"});
            });
            $jQuery('.registerkey_input_box_text').parent().css("float","none");
            $jQuery('.registerkey_input_box_text').parent().append('<textarea class="form-control" rows="3"' +
                                                                  ' id="inputKey" placeholder="支持批量激活,可以把整个网页文字复制过来&#10;' +
                                                                  '若一次激活的Key的数量超过9个则会自动分批激活(等待20秒)&#10;' +
                                                                  '激活多个SUB时每个SUB之间用英文逗号隔开&#10;' +
                                                                  '激活礼物卡或钱包充值码功能目前属于测试功,且不支持批量激活"' +
                                                                  ' style="margin: 3px 0px 0px; width: 525px; height: 102px;"></textarea><br>');
            /^https?:\/\/store\.steampowered\.com\/account\/registerkey\?key\=[\w\W]+/.test(url)&&(document.getElementById("inputKey").value=url.replace(/https?:\/\/store\.steampowered\.com\/account\/registerkey\?key\=/i,""));
            $jQuery('.registerkey_input_box_text').hide();
            $jQuery('#purchase_confirm_ssa').hide();

            $jQuery('#register_btn').parent().css("margin","10px 0")
            $jQuery('#register_btn').parent().append('<a tabindex="300" class="btnv6_blue_hoverfade btn_medium" style="margin-left:0"' +
                                                    ' id="redeemKey"><span>激活key</span></a>' + ' &nbsp;&nbsp;' +
                                                    '<a tabindex="300" class="btnv6_blue_hoverfade btn_medium" style="margin-left:0"' +
                                                    ' id="redeemSub"><span>激活sub</span></a>' + ' &nbsp;&nbsp;' +
                                                    '<a tabindex="300" class="btnv6_blue_hoverfade btn_medium" style="margin-left:0"' +
                                                    ' id="redeemCode"><span>激活礼物卡或钱包充值码</span></a>' + ' &nbsp;&nbsp;' +
                                                    '<a tabindex="300" class="btnv6_blue_hoverfade btn_medium" style="margin-left:0"' +
                                                    ' id="changeCountry"><span>更换国家/地区</span></a>' + ' &nbsp;&nbsp;');
            $jQuery('#register_btn').remove();
            /^https?:\/\/store\.steampowered\.com\/account\/registerkey\?key\=[\w\W]+/.test(url)&&(redeem(getKeysByRE(url.replace(/https?:\/\/store\.steampowered\.com\/account\/registerkey\?key\=/i,"").trim())));
            $jQuery('#redeemKey').click(()=>{redeemKeys()});
            $jQuery('#redeemSub').click(redeemSubs);
            $jQuery('#changeCountry').click(cc);


            function redeemSubs(){
                redeemSub($jQuery('#inputKey').val().trim());
            }

            arsStatic.redeemCode();

            toggleUnusedKeyArea();

        }else if(/https?:\/\/steamdb\.info\/freepackages\//.test(url)){//steamdb.info点击自动跳转到激活页面
            let activateConsole = function(e) {
                let sub=[];
                $("#freepackages span:visible").map(function(){
                    sub.push($(this).attr("data-subid"));
                });
                let freePackages=sub.join(",");
                let setting=GM_getValue("setting");
                window.open("https://store.steampowered.com/account/licenses/?sub=" + freePackages, "_self");
                //if(setting.asf) asfRedeem("!addlicense "+(setting.asfBot||"asf")+" "+freePackages);
                //else window.open("https://store.steampowered.com/account/licenses/?sub=" + freePackages, "_self");
            };
            let fp=setInterval(()=>{
                if(document.getElementById("freepackages")){
                    document.getElementById("freepackages").onclick=activateConsole;
                    clearInterval(fp);
                }
            },1000);
        }else if (/https?:\/\/store\.steampowered\.com\/account\/licenses\/(\?sub\=[\w\W]{0,})?/.test(url)){//自动添加sub
            $jQuery('.pageheader').parent().append('<div style="float: left;";>' +
                                                  '<textarea class="registerkey_input_box_text" rows="1"' + 'name="product_key"' +
                                                  ' id="gameSub" placeholder="输入SUB,多个SUB之间用英文逗号连接"' + 'value=""' + 'color:#fff;' +
                                                  ' style="margin: 3px 0px 0px; width: 400px; height: 15px;background-color:#102634; padding: 6px 18px 6px 18px; font-weight:bold; color:#fff;"></textarea>' +
                                                  ' &nbsp ' + '</div>' + '<a tabindex="300" class="btnv6_blue_hoverfade btn_medium"' +
                                                  ' style="width: 95px; height: 30px;"' +
                                                  ' id="buttonSUB"><span>激活SUB</span></a>'+ '<a tabindex="300" class="btnv6_blue_hoverfade btn_medium"' +
                                                  ' style="width: 125px; height: 30px;"' +
                                                  ' id="changeCountry"><span>更改国家/地区</span></a>');
            $jQuery('#buttonSUB').click(()=>{redeemSub()});
            $jQuery('#changeCountry').click(cc);
            if (/https?:\/\/store\.steampowered\.com\/account\/licenses\/\?sub\=([\d]{1,},){1,}/.test(url)){
                setTimeout(()=>{redeemSub(url)},2000);
            }
        }else if(GM_getValue("setting").clickListen){//点击添加链接

            function mouseClick($,e) {
                let $i = $("<span/>").text("Steam Key");
                let x = e.pageX,
                    y = e.pageY;
                $i.css({"z-index" : 9999999999999999999,"top" : y - 20,"left" : x,"position" : "absolute","font-weight" : "bold","color" : "#ff6651"});
                $("body").append($i);
                $i.animate({"top" : y - 180,"opacity" : 0}, 1500, ()=>{
                    //$i.remove()
                });
            };

            let htmlEl;
            if(window.document.body){
                window.document.body.onclick = function(event){
                    htmlEl = event.target;//鼠标每经过一个元素,就把该元素赋值给变量htmlEl
                    if($jQuery(htmlEl).parents('.swal-overlay').length==0&&htmlEl.tagName!=='A' && htmlEl.tagName!=='BUTTON' && htmlEl.getAttribute("type")!=='button' && htmlEl.tagName!=='TEXTAREA' && htmlEl.getAttribute("type")!=='text'){
                        if(($jQuery(htmlEl).children().length==0||!/([0-9,A-Z]{5}-){2,4}[0-9,A-Z]{5}/gim.test($jQuery.makeArray($jQuery(htmlEl).children().map(function(){
                            return $jQuery(this).text();
                        })).join("")))&&/([0-9,A-Z]{5}-){2,4}[0-9,A-Z]{5}/gim.test($jQuery(htmlEl).text())){
                            mouseClick($jQuery,event);
                            arr($jQuery(htmlEl).text().match(/[\w\d]{5}(-[\w\d]{5}){2}/gim)).map(function(e){
                                $jQuery(htmlEl).html($jQuery(htmlEl).html().replace(new RegExp(e,'gi'),`<a class="redee-key" href='javascript:void(0)' target="_self" key='${e}'>${e}</a>`));
                            });
                            $jQuery('.redee-key').click(function(){
                                registerkey($jQuery(this).attr("key"),1);
                            });
                        }
                    }
                }
            }
        }else{
            //激活页面内所有key
            function addBtn(){
                let div = document.createElement("div");
                div.setAttribute("id", "keyDiv");
                div.setAttribute("style", "position:fixed;left:5px;bottom:5px");
                let btn=document.createElement("button");
                btn.setAttribute("id", "allKey");
                btn.setAttribute("key", "");
                btn.setAttribute("style", "display:none;z-index:9999");
                btn.innerText="激活本页面所有key(共0个)";
                btn.onclick=function(){
                    let setting=GM_getValue("setting");
                    let keys=getKeysByRE($jQuery(this).attr("key"));
                    if(setting.asf) asfRedeem("!redeem "+setting.asfBot+" "+keys.join(","));
                    else if(setting.newTab) window.open("https://store.steampowered.com/account/registerkey?key=" + keys.join(","), "_blank");
                    else webRedeem(keys);
                }
                $jQuery('body').append(div);
                div.appendChild(btn);
                return btn;
            }
            function redeemAllKey(){
                let len=0;
                let keyList="";
                let hasKey=[];
                let btn=addBtn();
                setInterval(function(){
                    let allSteamKey=document.getElementsByTagName('body')[0].innerText;
                    allSteamKey=allSteamKey.match(/[\w\d]{5}(-[\w\d]{5}){2}/gim)||[];
                    allSteamKey=arr(allSteamKey)||[];
                    len=allSteamKey.length;
                    if(len>0){
                        hasKey.push(...allSteamKey);
                        hasKey=arr(hasKey);
                        keyList=hasKey.join(",");
                        $jQuery(btn).attr("key",keyList);
                        $jQuery(btn).text("激活本页面所有key(共" + hasKey.length + "个)");
                        $jQuery(btn).show();
                    }else if(document.getElementById('allKey')&&(document.getElementById('allKey').style.display==="block")){
                        $jQuery(btn).hide();
                        $jQuery(btn).text("激活本页面所有key(共0个)");
                    }
                },1000);
            }
            redeemAllKey();
        }

        GM_addStyle(arsStatic.css);

        GM_registerMenuCommand("⚙设置",setting);
        GM_registerMenuCommand("执行ASF指令",asfSend);
        GM_registerMenuCommand("查看上次激活记录",showHistory);
        GM_registerMenuCommand("Key格式转换",showSwitchKey);
        GM_registerMenuCommand("新版使用说明",()=>{window.open('https://steamcn.com/t344489-1-1','_blank')});
    }catch(e){
        swal("AuTo Redeemer Steamkey脚本执行出错:",e.stack,'error');
    }

}());