Greasy Fork

Greasy Fork is available in English.

哔哩哔哩直播 被吞敏感弹幕 标记提示

在B站直播发送弹幕时,被吞的弹幕会被标红并划线。

当前为 2022-10-21 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name                Bilibili Live Banned Danmaku Marker
// @name:zh-CN          哔哩哔哩直播 被吞敏感弹幕 标记提示
// @name:zh-TW          嗶哩嗶哩直播 烙賽封鎖彈幕 標記小幫手
// @description         When sending a danmaku, the banned danmaku will be marked red and add strikethrough line.
// @description:zh-CN   在B站直播发送弹幕时,被吞的弹幕会被标红并划线。
// @description:zh-TW   在B站直播發送彈幕時,被封鎖的彈幕會被標紅並劃線。
// @version             0.1
// @author              Yulon
// @namespace           https://github.com/yulon
// @icon                https://www.bilibili.com/favicon.ico
// @license             MIT
// @match               *://live.bilibili.com/*
// @grant               unsafeWindow
// @run-at              document-start
// ==/UserScript==

(function() {
    'use strict';

    var xhrPt = unsafeWindow.XMLHttpRequest.prototype
    const xhrPtOpen = xhrPt.open
    const xhrPtSend = xhrPt.send

    function parseJson(t) {
        if (!t || t.length === 0) {
            return null
        }
        try {
            return JSON.parse(t)
        } catch (e) {
            return null
        }
    }

    function getContent(r) {
        if (
            r &&
            (('msg' in r && r.msg === 'f') || ('message' in r && r.message === 'f')) &&
            'data' in r && 'mode_info' in r.data && 'extra' in r.data.mode_info
        ) {
            const extra = parseJson(r.data.mode_info.extra)
            if (extra && 'content' in extra) {
                return extra.content
            }
        }
        return null
    }

    function checkContent(r) {
        const cont = getContent(r)
        if (!cont) {
            return
        }
        ;(function lineThrough() {
            const danmakus = document.querySelectorAll('#chat-items .danmaku-item-right')
            for (let danmaku of danmakus) {
                if (danmaku.innerText === cont) {
                    const danmakuItem = danmaku.parentElement
                    danmakuItem.style.textDecoration = 'line-through'
                    danmakuItem.style.color = 'red'
                    const userName = danmakuItem.querySelector('.user-name')
                    if (userName) {
                        userName.style.color = 'red'
                    }
                    return
                }
            }
            setTimeout(lineThrough, 500)
        })()
    }

    xhrPt.open = function(method, url, async, user, password) {
        this._isSendDanmaku = url.endsWith('api.live.bilibili.com/msg/send')
        return xhrPtOpen.apply(this, arguments)
    }

    const onreadystatechangeHook = function() {
        if (this.readyState === 4 && this.status === 200) {
			checkContent(parseJson(this.responseText))
		}
        return this._original_onreadystatechange.apply(this, arguments)
    }

    xhrPt.send = function() {
        if ('_isSendDanmaku' in this && this._isSendDanmaku) {
            this._original_onreadystatechange = this.onreadystatechange
            this.onreadystatechange = onreadystatechangeHook
        }
        return xhrPtSend.apply(this, arguments)
    }

    const fetch = unsafeWindow.fetch

    unsafeWindow.fetch = function(url) {
        const prm = fetch.apply(this, arguments)
        if (!url.endsWith('api.live.bilibili.com/msg/send')) {
            return prm
        }
        return prm.then((resp) => {
            return resp.json().then((r) => {
                checkContent(r)
                resp.json = function() {
                    return Promise.resolve(r)
                }
                resp.text = function() {
                    return Promise.resolve(JSON.stringify(r))
                }
                return resp
            })
        })
    }
})();