Bilibili隐藏短视频

视频检测设置面板,样式自定义、临界时长调整,支持禁用检测恢复原样

当前为 2024-11-04 提交的版本,查看 最新版本

// ==UserScript==
// @name         Bilibili隐藏短视频
// @namespace    http://tampermonkey.net/
// @version      6.0
// @description  视频检测设置面板,样式自定义、临界时长调整,支持禁用检测恢复原样
// @match        *://www.bilibili.com/*
// @grant        GM_registerMenuCommand
// @license GPL 2.0
// ==/UserScript==

(function () {
    'use strict';

    let minDuration = parseInt(localStorage.getItem('minDuration')) || 300; // 默认短视频临界时长(秒)
    let debounceDelay = parseInt(localStorage.getItem('debounceDelay')) || 500; // 默认防抖延迟
    let isActive = JSON.parse(localStorage.getItem('isActive')) || true; // 是否启用检测
    let isPanelVisible = JSON.parse(localStorage.getItem('isPanelVisible')) || false; // 控制面板显示状态
    let styleChoice = localStorage.getItem('styleChoice') || '半透明'; // 默认样式
    let detectedElements = [];

    // 初始化控制面板
    function initControlPanel() {
        if (document.getElementById("controlPanel")) return;

        const panel = document.createElement("div");
        panel.style.position = "fixed";
        panel.style.top = "10px";
        panel.style.right = "10px";
        panel.style.width = "240px";
        panel.style.padding = "10px";
        panel.style.backgroundColor = "#f9f9f9";
        panel.style.border = "1px solid #ccc";
        panel.style.borderRadius = "8px";
        panel.style.boxShadow = "0px 0px 10px rgba(0, 0, 0, 0.1)";
        panel.style.zIndex = "9999";
        panel.id = "controlPanel";
        panel.style.display = isPanelVisible ? "block" : "none";

        panel.innerHTML = `
            <h3>检测设置 <span id="closePanel" style="cursor:pointer;float:right;">×</span></h3>
            <label>分界时间 (秒): <input type="number" id="minDuration" value="${minDuration}"></label><br>
            <label>防抖延迟 (毫秒): <input type="number" id="debounceDelay" value="${debounceDelay}"></label><br>
            <label>样式选择:
                <select id="styleChoice">
                    <option value="半透明" ${styleChoice === '半透明' ? 'selected' : ''}>半透明</option>
                    <option value="边框高亮" ${styleChoice === '边框高亮' ? 'selected' : ''}>边框高亮</option>
                    <option value="背景高亮" ${styleChoice === '背景高亮' ? 'selected' : ''}>背景高亮</option>
                </select>
            </label><br>
            <button id="toggleDetection">${isActive ? "禁用检测" : "启用检测"}</button>
            <button id="clearLogs">清空日志</button>
            <h4>检测日志</h4>
            <div id="logInfo" style="height: 100px; overflow-y: auto; background: #e9e9e9; padding: 5px; border-radius: 4px;"></div>
        `;

        document.body.appendChild(panel);

        // 控制面板事件监听
        document.getElementById("toggleDetection").onclick = toggleDetection;
        document.getElementById("closePanel").onclick = closePanel;
        document.getElementById("minDuration").onchange = updateSettings;
        document.getElementById("debounceDelay").onchange = updateSettings;
        document.getElementById("styleChoice").onchange = updateSettings;
        document.getElementById("clearLogs").onclick = clearLogs;
    }

    // 切换启用/禁用状态
    function toggleDetection() {
        isActive = !isActive;
        localStorage.setItem("isActive", isActive);
        document.getElementById("toggleDetection").textContent = isActive ? "禁用检测" : "启用检测";
        if (!isActive) {
            clearMarkers();
        } else {
            runDetection();
        }
    }

    // 关闭控制面板
    function closePanel() {
        isPanelVisible = false;
        localStorage.setItem("isPanelVisible", isPanelVisible);
        document.getElementById("controlPanel").style.display = "none";
    }

    // 更新设置并保存
    function updateSettings() {
        minDuration = parseInt(document.getElementById("minDuration").value);
        debounceDelay = parseInt(document.getElementById("debounceDelay").value);
        styleChoice = document.getElementById("styleChoice").value;
        localStorage.setItem("minDuration", minDuration);
        localStorage.setItem("debounceDelay", debounceDelay);
        localStorage.setItem("styleChoice", styleChoice);
        runDetection();
    }

    // 清空日志
    function clearLogs() {
        detectedElements = [];
        document.getElementById("logInfo").innerHTML = "";
    }

    // 更新日志信息
    function updateLogInfo() {
        const logDiv = document.getElementById("logInfo");
        logDiv.innerHTML = `
            当前检测到的短视频数量:${detectedElements.length}<br>
            索引位置:${detectedElements.map((elem) => elem.index).join(", ")}
        `;
    }

    // 将时长文本转换为秒数
    function convertDurationToSeconds(durationText) {
        const timeParts = durationText.split(":").map(Number);
        return timeParts.length === 2 ? timeParts[0] * 60 + timeParts[1] : timeParts[0] * 3600 + timeParts[1] * 60 + timeParts[2];
    }

    // 清除已标记元素的样式
    function clearMarkers() {
        detectedElements.forEach((item) => {
            item.element.style.opacity = "1";
            item.element.style.border = "";
            item.element.style.backgroundColor = "";
            const warning = item.element.querySelector(".short-video-warning");
            if (warning) warning.remove();
        });
        detectedElements = [];
        updateLogInfo();
    }

    // 设置检测样式
    function applyStyle(element) {
        if (styleChoice === "半透明") {
            element.style.opacity = "0.5";
        } else if (styleChoice === "边框高亮") {
            element.style.border = "2px solid red";
        } else if (styleChoice === "背景高亮") {
            element.style.backgroundColor = "rgba(255, 0, 0, 0.2)";
        }
    }

    // 添加短视频提示文字
    function addShortVideoWarning(element) {
        const warningText = document.createElement("div");
        warningText.className = "short-video-warning";
        warningText.style.position = "absolute";
        warningText.style.top = "10px";
        warningText.style.left = "10px";
        warningText.style.padding = "4px 8px";
        warningText.style.backgroundColor = "rgba(255, 0, 0, 0.6)";
        warningText.style.color = "white";
        warningText.style.fontSize = "12px";
        warningText.style.fontWeight = "bold";
        warningText.style.zIndex = "10";
        warningText.style.borderRadius = "4px";
        warningText.textContent = "小心沉迷短视频!";
        element.style.position = "relative";
        element.appendChild(warningText);
    }

    // 防抖函数
    function debounce(func, delay) {
        let timeout;
        return function (...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), delay);
        };
    }

    // 检测并处理视频卡片
    function processVideoCards() {
        const videoSelectors = ['.bili-video-card', '.video-page-card-small'];
        videoSelectors.forEach((selector) => {
            const videoCards = document.querySelectorAll(selector);

            videoCards.forEach((card, index) => {
                if (detectedElements.find((elem) => elem.element === card)) return;

                const followedElement = card.querySelector('.bili-video-card__info--icon-text') || card.querySelector('.upname .name');
                if (followedElement && followedElement.textContent.includes('已关注')) return;

                const upNameElement = card.querySelector('.bili-video-card__info--author') || card.querySelector('.upname .name');
                if (upNameElement && (upNameElement.textContent.match(/_/g) || []).length >= 2) {
                    applyStyle(card);
                    detectedElements.push({ element: card, index });
                    updateLogInfo();
                    return;
                }

                const titleElement = card.querySelector('.bili-video-card__info--tit') || card.querySelector('.title');
                if (titleElement && (titleElement.textContent.match(/!/g) || []).length >= 2) {
                    applyStyle(card);
                    detectedElements.push({ element: card, index });
                    updateLogInfo();
                    return;
                }

                const durationElement = card.querySelector('.bili-video-card__stats__duration') || card.querySelector('.duration');
                if (durationElement) {
                    const durationText = durationElement.textContent.trim();
                    const durationInSeconds = convertDurationToSeconds(durationText);
                    if (durationInSeconds < minDuration) {
                        applyStyle(card);
                        detectedElements.push({ element: card, index });
                        updateLogInfo();
                    }
                    if (durationInSeconds < 60) {
                        addShortVideoWarning(card);
                    }
                }
            });
        });
    }

    // 观察DOM变化并调用检测
    const observer = new MutationObserver(debounce(() => {
        if (isActive) runDetection();
    }, debounceDelay));

    function runDetection() {
        clearMarkers();
        processVideoCards();
    }

    // 初始化控制面板和观察器
    initControlPanel();
    observer.observe(document.body, { childList: true, subtree: true });

    // 设置油猴菜单选项
    GM_registerMenuCommand("显示/隐藏控制面板", () => {
        isPanelVisible = !isPanelVisible;
        localStorage.setItem("isPanelVisible", isPanelVisible);
        document.getElementById("controlPanel").style.display = isPanelVisible ? "block" : "none";
    });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址