Greasy Fork

Greasy Fork is available in English.

斗鱼全等级弹幕屏蔽

douyu斗鱼,高级弹幕屏蔽,突破30级等级屏蔽限制

目前为 2023-04-25 提交的版本。查看 最新版本

// ==UserScript==
// @name         斗鱼全等级弹幕屏蔽
// @namespace    https://www.liebev.site
// @version      1.2
// @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.2,添加了在飘屏区右键弹幕时快速添加id的功能
// 更新计划,添加在右侧弹幕区快速添加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("尝试获取Right弹幕区...");
        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("已获取飘屏弹幕区,准备开启midMO感知");
        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();
    await subadd();

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

    const inner = document.createElement("div");
    inner.classList.add("liebevmnqInner");
    Object.assign(inner.style, {
        width: "100%",
        height: "100%",
    });

    const btn = document.createElement("div");
    btn.classList.add("liebevmnqBtn");
    Object.assign(btn.style, {
        position: "relative",
        color: "rgb(255, 255, 255)",
        background: "rgb(187, 187, 187)",
        borderRadius: "4px",
        cursor: "pointer",
        textAlign: "center",
        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",
        });
        const idList = GM_getValue("bannedIds", []);
        panel.innerText = `当前被您屏蔽的用户ID列表:\n${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);
    }
}

async function subadd() {
    document.addEventListener("mouseup", function (event) {
        if (event.button === 2) {
            setTimeout(() => {
                const sub = document.querySelector(".danmudiv-32f498");
                // console.log(sub);
                const subbtn = document.createElement("div");
                subbtn.classList.add("subaddbtn");
                subbtn.innerText = "模--添加id";
                Object.assign(subbtn.style, {
                    margin: "2px 40px",
                    cursor: "crosshair",
                    position: "relative",
                    color: "rgb(255, 255, 255)",
                    background: "rgb(187, 187, 187)",
                    borderRadius: "20px",
                    textAlign: "center",
                });
                sub.appendChild(subbtn);
                let Id = document.querySelector(".danmuAuthor-3d7b4a").innerText;
                subbtn.addEventListener("click", function() {
                    addId(Id);
                    subbtn.style.backgroundColor = "green";
                    subbtn.style.border = "2px solid green";
                    setTimeout(() => {
                        subbtn.style.backgroundColor = "rgb(187, 187, 187)";
                        subbtn.style.border = "none";
                    }, 500);
                });
            }, 100);
        }
    });
}

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