在B站直播发送弹幕时,被吞的弹幕会被划线,蜀黍吞的会变红,主播吞的会变黄。
// ==UserScript==
// @name Bilibili Live Banned Danmaku Marker
// @name:zh-CN 哔哩哔哩直播 被吞弹幕标记
// @name:zh-TW 嗶哩嗶哩直播 烙賽彈幕標記
// @description You sent banned danmakus will be add strikethrough line.
// @description:zh-CN 在B站直播发送弹幕时,被吞的弹幕会被划线,蜀黍吞的会变红,主播吞的会变黄。
// @description:zh-TW 在B站直播發送彈幕時,被封鎖的彈幕會被劃線。
// @version 0.5
// @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';
function parseJson(t) {
if (!t || t.length === 0) {
return null
}
try {
return JSON.parse(t)
} catch (e) {
return null
}
}
function FetchHook(onResp, urlFilter, gThis) {
if (!gThis) {
gThis = window
}
const th1s = this
this.fetch = gThis.fetch
gThis.fetch = function (url) {
const prm = th1s.fetch.apply(this, arguments)
if (urlFilter && (typeof url !== 'string' || !urlFilter(url))) {
return prm
}
return prm.then((resp) => resp.text().then((t) => {
t = onResp(t, url, th1s.fetch)
resp.json = function () {
try {
return Promise.resolve(JSON.parse(t))
} catch (e) {
return Promise.reject(e)
}
}
resp.text = function () {
return Promise.resolve(t)
}
return resp
}))
}
const xhrPt = gThis.XMLHttpRequest.prototype
const xhrOpen = xhrPt.open
const xhrSend = xhrPt.send
this.newXMLHttpRequest = function () {
let xhr = new XMLHttpRequest()
xhr.open = xhrOpen
xhr.send = xhrSend
return xhr
}
xhrPt.open = function (method, url, async, user, password) {
if ((typeof url === 'string' && urlFilter(url)) || !urlFilter) {
this._fetchHookUrl = url
this._fetchHookAsync = async
}
return xhrOpen.apply(this, arguments)
}
const onreadystatechangeHook = function () {
if (this.readyState === 4 && this.status === 200) {
let newVal = onResp(this.responseText, this._fetchHookUrl, this.fetch)
if (newVal !== this.responseText) {
Object.defineProperty(this, 'responseText', {
value: newVal
})
}
}
if (!this._fetchHookOnreadystatechange) {
return
}
return this._fetchHookOnreadystatechange.apply(this, arguments)
}
xhrPt.send = function () {
if (!('_fetchHookUrl' in this)) {
return xhrSend.apply(this, arguments)
}
if (this._fetchHookAsync) {
this._fetchHookOnreadystatechange = this.onreadystatechange
this.onreadystatechange = onreadystatechangeHook
return xhrSend.apply(this, arguments)
}
const r = xhrSend.apply(this, arguments)
if (this.status === 200) {
let newVal = onResp(this.responseText, this._fetchHookUrl, this.fetch)
if (newVal !== this.responseText) {
Object.defineProperty(this, 'responseText', {
value: newVal
})
}
}
return r
}
}
function getContent(r) {
if (
r &&
(('msg' in r && (r.msg === 'f' || r.msg === 'k')) || ('message' in r && (r.message === 'f' || r.message === 'k'))) &&
'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 && !('_isMarked' in danmaku)) {
let danmakuItem = danmaku.parentElement
danmakuItem.style.textDecoration = 'line-through'
let clr = ((('msg' in r && r.msg === 'f') || ('message' in r && r.message === 'f'))) ? 'red' : '#f09300'
danmakuItem.style.color = clr
let userName = danmakuItem.querySelector('.user-name')
if (userName) {
userName.style.color = clr
}
danmaku._isMarked = true
return
}
}
setTimeout(lineThrough, 500)
})()
}
new FetchHook(
(t) => {
checkContent(parseJson(t))
return t
},
(url) => url.indexOf('api.live.bilibili.com/msg/send') >= 0,
unsafeWindow
)
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址