华为商城抢购助手

同步华为商城服务器时间,毫秒级华为商城抢购助手

// ==UserScript==
// @name         华为商城抢购助手
// @namespace    https://github.com/gorkys/TampermonkeyHub
// @version      1.2.0
// @description  同步华为商城服务器时间,毫秒级华为商城抢购助手
// @author       Gorkys
// @license      MIT

// @match        https://www.vmall.com/product/*.html
// @match        https://*.cloud.huawei.com/*
// @match        https://www.vmall.com/product/*.html?*
// @match        https://www.vmall.com/order/nowConfirmcart
// @match        https://sale.vmall.com/rush/*
// @supportURL   https://github.com/gorkys/TampermonkeyHub/issues
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {
    'use strict';

    let STARTTIME = 0 // 活动开始时间
    let OFFSETTIME = 0 // 与本地时间相差
    let NETWORKTIME = 0 // 网络延迟

    window.onload = () => {
        // 自动登录
        if (window.location.href.indexOf('cloud.huawei') !== -1) {
            // 浏览器记住密码的情况下
            setTimeout(() => {
                $('body').click()
            }, 1000)
            setTimeout(() => {
                $('.button-base-box').click()
            }, 2000)
        }
        // 提交订单
        if (window.location.href.indexOf('order') !== -1) {
            ec.order.confirmSubmit()
        }

        // 检查登录情况
        // 318 秒杀活动
        if (window.location.href.indexOf('/rush') !== -1) {
            if (ec.account.isLogin()) {
                const skuIds = ec.skuList.map((item) => { return item.skuInfo[0].id }).join(',')
                const getTime = new Date().getTime()
                getSkuRushbuyInfo(skuIds, getTime)
            } else {
                window.location.replace(ec.loginUrl)
            }
        }
        // 商城申购
        if (window.location.href.indexOf('/product') !== -1) {
            if (rush.account.isLogin()) {
                const skuIds = rush.sbom.getCurrSkuId()
                const getTime = new Date().getTime()
                getSkuRushbuyInfo(skuIds, getTime)
            } else {
                // ec.account.afterLogin()  弹窗登录
                rush.business.doGoLogin() //页面登录
            }
        }

    }

    let cycle = 0

    const initBox = () => {
            const style = `#rushToBuyBox{z-index: 9999;background-color:rgba(255,255,255,0.7);width:260px;font-size:14px;position:fixed;top:20%;right:-150px;padding:10px;border-radius:5px;box-shadow:1px 1px 9px 0 #888;transition:right 1s;text-align:center}#rushToBuyBox:hover{right:10px}.title{font-size:16px;font-weight:bold;margin:10px 0}.title span{font-size:12px;color:#9c9c9c}#formList{margin:10px}.time span{color:red}#formList input{background:0;height:20px;font-size:14px;outline:0;border:1px solid #ccc;margin-bottom:10px}#formList input:focus{border:1px solid #4ebd0d}#formList div span{font-size:12px;color:red}#formList div{margin-bottom:10px}.countdown{margin-top:10px}`
            const html = `
                    <div id='rushToBuyBox'>
                        <h3 class="title">
                            华为商城抢购助手 <span>by: Gorkys</span>
                        </h3>
                        <div class='time'>
                            <p>本地与服务器时间相差: <span id='offsetTime'>-1400ms</span></p>
                            <p>网络延迟: <span id='timer'>200ms</span></p>
                        </div>
                        <form id='formList'>
                            <div>活动开始时间</div>
                            <input type="text" id="g_startTime"  value="" placeholder="2020/03/07 12:49:00" />
                            <div>提前下单时间<span>(ms)</span></div>
                            <input type="number" id="g_beforeStartTime" value="" placeholder="200" /></br>
                            <div>提前刷新页面<span>(s)</span></div>
                            <input type="checkBox" id='isRefresh'> 开启</input>
                            <input style="margin-left:10px;width: 100px;" disabled id='refreshTime' type="number" /> 秒</br>
                            <button id='rushToBuy'>开始运行</button><button style='margin-left:5px' id='stop'>停止</button>
                        </form>
                        <div class='countdown'>倒计时: <span id='g_countdown'>1天 2:3:4</span></div>
                    </div>
                    `
            var stylenode = document.createElement('style');
            stylenode.setAttribute("type", "text/css");
            if (stylenode.styleSheet) { // IE
                stylenode.styleSheet.cssText = style;
            } else { // w3c
                var cssText = document.createTextNode(style);
                stylenode.appendChild(cssText);
            }
            var node = document.createElement('div');
            node.innerHTML = html;
            document.head.appendChild(stylenode);
            document.body.appendChild(node);

            const g_startTime = document.querySelector('#g_startTime')
            const g_beforeStartTime = document.querySelector('#g_beforeStartTime')
            const isRefresh = document.querySelector('#isRefresh')
            const refreshTime = document.querySelector('#refreshTime')
                // 设置活动开始时间
            g_startTime.value = formatTime(STARTTIME) || rush.activity.getActivity(rush.sbom.getCurrSkuId()).startTime
            g_beforeStartTime.value = 200
            refreshTime.value = 30
                // 延时
            document.querySelector('#offsetTime').innerText = OFFSETTIME || rush.business.offsetTime + 'ms'
            document.querySelector('#timer').innerText = NETWORKTIME || rush.business.timer + 'ms'


            // 倒计时
            const countdownId = setInterval(() => {
                document.querySelector('#g_countdown').innerText = getDistanceSpecifiedTime(g_startTime.value, new Date().getTime() + OFFSETTIME)
            }, 1000)

            const countdown = document.querySelector('#rushToBuy')
            const stop = document.querySelector('#stop')

            isRefresh.addEventListener('change', () => {
                sessionStorage.setItem('isRefresh', isRefresh.checked)
                refreshTime.disabled = !isRefresh.checked
            })

            countdown.addEventListener('click', () => {
                countdown.disabled = true
                countdown.innerText = '抢购中...'
                sessionStorage.setItem('g_startTime', g_startTime.value)
                sessionStorage.setItem('g_beforeStartTime', g_beforeStartTime.value)
                sessionStorage.setItem('isRun', true)

                getServerTime(g_startTime.value, g_beforeStartTime.value)
            })
            stop.addEventListener('click', () => {
                countdown.disabled = false
                countdown.innerText = '开始运行'
                sessionStorage.setItem('isRun', false)
                clearInterval(cycle)
            })

            if (sessionStorage.getItem('isRun') === 'true') {
                g_startTime.value = sessionStorage.getItem('g_startTime')
                g_beforeStartTime.value = sessionStorage.getItem('g_beforeStartTime')
                countdown.click()
            }
        }
        // 获取服务器时间
    const getServerTime = (g_startTime, g_beforeStartTime) => {
            const details = {
                method: 'GET',
                url: 'https://buy.vmall.com/getSkuRushbuyInfo.json',
                onload: (responseDetails) => {
                    if (responseDetails.status === 200) {
                        const res = JSON.parse(responseDetails.responseText)
                        const startTime = new Date(g_startTime).getTime()
                        const isRefresh = document.querySelector('#isRefresh')
                        const refreshTime = document.querySelector('#refreshTime')

                        let currentTime = res.currentTime
                        OFFSETTIME = new Date().getTime() - res.currentTime

                        cycle = setInterval(() => {
                            console.log(startTime - currentTime)
                            if (isRefresh.checked && startTime - currentTime <= refreshTime.value * 1000) {
                                sessionStorage.setItem('isRefresh', !isRefresh.checked)
                                window.location.reload()
                                clearInterval(cycle)
                            }

                            rushToBuy(startTime, currentTime, g_beforeStartTime)
                            currentTime += 10
                        }, 10)
                    }
                }
            }
            GM_xmlhttpRequest(details)
        }
        // 获取活动信息
    const getSkuRushbuyInfo = (skuIds, getTime) => {
            const details = {
                method: 'GET',
                url: `https://buy.vmall.com/getSkuRushbuyInfo.json?skuIds=${skuIds}&t=${new Date().getTime()}`,
                onload: (responseDetails) => {
                    if (responseDetails.status === 200) {
                        const res = JSON.parse(responseDetails.responseText)
                        NETWORKTIME = new Date().getTime() - getTime
                        OFFSETTIME = res.currentTime - new Date().getTime()
                        STARTTIME = res.skuRushBuyInfoList[0].startTime
                        initBox()
                    }
                }
            }
            GM_xmlhttpRequest(details)
        }
        // 提前申购
    const rushToBuy = (startTime, currentTime, g_beforeStartTime) => {
            if (startTime - currentTime <= g_beforeStartTime) {
                if (window.location.href.indexOf('/rush') !== -1) {
                    ec.submit(0)
                }
                if (window.location.href.indexOf('/product') !== -1) {
                    rush.business.doGoRush(1);
                }
                sessionStorage.setItem('isRun', false)
                clearInterval(cycle)
            }
        }
        // 抢购倒计时对比
    const getDistanceSpecifiedTime = (dateTime, currentTime) => {
            // 指定日期和时间
            var EndTime = new Date(dateTime).getTime();
            // 当前系统时间
            // var NowTime = new Date();
            // var t = EndTime.getTime() - NowTime.getTime();
            var t = EndTime - currentTime
            var d = Math.floor(t / 1000 / 60 / 60 / 24);
            var h = Math.floor(t / 1000 / 60 / 60 % 24);
            var m = Math.floor(t / 1000 / 60 % 60);
            var s = Math.floor(t / 1000 % 60);
            return `${fillZero(d)}天 ${fillZero(h)}:${fillZero(m)}:${fillZero(s)}`
        }
        // 格式化时间
    const formatTime = (time) => {
            var datetime = new Date();
            datetime.setTime(time);
            var year = datetime.getFullYear();
            var month = datetime.getMonth() + 1
            var date = datetime.getDate()
            var hour = datetime.getHours()
            var minute = datetime.getMinutes()
            var second = datetime.getSeconds()
            return `${year}-${fillZero(month)}-${fillZero(date)} ${fillZero(hour)}:${fillZero(minute)}:${fillZero(second)}`
        }
        // 补零
    const fillZero = (str, len = 2) => {
        return (`${str}`).padStart(len, '0')
            // return (`${str}`).slice(-len)
    }
})();