Greasy Fork

Greasy Fork is available in English.

微博超话自动签到

用户登录后进入微博主页,获取超级话题并自动签到

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name       微博超话自动签到
// @description  用户登录后进入微博主页,获取超级话题并自动签到
// @homepageURL  https://github.com/Deuscx/WB_SIGN_EXT
// @supportURL   https://github.com/Deuscx/WB_SIGN_EXT/issues
// @grant       none
// @version     2.0.4
// @author       deus
// @match        https://weibo.com/*
// @match        https://www.weibo.com/*
// @require     https://cdn.jsdelivr.net/npm/@violentmonkey/dom@1
// @require     https://cdn.jsdelivr.net/npm/@violentmonkey/[email protected]
// @require    https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js
// @namespace https://deuscx.github.io/
// ==/UserScript==
(function() {
    "use strict";
    var e = ".configContainer{display:flex;flex-direction:column;position:fixed;--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity));z-index:10;border-radius:.25rem;border-width:1px;--border-opacity:1;border-color:#cbd5e0;border-color:rgba(203,213,224,var(--border-opacity));padding:.75rem .5rem;max-width:190px;bottom:80px;right:0;transform:translateX(100%);transition-duration:.5s;transition-timing-function:cubic-bezier(.22,1,.36,1);transition-property:transform}.configContainer .cItem{font-size:.875rem;display:flex;justify-content:space-between;cursor:pointer}.configContainer .cItem .des{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}#TIMEOUT{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-block;width:60px}.configContainer .action{padding-top:.5rem;padding-bottom:.5rem;border-radius:.25rem;background-color:#fff;cursor:pointer;position:absolute;top:50%;left:0;transform:translate3d(-100%,-50%,0)}.configContainer .action:hover{color:#ccc}.active{transform:translateX(0)}";
    const t = (new Date).getTimezoneOffset() + 480;
    const n = Date.now;
    const isNewDay = e => {
        if (!e) return true;
        const n = new Date(e);
        n.setMinutes(n.getMinutes() + t);
        n.setHours(0, 0, 0, 0);
        const o = new Date;
        o.setMinutes(n.getMinutes() + t);
        return o - n > 864e5;
    };
    const o = function() {
        const set = function(e, t) {
            localStorage.setItem(e, JSON.stringify(t));
        };
        const get = function(e) {
            const t = localStorage.getItem(e);
            try {
                return JSON.parse(t);
            } catch (e) {
                return t;
            }
        };
        const remove = function(e) {
            localStorage.removeItem(e);
        };
        const has = function(e) {
            return Reflect.has(localStorage, e);
        };
        return {
            set: set,
            get: get,
            remove: remove,
            has: has
        };
    }();
    const r = (e => () => e++)(0);
    const a = "WB";
    const c = `${a}_SIGNED_ARR`;
    const s = "WB_CONFIG";
    const i = {
        SUCCESS: "success",
        ERROR: "error",
        INFO: "info",
        WARNING: "warning"
    };
    let u = o.get(s);
    function ConfigPanel() {
        const handleAutoSign = e => {
            const t = e.target.checked;
            const n = Object.assign({}, u, {
                AUTO_SIGN: t
            });
            u = n;
            o.set(s, u);
        };
        const handleShowToast = e => {
            const t = e.target.checked;
            const n = Object.assign({}, u, {
                SHOW_TOAST: t
            });
            u = n;
            o.set(s, u);
        };
        const handleTimeout = e => {
            const t = e.target.value;
            const n = Object.assign({}, u, {
                TIMEOUT: t
            });
            u = n;
            o.set(s, u);
        };
        const toggleClassList = () => {
            document.querySelector(".configContainer").classList.toggle("active");
        };
        return VM.createElement(VM.Fragment, null, VM.createElement("div", {
            className: "configContainer"
        }, VM.createElement("label", {
            htmlFor: "AUTO_SIGN",
            className: "cItem"
        }, VM.createElement("span", {
            className: "des"
        }, "自动签到"), VM.createElement("input", {
            id: "AUTO_SIGN",
            type: "checkbox",
            onInput: handleAutoSign,
            checked: u.AUTO_SIGN
        })), VM.createElement("label", {
            htmlFor: "SHOW_TOAST",
            className: "cItem"
        }, VM.createElement("span", {
            className: "des"
        }, "是否展示气泡"), VM.createElement("input", {
            id: "SHOW_TOAST",
            type: "checkbox",
            onInput: handleShowToast,
            checked: u.SHOW_TOAST
        })), VM.createElement("label", {
            htmlFor: "TIMEOUT",
            className: "cItem"
        }, VM.createElement("span", {
            className: "des"
        }, "气泡展示时间"), VM.createElement("input", {
            id: "TIMEOUT",
            type: "number",
            onInput: handleTimeout,
            min: "0",
            value: parseInt(u.TIMEOUT, 10),
            placeholder: "单位为毫秒"
        })), VM.createElement("div", {
            className: "action",
            onClick: toggleClassList
        }, "收放")), VM.createElement("style", null, e));
    }
    var l = ".msgContainer{position:fixed;background-color:initial;top:4rem;right:40px}@keyframes slide-in-right{0%{transform:translateX(1000px);opacity:0}to{transform:translateX(0);opacity:1}}@keyframes slide-out-right{0%{transform:translateX(0);opacity:1}to{transform:translateX(1000px);opacity:0}}.removing{animation:slide-out-right .5s cubic-bezier(.55,.085,.68,.53) both}.toastItem{background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity));border-width:1px;--border-opacity:1;border-color:#cbd5e0;border-color:rgba(203,213,224,var(--border-opacity));border-radius:.375rem;max-width:20rem;--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity));z-index:10;padding:1rem 1.5rem;cursor:pointer;--bg-opacity:1;background-color:#3182ce;background-color:rgba(49,130,206,var(--bg-opacity));opacity:.8;margin-bottom:.5rem;animation:slide-in-right .5s cubic-bezier(.25,.46,.45,.94) both}.toast-info{--bg-opacity:1;background-color:#63b3ed;background-color:rgba(99,179,237,var(--bg-opacity))}.toast-default{--bg-opacity:1;background-color:#3182ce;background-color:rgba(49,130,206,var(--bg-opacity))}.toast-success{--bg-opacity:1;background-color:#48bb78;background-color:rgba(72,187,120,var(--bg-opacity))}.toast-error{background-color:#ff5252}.toast-warning{--bg-opacity:1;background-color:#f6e05e;background-color:rgba(246,224,94,var(--bg-opacity))}";
    const m = 8;
    let d = 0;
    const innerToast = e => {
        const {content: t, type: n, timeout: o} = e;
        function remove() {
            const t = document.querySelector(`[data-tid='${e.id}']`);
            t.classList.add("removing");
            requestAnimationFrame((() => {
                t.parentNode.removeChild(t);
                d--;
            }));
        }
        o && setTimeout((() => {
            remove();
        }), o);
        return VM.createElement(VM.Fragment, null, VM.createElement("div", {
            "data-tid": e.id,
            className: `toastItem toast-${n}`,
            onClick: remove
        }, t));
    };
    const ToastContainer = () => VM.createElement("div", {
        className: "msgContainer"
    }, VM.createElement("style", null, l));
    const g = {
        type: i.INFO,
        timeout: 5e3
    };
    const toastFactory = () => {
        const e = ToastContainer();
        const t = document.body.appendChild(e);
        const toast = (e, n) => {
            if (!o.get(s).SHOW_TOAST) return;
            const a = Object.assign({}, g, {
                id: r()
            }, n, {
                content: e
            });
            if (d < m) {
                d++;
                t.appendChild(innerToast(a));
            }
        };
        toast.success = (e, t) => toast(e, Object.assign({}, t, {
            type: i.SUCCESS
        }));
        toast.error = (e, t) => toast(e, Object.assign({}, t, {
            type: i.ERROR
        }));
        toast.info = (e, t) => toast(e, Object.assign({}, t, {
            type: i.INFO
        }));
        toast.warn = (e, t) => toast(e, Object.assign({}, t, {
            type: i.WARNING
        }));
        return toast;
    };
    const p = toastFactory();
    const f = {
        AUTO_SIGN: true,
        SHOW_TOAST: true,
        TIMEOUT: 1e3
    };
    const b = axios.create({
        baseURL: "https://weibo.com/",
        timeout: 1e3 * 5
    });
    b.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
    b.interceptors.request.use((e => e), (e => Promise.error(e)));
    b.interceptors.response.use((e => e.status === 200 ? Promise.resolve(e) : Promise.reject(e)), (e => {
        const {response: t} = e;
        if (t) {
            console.log("发送请求失败", t);
            return Promise.reject(t);
        }
        if (!window.navigator.onLine) console.error("断网"); else return Promise.reject(e);
    }));
    class BaseFeature {
        constructor({name: e}) {
            this.launch = () => {};
            this.name = e;
        }
        get store() {
            const e = o.get(this.name);
            if (e) return e;
            o.set(this.name, void 0);
            return;
        }
        set store(e) {
            o.set(this.name, e);
        }
        init() {
            return new Promise(((e, t) => {
                try {
                    this.launch();
                    e(this);
                } catch (e) {
                    console.log(`run ${this.name} error`);
                    t(e);
                }
            }));
        }
    }
    function isCheck() {
        return o.get("isCheck") || false;
    }
    const h = o.get("lastCheck");
    const signInterestAPI = e => b({
        url: "p/aj/general/button",
        params: {
            ajwvr: 6,
            api: "http://i.huati.weibo.com/aj/super/checkin",
            texta: encodeURI("签到"),
            textb: encodeURI("已签到"),
            status: 0,
            id: e,
            __rnd: (new Date).getTime()
        }
    });
    let y = o.get(c) || [];
    const signInterest = ({id: e, name: t}) => new Promise(((r, a) => {
        signInterestAPI(e).then((e => {
            const {data: s} = e;
            if (s.code === "100000") {
                window.toast.success(`[${t}签到成功]${s.msg} ---${s.data.alert_title}`);
                o.set("lastCheck", n());
                y.push(t);
                y = Array.from(new Set(y));
                o.set(c, y);
            } else {
                window.toast.warn(`[${t}超话签到]${s.msg}`);
                if (s.code !== 382004) a("error"); else {
                    o.set("lastCheck", n());
                    y.push(t);
                    y = Array.from(new Set(y));
                    o.set(c, y);
                }
            }
            r();
        }), (e => {
            a(e);
            window.toast.error(`[${t}超话签到]签到失败,请检查网络`);
        }));
    }));
    function delay(e) {
        return new Promise((t => setTimeout(t, e)));
    }
    function getInterestNameAId(e = 1) {
        return new Promise(((t, n) => {
            b({
                url: `ajax/profile/topicContent?tabid=231093_-_chaohua&page=${e}`
            }).then((o => {
                const {data: {data: r, ok: a}} = o;
                if (a !== 1) n({
                    err: "获取关注超话失败",
                    data: r
                });
                const c = r.list;
                const s = r.max_page;
                function extractId(e) {
                    return e.slice(5);
                }
                const i = c.map((({oid: e, topic_name: t}) => ({
                    id: extractId(e),
                    name: t
                })));
                if (e < s) getInterestNameAId(e + 1).then((e => {
                    t(i.concat(e));
                })); else t(i);
            }), (e => {
                console.error(`[${a}]`, e);
                n("获取hash失败");
            }));
        }));
    }
    class PromiseQueue {
        constructor({concurrency: e = 1, timeout: t = 0} = {}) {
            this.queue = [];
            this.running = 0;
            this.concurrency = e;
            this.timeout = t;
        }
        add(e) {
            return new Promise(((t, n) => {
                const wrappedFn = async () => {
                    try {
                        const n = e();
                        await delay(this.timeout);
                        const o = await n;
                        t(o);
                    } catch (e) {
                        n(e);
                    } finally {
                        this.running--;
                        this.processQueue();
                    }
                };
                this.queue.push(wrappedFn);
                this.processQueue();
            }));
        }
        processQueue() {
            while (this.running < this.concurrency && this.queue.length > 0) {
                this.running++;
                const e = this.queue.shift();
                e();
            }
        }
    }
    class Interest extends BaseFeature {
        constructor() {
            super({
                name: s
            });
            this.launch = async () => {
                const e = super.store;
                if (!e.AUTO_SIGN) return;
                if (isCheck() && !isNewDay(h)) {
                    window.toast.info("今日已签到");
                    return;
                }
                if (isNewDay(h)) {
                    o.remove(c);
                    o.set("isCheck", false);
                }
                let t = await getInterestNameAId();
                const n = o.get(c);
                if (n && n.length) t = t.filter((e => !n.includes(e.name)));
                const r = new PromiseQueue({
                    concurrency: 1,
                    timeout: 500
                });
                for (const {name: e, id: n} of t) await r.add((() => signInterest({
                    id: n,
                    name: e
                })));
                o.set("isCheck", true);
            };
        }
        run() {
            this.init().then((e => {}));
        }
    }
    var w = new Interest;
    function initConfig() {
        if (!o.get(s)) o.set(s, f);
    }
    function initDOM() {
        return new Promise(((e, t) => {
            try {
                const e = ConfigPanel();
                document.body.appendChild(e);
            } catch (e) {
                throw new Error("初始化DOM失败");
            }
        }));
    }
    function BaseInit() {
        initConfig();
        window.toast = p;
    }
    function OtherInit() {
        initDOM();
    }
    function main() {
        BaseInit();
        OtherInit();
        w.run();
    }
    main();
})();