Greasy Fork

Greasy Fork is available in English.

斗鱼全等级弹幕屏蔽

douyu斗鱼,高级弹幕屏蔽,突破30级等级屏蔽限制,房管模拟器

当前为 2023-04-20 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         斗鱼全等级弹幕屏蔽
// @namespace    https://www.liebev.site
// @version      1.1
// @description  douyu斗鱼,高级弹幕屏蔽,突破30级等级屏蔽限制,房管模拟器
// @author       LiebeV
// @license      MIT: Copyright (c) 2023 LiebeV
// @match        https://www.douyu.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=douyu.com
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

"use strict";

// v1.1,更新了代码逻辑。添加了一个“模”按钮,用于取代GM_registerMenuCommand。添加了移除id的功能
// 已知问题,弹幕瞬间过多时,rightMO会挂(无解)
// 更新计划,添加快速添加id的功能

let userBannedIds = GM_getValue("bannedIds", []);
let bannedIds = userBannedIds;
let dmCache = [];

//尝试获取弹幕区
async function getRightList() {
    // console.log('高级弹幕屏蔽初始化成功');
    let ulList;
    let count = 0;
    while (!ulList && count < 20) {
        ulList = document.getElementById("js-barrage-list");
        console.log("尝试获取弹幕区...");
        if (!ulList) {
            console.log(`失败,等待1秒钟再尝试获取,剩余重试:${20 - count}`);
            await new Promise((resolve) => setTimeout(resolve, 1000));
            count++;
        }
    }
    if (!ulList) {
        console.log("无法获取Right弹幕区,请刷新网页");
    } else {
        console.log("已获Right取弹幕区,准备开启rightMO感知");
        console.log(ulList);
    }
    return ulList;
}

// 右侧 mutation observer
async function rightMO() {
    const ulList = await getRightList();
    //    console.log('Right感知准备完成');
    const rightObserver = new MutationObserver(function (mutations) {
        mutations.forEach(function (mutation) {
            mutation.addedNodes.forEach(function (righNode) {
                if (righNode.nodeName === "LI") {
                    // console.log('\x1b[32m%s\x1b[0m', 'Right弹幕区感知到新弹幕:');
                    // console.log(righNode);
                    rightCheck(righNode);
                }
            });
        });
    });
    const config = { childList: true };
    rightObserver.observe(ulList, config);
    console.log("Right感知挂载完成,等待新弹幕...");
}

// 检查id,获取发言内容,right2mid
async function rightCheck(righNode) {
    const userId = righNode.querySelector("span.Barrage-nickName[title]").getAttribute("title");
    if (userBannedIds.includes(userId)) {
        righNode.style.display = "none";
        const danmu = righNode.querySelector("span.Barrage-content").textContent.trim();
        // console.log("rightcheck:" + danmu);
        if (dmCache.includes(danmu)) {
            const xpath = `//div[contains(text(), "${danmu}")]`;
            // const midDivElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
            const snapshotResult = document.evaluate(
                xpath,
                document,
                null,
                XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                null
            );
            for (let i = 0; i < snapshotResult.snapshotLength; i++) {
                const midDivElement = snapshotResult.snapshotItem(i);
                midDivElement.parentElement.style.display = "none";
            }
        }
        console.log(`"${userId}" 的发言已被屏蔽!`);
    }
}

// 获取飘屏弹幕区
async function getMainList() {
    let divList;
    let count = 0;
    // 尝试等待页面加载 20s
    while (!divList && count < 20) {
        divList = document.querySelector(".danmu-e7f029");
        if (!divList) {
            await new Promise((resolve) => setTimeout(resolve, 1000));
            count++;
        }
    }
    if (!divList) {
        console.log("无法获取飘屏弹幕区,请刷新网页");
    } else {
        console.log("已获取飘屏弹幕区,准备开启Mutation感知");
        console.log(divList);
    }
    return divList;
}

// 飘屏mutation observer
async function midMO() {
    const middivList = await getMainList();
    // console.log('mid感知准备完成');
    const midObserver = new MutationObserver(function (mutations) {
        mutations.forEach(function (mutation) {
            mutation.addedNodes.forEach(function (midNode) {
                if (midNode.nodeName === "DIV") {
                    // console.log('\x1b[32m%s\x1b[0m', '飘屏区感知到新弹幕:');
                    // console.log(midNode);
                    getMidText(midNode);
                }
            });
        });
    });
    const midConfig = { childList: true };
    midObserver.observe(middivList, midConfig);
    console.log("mid感知挂载完成,等待新弹幕...");
}

// 获取飘屏区弹幕内容,存入临时数组,等待比对
async function getMidText(midNode) {
    const midText = midNode.querySelector("div.text-edf4e7").textContent;
    // console.log(midText);
    dmCache.push(midText);
    // console.log(dmCache);
    if (dmCache.length > 10) {
        dmCache.splice(0, dmCache.length);
    }
}

//通过setValue像存储器添加id
async function addId(userIdInput) {
    // console.log('addId接收到传入');
    if (!bannedIds.includes(userIdInput)) {
        bannedIds.push(userIdInput);
        console.log(`已添加屏蔽用户: ${userIdInput}`);
        GM_setValue("bannedIds", bannedIds);
    } else {
        const index = bannedIds.indexOf(userIdInput);
        if (index !== -1) {
            bannedIds.splice(index, 1);
            console.log(`已移除屏蔽用户 ${userIdInput}`);
            GM_setValue("bannedIds", bannedIds);
        }
    }
}

async function showSettings() {
    let message = "当前被您屏蔽的用户ID列表:\n";
    const idList = GM_getValue("bannedIds", []);
    for (let i = 0; i < idList.length; i++) {
        message += `${i + 1}. ${idList[i]}\n`;
    }
    const userIdInput = prompt(`${message}\n请输入要屏蔽发言的用户id`);
    if (userIdInput) {
        console.log("接收到用户id");
        addId(userIdInput);
    }
}

GM_registerMenuCommand("添加屏蔽用户", showSettings);

async function menu() {
    await rightMO();
    await midMO();

    const container = document.querySelector(".ChatToolBar");
    const mnq = document.createElement("div");
    mnq.classList.add("liebevmnq");
    mnq.style.display = "inline-block";
    mnq.style.verticalAlign = "middle";
    mnq.style.width = "18px";
    mnq.style.height = "18px";
    mnq.style.marginRight = "8px";

    const inner = document.createElement("div");
    inner.classList.add("liebevmnqInner");
    inner.style.width = "100%";
    inner.style.height = "100%";

    const btn = document.createElement("div");
    btn.classList.add("liebevmnqBtn");
    btn.style.position = "relative";
    btn.style.color = "#fff";
    btn.style.background = "#bbb";
    btn.style.borderRadius = "4px";
    btn.style.cursor = "pointer";
    btn.style.textAlign = "center";
    btn.style.userSelect = "none";

    const moniqi = document.createElement("span");
    moniqi.innerText = "模";

    container.appendChild(mnq);
    mnq.appendChild(inner);
    inner.appendChild(btn);
    btn.appendChild(moniqi);

    btn.addEventListener("click", showmenu);
}

async function showmenu() {
    const btn = document.querySelector("div.liebevmnq");
    const checker = document.querySelector("div.mnqHeader");

    if (checker) {
        checker.remove();
    } else {
        const commandmenu = document.createElement("div");
        commandmenu.classList.add("mnqHeader");
        Object.assign(commandmenu.style, {
            position: "absolute",
            left: "-8px",
            right: "-8px",
            bottom: "32px",
            boxShadow: "0 -3px 6px rgba(0,0,0,.1)",
            border: "1px solid #e5e5e5",
            borderTopRightRadius: "8px",
            borderTopLeftRadius: "8px",
            animation: "slideUp .3s cubic-bezier(.22,.58,.12,.98) forwards",
            backgroundColor: "#fff",
        });

        const head = document.createElement("div");
        head.classList.add("Header-head");
        Object.assign(head.style, {
            height: "45px",
            lineHeight: "45px",
            color: "#333",
            fontSize: "16px",
            padding: "0 38px 0 16px",
            backgroundColor: "#f4f4f4",
            position: "relative",
            borderTopLeftRadius: "8px",
            borderTopRightRadius: "8px",
            userSelect: "none",
        });
        head.innerText = "LiebeV房管模拟器";

        const panel = document.createElement("div");
        panel.classList.add("mnqPanel");
        Object.assign(panel.style, {
            padding: "0 0 0 16px",
            height: "206px",
            boxSizing: "border-box",
            overflowY: "auto",
        });
        const idList = GM_getValue("bannedIds", []);
        panel.innerText = `${idList.map((id, i) => `${i + 1}. ${id}`).join("\n")}`;

        const input = document.createElement("div");
        input.classList.add("mnqinput");
        Object.assign(input.style, {
            position: "relative",
            margin: "0 16px",
            borderTop: "1px solid #e8e8e8",
            height: "46px",
            background: "#fff",
            lineHeight: "46px",
        });

        const textInput = document.createElement("input");
        textInput.type = "text";
        textInput.placeholder = "请输入您要屏蔽/移除的用户ID";
        Object.assign(textInput.style, {
            width: "80%",
            height: "100%",
            border: "none",
            outline: "none",
            paddingLeft: "10px",
            fontSize: "16px",
        });
        textInput.addEventListener("keydown", function (event) {
            if (event.key === "Enter") {
                addId(event.target.value);
                event.target.value = "";
            }
        });

        btn.appendChild(commandmenu);
        commandmenu.appendChild(head);
        commandmenu.appendChild(panel);
        commandmenu.appendChild(input);
        input.appendChild(textInput);
    }
}

(function () {
    menu();
})();