掘金签到+可视化智能抽奖

掘金签到和智能可视化抽奖

// ==UserScript==
// @name         掘金签到+可视化智能抽奖
// @namespace    http://tampermonkey.net/
// @version      0.1.2
// @description  掘金签到和智能可视化抽奖
// @author       凡繁烦
// @icon         chrome://favicon/http://juejin.cn/
// @grant        GM_getValue
// @grant        GM_setValue
// @create       2021-08-29
// @run-at       document-body
// @include      https://juejin.cn/*
// @exclude      https://juejin.cn/editor/drafts/*
// @require      https://unpkg.com/coco-message/coco-message.min.js
// @note         2021-09-29 V0.1.2 增加自动签到,签到后使用一次免费抽奖;使用第三方弹框库提示;排除文章编辑页面
// ==/UserScript==

(function() {
    'use strict';

    var autoSign = true;

    console.log(
              `%c 反馈问题->掘金 %c https://juejin.cn/post/7000936088969674783 %c`,
              `background:#2d8cf0;border:1px solid #2d8cf0; padding: 1px; border-radius: 4px 0 0 4px; color: #fff;`,
              `border:1px solid #2d8cf0; padding: 1px; border-radius: 0 4px 4px 0; color: #2d8cf0;`,
              'background:transparent'
          )

    cocoMessage.config({
        duration: 2000,
    });

    const styleContent = `
    ._jj_draw_container {
        position:fixed;
        top: 80px;
        right: 0;
        z-index: 9999;
        background-color: rgba(0,0,0,0.6);
        padding: 20px;
    }
        ._jj_button {
            padding: 6px;
            background-color: #1e80ff;
            color: #fff;
            border-radius: 4px;
            text-align: center;
            vertical-align: middle;
            border: 1px solid transparent;
            font-weight: 700;
            letter-spacing: 1em;
            text-indent: 1em;
            cursor: pointer;
        }
        ._jj_btn_sign_in{
            background-color:#e8f3ff !important;
            color:#1e80ff !important;
        }
        ._jj_button:hover {
            opacity: 0.8;
        }
        table._jj_hovertable thead {
            text-align: center;
            font-size: 16px;
            font-weight: 700;
            color:#333;
        }
        table._jj_hovertable {
            font-family: verdana, arial, sans-serif;
            font-size: 11px;
            color: #d25f00;
            border-width: 1px;
            border-color: #999999;
            border-collapse: collapse;
        }
        table._jj_hovertable th {
            background-color: #c3dde0;
            border-width: 1px;
            padding: 8px;
            border-style: solid;
            border-color: #a9c6c9;
        }
        table._jj_hovertable tr {
            background-color: #fff;
        }
        table._jj_hovertable td {
            border-width: 1px;
            padding: 8px;
            border-style: solid;
            border-color: #a9c6c9;
        }
        ._jj_button_close{
            font-size: 20px;
            font-weight: 700;
            color: #FFF;
        }
        .__jj_dialog_title{
            display: flex;
        }
        .__jj_dialog_title_left{
            flex:1;
            font-size: 14px;
            color: #fff;
        }
        .__jj_dialog_title_left span{
            color: #1e80ff;
            font-size:20px;
            font-weight: 700;
        }
        .__jj_dialog_title_right{
            width: 30px;
        }

    `;


    const htmlContent = `
    <div class="">
        <div class="__jj_dialog_title">
            <div class="__jj_dialog_title_left" id="__jj_dialog_title_left" style="visibility:hidden;">矿石<span id="ore_num">0</span>个 | 可抽奖<span id="draws_num">0</span>次</div>
            <div class="__jj_dialog_title_right">
            <a href="javascript:void(0)" id="_jj_btn_close" class="_jj_button_close">X</a>
            </div>
        </div>
        <div style="text-align:center;margin: 10px;">
            <button id="_jj_btn_sign_in" type="button" class="_jj_button _jj_btn_sign_in">签到</button>
            <button id="_jj_btn_draw" type="button" class="_jj_button _jj_btn_draw">抽奖</button>
            <button id="_jj_btn_stop" type="button" class="_jj_button">停止</button>
            
        </div>
        <table class="_jj_hovertable">
            <thead>
                <tr>
                    <td>奖品图标</td>
                    <td>奖品名称</td>
                    <td>中奖次数</td>
                    <td>累计奖励</td>
                </tr>
            <tbody id="_jj_tbodyList">
            </tbody>
            </thead>
        </table>
    </div>
    `



    function appendStyle(text) {
        const styleEl = document.createElement('style');
        styleEl.textContent = text;
        document.head.appendChild(styleEl);
    }

    function appendHTML(htmlContent) {
        const htmlEl = document.createElement('div');
        htmlEl.id = "_jj_draw_container";
        htmlEl.className = "_jj_draw_container";
        htmlEl.innerHTML = htmlContent;
        document.body.appendChild(htmlEl);
        getCurPoint();
    }

    appendStyle(styleContent);
    appendHTML(htmlContent);

    let lotteryConfig = [];
    let isDrawing = false;
    let prizes = [];
    const tbodyListEl = document.getElementById("_jj_tbodyList")

    function delay(fn = () => { }, delay = 5000, context = null) {
        let ticket = null;
        let runned = false;
        return {
            run(...args) {
                return new Promise((resolve, reject) => {
                    if (runned === true) {
                        return;
                    }
                    runned = true;
                    ticket = setTimeout(async () => {
                        try {
                            const res = await fn.apply(context, args);
                            resolve(res);
                        } catch (err) {
                            reject(err)
                        }
                    }, delay)
                })
            },
            cancel: () => {
                clearTimeout(ticket);
            }
        }
    }

    function getLotteryConfig() {
        return fetch("https://api.juejin.cn/growth_api/v1/lottery_config/get")
            .then(res => res.json())
    }

    function getSignCount(){
        return fetch('https://api.juejin.cn/growth_api/v1/get_counts?aid=2608&uuid=6986922219256989198',{
            method: 'GET',
            credentials: "include"
        }).then(res => res.json())
    }

    function getCurPoint(){
        return fetch('https://api.juejin.cn/growth_api/v1/get_cur_point?aid=2608&uuid=6986922219256989198',{
            method: 'GET',
            credentials: "include"
        }).then(res => res.json()).then(data=>{
            document.getElementById("ore_num").innerText = data.data;
            document.getElementById("draws_num").innerText = Math.floor(data.data/200);
            document.getElementById("__jj_dialog_title_left").style.visibility='visible';
        })
    }

    function onSignIn(isAuto=false) {
        return fetch('https://api.juejin.cn/growth_api/v1/check_in',{
            method: 'POST',
            credentials: "include",
            headers: {
                'Content-Type': 'application/json;charset=utf-8;'
            },
            body: JSON.stringify({aid: '2608',uuid:'6986922219256989198'})
        }).then(res => res.json()).then(data=>{
            if(data.err_no!==0){
                cocoMessage.error(data.err_msg)
            }else{
                onSuccess(isAuto);
            }
        })
    }

    //自动签到
    function autoSignHandle(){
        let signDate = GM_getValue("signDate");
        console.log(signDate)
        if(autoSign && (!signDate || signDate < today())){
            onSignIn(true)
        }
    }

    autoSignHandle();

    //获取今天的日期
    function today(){
        var date = new Date();
        var seperator1 = "-";
        var seperator2 = ":";
        var month = date.getMonth() + 1;
        var strDate = date.getDate();
        if (month >= 1 && month <= 9) {
            month = "0" + month;
        }
        if (strDate >= 0 && strDate <= 9) {
            strDate = "0" + strDate;
        }
        var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate;
        return currentdate;

    }

    async function onSuccess(isAuto){
        const count = await getSignCount();
        getCurPoint();
        GM_setValue("signDate",today())
        cocoMessage.success(`签到成功,连续签到${count.data.cont_count}天,累计签到${count.data.sum_count}天`);
        if(isAuto){
          onDraw(!isAuto)
        }
    }

    // {"err_no":7003,"err_msg":"积分不足,无法进行抽奖lack of point","data":null}
    function doDraw() {
        return fetch('https://api.juejin.cn/growth_api/v1/lottery/draw', {
            method: 'POST',
            credentials: "include"
        }).then(res => res.json())
    }


    async function onDraw(isOnce=true) {
        if (isDrawing) {
            return;
        }
        isDrawing = true;

        try {
            let errNo = 0;
            do {
                if(!isDrawing){
                    break;
                }

                const res = await doDraw();
                getCurPoint();
                errNo = res.err_no;

                if (errNo !== 0) {
                    cocoMessage.error(res.err_msg);
                    isDrawing = false;
                    break;
                }

                // 增加奖励
                addPrize(res.data)
                // 渲染
                renderPrizes();
                // 暂停16ms
                await delay(undefined, 16).run();

                //isDrawing = false;
                //break;

            } while (errNo == 0 && isOnce)

        } catch (err) {
            isDrawing = false
            cocoMessage.error(err.message);
        }
    }

    function addPrize(data) {

        let prize = prizes.find(p => p.lottery_id == data.lottery_id);
        if(!prize) {
            return;
        }
        prize.counts += 1;

    }

    function onStop() {
        isDrawing = false;
    }

    function getTotal(data){
        if(data.lottery_id == "6981716980386496552" || data.lottery_name == "66矿石"){
            return data.counts * 66;
        }
        return data.counts;
    }

    function renderPrizes() {
        tbodyListEl.innerHTML = prizes.map(prize => `
        <tr id="_jj_${prize.lottery_id}">
            <td class="_jj_price_icon"><img style="height:30px" src="${prize.lottery_image}" /></td>
            <td>${prize.lottery_name}</td>
            <td class="_jj_count">${prize.counts}</td>
            <td class="_jj_total">${getTotal(prize)}</td>
        </tr>
    `).join("");

    }


    async function init() {
        lotteryConfig = (await getLotteryConfig()).data.lottery;

        prizes = lotteryConfig.map(c => ({
            lottery_id: c.lottery_id,
            lottery_name: c.lottery_name,
            lottery_image: c.lottery_image,
            counts: 0
        }));

        renderPrizes();
        document.getElementById("_jj_btn_sign_in").addEventListener("click",onSignIn)
        document.getElementById("_jj_btn_draw").addEventListener("click", onDraw);
        document.getElementById("_jj_btn_stop").addEventListener("click", onStop);
        document.getElementById("_jj_btn_close").addEventListener("click", function () {
            document.querySelector("#_jj_draw_container").style.display = "none"
        });
    }
    init();
})();