Greasy Fork

来自缓存

Humble Choice Get Key

HB月包选择游戏(只选不刮),刮key

目前为 2021-03-03 提交的版本。查看 最新版本

// ==UserScript==
// @name         Humble Choice Get Key
// @namespace    http://tampermonkey.net/
// @version      0.14
// @description  HB月包选择游戏(只选不刮),刮key
// @author       ku mi
// @include      /https:\/\/www\.humblebundle\.com\/subscription\/.*?/
// @include      /https:\/\/www\.indiegala\.com\/(gift-bundle\/|gift\?gift_id=).*?/
// @grant        GM_addStyle
// @require      https://cdn.staticfile.org/html2canvas/0.5.0-beta4/html2canvas.min.js
// ==/UserScript==
//https:\/\/www\.(indiegala|humblebundle)\.com\/(subscription\/|gift-bundle\/|gift\?gift_id=).*?
(async () => {
    const countryMap = {
        AD: '安道尔',
        AE: '阿拉伯联合酋长国',
        AF: '阿富汗',
        AG: '安提瓜和巴布达',
        AI: '安圭拉',
        AL: '阿尔巴尼亚',
        AM: '亚美尼亚',
        AO: '安哥拉',
        AQ: '南极洲',
        AR: '阿根廷',
        AS: '美属萨摩亚',
        AT: '奥地利',
        AU: '澳大利亚',
        AW: '阿鲁巴',
        AX: '奥兰群岛',
        AZ: '阿塞拜疆',
        BA: '波斯尼亚和黑塞哥维那',
        BB: '巴巴多斯',
        BD: '孟加拉',
        BE: '比利时',
        BF: '布基纳法索',
        BG: '保加利亚',
        BH: '巴林',
        BI: '布隆迪',
        BJ: '贝宁',
        BL: '圣巴托洛缪岛',
        BM: '百慕大',
        BN: '文莱',
        BO: '玻利维亚',
        BQ: '博奈尔',
        BR: '巴西',
        BS: '巴哈马',
        BT: '不丹',
        BU: '缅甸',
        BV: '布韦岛',
        BW: '博兹瓦纳',
        BY: '白俄罗斯',
        BZ: '伯利兹',
        CA: '加拿大',
        CC: '科科斯(基林)群岛',
        CD: '刚果(金)',
        CF: '中非共和国',
        CG: '刚果(布)',
        CH: '瑞士',
        CI: '科特迪瓦',
        CK: '库克群岛',
        CL: '智利',
        CM: '喀麦隆',
        CN: '中国',
        CO: '哥伦比亚',
        CR: '哥斯达黎加',
        CS: '塞尔维亚和黑山',
        CU: '古巴',
        CV: '佛得角',
        CW: '库拉索',
        CX: '圣诞岛',
        CY: '塞浦路斯',
        CZ: '捷克',
        DE: '德国',
        DJ: '吉布提',
        DK: '丹麦',
        DM: '多米尼克',
        DO: '多米尼加',
        DZ: '阿尔及利亚',
        EC: '厄瓜多尔',
        EE: '爱沙尼亚',
        EG: '埃及',
        EH: '西撒哈拉',
        ER: '厄立特里亚',
        ES: '西班牙',
        ET: '埃塞俄比亚',
        FI: '芬兰',
        FJ: '斐济',
        FK: '福克兰群岛',
        FM: '密克罗尼西亚',
        FO: '法罗群岛',
        FR: '法国',
        GA: '加蓬',
        GB: '英国',
        GD: '格林纳达',
        GE: '格鲁吉亚',
        GF: '法属圭亚那',
        GG: '根西',
        GH: '加纳',
        GI: '直布罗陀',
        GL: '格陵兰',
        GM: '冈比亚',
        GN: '几内亚',
        GP: '瓜德鲁普',
        GQ: '赤道几内亚',
        GR: '希腊',
        GS: '南乔治亚岛和南桑威奇群岛',
        GT: '危地马拉',
        GU: '关岛',
        GW: '几内亚比绍',
        GY: '圭亚那',
        HK: '香港',
        HM: '赫德岛和麦克唐纳群岛',
        HN: '洪都拉斯',
        HR: '克罗地亚',
        HT: '海地',
        HU: '匈牙利',
        ID: '印尼',
        IE: '爱尔兰',
        IL: '以色列',
        IM: '马恩岛',
        IN: '印度',
        IO: '英属印度洋领地',
        IQ: '伊拉克',
        IR: '伊朗',
        IS: '冰岛',
        IT: '意大利',
        JE: '泽西岛',
        JM: '牙买加',
        JO: '约旦',
        JP: '日本',
        KE: '肯尼亚',
        KG: '吉尔吉斯',
        KH: '柬埔寨',
        KI: '基里巴斯',
        KM: '科摩罗',
        KN: '圣基茨和尼维斯',
        KP: '朝鲜',
        KR: '韩国',
        KW: '科威特',
        KY: '开曼群岛',
        KZ: '哈萨克斯坦',
        LA: '老挝',
        LB: '黎巴嫩',
        LC: '圣卢西亚',
        LI: '列支敦士登',
        LK: '斯里兰卡',
        LR: '利比里亚',
        LS: '莱索托',
        LT: '立陶宛',
        LU: '卢森堡',
        LV: '拉脱维亚',
        LY: '利比亚',
        MA: '摩洛哥',
        MC: '摩纳哥',
        MD: '摩尔多瓦',
        ME: '黑山',
        MF: '法属圣马丁',
        MG: '马达加斯加',
        MH: '马绍尔群岛',
        MK: '马其顿',
        ML: '马里',
        MM: '缅甸',
        MN: '蒙古',
        MO: '澳门',
        MP: '北马里亚纳群岛',
        MQ: '马提尼克',
        MR: '毛里塔尼亚',
        MS: '蒙塞拉特',
        MT: '马耳他',
        MU: '毛里求斯',
        MV: '马尔代夫',
        MW: '马拉维',
        MX: '墨西哥',
        MY: '马来西亚',
        MZ: '莫桑比克',
        NA: '纳米比亚',
        NC: '新喀里多尼亚',
        NE: '尼日尔',
        NF: '诺福克岛',
        NG: '尼日利',
        NI: '尼加拉瓜',
        NL: '荷兰',
        NO: '挪威',
        NP: '尼泊尔',
        NR: '瑙鲁',
        NU: '纽埃',
        NZ: '新西兰',
        OM: '阿曼',
        PA: '巴拿马',
        PE: '秘鲁',
        PF: '法属波利尼西亚a',
        PG: '巴布亚新几内亚',
        PH: '菲律宾',
        PK: '巴基斯坦',
        PL: '波兰',
        PM: '圣皮埃尔和密克隆',
        PN: '皮特凯恩群岛',
        PR: '波多黎各',
        PS: '巴勒斯坦',
        PT: '葡萄牙',
        PW: '帕劳',
        PY: '巴拉圭',
        QA: '卡塔尔',
        RE: '留尼旺島',
        RO: '罗马尼亚',
        RS: '塞尔维亚',
        RU: '俄罗斯',
        RW: '卢旺达',
        SA: '沙特阿拉伯',
        SB: '所罗门群岛',
        SC: '塞舌尔',
        SD: '苏丹',
        SE: '瑞典',
        SG: '新加坡',
        SH: '圣赫勒拿、阿森松与特斯坦达库尼亚',
        SI: '斯洛文尼',
        SJ: '斯瓦尔巴群岛和扬马延岛',
        SK: '斯洛伐克',
        SL: '塞拉利昂',
        SM: '圣马力诺',
        SN: '塞内加尔',
        SO: '索马里',
        SR: '苏里南',
        SS: '南苏丹',
        ST: '圣多美和普林西比',
        SV: '萨尔瓦多',
        SX: '荷属圣马丁',
        SY: '叙利亚',
        SZ: '斯威士兰',
        TC: '特克斯和凯科斯群岛',
        TD: '乍得',
        TF: '法属南部领土',
        TG: '多哥',
        TH: '泰国',
        TJ: '塔吉克斯坦',
        TK: '托克劳',
        TL: '东帝汶',
        TM: '土库曼斯坦',
        TN: '突尼斯',
        TO: '汤加',
        TR: '土耳其',
        TT: '特立尼达和多巴哥',
        TV: '图瓦卢',
        TW: '台湾',
        TZ: '坦桑尼亚',
        UA: '乌克兰',
        UG: '乌干达',
        UM: '美国本土外小岛屿',
        US: '美国',
        UY: '乌拉圭',
        UZ: '乌兹别克斯坦',
        VA: '圣座',
        VC: '圣文森特和格林纳丁斯',
        VE: '委内瑞拉',
        VG: '英属维尔京群岛',
        VI: '美属维尔京群岛',
        VN: '越南',
        VU: '瓦努阿图',
        WF: '瓦利斯和富图纳群岛',
        WS: '萨摩亚',
        XK: '科索沃',
        YE: '也门',
        YT: '马约特',
        ZA: '南非',
        ZM: '赞比亚',
        ZW: '津巴布韦'
    }
    async function http(data, flag) {
        const res = await fetch(data.url, {
            method: data.method || 'GET',
            body: data.body || null,
            headers: data.headers
        })
        if (res.status !== 200) return {}
        return await flag ? res.text() : res.json()
    }
    getInitData(new DOMParser().parseFromString(await http({ url: location.href }, true), 'text/html'))
    function getInitData(el) {
        const script = el.getElementById('webpack-monthly-product-data') || el.getElementById('webpack-subscriber-hub-data')
        if (!script) return
        const { contentChoiceOptions: { contentChoiceData: { extras, initial: { content_choices, display_order, total_choices } }, gamekey, contentChoicesMade, downloadPageUrl }, csrfTokenInput } = JSON.parse(script.innerText.trim())
        const [, csrfToken] = csrfTokenInput.match(/value='([\w-_]+)'.+/)
        console.log(JSON.parse(script.innerText.trim()).contentChoiceOptions)
        if (!gamekey) return
        const extrasUrl = { url: `https://www.humblebundle.com/api/v1/order/${gamekey}?wallet_data=true&all_tpkds=true` }
        const selecedGame = contentChoicesMade ? contentChoicesMade.initial.choices_made : []
        const extrasSteam = extras.filter(item => item.types.includes('steam'))
        console.log(display_order)
        const allGame = display_order.map(name => {
            let { machine_name, human_name: title, exclusive_countries: exclusive, disallowed_countries: disallowed, redeemed_key_val: key = '', steam_app_id: appid = '' } = content_choices[name].tpkds ? content_choices[name].tpkds[0] : content_choices[name].nested_choice_tpkds[name + '_steam'][0]
            return {
                machine_name,
                title,
                exclusive,
                disallowed,
                appid,
                name,
                key
            }
        })
        const gameBox = document.createElement('div')
        const optionBox = document.createElement('div')
        gameBox.innerHTML = `<div class="_mask_"><div class="_alert_"></div></div><div class="_sh_box_"><button class="_sh_hd_ current">隐藏锁区信息</button><span style="margin-left: 20px; font-size: 20px; color: #c93756;">注: 锁区信息仅供参考,以激活后的SUB为准!</span><a class="_down_page_" target="_blank" href=${downloadPageUrl}>Download页面</a/></div><ul class="_self_view_"></ul>`
        optionBox.innerHTML = `<div class="_option_ul_"></div><div class="_select_ul_"></div><div style="display: flex;"><textarea class="_key_value_"></textarea><div><button class="_copy_">复制</button><button class="_clear_">清空</button></div></div>`
        const gamelist = gameBox.querySelector('._self_view_')
        const sButton = gameBox.querySelector('._sh_hd_')
        const sMask = gameBox.querySelector('._mask_')
        const sAlert = sMask.firstElementChild
        const textArr = ['选择游戏(只选不刮)', '刮开/提取', '全选高亮', '取消高亮', '多选高亮截图']
        const classArr = ['._copy_', '._clear_', '._option_ul_', '._select_ul_', '._key_value_']
        const [cButton, clearKey, optionUl, selectUl, keyValue] = classArr.map(item => optionBox.querySelector(item))
        const [selectKey, getKey, allLight, noLight, screenShot] = createButton()
        const liChild = createLiChild(allGame)
        setNum()
        eventInt()
        gameBox.insertBefore(optionBox, sMask)
        appendLi(allGame)
        const selectList = gamelist.querySelectorAll('li button:nth-child(2n+1)')
        const getList = gamelist.querySelectorAll('li button:nth-child(2n)')
        const view = document.querySelector('.content-choices-view')
        const list = document.querySelector(".content-choice-tiles.js-content-choice-tiles")
        view.insertBefore(gameBox, list)
        selectList.forEach(item => item.addEventListener('click', function (e) {
            if (this.classList.contains('current')) return
            sendRquest(true, [this], e)
        }))
        getList.forEach(item => item.addEventListener('click', seake))
        checkHaveDlc(extrasSteam)
        async function seake(e) {
            if (this.classList.contains('current')) return
            if (this.dataset.name && !selecedGame.includes(this.dataset.name)) {
                const res = await sendRquest(false, [this], e)
                if (!res) return alertFun(`刮开失败!๐·°(৹˃̵﹏˂̵৹)°·๐`)
            }
            sendKeyRquest([this], e)
        }
        function getZhName(arr) {
            return arr.map(item => {
                if (/\u53f0\u6e7e|\u4e2d\u56fd|\u9999\u6e2f|\u6fb3\u95e8/.test(countryMap[item])) return `<span style="color: #c93756; font-size: 20px;">${countryMap[item]}</span>`
                return countryMap[item]
            }).join('、')
        }
        function getLock(game) {
            if (game.exclusive.length) return `<span style="color: #cc6699"><span style="color: #c93756; font-size: 20px;">只能在</span>以下激活:  ${getZhName(game.exclusive)}</span>`
            if (game.disallowed.length) return `<span style="color: #B0E2FF"><span style="color: #c93756; font-size: 20px;">不能在</span>以下地区激活: ${getZhName(game.disallowed)}<span>`
            return `<span style="color: #279b61">无限制激活</span>`
        }
        function alertFun(msg, flag) {
            sAlert.innerHTML = msg
            sMask.style.display = 'block'
            sAlert.classList.add('_bunceIn_')
            if (flag) return
            let time = setTimeout(() => {
                sMask.style.display = 'none'
                sAlert.classList.remove('_bunceIn_')
                clearTimeout(time)
            }, 1200)
        }
        async function selectGet(flag) {
            if (flag && selecedGame.length >= total_choices) return alertFun(`已经没得选择了!(。•ˇ‸ˇ•。)`)
            const newliChild = selectUl.querySelectorAll('button')
            const noSelect = []
            const noSelectLi = []
            const selected = []
            const no = flag ? selectList : getList
            const arr = liChild.filter((li, index) => {
                if (li.classList.contains('current') && (selected.length + noSelect.length < total_choices)) {
                    if (!flag && selecedGame.includes(li.dataset.name) && !li.dataset.key) selected.push(no[index])
                    else if (!selecedGame.includes(li.dataset.name) && (noSelect.length + selecedGame.length < total_choices)) {
                        noSelect.push(no[index])
                        noSelectLi.push(li)
                    }
                }
                return li.classList.contains('current')
            })
            if (arr.length > total_choices) return alertFun(`最多选${total_choices}个!ヽ(#\`Д´)ノ`)
            if (flag && !noSelect.length) return alertFun(`已经选过了!ヽ(#\`Д´)ノ`)
            if (!flag && newliChild.length !== liChild.length) {
                newliChild.forEach((li, index) => {
                    if (li.classList.contains('current') && !li.dataset.name) {
                        arr.push(li)
                        if (!li.dataset.key) selected.push(no[index])
                    }
                })
            }
            if (!arr.length) return
            noLight.click()
            if (noSelect.length) {
                const res = await sendRquest(flag, noSelect)
                if (!res && !flag) return alertFun(`刮开失败!๐·°(৹˃̵﹏˂̵৹)°·๐`)
                if (flag) return arr.forEach(item => selecedGame.includes(item.dataset.name) && (keyValue.value += `${item.dataset.title}: 选择成功\n`))
            }
            if (selected.length || noSelect.length) await sendKeyRquest(selected.concat(noSelect))
            keyValue.value = ''
            arr.forEach(item => item.dataset.key && (keyValue.value += `${item.dataset.title}\t${item.dataset.key}\n`))
        }
        async function sendKeyRquest(arr, e) {
            alertFun(`正在努力请求...!(,,•́ . •̀,,)`, true)
            if (!e) keyValue.value = ''
            const res = await Promise.all(arr.map(item => {
                return http({
                    url: 'https://www.humblebundle.com/humbler/redeemkey',
                    body: `keytype=${item.dataset.machine_name}&key=${gamekey}&keyindex=0`,
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                    },
                    method: 'POST'
                })
            }))
            alertFun(`已经刮好了!(๑˃́ꇴ˂̀๑)`)
            arr.forEach((item, index) => {
                const newliChild = [...selectUl.querySelectorAll('button')]
                newliChild.find(it => it.dataset.machine_name === item.dataset.machine_name).dataset.key = res[index].key || '刷新重试'
                item.innerText = '已刮开'
                item.className = 'current'
                const input = item.nextElementSibling.nextElementSibling
                input.style.display = 'block'
                input.value = res[index].key || '刷新重试'
                if (e) keyValue.value += `${item.dataset.title}\t${res[index].key}\n`
            })
        }
        async function sendRquest(flag, arr, e) {
            keyValue.value = ''
            let url = ''
            arr.forEach(item => {
                url += `&chosen_identifiers[]=${item.dataset.name}`
            })
            alertFun(`正在努力请求...!(,,•́ . •̀,,)`, true)
            const res = await http(
                {
                    method: 'POST',
                    url: 'https://www.humblebundle.com/humbler/choosecontent',
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                        'csrf-prevention-token': csrfToken,
                        'x-requested-with': 'XMLHttpRequest'
                    },
                    body: `gamekey=${gamekey}&parent_identifier=initial${url}`,
                })
            if (flag) alertFun(res.force_refresh ? `已经选择好了!(๑˃́ꇴ˂̀๑)` : `选择失败!๐·°(৹˃̵﹏˂̵৹)°·๐`)
            if (res.force_refresh) {
                const titles = arr.map(item => {
                    const itemName = item.dataset.name
                    if (flag) {
                        item.innerText = '已选择'
                        item.className = 'current'
                    } else {
                        const next = item.nextElementSibling
                        next.innerText = '已选择'
                        next.className = 'current'
                    }
                    selecedGame.push(itemName)
                    if (e && flag) keyValue.value += `${item.dataset.title}: 选择成功\n`
                    return item.dataset.title.toLocaleLowerCase()

                })
                checkHaveDlc(titles, true)
            } else {
                arr.forEach(item => {
                    if (e && flag) keyValue.value += `${item.dataset.title}: 选择失败\n`
                })
            }
            return res.force_refresh
        }
        async function checkHaveDlc(arr, flag) {
            if (!arr.length) return
            const extrasRes = await http(extrasUrl)
            let dlc = flag ? extrasRes.tpkd_dict.all_tpks.filter(item => arr.some(it => it !== item.human_name.toLocaleLowerCase() && item.human_name.toLocaleLowerCase().indexOf(it) === 0)) : extrasRes.tpkd_dict.all_tpks.filter(item => arr.some(it => it.machine_name === item.machine_name))
            dlc = dlc.map(item => ({
                machine_name: item.machine_name,
                title: item.human_name,
                exclusive: item.exclusive_countries,
                disallowed: item.disallowed_countries,
                appid: item.steam_app_id || '',
                name: '',
                key: item.redeemed_key_val || ''
            }))
            if (!dlc.length) return
            createLiChild(dlc, true)
            appendLi(dlc)
        }
        function appendLi(data) {
            const fragment = document.createDocumentFragment()
            data.forEach(item => {
                const li = document.createElement('li')
                li.innerHTML = `<div style="width: 100%;"><a style="text-decoration: none; color: #169fe3" ${item.appid && `href="https://store.steampowered.com/app/${item.appid}"`} target="_blank">${item.title}</a><button class="${item.key ? 'current' : ''}" data-name="${item.name}" data-machine_name="${item.machine_name}"  data-title="${item.title}">${item.key ? '已刮开' : '未刮开'}</button><button ${item.name ? '' : `style="visibility: hidden"`} class="${selecedGame.includes(item.name) ? 'current' : ''}" data-name="${item.name}" data-machine_name="${item.machine_name}" data-title="${item.title}">${selecedGame.includes(item.name) ? '已选择' : '未选择'}</button><input type="text" class="_click_key_" ${item.key ? '' : `style="display: none"`} value=${item.key}><p style="margin: 15px 15px 15px 0; ">${getLock(item)}</p></div>`
                fragment.appendChild(li)
                li.querySelector('button').addEventListener('click', seake)
            })
            gamelist.appendChild(fragment)
        }
        function createButton() {
            const fragment = document.createDocumentFragment()
            const buttonList = textArr.map((item, index) => {
                const button = document.createElement('button')
                button.innerText = item
                fragment.appendChild(button)
                return button
            })
            optionUl.appendChild(fragment)
            return buttonList
        }
        function createLiChild(arr, flag) {
            const fragment = document.createDocumentFragment()
            const liChild = arr.map((item, index) => {
                const button = document.createElement('button')
                button.innerText = flag ? 'DLC' : index + 1
                Object.assign(button.dataset, {
                    name: item.name,
                    title: item.title,
                    key: item.key,
                    machine_name: item.machine_name
                })
                fragment.appendChild(button)
                return button
            })
            selectUl.appendChild(fragment)
            return liChild
        }
        function setNum() {
            const els = document.querySelectorAll('.js-content-choices .choice-image-container')
            els.forEach((item, index) => {
                let div = document.createElement('div')
                div.setAttribute('class', '_game_num_')
                div.innerText = index + 1
                item.appendChild(div)
            })
        }
        function eventInt() {
            optionUl.onselectstart = () => false
            selectUl.onselectstart = () => false
            selectUl.addEventListener('click', (e) => { if (e.target.nodeName === 'BUTTON') e.target.classList.toggle('current') })
            allLight.addEventListener('click', () => selectUl.querySelectorAll('button').forEach(item => item.classList.add('current')))
            noLight.addEventListener('click', () => selectUl.querySelectorAll('button').forEach(item => item.classList.remove('current')))
            clearKey.addEventListener('click', () => (keyValue.value = ''))
            cButton.addEventListener('click', () => {
                if (!keyValue.value.length) return
                keyValue.select()
                document.execCommand('copy')
            })
            clearKey.addEventListener('click', () => (keyValue.value = ''))
            sButton.addEventListener('click', function () {
                const flag = this.classList.contains('current')
                gamelist.classList.remove(flag ? '_slide_down_' : '_slide_up_')
                gamelist.classList.add(flag ? '_slide_up_' : '_slide_down_')
                this.innerText = flag ? '显示锁区信息' : '隐藏锁区信息'
                this.classList.toggle('current')
            })
            getKey.addEventListener('click', () => selectGet())
            selectKey.addEventListener('click', () => selectGet(true))
            screenShot.addEventListener('click', () => {
                let flag
                const newButton = selectUl.querySelectorAll('button')
                if (!sButton.classList.contains('current')) sButton.click()
                const arr = [...gamelist.children].filter((item, index) => !newButton[index].classList.contains('current'))
                if (arr.length !== newButton.length) arr.forEach(item => (item.style.display = 'none'))
                alertFun(`正在截图...(,,•́ . •̀,,)`, true)
                sMask.onclick = () => {
                    arr.forEach(item => (item.style.display = 'block'))
                    sMask.style.display = 'none'
                    flag = true
                    sMask.onclick = null
                }
                html2canvas(gamelist).then(canvas => {
                    if (flag) return
                    sAlert.style.backgroundColor = '#494f5c'
                    alertFun(`<img src=${canvas.toDataURL()}>`, true)
                    sMask.onclick = () => {
                        arr.forEach(item => (item.style.display = 'block'))
                        sMask.style.display = 'none'
                        sAlert.style.backgroundColor = '#c93756'
                        sMask.onclick = null
                        noLight.click()
                    }
                })
            })
        }
        GM_addStyle(`._click_key_{border-radius:4px;outline:none;border:none;background-color:#454c5e;width:250px;padding:5px 0;text-align:center;float:right;}._mask_{position:fixed;left:0;top:0;bottom:0;right:0;display:none;background-color:rgba(0,0,0,.3);z-index:999;}._alert_{background-color:#c93756;border-radius:8px;box-shadow:0 0 15px #c93756;font-size:1.5em;position:absolute;text-align:center;left:50%;top:50%;padding:0 30px;line-height:3em;translate(-50%,-50%)}._alert_ img{display:block;}._bunceIn_{animation:bunceIn .3s forwards;}._sh_hd_{border:none;outline:none;color:#A4D7F5;background-image:linear-gradient( to bottom,rgba(47,137,188,1) 5%,rgba(23,67,92,1) 95%);margin:20px 0 0 20px;border-radius:5px;line-height:50px;padding:0 20px;}._slide_down_{animation:slideDown .3s forwards;}._slide_up_{animation:slideUp .3s forwards;}@keyframes bunceIn{0%{transform:translate(-50%,-50%)  scale(.8);}50%{transform:translate(-50%,-50%) scale(1.2);}100%{transform:translate(-50%,-50%) scale(1);}}@keyframes slideUp{0%{max-height:2000px;}100%{max-height:0;}}@keyframes slideDown{0%{max-height:0;}100%{max-height:2000px;}}._down_page_{float:right;padding:0 20px;border-radius:5px;height:50px;margin:20px 20px 0 0;line-height:50px;background:linear-gradient( to bottom,rgba(47,137,188,1) 5%,rgba(23,67,92,1) 95%);color:#A4D7F5;text-decoration:none;}._key_value_{margin:20px 0 0 20px;width:650px;height:200px;resize:none;font-size:18px;color:#fff;outline:none;background-color:#454c5e;border:none;}._option_ul_,._select_ul_{margin:0 0 0 20px;line-height:50px;}._option_ul_>button,._select_ul_>button{border:none;outline:none;padding:0 20px;margin:20px 20px 0 0;border-radius:5px;font-size:16px;background-image:linear-gradient( to bottom,rgba(47,137,188,1) 5%,rgba(23,67,92,1) 95%);}._select_ul_>button{background:#454c5e;}._select_ul_> button.current{background-image:linear-gradient(to top,#0c3483 0%,#a2b6df 100%,#6b8cce 100%,#a2b6df 100%);}._game_num_{width:100%;height:100%;position:absolute;left:0;top:0;z-index:1;background-color:rgba(0,0,0,.3);text-align:center;font-size:100px;}._sh_hd_.current{background-image:linear-gradient(to top,#c71d6f 0%,#d09693 100%);color:#fff;}._self_view_{max-height:2000px;list-style:none;margin:20px 0 0 0;padding:0;overflow:hidden;background-color:#363c49;}._self_view_>li{font-size:16px;padding:20px 0 0px 20px;border-bottom:10px solid #454c5e;display:flex;justify-content:space-between;}._self_view_>li button{border:none;outline:none;background-image:linear-gradient( to bottom,rgba(47,137,188,1) 5%,rgba(23,67,92,1) 95%);color:#A4D7F5;margin:0 10px;font-size:16px;border-radius:0.8em;padding:5px 15px;width:100px;float:right;}._copy_,._clear_{background:linear-gradient( to bottom,rgba(47,137,188,1) 5%,rgba(23,67,92,1) 95%);color:#A4D7F5;border-radius:5px;border:none;outline:none;font-size:16px;line-height:50px;text-align:center;margin:170px 0 0 20px;width:70px;}._self_view_>li .current{opacity:0.45;}._self_view_>li:last-child{border:none;}`)
    }
})();