// ==UserScript== // @name 哔哩发评反诈-beta // @namespace http://tampermonkey.net/ // @version beta-20260226 // @description 评论发送后自动检测状态,避免被发送成功的谎言所欺骗! // @author freedom-introvert & ChatGPT // @match https://*.bilibili.com/* // @run-at document-idle // @grant none // @license GPL // @noframes // ==/UserScript== (function () { "use strict"; class WbiSign { constructor() { this.mixinKeyEncTab =[ 46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11, 36, 20, 34, 44, 52, ]; } getMixinKey = (orig) => this.mixinKeyEncTab .map((n) => orig[n]) .join("") .slice(0, 32); encWbi(params, img_key, sub_key) { const mixin_key = this.getMixinKey(img_key + sub_key), curr_time = Math.round(Date.now() / 1000), chr_filter = /[!'()*]/g; Object.assign(params, { wts: curr_time }); const query = Object.keys(params) .sort() .map((key) => { const value = params[key].toString().replace(chr_filter, ""); return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; }) .join("&"); const wbi_sign = SparkMD5.hash(query + mixin_key); return query + "&w_rid=" + wbi_sign; } } const SparkMD5 = (function () { "use strict"; var add32 = function (a, b) { return (a + b) & 0xffffffff; }, hex_chr =[ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", ]; function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a += (((b & c) | (~b & d)) + k[0] - 680876936) | 0; a = (((a << 7) | (a >>> 25)) + b) | 0; d += (((a & b) | (~a & c)) + k[1] - 389564586) | 0; d = (((d << 12) | (d >>> 20)) + a) | 0; c += (((d & a) | (~d & b)) + k[2] + 606105819) | 0; c = (((c << 17) | (c >>> 15)) + d) | 0; b += (((c & d) | (~c & a)) + k[3] - 1044525330) | 0; b = (((b << 22) | (b >>> 10)) + c) | 0; a += (((b & c) | (~b & d)) + k[4] - 176418897) | 0; a = (((a << 7) | (a >>> 25)) + b) | 0; d += (((a & b) | (~a & c)) + k[5] + 1200080426) | 0; d = (((d << 12) | (d >>> 20)) + a) | 0; c += (((d & a) | (~d & b)) + k[6] - 1473231341) | 0; c = (((c << 17) | (c >>> 15)) + d) | 0; b += (((c & d) | (~c & a)) + k[7] - 45705983) | 0; b = (((b << 22) | (b >>> 10)) + c) | 0; a += (((b & c) | (~b & d)) + k[8] + 1770035416) | 0; a = (((a << 7) | (a >>> 25)) + b) | 0; d += (((a & b) | (~a & c)) + k[9] - 1958414417) | 0; d = (((d << 12) | (d >>> 20)) + a) | 0; c += (((d & a) | (~d & b)) + k[10] - 42063) | 0; c = (((c << 17) | (c >>> 15)) + d) | 0; b += (((c & d) | (~c & a)) + k[11] - 1990404162) | 0; b = (((b << 22) | (b >>> 10)) + c) | 0; a += (((b & c) | (~b & d)) + k[12] + 1804603682) | 0; a = (((a << 7) | (a >>> 25)) + b) | 0; d += (((a & b) | (~a & c)) + k[13] - 40341101) | 0; d = (((d << 12) | (d >>> 20)) + a) | 0; c += (((d & a) | (~d & b)) + k[14] - 1502002290) | 0; c = (((c << 17) | (c >>> 15)) + d) | 0; b += (((c & d) | (~c & a)) + k[15] + 1236535329) | 0; b = (((b << 22) | (b >>> 10)) + c) | 0; a += (((b & d) | (c & ~d)) + k[1] - 165796510) | 0; a = (((a << 5) | (a >>> 27)) + b) | 0; d += (((a & c) | (b & ~c)) + k[6] - 1069501632) | 0; d = (((d << 9) | (d >>> 23)) + a) | 0; c += (((d & b) | (a & ~b)) + k[11] + 643717713) | 0; c = (((c << 14) | (c >>> 18)) + d) | 0; b += (((c & a) | (d & ~a)) + k[0] - 373897302) | 0; b = (((b << 20) | (b >>> 12)) + c) | 0; a += (((b & d) | (c & ~d)) + k[5] - 701558691) | 0; a = (((a << 5) | (a >>> 27)) + b) | 0; d += (((a & c) | (b & ~c)) + k[10] + 38016083) | 0; d = (((d << 9) | (d >>> 23)) + a) | 0; c += (((d & b) | (a & ~b)) + k[15] - 660478335) | 0; c = (((c << 14) | (c >>> 18)) + d) | 0; b += (((c & a) | (d & ~a)) + k[4] - 405537848) | 0; b = (((b << 20) | (b >>> 12)) + c) | 0; a += (((b & d) | (c & ~d)) + k[9] + 568446438) | 0; a = (((a << 5) | (a >>> 27)) + b) | 0; d += (((a & c) | (b & ~c)) + k[14] - 1019803690) | 0; d = (((d << 9) | (d >>> 23)) + a) | 0; c += (((d & b) | (a & ~b)) + k[3] - 187363961) | 0; c = (((c << 14) | (c >>> 18)) + d) | 0; b += (((c & a) | (d & ~a)) + k[8] + 1163531501) | 0; b = (((b << 20) | (b >>> 12)) + c) | 0; a += (((b & d) | (c & ~d)) + k[13] - 1444681467) | 0; a = (((a << 5) | (a >>> 27)) + b) | 0; d += (((a & c) | (b & ~c)) + k[2] - 51403784) | 0; d = (((d << 9) | (d >>> 23)) + a) | 0; c += (((d & b) | (a & ~b)) + k[7] + 1735328473) | 0; c = (((c << 14) | (c >>> 18)) + d) | 0; b += (((c & a) | (d & ~a)) + k[12] - 1926607734) | 0; b = (((b << 20) | (b >>> 12)) + c) | 0; a += ((b ^ c ^ d) + k[5] - 378558) | 0; a = (((a << 4) | (a >>> 28)) + b) | 0; d += ((a ^ b ^ c) + k[8] - 2022574463) | 0; d = (((d << 11) | (d >>> 21)) + a) | 0; c += ((d ^ a ^ b) + k[11] + 1839030562) | 0; c = (((c << 16) | (c >>> 16)) + d) | 0; b += ((c ^ d ^ a) + k[14] - 35309556) | 0; b = (((b << 23) | (b >>> 9)) + c) | 0; a += ((b ^ c ^ d) + k[1] - 1530992060) | 0; a = (((a << 4) | (a >>> 28)) + b) | 0; d += ((a ^ b ^ c) + k[4] + 1272893353) | 0; d = (((d << 11) | (d >>> 21)) + a) | 0; c += ((d ^ a ^ b) + k[7] - 155497632) | 0; c = (((c << 16) | (c >>> 16)) + d) | 0; b += ((c ^ d ^ a) + k[10] - 1094730640) | 0; b = (((b << 23) | (b >>> 9)) + c) | 0; a += ((b ^ c ^ d) + k[13] + 681279174) | 0; a = (((a << 4) | (a >>> 28)) + b) | 0; d += ((a ^ b ^ c) + k[0] - 358537222) | 0; d = (((d << 11) | (d >>> 21)) + a) | 0; c += ((d ^ a ^ b) + k[3] - 722521979) | 0; c = (((c << 16) | (c >>> 16)) + d) | 0; b += ((c ^ d ^ a) + k[6] + 76029189) | 0; b = (((b << 23) | (b >>> 9)) + c) | 0; a += ((b ^ c ^ d) + k[9] - 640364487) | 0; a = (((a << 4) | (a >>> 28)) + b) | 0; d += ((a ^ b ^ c) + k[12] - 421815835) | 0; d = (((d << 11) | (d >>> 21)) + a) | 0; c += ((d ^ a ^ b) + k[15] + 530742520) | 0; c = (((c << 16) | (c >>> 16)) + d) | 0; b += ((c ^ d ^ a) + k[2] - 995338651) | 0; b = (((b << 23) | (b >>> 9)) + c) | 0; a += ((c ^ (b | ~d)) + k[0] - 198630844) | 0; a = (((a << 6) | (a >>> 26)) + b) | 0; d += ((b ^ (a | ~c)) + k[7] + 1126891415) | 0; d = (((d << 10) | (d >>> 22)) + a) | 0; c += ((a ^ (d | ~b)) + k[14] - 1416354905) | 0; c = (((c << 15) | (c >>> 17)) + d) | 0; b += ((d ^ (c | ~a)) + k[5] - 57434055) | 0; b = (((b << 21) | (b >>> 11)) + c) | 0; a += ((c ^ (b | ~d)) + k[12] + 1700485571) | 0; a = (((a << 6) | (a >>> 26)) + b) | 0; d += ((b ^ (a | ~c)) + k[3] - 1894986606) | 0; d = (((d << 10) | (d >>> 22)) + a) | 0; c += ((a ^ (d | ~b)) + k[10] - 1051523) | 0; c = (((c << 15) | (c >>> 17)) + d) | 0; b += ((d ^ (c | ~a)) + k[1] - 2054922799) | 0; b = (((b << 21) | (b >>> 11)) + c) | 0; a += ((c ^ (b | ~d)) + k[8] + 1873313359) | 0; a = (((a << 6) | (a >>> 26)) + b) | 0; d += ((b ^ (a | ~c)) + k[15] - 30611744) | 0; d = (((d << 10) | (d >>> 22)) + a) | 0; c += ((a ^ (d | ~b)) + k[6] - 1560198380) | 0; c = (((c << 15) | (c >>> 17)) + d) | 0; b += ((d ^ (c | ~a)) + k[13] + 1309151649) | 0; b = (((b << 21) | (b >>> 11)) + c) | 0; a += ((c ^ (b | ~d)) + k[4] - 145523070) | 0; a = (((a << 6) | (a >>> 26)) + b) | 0; d += ((b ^ (a | ~c)) + k[11] - 1120210379) | 0; d = (((d << 10) | (d >>> 22)) + a) | 0; c += ((a ^ (d | ~b)) + k[2] + 718787259) | 0; c = (((c << 15) | (c >>> 17)) + d) | 0; b += ((d ^ (c | ~a)) + k[9] - 343485551) | 0; b = (((b << 21) | (b >>> 11)) + c) | 0; x[0] = (a + x[0]) | 0; x[1] = (b + x[1]) | 0; x[2] = (c + x[2]) | 0; x[3] = (d + x[3]) | 0; } function md5blk(s) { var md5blks =[], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } function md51(s) { var n = s.length, state =[1732584193, -271733879, -1732584194, 271733878], i, length, tail, tmp, lo, hi; for (i = 64; i <= n; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); length = s.length; tail =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < length; i += 1) { tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); } tail[i >> 2] |= 0x80 << ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i += 1) { tail[i] = 0; } } tmp = n * 8; tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); lo = parseInt(tmp[2], 16); hi = parseInt(tmp[1], 16) || 0; tail[14] = lo; tail[15] = hi; md5cycle(state, tail); return state; } function rhex(n) { var s = "", j; for (j = 0; j < 4; j += 1) { s += hex_chr[(n >> (j * 8 + 4)) & 0x0f] + hex_chr[(n >> (j * 8)) & 0x0f]; } return s; } function hex(x) { var i; for (i = 0; i < x.length; i += 1) { x[i] = rhex(x[i]); } return x.join(""); } if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") { add32 = function (x, y) { var lsw = (x & 0xffff) + (y & 0xffff), msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xffff); }; } return { hash: function (str) { return hex(md51(str)); } }; })(); const web_key_urls = { img_key_url: localStorage.getItem("wbi_img_url") || "", sub_key_url: localStorage.getItem("wbi_sub_url") || "", }; const getWebKey = function (str) { if (!str) return ""; return str.slice(str.lastIndexOf("/") + 1, str.lastIndexOf(".")); }; let img_key = getWebKey(web_key_urls.img_key_url); let sub_key = getWebKey(web_key_urls.sub_key_url); async function ensureWbiKeys() { if (img_key && sub_key) return; try { const resp = await originalFetch("https://api.bilibili.com/x/web-interface/nav", { credentials: 'include' }); const data = await resp.json(); if (data.data && data.data.wbi_img) { const imgUrl = data.data.wbi_img.img_url || ""; const subUrl = data.data.wbi_img.sub_url || ""; img_key = getWebKey(imgUrl); sub_key = getWebKey(subUrl); localStorage.setItem("wbi_img_url", imgUrl); localStorage.setItem("wbi_sub_url", subUrl); console.log("已从nav接口获取Wbi密钥"); } } catch (e) { console.error("获取Wbi密钥失败", e); } } const originalFetch = window.fetch; window.fetch = async function (input, init = {}) { let url = ""; if (typeof input === "string") { url = input; } else if (input instanceof Request) { url = input.url; } const response = await originalFetch.call(this, input, init); const clonedResponse = response.clone(); clonedResponse.text().then(content => { if (url.includes("//api.bilibili.com/x/v2/reply/add")) { try { handleAddCommentResponse(url, JSON.parse(content)); } catch (e) { console.error("发评反诈检测出错", e); showErrorResult("检测过程发生错误:" + e.message); } } }).catch(e => { console.error("读取响应失败", e); }); return response; }; const waitTime = 5000; const sortByTime = 0; const SORT_MODE_TIME = 2; window.addEventListener('load', function () { const hostname = window.location.hostname; let id = null; if (hostname === 't.bilibili.com') { const urlPath = window.location.pathname; id = urlPath.split('/')[1]; } else if (hostname === 'www.bilibili.com') { const urlPath = window.location.pathname; const pathParts = urlPath.split('/'); if (pathParts[1] === 'opus') { id = pathParts[2]; } } if (id) { console.log('Dynamic ID:', id); handleCheckDynamic(id); } }); console.log("哔哩发评反诈脚本已加载"); const dialogHTML = `

Progress

`; const ProgressDialog = { init: function () { if (!document.getElementById('progress-overlay')) { document.body.insertAdjacentHTML('beforeend', dialogHTML); document.getElementById('close-button').addEventListener('click', function () { ProgressDialog.hide(); }); } }, show: function () { this.init(); document.getElementById('progress-overlay').style.display = 'block'; document.getElementById('progress-dialog').style.display = 'block'; }, hide: function () { const overlay = document.getElementById('progress-overlay'); const dialog = document.getElementById('progress-dialog'); if (overlay) overlay.style.display = 'none'; if (dialog) dialog.style.display = 'none'; }, setTitle: function (title) { const el = document.getElementById('progress-title'); if (el) el.textContent = title; }, setMessage: function (message) { const el = document.getElementById('progress-message'); if (el) el.innerText = message; }, setProgress: function (progress) { const progressBar = document.getElementById('progressBar'); if (progressBar) progressBar.style.width = progress + '%'; }, setIndeterminate: function (indeterminate) { var progressBar = document.getElementById('progressBar'); if (progressBar) { if (indeterminate) { progressBar.className = "progress-bar-indeterminate"; progressBar.style.width = "30%"; } else { progressBar.className = "progress-bar"; progressBar.style.width = "0"; } } } }; function sleep(time) { return new Promise((resolve) => setTimeout(resolve, time)); } async function handleAddCommentResponse(url, responseJson) { console.log(url); console.log(responseJson); await ensureWbiKeys(); if (responseJson.code == 0) { var data = responseJson.data; var reply = data.reply; var oid = reply.oid; var type = reply.type; var rpid = reply.rpid; var root = reply.root; console.log(`${data.success_toast},准备检查评论`); ProgressDialog.show(); await sleepAndShowInDialog(waitTime); ProgressDialog.setIndeterminate(true); ProgressDialog.setTitle("检查中……"); if (root == 0) { var found = null; var sentTime = reply.ctime; var nextOffset = ""; for (let page = 0; page < 30; page++) { ProgressDialog.setMessage(`无账号翻找评论区第${page + 1}页……`); var resp = await getMainCommentList(oid, type, nextOffset, SORT_MODE_TIME, false); if (resp.code != 0) { showErrorResult("获取评论主列表时发生错误,响应数据:" + JSON.stringify(resp)); return; } if (page === 0 && resp.data.top_replies) { found = findReplies(resp.data.top_replies, rpid); if (found) break; } var replies = resp.data.replies; if (!replies || replies.length === 0) break; found = findReplies(replies, rpid); if (found) break; var lastReply = replies[replies.length - 1]; if (lastReply.ctime < sentTime) break; var pagination = resp.data.cursor?.pagination_reply; if (pagination && pagination.next_offset) { nextOffset = pagination.next_offset; } else { break; } } if (found) { if (found.invisible) { showInvisibleResult(reply); } else { showOkResult(reply); } } else { ProgressDialog.setMessage("有账号获取此评论的回复列表"); resp = await fetchBilibiliCommentReplies(oid, type, rpid, 0, sortByTime, true); if (resp.code == 12022) { showQuickDeleteResult(reply); } else if (resp.code == 0) { ProgressDialog.setMessage("无账号获取此评论的回复列表"); resp = await fetchBilibiliCommentReplies(oid, type, rpid, 0, sortByTime, false); if (resp.code == 12022) { showShadowBanResult(reply); } else if (resp.code == 0) { var rootComment = resp.data?.root; if (rootComment && rootComment.invisible) { showInvisibleResult(reply); } else { showSusResult(reply); } } else { showErrorResult("获取评论回复列表时发生错误,响应数据:" + JSON.stringify(resp)); } } else { showErrorResult("有账号获取评论回复列表时发生错误,响应数据:" + JSON.stringify(resp)); } } } else { ProgressDialog.setMessage("无账号seek_rpid定位查找回复评论……"); var foundNoLogin = await findReplyUsingSeekRpid(oid, type, rpid, root, false); if (foundNoLogin) { showOkResult(reply); } else { ProgressDialog.setMessage("有账号seek_rpid定位查找回复评论……"); var foundLogin = await findReplyUsingSeekRpid(oid, type, rpid, root, true); if (foundLogin) { showShadowBanResult(reply); } else { showQuickDeleteResult(reply); } } } } } async function handleCheckDynamic(id) { await ensureWbiKeys(); var resp = await fetchDynamic(id, false); if (resp.code == -352) { addDynamicShadowBannedHint("无账号获取此动态返回-352(风控拦截),可能原因:动态被shadowBan仅自己可见、请求IP异常、或请求频率过高。建议在无痕模式下验证。"); } else if (resp.code == 4101131) { addDynamicShadowBannedHint("无账号获取此动态返回4101131,此动态可能被shadowBan(可能你转发到动态的评论被ShadowBan)"); } else if (resp.code == 500) { addDynamicShadowBannedHint("无账号获取此动态返回500(服务端错误),此动态可能被shadowBan(可能你转发到动态的评论疑似审核中)"); } else if (resp.code == 0) { console.log("检查到此动态正常,没被shadowBan"); } } function findReplies(replies, rpid) { if (!replies) return null; for (const item of replies) { if (String(item.rpid) === String(rpid)) return item; } return null; } async function findReplyUsingSeekRpid(oid, type, rpid, root, isLogin) { var resp = await getMainCommentList(oid, type, "", SORT_MODE_TIME, isLogin, rpid); if (resp.code != 0) return null; var replies = resp.data.replies || []; if (resp.data.top_replies) { replies = replies.concat(resp.data.top_replies); } for (var comment of replies) { if (comment.rpid == root) { if (comment.replies) { var found = findReplies(comment.replies, rpid); if (found) return found; } } if (comment.rpid == rpid) return comment; if (comment.replies) { var found = findReplies(comment.replies, rpid); if (found) return found; } } return null; } async function sleepAndShowInDialog(sleepTime) { ProgressDialog.setTitle("等待检查中"); var sleepCount = sleepTime / 10; for (var i = 0; i <= sleepCount; i++) { await sleep(10); ProgressDialog.setMessage(`等待 ${i * 10}/${sleepTime}ms 后检查评论`); ProgressDialog.setProgress(100 / sleepCount * i); } ProgressDialog.setProgress(100); } async function getMainCommentList(oid, type, next, mode, isLogin, seek_rpid) { const pagination = (!next || next === "" || next === 0) ? '{"offset":""}' : `{"offset":"${next}"}`; const params = { oid, type, mode, plat: 1, web_location: 1315875, pagination_str: pagination }; if (seek_rpid) params.seek_rpid = seek_rpid; const query = new WbiSign().encWbi(params, img_key, sub_key); let url = `https://api.bilibili.com/x/v2/reply/wbi/main?${query}`; try { const response = await originalFetch(url, isLogin ? { credentials: 'include' } : { credentials: 'omit' }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); return await response.json(); } catch (error) { console.error("获取主评论列表出错", error); return { code: -1, message: error.message }; } } async function fetchBilibiliCommentReplies(oid, type, root, pn, sort, hasCookie) { const params = { oid, type, root, pn, sort }; const query = new WbiSign().encWbi(params, img_key, sub_key); const url = `https://api.bilibili.com/x/v2/reply/reply?${query}`; const response = await originalFetch(url, hasCookie ? { credentials: 'include' } : { credentials: 'omit' }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); return await response.json(); } async function fetchDynamic(id, hasCookie) { const url = new URL('https://api.bilibili.com/x/polymer/web-dynamic/v1/detail'); const params = { id }; url.search = new URLSearchParams(params).toString(); const response = await originalFetch(url.toString(), hasCookie ? { credentials: 'include' } : { credentials: 'omit' }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); return await response.json(); } function showOkResult(reply) { showResult("恭喜,无账号状态下找到了你的评论,你的评论正常!\n\n你的评论:" + reply.content.message); } function showShadowBanResult(reply) { showResult("你被骗了,此评论被shadow ban(仅自己可见)!\n\n你的评论:" + reply.content.message); } function showQuickDeleteResult(reply) { showResult("你评论没了,此评论已被系统秒删!刷新评论区也许就不见了,复制留个档吧。\n\n你的评论:" + reply.content.message); } function showInvisibleResult(reply) { showResult("你的评论被标记为invisible(前端隐藏),虽然API返回了但不会显示。\n\n你的评论:" + reply.content.message); } function showSusResult(reply) { showResult(`你评论状态有点可疑,虽然无账号翻找评论区获取不到你的评论,但是无账号可通过\nhttps://api.bilibili.com/x/v2/reply/reply?oid=${reply.oid}&pn=1&ps=20&root=${reply.rpid}&type=${reply.type}&sort=0\n获取你的评论,疑似评论区被戒严或评论审核中。\n\n你的评论:${reply.content.message}`); } function showResult(message) { ProgressDialog.setIndeterminate(false); ProgressDialog.setProgress(100); ProgressDialog.setTitle("检查完毕"); ProgressDialog.setMessage(message); } function showErrorResult(message) { ProgressDialog.setIndeterminate(false); ProgressDialog.setProgress(0); ProgressDialog.setTitle("发生错误"); ProgressDialog.setMessage(message); } function addDynamicShadowBannedHint(message) { const biliDynContent = document.querySelector('.bili-dyn-content'); if (biliDynContent) { const shadowbanMessage = document.createElement('div'); shadowbanMessage.className = 'shadowban-scanner-message'; shadowbanMessage.style.setProperty('--md-sys-color-on-primary', 'rgb(15, 20, 25)'); const messageSpan = document.createElement('span'); messageSpan.textContent = message; shadowbanMessage.appendChild(messageSpan); biliDynContent.appendChild(shadowbanMessage); } } })();