B站直播间自动抢天选和自动跟风combo弹幕

自动点击天选、自动跟风发送combo弹幕,可以配置是否需要关注才执行,默认需要关注,有直播间黑名单功能

当前为 2024-09-01 提交的版本,查看 最新版本

// ==UserScript==
// @name         B站直播间自动抢天选和自动跟风combo弹幕
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @description  自动点击天选、自动跟风发送combo弹幕,可以配置是否需要关注才执行,默认需要关注,有直播间黑名单功能
// @author       ltxlong
// @match        *://live.bilibili.com/1*
// @match        *://live.bilibili.com/2*
// @match        *://live.bilibili.com/3*
// @match        *://live.bilibili.com/4*
// @match        *://live.bilibili.com/5*
// @match        *://live.bilibili.com/6*
// @match        *://live.bilibili.com/7*
// @match        *://live.bilibili.com/8*
// @match        *://live.bilibili.com/9*
// @match        *://live.bilibili.com/blanc/1*
// @match        *://live.bilibili.com/blanc/2*
// @match        *://live.bilibili.com/blanc/3*
// @match        *://live.bilibili.com/blanc/4*
// @match        *://live.bilibili.com/blanc/5*
// @match        *://live.bilibili.com/blanc/6*
// @match        *://live.bilibili.com/blanc/7*
// @match        *://live.bilibili.com/blanc/8*
// @match        *://live.bilibili.com/blanc/9*
// @icon         https://www.bilibili.com/favicon.ico
// @require      https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js
// @grant        unsafeWindow
// @grant        GM_registerMenuCommand
// @license      GPL-3.0-or-later

// ==/UserScript==
(function() {
    'use strict';

    let live_player_div = document.getElementById('live-player');
    if (!live_player_div) { return; }

    let room_id = unsafeWindow.location.pathname.split('/').pop();

    let room_url_api = 'https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=';
    let room_fetch_url = room_url_api + room_id;

    let follow_api = 'https://api.bilibili.com/x/relation?fid=';
    let live_room_up_uid = 0; // 主播的uid,查询关注关系用

    let dm_send_api = 'https://api.live.bilibili.com/msg/send';
    let u_frsc = document.cookie.split(';').map(c=>c.trim()).filter(c => c.startsWith('bili_jct='))[0].split('bili_jct=')[1]; // 发送弹幕用
    let combo_dm_recent_send_arr = []; // 已经跟风发送的combo弹幕,发送后,30秒剔除
    let auto_dm_send_last_rnd = 0; // 上一次跟风发送combo弹幕的时间s,用于判断至少间隔20秒才再次查询关注
    let last_follow_check_flag = false; // 上一次查询关注结果
    let combo_dm_send_fail_arr = []; // 发送失败的combo弹幕,用于再次发送判断,失败10秒后或者发送成功后剔除

    let flag_isFullscreen = false;

    let live_auto_tianxuan_follow_flag = true; // 是否关注了的主播才自动天选

    let live_auto_dm_combo_follow_flag = true; // 是否关注了的主播才自动跟风

    function check_blacklist_menu(room_id) {
        let auto_room_black_list_json = unsafeWindow.localStorage.getItem('live_auto_room_blacklist');
        if (auto_room_black_list_json === null || auto_room_black_list_json === 'null' || auto_room_black_list_json === '[]' || auto_room_black_list_json === '') {
            // 显示加入黑名单
            GM_registerMenuCommand('点击将当前直播房间加入黑名单', function() {
                unsafeWindow.localStorage.setItem('live_auto_room_blacklist', JSON.stringify([room_id]));
                alert("当前直播房间已加入黑名单,刷新页面生效!");
                unsafeWindow.location.reload();
            });

            return true;
        } else {
            let auto_room_black_list = JSON.parse(auto_room_black_list_json);
            if (auto_room_black_list.includes(room_id)) {
                // 显示移除黑名单
                GM_registerMenuCommand('当前直播房间已加入黑名单,点击移出黑名单', function() {
                    auto_room_black_list = auto_room_black_list.filter(item => item !== room_id);
                    unsafeWindow.localStorage.setItem('live_auto_room_blacklist', JSON.stringify(auto_room_black_list));
                    alert("当前直播房间已除出黑名单,刷新页面生效!");
                    unsafeWindow.location.reload();
                });

                return false;
            } else {
                // 显示加入黑名单
                GM_registerMenuCommand('点击将当前直播房间加入黑名单', function() {
                    auto_room_black_list.push(room_id);
                    unsafeWindow.localStorage.setItem('live_auto_room_blacklist', JSON.stringify(auto_room_black_list));
                    alert("当前直播房间已加入黑名单,刷新页面生效!");
                    unsafeWindow.location.reload();
                });

                return true;
            }
        }
    }

    if (!check_blacklist_menu(room_id)) { return; }

    function check_follow_tianxuan_config_menu() {
        let live_auto_tianxuan_follow_flag_get = unsafeWindow.localStorage.getItem('live_auto_tianxuan_follow_flag');
        if (live_auto_tianxuan_follow_flag_get === null || live_auto_tianxuan_follow_flag_get === 'null' || live_auto_tianxuan_follow_flag_get === '') {
            // 显示取消必须关注才生效
            GM_registerMenuCommand('点击设置不需要关注也自动抢天选(现在需要)', function() {

                unsafeWindow.localStorage.setItem('live_auto_tianxuan_follow_flag', 'false');

                live_auto_tianxuan_follow_flag = false;

                alert("已成功设置不需要关注主播也自动抢天选!");

                unsafeWindow.location.reload();
            });

        } else {

            if (live_auto_tianxuan_follow_flag_get === 'true') {
                // 显示取消必须关注才生效
                GM_registerMenuCommand('点击设置不需要关注也自动抢天选(现在需要)', function() {

                    unsafeWindow.localStorage.setItem('live_auto_tianxuan_follow_flag', 'false');

                    live_auto_tianxuan_follow_flag = false;

                    alert("已成功设置不需要关注主播也自动抢天选!");

                    unsafeWindow.location.reload();
                });

                live_auto_tianxuan_follow_flag = true;

            } else {
                // 显示必须关注才生效
                GM_registerMenuCommand('点击设置需要关注才会自动抢天选(现在不需要)', function() {

                    unsafeWindow.localStorage.setItem('live_auto_tianxuan_follow_flag', 'true');

                    live_auto_tianxuan_follow_flag = true;

                    alert("已成功设置需要关注主播才会自动抢天选!");

                    unsafeWindow.location.reload();
                });

                live_auto_tianxuan_follow_flag = false;
            }
        }
    }

    check_follow_tianxuan_config_menu();

    function check_follow_dm_combo_config_menu() {
        let live_auto_dm_combo_follow_flag_get = unsafeWindow.localStorage.getItem('live_auto_dm_combo_follow_flag');
        if (live_auto_dm_combo_follow_flag_get === null || live_auto_dm_combo_follow_flag_get === 'null' || live_auto_dm_combo_follow_flag_get === '') {
            // 显示取消必须关注才生效
            GM_registerMenuCommand('点击设置不需要关注也自动跟风combo弹幕(现在需要)', function() {

                unsafeWindow.localStorage.setItem('live_auto_dm_combo_follow_flag', 'false');

                live_auto_dm_combo_follow_flag = false;

                alert("已成功设置不需要关注主播也自动跟风combo弹幕!");

                unsafeWindow.location.reload();
            });

        } else {

            if (live_auto_dm_combo_follow_flag_get === 'true') {
                // 显示取消必须关注才生效
                GM_registerMenuCommand('点击设置不需要关注也自动跟风combo弹幕(现在需要)', function() {

                    unsafeWindow.localStorage.setItem('live_auto_dm_combo_follow_flag', 'false');

                    live_auto_dm_combo_follow_flag = false;

                    alert("已成功设置不需要关注主播也自动跟风combo弹幕!");

                    unsafeWindow.location.reload();
                });

                live_auto_dm_combo_follow_flag = true;

            } else {
                // 显示必须关注才生效
                GM_registerMenuCommand('点击设置需要关注才会自动跟风combo弹幕(现在不需要)', function() {

                    unsafeWindow.localStorage.setItem('live_auto_dm_combo_follow_flag', 'true');

                    live_auto_dm_combo_follow_flag = true;

                    alert("已成功设置需要关注主播才会自动跟风combo弹幕!");

                    unsafeWindow.location.reload();
                });

                live_auto_dm_combo_follow_flag = false;
            }
        }
    }

    check_follow_dm_combo_config_menu();

    function roominfo_get_upuid_fetch() {
        // 获取room消息,并且解析出up_uid
        return fetch(room_fetch_url).then(response => {
            return response.json();
        }).then(ret => {
            if (ret.code === 0) {
                live_room_up_uid = ret.data?.room_info?.uid || 0;
            }

            return live_room_up_uid;
        }).catch(error => {
            return live_room_up_uid;
        });
    }

    // 返回true-已关注,false-未关注。需要.then()链式调用获取结果
    function get_follow_up_flag() {
        if (live_room_up_uid === 0) {
            roominfo_get_upuid_fetch().then(the_live_room_up_uid => {
                live_room_up_uid = the_live_room_up_uid;
            });
        }

        return fetch(follow_api + live_room_up_uid, {
            credentials: 'include'
        }).then(response => {
            return response.json();
        }).then(ret => {
            if (ret.code === 0 && ret.data.attribute !== 0 && ret.data.attribute !== 128) {
                return true;
            } else {
                return false;
            }
        }).catch(error => {
            return false;
        });
    }

    function close_and_remove_tip_modal() {
        // 关闭模态框
        $(document).find('.auto_tip_mod').hide();

        // 从 body 中移除模态框
        $(document).find('.auto_tip_mod').remove();
    }

    function open_and_close_tip_modal(show_str, show_color) {

        let auto_tip_modal = document.createElement('div');
        auto_tip_modal.className = 'auto_tip_mod';
        auto_tip_modal.style.position = 'fixed';
        auto_tip_modal.style.display = 'none';
        auto_tip_modal.style.color = show_color;
        auto_tip_modal.style.textAlign = 'center';
        auto_tip_modal.style.backgroundColor = '#ffffff';
        auto_tip_modal.style.border = 0;
        auto_tip_modal.style.boxShadow = '0 0 3px rgba(0, 0, 0, 0.3)';
        auto_tip_modal.innerHTML = show_str;
        auto_tip_modal.style.zIndex = 3333;

        auto_tip_modal.style.borderRadius = '10px';
        auto_tip_modal.style.padding = '10px';
        auto_tip_modal.style.left = unsafeWindow.innerWidth / 2 + 'px';
        auto_tip_modal.style.top = unsafeWindow.innerHeight / 2 + 'px';

        if (flag_isFullscreen) {
            $(document).find('#live-player').append(auto_tip_modal);
        } else {
            document.body.appendChild(auto_tip_modal);
        }

        // 显示模态框
        auto_tip_modal.style.display = 'block';

        // 在一定时间后关闭并删除模态框
        setTimeout(() => {
            close_and_remove_tip_modal();
        }, 1500);
    }

    // 自动天选
    function auto_tianxuan_handle(the_sc_follow_up_flag) {
        setTimeout(() => {
            let the_anchor_box_iframe_obj = $('#anchor-guest-box-id iframe').contents();
            let the_click_btn = the_anchor_box_iframe_obj.find('#app .participation-box .particitation-btn img.btn-name');
            let the_close_btn = the_anchor_box_iframe_obj.find('#app .participation-box .close-btn');

            let the_anchor_auto_joinTimeout;
            let the_anchor_auto_closeTimeout;

            if (the_sc_follow_up_flag && the_click_btn.length) {

                clearTimeout(the_anchor_auto_joinTimeout);
                clearTimeout(the_anchor_auto_closeTimeout);

                // 延时2s后
                the_anchor_auto_joinTimeout = setTimeout(() => {
                    the_click_btn.trigger('click');

                    open_and_close_tip_modal('成功自动点击天选 ✓', '#A7C9D3');

                }, 2000);

                // 延时2s后
                the_anchor_auto_closeTimeout = setTimeout(() => {
                    the_close_btn.trigger('click');
                }, 2000);
            }
        }, 1000); // 等渲染完成
    }

    // 发送弹幕
    function send_dm_fetch(msg, rnd) {

        return fetch(dm_send_api, {
            method: 'POST',
            credentials: 'include',
            headers: {
                'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
            },
            body: `color=16777215&fontsize=25&mode=1&msg=${msg}&rnd=${rnd}&roomid=${room_id}&csrf=${u_frsc}`
        }).then(response => {
            return response.json();
        }).then(ret => {

            if (ret.code === 0) {
                return true;
            } else {
                return false;
            }
        }).catch(error => {
            return false;
        });
    }

    function to_dm_fetch(the_combo_dm_msg, the_time_rnd) {

        send_dm_fetch(the_combo_dm_msg, the_time_rnd).then(the_dm_send_flag => {

            if (the_dm_send_flag) {
                // 定时、剔除(相同的combo弹幕相隔30秒)
                setTimeout(() => {
                    combo_dm_recent_send_arr = combo_dm_recent_send_arr.filter(dm_item => dm_item !== the_combo_dm_msg);
                    combo_dm_send_fail_arr = combo_dm_send_fail_arr.filter(dm_item => dm_item !== the_combo_dm_msg);
                }, 30 * 1000);

            } else {

                if (combo_dm_send_fail_arr.includes(the_combo_dm_msg)) {
                    // 连续两次发送失败,10s后再给机会
                    setTimeout(() => {
                        combo_dm_recent_send_arr = combo_dm_recent_send_arr.filter(dm_item => dm_item !== the_combo_dm_msg);
                        combo_dm_send_fail_arr = combo_dm_send_fail_arr.filter(dm_item => dm_item !== the_combo_dm_msg);
                    }, 10 * 1000);

                } else {
                    combo_dm_recent_send_arr = combo_dm_recent_send_arr.filter(dm_item => dm_item !== the_combo_dm_msg);
                    combo_dm_send_fail_arr.push(the_combo_dm_msg);
                }
            }
        });
    }

    // 自动跟风发送combo弹幕
    function auto_dm_combo_handle(parsedArr_info) {

        const the_combo_dm_msg = parsedArr_info[1];

        // 因有时候combo弹幕会额外的带 x/×/X数字结尾,故过滤掉
        if (!/[x×X]\d+$/.test(the_combo_dm_msg)) {

            combo_dm_recent_send_arr.push(the_combo_dm_msg);

            const the_time_rnd = parseInt((new Date).getTime() / 1000);

            // 查询关注至少相隔20s(10s好像太少,30s又太多,那就20s吧)
            if (the_time_rnd - auto_dm_send_last_rnd > 20) {

                if (live_auto_dm_combo_follow_flag) {
                    get_follow_up_flag().then(the_sc_follow_up_flag => {

                        auto_dm_send_last_rnd = the_time_rnd;
                        last_follow_check_flag = the_sc_follow_up_flag;

                        if (the_sc_follow_up_flag) {
                            to_dm_fetch(the_combo_dm_msg, the_time_rnd);
                        }
                    });
                } else {
                    to_dm_fetch(the_combo_dm_msg, the_time_rnd);
                }

            } else {

                if (live_auto_dm_combo_follow_flag) {
                    if (last_follow_check_flag) {
                        to_dm_fetch(the_combo_dm_msg, the_time_rnd);
                    }
                } else {
                    to_dm_fetch(the_combo_dm_msg, the_time_rnd);
                }
            }
        }
    }

    function sc_handleFullscreenChange() {
        if (document.fullscreenElement ||
            document.webkitFullscreenElement ||
            document.mozFullScreenElement ||
            document.msFullscreenElement) {

            flag_isFullscreen = true;
        } else {
            flag_isFullscreen = false;
        }
    }

    live_player_div.addEventListener('fullscreenchange', sc_handleFullscreenChange);
    live_player_div.addEventListener('webkitfullscreenchange', sc_handleFullscreenChange);
    live_player_div.addEventListener('mozfullscreenchange', sc_handleFullscreenChange);
    live_player_div.addEventListener('MSFullscreenChange', sc_handleFullscreenChange);

    roominfo_get_upuid_fetch().then(the_live_room_up_uid => {

        live_room_up_uid = the_live_room_up_uid;

        setTimeout(() => {
            if (live_auto_tianxuan_follow_flag) {
                get_follow_up_flag().then(the_sc_follow_up_flag => {
                    let the_anchor_before_obj = $(document).find('#gift-control-vm .anchor-lottery-entry');

                    if (the_sc_follow_up_flag && the_anchor_before_obj.length) {
                        the_anchor_before_obj.trigger('click'); // 若已关注,并且已经存在天选,则先触发点击,展开天选弹窗

                        auto_tianxuan_handle(the_sc_follow_up_flag);
                    }
                });

            } else {
                let the_anchor_before_obj = $(document).find('#gift-control-vm .anchor-lottery-entry');

                if (the_anchor_before_obj.length) {
                    the_anchor_before_obj.trigger('click'); // 若已关注,并且已经存在天选,则先触发点击,展开天选弹窗

                    auto_tianxuan_handle(true);
                }
            }
        }, 3000); // 等渲染完成
    });

    const original_parse = JSON.parse;
    JSON.parse = function (str) {
        try {
            const parsed_arr = original_parse(str);
            if (parsed_arr && parsed_arr.cmd !== undefined) {
                if (parsed_arr.cmd === 'DANMU_MSG') {
                    if (parsed_arr.info && parsed_arr.info[0][15]['extra'].includes('"hit_combo\":1') && !combo_dm_recent_send_arr.includes(parsed_arr.info[1])) {
                        auto_dm_combo_handle(parsed_arr.info);
                    }

                } else if (parsed_arr.cmd === 'ANCHOR_LOT_START') {
                    if (live_auto_tianxuan_follow_flag) {
                        get_follow_up_flag().then(the_sc_follow_up_flag => {
                            auto_tianxuan_handle(the_sc_follow_up_flag);
                        });
                    } else {
                        auto_tianxuan_handle(true);
                    }
                }
            }

            return parsed_arr;
        } catch (error) {
            throw error;
        }
    };

})();

QingJ © 2025

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