少前2bbs自动兑换物品脚本

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

当前为 2025-03-08 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         少前2bbs自动兑换物品脚本
// @namespace    http://tampermonkey.net/
// @version      1.0.1
// @description  一个简单的少前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: fixed; z-index: 1000; padding: 0 10px; top: -60px; right: 0; height: 60px; display: flex; align-items: center; color: white; font-size: 14px; transition: all 0.2s";
    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 })
        });
        try {
            return (await resp.json()).data.account.token;
        } catch (e) {
            throw e;
        }
    }
    // 获取现在到凌晨的秒数,作为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(1000);
            if (item.is_like) {
                resps.push(await like(token, topicId));
                await delay(1000);
            }
        }
        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(1000);
        }
        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(1000);
            }
        }
        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()}`;
        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 btn = document.querySelector('.btns .btn');
        const [img, span, i] = [...btn.children];
        if (img.src !== SIGNED_IMG) {
            img.src = SIGNED_IMG;
            span.innerText = "已签到";
            i.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;
        node.style = NOTIFICATION_STYLE;
        node.innerText = message;
        document.body.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路径跳转时,尝试获取令牌进行判断(不提供账号密码时才会调用该方法)
    function waitingForLogin() {
        log(waitingForLogin.name, 'warn');
        let previous = location.href;
        const handler = (ev) => {
            if (previous.endsWith('login')) {
                const token = getToken();
                if (token) {
                    log(`检测到用户已经登录,开始执行${SCRIPT_NAME}...`);
                    runner(token, {})
                        .then(() => {
                            log(`${SCRIPT_NAME}执行完成.`);
                        })
                        .catch(errorHandler);
                    window.removeEventListener('urlchange', handler);
                }
            }
            previous = ev.url;
        };
        if (window.onurlchange === null) {
            window.addEventListener('urlchange', handler);
        }
    }
    // ----------------------------------
    window.addEventListener('error', errorHandler);
    let token = getToken();
    // 令牌不存在或过期时,进行登录;但若不提供配置时,则由用户自己进行
    if (token) {
        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(`${SCRIPT_NAME}执行完成. 由于令牌已过期,且未提供配置文件,本次未执行任何有效动作.`, 'warn');
        console.warn(`尝试等待用户登录...`);
        waitingForLogin();
    }
})();