GF2 BBS Claimer

一个简单的少前2论坛自动兑换物品脚本(包括签到);当因登录(不可用)凭证过期时,可根据提供的账号密码自动登录(不可用);其中,GM_getResourceText()需要启用油猴插件"允许访问文件网址"权限(具体配置请查看文档),以chrome为例,浏览器右上角"更多设置(三点)" -> "拓展程序" -> "管理拓展程序" -> "篡改猴" -> "详情" -> "允许访问文件网址" -> 启用;

// ==UserScript==
// @name         GF2 BBS Claimer
// @name:zh-CN   少前2bbs自动兑换物品脚本
// @namespace    http://tampermonkey.net/
// @version      1.1.1
// @description  一个简单的少前2论坛自动兑换物品脚本(包括签到);当因登录(不可用)凭证过期时,可根据提供的账号密码自动登录(不可用);其中,GM_getResourceText()需要启用油猴插件"允许访问文件网址"权限(具体配置请查看文档),以chrome为例,浏览器右上角"更多设置(三点)" -> "拓展程序" -> "管理拓展程序" -> "篡改猴" -> "详情" -> "允许访问文件网址" -> 启用;
// @description:zh-CN  一个简单的少前2论坛自动兑换物品脚本(包括签到);当因登录(不可用)凭证过期时,可根据提供的账号密码自动登录(不可用);其中,GM_getResourceText()需要启用油猴插件"允许访问文件网址"权限(具体配置请查看文档),以chrome为例,浏览器右上角"更多设置(三点)" -> "拓展程序" -> "管理拓展程序" -> "篡改猴" -> "详情" -> "允许访问文件网址" -> 启用;
// @author       [email protected]
// @match        https://gf2-bbs.exiliumgf.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=exiliumgf.com
// @grant        GM_getResourceText
// @grant        window.onurlchange
// @resource     config http://your/path/to/config.json
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    const SCRIPT_NAME = GM_info.script.name;
    log(`开始执行${SCRIPT_NAME}...`);
    const states = {};
    const PERFORMED = "performed", SIGNED = "signed", EXCHANGED = "exchanged";
    if ((states[SIGNED] = getKey(SIGNED)) && (states[PERFORMED] = getKey(PERFORMED)) && (states[EXCHANGED] = getKey(EXCHANGED))) {
        log('今日已执行.');
        return;
    }
    const TASK_1 = "点赞帖子", TASK_2 = "分享帖子", TASK_3 = "浏览帖子";
    const DEFAULT = {
        exchanging: '1,2,3,4,5',
        notification: 1,
        base_url: 'https://gf2-bbs-api.exiliumgf.com'
    };
    const configPath = getConfigPath();
    const configPathNotEmpty = configPath !== '';
    !configPathNotEmpty && log('配置文件路径为空', 'warn');
    const _config = configPathNotEmpty ? GM_getResourceText('config') : '';
    const config = Object.assign({}, DEFAULT, _config ? JSON.parse(_config) : {});
    const BASE_URL = config.base_url, OK = "OK";
    const NOTIFICATION_STYLE = "position: absolute; z-index: 1000; padding: 0 10px; display: flex; align-items: center; color: white; transition: all 0.2s;";
    const NOTIFICATION_STYLE_FOR_PC = "right: 0; font-size: .12rem;";
    const NOTIFICATION_STYLE_FOR_PHONE = "left: 0; font-size: .13rem;";
    const SIGNED_IMG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAABXCAMAAAC3HXLTAAADAFBMVEVHcEzg4ODg4ODg4OD////g4ODf39/////////////h4eHg4ODg4ODg4ODe3t7g4OD////g4ODh4eHg4ODg4ODf39/////h4eH////g4ODg4ODg4OD+/v7c3Nzh4eHh4eHg4ODm5ub////////////g4ODc3Nzh4eH////////i4uL////g4ODh4eHg4OD////h4eHg4OD+/v7////g4ODh4eHj4+Pe3t7g4ODg4ODd3d3////////h4eHg4OD////f39/k5OT////////////////////////////////////////l5eX////e3t7f39/k5OTg4ODh4eH////////////////////////h4eH////f39/z8/P////////f39/////f39/////f39/////////////g4OD////////////////f39/////////////////////////////////////////////////h4eH////////////////////////i4uL////////////i4uL////j4+Ps7Oz19fX////////////////////t7e3////l5eX////////m5ub////+/v7b29ve3t7g4ODY2Njd3d3c3Nz////g4ODl5eXd3d3m5ubh4eH8/Pz////g4OD///////////+rq6vg4OCkpKSqqqqlpaWoqKinp6f4+Pjf39+srKz+/v6mpqapqanj4+PU1NSurq6jo6Pm5ua0tLS1tbXz8/PIyMjMzMzi4uLs7OywsLDS0tL7+/v9/f3k5OTh4eHd3d3JycmysrKtra3u7u709PTe3t78/Pz6+vrPz8/V1dXv7+/BwcHX19f5+fnl5eXr6+uvr6/Dw8P39/ezs7Pn5+fR0dHLy8vx8fHc3Nzq6urt7e3o6OjZ2dm7u7vw8PDHx8fb29vT09PFxcWxsbH29vby8vK3t7fQ0NDa2tqhoaG9vb2+vr6fn5+2tra4uLjOzs7AwMD19fXGxsbExMTNzc3CwsK/v7/W1tZAfWO5AAAAp3RSTlMA7tbylvQYRtAyN/bZERsuJfDc8DkwCh/+6dA8RSvUKc8TB/oz2hYyAx80NB3dPu/z3kpf6+0PJubcLdqzFjF5GS9n8QTsE8WVECL2HQs2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";
    // 获取配置文件路径;
    function getConfigPath() {
        const pattern = /(@resource\s+)(.*?)\n/;
        const meta = GM_info.scriptMetaStr;
        const groups = meta.match(pattern);
        if (groups) {
            const path = groups[2];
            if (!path.split(" ")[1].startsWith("file://")) {
                return "";
            }
            return path;
        }
        return "";
    }
    // 账号登录(不可用);返回一个令牌
    async function login(account, password) {
        if (!account || !password) {
            throw new Error("账号密码不能为空");
        }
        const pattern = /^1[3456789]\d{9}$/;
        let source;
        if (pattern.test(account)) {
            source = "phone";
        }
        else if (account.includes("@")) {
            source = "email";
        }
        else {
            throw new Error("账号格式错误");
        }
        const resp = await fetch(`${BASE_URL}/login/account`, {
            method: "post",
            headers: { Authorization: token, "Content-Type": "application/json" },
            body: JSON.stringify({ account_name: account, passwd: encrypt(password), source })
        });
        return (await resp.json()).data.account.token;
    }
    // 获取现在到凌晨的秒数,作为cookie的有效期;
    function getSecondsBeforeDawn() {
        const date = new Date();
        return (23 - date.getHours()) * 60 * 60 + (59 - date.getMinutes()) * 60 + 59 - date.getSeconds();
    }
    // 是否已经签到
    async function signed(token) {
        const resp = await (await fetch(`${BASE_URL}/community/task/get_current_sign_in_status`, {
            headers: { Authorization: token, "Content-Type": "application/json" }
        })).json();
        return resp.data.has_sign_in;
    }
    function successful(resp) {
        return resp.Message === OK;
    }
    // 签到
    async function signIn(token, _signed) {
        log(signIn.name);
        // 一共两次判断,一次为本地判断,另一次为从服务器获取数据判断,兑换和执行每日任务同理
        if (_signed || (await signed(token))) {
            console.log('今日已签到');
            return { [SIGNED]: setKey(SIGNED) };
        }
        let resp = await fetch(`${BASE_URL}/community/task/sign_in`, {
            method: "post",
            headers: { Authorization: token, "Content-Type": "application/json" },
            body: "{}"
        });
        resp = await resp.json();
        successful(resp) && (resp[SIGNED] = setKey(SIGNED));
        return resp;
    }
    function delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    async function like(token, topicId) {
        return await (await fetch(`${BASE_URL}/community/topic/like/${topicId}?id=${topicId}`, {
            headers: { Authorization: token, "Content-Type": "application/json" }
        })).json();
    }
    // 点赞(三个帖子);
    // 如果帖子为"点赞"状态,则需要先取消点赞,再重新点赞
    async function task1(token, posts) {
        const resps = [];
        for(const item of posts) {
            const topicId = item.topic_id;
            resps.push(await like(token, topicId));
            await delay(600);
            if (item.is_like) {
                resps.push(await like(token, topicId));
                await delay(600);
            }
        }
        return resps;
    }
    // 分享
    async function task2(token, posts) {
        const topicId = posts[0].topic_id;
        const resp = await fetch(`${BASE_URL}/community/topic/share/${topicId}?id=${topicId}`, {
            headers: { Authorization: token, "Content-Type": "application/json" }
        });
        return await resp.json();
    }
    // 浏览
    async function task3(token, posts) {
        const resps = [];
        for(const item of posts) {
            const topicId = item.topic_id;
            const resp = await fetch(`${BASE_URL}/community/topic/${topicId}?id=${topicId}`, {
                headers: { Authorization: token, "Content-Type": "application/json" }
            });
            resps.push(await resp.json());
            await delay(600);
        }
        return resps;
    }
    // 兑换物品;根据配置文件中的数据进行兑换;
    // 配置文件exchanging中,每个数字所代表的含义;1->情报拼图,2->萨狄斯金,3->战场报告,4->解析图纸,5->基原信息核;
    // 关于兑换的方式,存在两种情况:
    // - 积分足够时,将所有物品兑换完;
    // - 积分不足时,优先兑换1,其次是5234;
    // 但若每日都完成任务时,不会存在积分不足的问题。
    async function exchange(token, exchanging, exchanged) {
        log(exchange.name);
        if (exchanged) {
            console.log('今日已兑换');
            return null;
        }
        const idMap = {};
        const result = {};
        for (const item of exchanging.split(',')) {
            idMap[item] = item;
        }
        const [exchangeList, memberInfoResp] = await Promise.all([getExchangeList(token), getInfo(token)]);
        // 按exchange_id升序排序,并将信息核移至下标1位置
        exchangeList.sort((a, b) => a.exchange_id - b.exchange_id);
        exchangeList.splice(1, 0, exchangeList.pop());
        let score = (await memberInfoResp.json()).data.user.score;
        for (const item of exchangeList) {
            const id = item.exchange_id;
            while (idMap[id] && score >= item.use_score && (item.exchange_count < item.max_exchange_count)) {
                const resp = await fetch(`${BASE_URL}/community/item/exchange`, {
                    method: 'post',
                    headers: { Authorization: token, "Content-Type": "application/json" },
                    body: JSON.stringify({ exchange_id: id })
                });
                item.exchange_count++;
                score -= item.use_score;
                result[id] = await resp.json();
                await delay(600);
            }
        }
        Object.values(result).every(successful) && setKey(EXCHANGED);
        return result;
    }
    async function getPost(token) {
        const resp = await fetch(`${BASE_URL}/community/topic/list?sort_type=1&category_id=1&query_type=1&last_tid=0&pub_time=0&reply_time=0&hot_value=0`, {
            headers: { Authorization: token, "Content-Type": "application/json" },
        });
        const _resp = await resp.json();
        return _resp.data.list;
    }
    /**
     * 获取兑换列表
     * @param {String} token
     * @returns {Array}
     */
    async function getExchangeList(token) {
        const resp = await fetch(`${BASE_URL}/community/item/exchange_list`, {
            headers: { Authorization: token, "Content-Type": "application/json" },
        });
        return (await resp.json()).data.list;
    }
    function notLikeFilter(list) {
        return list.filter(item => !item.is_like);
    }
    async function getTask(token) {
        const resp = await (await fetch(`${BASE_URL}/community/task/get_current_task_list`, {
            headers: { Authorization: token, "Content-Type": "application/json" }
        })).json();
        return resp.data.daily_task;
    }
    function getKey(key) {
        for (const item of document.cookie.split(";").map(item => item.trim())) {
            if (item.startsWith(key)) {
                return item.split("=")[1];
            }
        }
        return "";
    }
    function setKey(key) {
        document.cookie = `${key}=1; max-age=${getSecondsBeforeDawn()}; path=/;`;
        return 1;
    }
    // 执行每日任务
    async function performTask(token, performed) {
        log(performTask.name);
        if (performed) {
            console.log('今日已完成任务');
            return null;
        }
        const results = {};
        const tasks = await getTask(token);
        // 待执行任务列表;当key存在时表示需要执行
        const pending = {};
        for (const item of tasks) {
            if (item.complete_count < item.max_complete_count) {
                pending[item.task_name] = "1";
            }
        }
        if (!Object.keys(pending).length) {
            results[PERFORMED] = setKey(PERFORMED);
            console.log('今日已完成任务');
            return results;
        }
        const posts = await getPost(token);
        let filtered = notLikeFilter(posts);
        // 如果没有符合条件的数据,则使用原始数据(但估计会很少遇到,毕竟是极端情况)
        if (!filtered.length) {
            filtered = posts;
        }
        const _posts = filtered.slice(0, 3);
        pending[TASK_1] && (pending[TASK_1] = task1(token, _posts));
        pending[TASK_3] && (pending[TASK_3] = task3(token, _posts));
        pending[TASK_2] && (pending[TASK_2] = task2(token, _posts));
        const [a=null, b=null, c=null] = await Promise.all(Object.values(pending));
        results[TASK_1] = a;
        results[TASK_3] = b;
        results[TASK_2] = c;
        [...a, ...b, c].every(successful) && setKey(PERFORMED);
        return results;
    }
    // 更新节点(签到成功后);pc貌似有点问题,即使刷新页面,文字也依旧不变;
    function updateNodeForSigning() {
        const selector = location.pathname.startsWith("/m") ? '.nav_con div:first-child' : '.btns .btn';
        const node = document.querySelector(selector);
        const [img, a, b] = [...node.children];
        if (img.src !== SIGNED_IMG) {
            img.src = SIGNED_IMG;
            a.innerText = "已签到";
            b.remove();
        }
    }
    async function runner(token, states) {
        const resp2signIn = await signIn(token, states[SIGNED]);
        if (resp2signIn) {
            console.log(resp2signIn);
            resp2signIn[SIGNED] && updateNodeForSigning();
        }
        const resp2performTask = await performTask(token, states[PERFORMED]);
        resp2performTask && console.log(resp2performTask);
        const resp2exchange = await exchange(token, config.exchanging, states[EXCHANGED]);
        resp2exchange && console.log(resp2exchange);
    }
    // (md5)加密
    function encrypt(input) {
        return ke(input);
    }
    async function getInfo(token) {
        return await fetch(`${BASE_URL}/community/member/info`, {
            method: 'post',
            headers: { Authorization: token, "Content-Type": "application/json" },
            body: "{}"
        });
    }
    // 获取用户信息(其实是用于检查令牌是否有效);
    // 测试发现,只要令牌未过期,都可获取到数据,即可存在多个令牌(服务器不记录状态);
    // 当response.status为401时,表示令牌过期。
    async function checkToken(token) {
        const resp = await getInfo(token);
        return resp.status === 200;
    }
    function saveToken(token) {
        localStorage.setItem('key', token);
    }
    function log(msg, level='log') {
        console[level](`[${new Date().toLocaleString()} ${msg}]`);
    }
    function errorHandler(ev) {
        log(`${SCRIPT_NAME}执行出现错误:`, 'error');
        console.error(ev);
        console.warn("若未完成兑换时,请手动处理.");
        notice3(config);
    }
    function removeNotification(node, delay) {
        return new Promise(resolve => {
            setTimeout(() => {
                node.style.top = "-60px";
                setTimeout(() => {
                    node.remove();
                    resolve();
                }, 50);
            }, delay);
        })
    }
    let _node, promise;
    async function notice(message, duration, _delay=50) {
        promise && await promise;
        _node && await removeNotification(_node, 1000);
        const node = document.createElement("div");
        _node = node;
        const head = document.querySelector('.head');
        node.style = `${NOTIFICATION_STYLE}${location.pathname.startsWith("/m") ? NOTIFICATION_STYLE_FOR_PHONE : NOTIFICATION_STYLE_FOR_PC}top: -${head.clientHeight}px; height: ${head.clientHeight}px;`;
        node.innerText = message;
        head.appendChild(node);
        if (duration > 0) {
            promise = new Promise(resolve => {
                setTimeout(() => {
                    node.style.top = "0";
                    removeNotification(node, duration);
                    _node = null;
                    promise = null;
                    resolve();
                }, _delay);
            });
        }
        else {
            promise = new Promise(resolve => {
                setTimeout(() => {
                    node.style.top = "0";
                    promise = null;
                    resolve();
                }, _delay);
            });
        }
    }
    function notice1(config) {
        if (+config.notification) {
            notice(`脚本执行完成.`, 3000);
        }
    }
    function notice2(config) {
        if (+config.notification) {
            notice(`脚本执行中...`, -1, 100);
        }
    }
    function notice3(config) {
        if (+config.notification) {
            notice(`脚本执行出现错误.`, 3000);
        }
    }
    // -----------------加密相关(无需理会)-----------------
    function Ht(t) {
        for (var e = 0; e < t; e++)
            this[e] = 0;
        this.length = t
    }
    function Dt(t) {
        return t % 4294967296
    }
    function Bt(t, e) {
        return t = Dt(t),
        e = Dt(e),
        t - 2147483648 >= 0 ? (t %= 2147483648,
        t >>= e,
        t += 1073741824 >> e - 1) : t >>= e,
        t
    }
    function Nt(t) {
        return t %= 2147483648,
        !0 & t ? (t -= 1073741824,
        t *= 2,
        t += 2147483648) : t *= 2,
        t
    }
    function Et(t, e) {
        t = Dt(t),
        e = Dt(e);
        for (var s = 0; s < e; s++)
            t = Nt(t);
        return t
    }
    function Mt(t, e) {
        t = Dt(t),
        e = Dt(e);
        var s = t - 2147483648
          , i = e - 2147483648;
        return s >= 0 ? i >= 0 ? 2147483648 + (s & i) : s & e : i >= 0 ? t & i : t & e
    }
    function Pt(t, e) {
        t = Dt(t),
        e = Dt(e);
        var s = t - 2147483648
          , i = e - 2147483648;
        return s >= 0 ? i >= 0 ? 2147483648 + (s | i) : 2147483648 + (s | e) : i >= 0 ? 2147483648 + (t | i) : t | e
    }
    function Zt(t, e) {
        t = Dt(t),
        e = Dt(e);
        var s = t - 2147483648
          , i = e - 2147483648;
        return s >= 0 ? i >= 0 ? s ^ i : 2147483648 + (s ^ e) : i >= 0 ? 2147483648 + (t ^ i) : t ^ e
    }
    function Rt(t) {
        return t = Dt(t),
        4294967295 - t
    }
    var Ut = new Ht(4)
      , Gt = new Ht(2);
    Gt[0] = 0,
    Gt[1] = 0;
    var Ft = new Ht(64)
      , Vt = new Ht(16)
      , qt = new Ht(16)
      , Kt = 7
      , Qt = 12
      , Xt = 17
      , Yt = 22
      , Jt = 5
      , Wt = 9
      , $t = 14
      , te = 20
      , ee = 4
      , se = 11
      , ie = 16
      , ne = 23
      , ae = 6
      , oe = 10
      , ce = 15
      , le = 21;
    function re(t, e, s) {
        return Pt(Mt(t, e), Mt(Rt(t), s))
    }
    function ge(t, e, s) {
        return Pt(Mt(t, s), Mt(e, Rt(s)))
    }
    function ue(t, e, s) {
        return Zt(Zt(t, e), s)
    }
    function he(t, e, s) {
        return Zt(e, Pt(t, Rt(s)))
    }
    function me(t, e) {
        return Pt(Et(t, e), Bt(t, 32 - e))
    }
    function de(t, e, s, i, n, a, o) {
        return t = t + re(e, s, i) + n + o,
        t = me(t, a),
        t += e,
        t
    }
    function Ae(t, e, s, i, n, a, o) {
        return t = t + ge(e, s, i) + n + o,
        t = me(t, a),
        t += e,
        t
    }
    function _e(t, e, s, i, n, a, o) {
        return t = t + ue(e, s, i) + n + o,
        t = me(t, a),
        t += e,
        t
    }
    function fe(t, e, s, i, n, a, o) {
        return t = t + he(e, s, i) + n + o,
        t = me(t, a),
        t += e,
        t
    }
    function pe(t, e) {
        var s = 0
          , i = 0
          , n = 0
          , a = 0
          , o = Vt;
        s = Ut[0],
        i = Ut[1],
        n = Ut[2],
        a = Ut[3];
        for (var c = 0; c < 16; c++) {
            o[c] = Mt(t[4 * c + e], 255);
            for (var l = 1; l < 4; l++)
                o[c] += Et(Mt(t[4 * c + l + e], 255), 8 * l)
        }
        s = de(s, i, n, a, o[0], Kt, 3614090360),
        a = de(a, s, i, n, o[1], Qt, 3905402710),
        n = de(n, a, s, i, o[2], Xt, 606105819),
        i = de(i, n, a, s, o[3], Yt, 3250441966),
        s = de(s, i, n, a, o[4], Kt, 4118548399),
        a = de(a, s, i, n, o[5], Qt, 1200080426),
        n = de(n, a, s, i, o[6], Xt, 2821735955),
        i = de(i, n, a, s, o[7], Yt, 4249261313),
        s = de(s, i, n, a, o[8], Kt, 1770035416),
        a = de(a, s, i, n, o[9], Qt, 2336552879),
        n = de(n, a, s, i, o[10], Xt, 4294925233),
        i = de(i, n, a, s, o[11], Yt, 2304563134),
        s = de(s, i, n, a, o[12], Kt, 1804603682),
        a = de(a, s, i, n, o[13], Qt, 4254626195),
        n = de(n, a, s, i, o[14], Xt, 2792965006),
        i = de(i, n, a, s, o[15], Yt, 1236535329),
        s = Ae(s, i, n, a, o[1], Jt, 4129170786),
        a = Ae(a, s, i, n, o[6], Wt, 3225465664),
        n = Ae(n, a, s, i, o[11], $t, 643717713),
        i = Ae(i, n, a, s, o[0], te, 3921069994),
        s = Ae(s, i, n, a, o[5], Jt, 3593408605),
        a = Ae(a, s, i, n, o[10], Wt, 38016083),
        n = Ae(n, a, s, i, o[15], $t, 3634488961),
        i = Ae(i, n, a, s, o[4], te, 3889429448),
        s = Ae(s, i, n, a, o[9], Jt, 568446438),
        a = Ae(a, s, i, n, o[14], Wt, 3275163606),
        n = Ae(n, a, s, i, o[3], $t, 4107603335),
        i = Ae(i, n, a, s, o[8], te, 1163531501),
        s = Ae(s, i, n, a, o[13], Jt, 2850285829),
        a = Ae(a, s, i, n, o[2], Wt, 4243563512),
        n = Ae(n, a, s, i, o[7], $t, 1735328473),
        i = Ae(i, n, a, s, o[12], te, 2368359562),
        s = _e(s, i, n, a, o[5], ee, 4294588738),
        a = _e(a, s, i, n, o[8], se, 2272392833),
        n = _e(n, a, s, i, o[11], ie, 1839030562),
        i = _e(i, n, a, s, o[14], ne, 4259657740),
        s = _e(s, i, n, a, o[1], ee, 2763975236),
        a = _e(a, s, i, n, o[4], se, 1272893353),
        n = _e(n, a, s, i, o[7], ie, 4139469664),
        i = _e(i, n, a, s, o[10], ne, 3200236656),
        s = _e(s, i, n, a, o[13], ee, 681279174),
        a = _e(a, s, i, n, o[0], se, 3936430074),
        n = _e(n, a, s, i, o[3], ie, 3572445317),
        i = _e(i, n, a, s, o[6], ne, 76029189),
        s = _e(s, i, n, a, o[9], ee, 3654602809),
        a = _e(a, s, i, n, o[12], se, 3873151461),
        n = _e(n, a, s, i, o[15], ie, 530742520),
        i = _e(i, n, a, s, o[2], ne, 3299628645),
        s = fe(s, i, n, a, o[0], ae, 4096336452),
        a = fe(a, s, i, n, o[7], oe, 1126891415),
        n = fe(n, a, s, i, o[14], ce, 2878612391),
        i = fe(i, n, a, s, o[5], le, 4237533241),
        s = fe(s, i, n, a, o[12], ae, 1700485571),
        a = fe(a, s, i, n, o[3], oe, 2399980690),
        n = fe(n, a, s, i, o[10], ce, 4293915773),
        i = fe(i, n, a, s, o[1], le, 2240044497),
        s = fe(s, i, n, a, o[8], ae, 1873313359),
        a = fe(a, s, i, n, o[15], oe, 4264355552),
        n = fe(n, a, s, i, o[6], ce, 2734768916),
        i = fe(i, n, a, s, o[13], le, 1309151649),
        s = fe(s, i, n, a, o[4], ae, 4149444226),
        a = fe(a, s, i, n, o[11], oe, 3174756917),
        n = fe(n, a, s, i, o[2], ce, 718787259),
        i = fe(i, n, a, s, o[9], le, 3951481745),
        Ut[0] += s,
        Ut[1] += i,
        Ut[2] += n,
        Ut[3] += a
    }
    function ve() {
        Gt[0] = Gt[1] = 0,
        Ut[0] = 1732584193,
        Ut[1] = 4023233417,
        Ut[2] = 2562383102,
        Ut[3] = 271733878;
        for (var t = 0; t < qt.length; t++)
            qt[t] = 0
    }
    function ze(t) {
        var e;
        e = Mt(Bt(Gt[0], 3), 63),
        Gt[0] < 4294967288 || (Gt[1]++,
        Gt[0] -= 4294967296),
        Gt[0] += 8,
        Ft[e] = Mt(t, 255),
        e >= 63 && pe(Ft, 0)
    }
    function ye() {
        var t, e = new Ht(8), s = 0, i = 0, n = 0;
        for (s = 0; s < 4; s++)
            e[s] = Mt(Bt(Gt[0], 8 * s), 255);
        for (s = 0; s < 4; s++)
            e[s + 4] = Mt(Bt(Gt[1], 8 * s), 255);
        i = Mt(Bt(Gt[0], 3), 63),
        n = i < 56 ? 56 - i : 120 - i,
        t = new Ht(64),
        t[0] = 128;
        for (s = 0; s < n; s++)
            ze(t[s]);
        for (s = 0; s < 8; s++)
            ze(e[s]);
        for (s = 0; s < 4; s++)
            for (var a = 0; a < 4; a++)
                qt[4 * s + a] = Mt(Bt(Ut[s], 8 * a), 255)
    }
    function be(t) {
        for (var e = "0123456789abcdef", s = "", i = t, n = 0; n < 8; n++)
            s = e.charAt(Math.abs(i) % 16) + s,
            i = Math.floor(i / 16);
        return s
    }
    var Te = "01234567890123456789012345678901 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
    const ke = function(t) {
        var e, s, i, n, a, o;
        ve();
        for (var c = 0; c < t.length; c++)
            e = t.charAt(c),
            ze(Te.lastIndexOf(e));
        ye(),
        i = n = a = o = 0;
        for (var l = 0; l < 4; l++)
            i += Et(qt[15 - l], 8 * l);
        for (l = 4; l < 8; l++)
            n += Et(qt[15 - l], 8 * (l - 4));
        for (l = 8; l < 12; l++)
            a += Et(qt[15 - l], 8 * (l - 8));
        for (l = 12; l < 16; l++)
            o += Et(qt[15 - l], 8 * (l - 12));
        return s = be(o) + be(a) + be(n) + be(i),
        s
    };
    function getToken() {
        return localStorage.getItem('key') || "";
    }
    // 等待登录(不可用);
    // 通过监听url的变化,当检测到从/login、/loading路径跳转时,尝试获取令牌进行判断(不提供账号密码时才会调用该方法)
    function waitingForLogin() {
        log(waitingForLogin.name, 'warn');
        let previous = location.href;
        const handler = (ev) => {
            if (previous === ev.url) {
                return;
            }
            if (previous.endsWith('login') || previous.includes('/loading')) {
                const token = getToken();
                if (token) {
                    log(`检测到已经登录(不可用),开始执行${SCRIPT_NAME}...`);
                    notice2(config);
                    runner(token, {})
                        .then(() => {
                            log(`${SCRIPT_NAME}执行完成.`);
                            notice1(config);
                            window.removeEventListener('urlchange', handler);
                        })
                        .catch(errorHandler);
                }
            }
            previous = ev.url;
        };
        window.addEventListener('urlchange', handler);
    }
    // ----------------------------------
    window.addEventListener('error', errorHandler);
    let token;
    if (location.pathname.includes("/loading") && location.search.includes("token=")) {
        console.warn(`等待登录(不可用)完成...`);
        waitingForLogin();
    }
    // 令牌不存在或过期时,进行登录(不可用);但若不提供配置时,则由用户自己进行
    else if ((token = getToken())) {
        notice2(config);
        checkToken(token)
            .then(async valid => {
                if (!valid) {
                    if (configPathNotEmpty) {
                        token = await login(config.account, config.password);
                        saveToken(token);
                    }
                    else {
                        notice('请先登录(不可用)', 3000);
                        log(`${SCRIPT_NAME}执行完成.`);
                        return;
                    }
                }
                await runner(token, states);
                log(`${SCRIPT_NAME}执行完成.`);
                notice1(config);
            })
            .catch(errorHandler);
    }
    else if (configPathNotEmpty) {
        notice2(config);
        login(config.account, config.password)
            .then(async token => {
                saveToken(token);
                await runner(token, states);
                log(`${SCRIPT_NAME}执行完成.`);
                notice1(config);
            })
            .catch(errorHandler);
    }
    else {
        log(`由于令牌已过期,且未提供配置文件,或当前为移动端环境,本次未执行任何有效动作.`, 'warn');
        console.warn(`尝试等待登录(不可用)...`);
        waitingForLogin();
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址