Greasy Fork is available in English.

B站直播间定时发随机弹幕

定时发送;凌晨打卡;设置随机弹幕;弹幕分组管理;各直播间弹幕互不干扰;无人值守参与、关闭天选时刻;直播间防休眠;隐藏模块简化直播间

// ==UserScript==
// @name            B站直播间定时发随机弹幕
// @namespace       https://live.bilibili.com/暂无主页
// @home            https://github.com/Gamyou/bilibili-live-random-send
// @update          https://greasyfork.org/scripts/446725-b%E7%AB%99%E7%9B%B4%E6%92%AD%E9%97%B4%E5%AE%9A%E6%97%B6%E5%8F%91%E9%9A%8F%E6%9C%BA%E5%BC%B9%E5%B9%95/code/B%E7%AB%99%E7%9B%B4%E6%92%AD%E9%97%B4%E5%AE%9A%E6%97%B6%E5%8F%91%E9%9A%8F%E6%9C%BA%E5%BC%B9%E5%B9%95.user.js
// @download        https://greasyfork.org/scripts/446725-b%E7%AB%99%E7%9B%B4%E6%92%AD%E9%97%B4%E5%AE%9A%E6%97%B6%E5%8F%91%E9%9A%8F%E6%9C%BA%E5%BC%B9%E5%B9%95/code/B%E7%AB%99%E7%9B%B4%E6%92%AD%E9%97%B4%E5%AE%9A%E6%97%B6%E5%8F%91%E9%9A%8F%E6%9C%BA%E5%BC%B9%E5%B9%95.user.js
// @version         2.4.7
// @description     定时发送;凌晨打卡;设置随机弹幕;弹幕分组管理;各直播间弹幕互不干扰;无人值守参与、关闭天选时刻;直播间防休眠;隐藏模块简化直播间
// @author          Gamyou
// @match           *://live.bilibili.com/*
// @icon            https://www.bilibili.com/favicon.ico
// @license         Apache License, Version 2.0
// @run-at          document-idle
// @grant           GM_getValue
// @grant           GM_setValue
// @grant           GM_deleteValue
// @grant           GM_notification
// @note            24-01-07 2.4.7      指定组件最新版本进行获取
// @note            23-12-14 2.4.6      优化组件更新操作
// @note            23-10-21 2.4.5      替换CDN
// @note            23-07-13 2.4.4      迁移脚本
// ==/UserScript==


window.onload = (function () {
    const pdata = {
            signText: "打卡",
            version: "2.4.7",
            defaultKey: "danmu",
            configKey: "config",
            moduleId: "randomSendModule",
            moduleStatus: 0,
            moduleUrl: "https://gcore.jsdelivr.net/gh/gamyou/bilibili-live-random-send@latest/prod/bilibili-live-random-send.js"
        },
        getValue = (key, defaultVaue) => {
            if (!key) { key = pdata.defaultKey; }
            let data = GM_getValue(key, defaultVaue);
            return data ? data : GM_getValue(pdata.defaultKey);
        },
        setValue = (key, obj) => {
            if (!key) { key = pdata.defaultKey; }
            if (obj) { GM_setValue(key, obj); }
        },
        delValue = (key) => {
            if (key) { GM_deleteValue(key); }
        },
        notice = (msg) => {
            if (msg) { GM_notification(msg); }
            else { console.warn('消息对象为空,无效通知'); }
        },
        getVersion = txt => {
            let m = txt.match(/@version\s+\d+\.\d+\.\d+/i);
            if (!m || 1 > m.length || !m[0]) {
                return 0;
            }

            let n = m[0].match(/\d+\.\d+\.\d+/);
            if (!n || 1 > n.length || !n[0]) {
                return 0;
            }

            return n[0];
        },
        init = () => {
            setGmNotice(notice);
            setGmGetValue(getValue);
            setGmSetValue(setValue);
            setGmDelValue(delValue);
            setParentData(pdata);
            runStart();
        },
        create = (txtModule) => {
            let script = document.getElementById(pdata.moduleId);
            if (!script) {
                if (!txtModule) {
                    let config = getValue(pdata.configKey, null);
                    if (!config || !config.script) {
                        return;
                    }
    
                    txtModule = config.script;
                }

                script = document.createElement('script');
                script.id = pdata.moduleId;
                script.type = 'text/javascript';
                script.text = txtModule;
                document.head.appendChild(script);
                init();
            }
        },
        update = () => {
            let config = getValue(pdata.configKey, null);
            const nowDate = new Date().toLocaleDateString() + "/" + new Date().getHours();
            if (!config) { config = {}; }
            if (nowDate != config.lastUpdate) {
                if (1 === pdata.moduleStatus) {
                    return;
                }
                
                pdata.moduleStatus = 1;
                console.log('===> 进行组件更新,最后更新时间:' + config.lastUpdate);
                const controller = new AbortController();
                const promise = fetch(pdata.moduleUrl, { method: 'GET', signal: controller.signal, cache: 'no-store' });
                const requestTimer = setTimeout(() => controller.abort(), 20e3);
                promise.then(response => {
                        if (response.ok) {
                            return response.text();
                        }
                    }).then(txt => {
                        if (txt) {
                            if (requestTimer) {clearTimeout(requestTimer);}
                            create(txt);
                            config.script = txt;
                            config.moduleVersion = getVersion(txt);
                            config.lastUpdate = nowDate;
                            setValue(pdata.configKey, config);
                            pdata.moduleStatus = 2;
                            console.log('===> 组件更新完成');
                        }
                    }).catch(error => {
                        pdata.moduleStatus = 0;
                        console.warn('===> 网络请求超时,或其它报错', error);
                    });
            } else {
                pdata.moduleStatus = 2;
            }
        };



    create();
    let t = setInterval(() => {
        try {
            switch (pdata.moduleStatus) {
                case 0:
                    update();
                    break;
                case 2:
                    pdata.moduleStatus = 1;
                    create();
                    pdata.moduleStatus = 3;
                    break;
                case 3:
                    pdata.moduleStatus = 1;
                    checkVersion();
                    pdata.moduleStatus = 4;
                    clearInterval(t);
                    t = null;
                    break;
            }
        } catch (e) {
            pdata.moduleStatus = 0;
            console.warn('===> 组件加载失败', e);
        }
    }, 1.5e3);
})();