Greasy Fork is available in English.

百度网盘打开中文字幕(改)

百度网盘自动打开中文字幕

// ==UserScript==
// @name         百度网盘打开中文字幕(改)
// @namespace    http://tampermonkey.net/
// @version      1.22
// @description  百度网盘自动打开中文字幕
// @author       woshilisisui
// @match        https://pan.baidu.com/pfile/video?path=*.mp4*
// @icon         https://th.bing.com/th?id=ODLS.039b3eb8-253e-4d80-8727-6e7d039c3891&w=32&h=32&qlt=90&pcl=fffffa&o=6&pid=1.2
// @grant        none
// @license      GPL3
// ==/UserScript==


(function () {
    'use strict';


    let interval
    // 等待页面完全加载完毕后执行脚本
    window.onload = function() {
        //document.querySelector('.vjs-big-play-button').style.display = 'none';
        //document.querySelector('.vp-file-video-container__tools').style.display = 'none';
        var controlBar
        var controlBar2
        var controlBar3
        var controlBar4
        var controlBar5


        var videoElement
        var videoElement2

        let timeout;
        function getElement() {
            console.log('getElement')
            document.querySelector('.vjs-big-play-button').style.display = 'none';
            controlBar = document.querySelector('.video-js .vjs-control-bar');
            controlBar2 = document.querySelector('.vp-video .vp-video__control-bar');
            controlBar3 = document.querySelector('.vp-video .vp-video__control-bar--play-time-current');
            controlBar4 = document.querySelector('.vp-video .vp-video__control-bar--play-time-all');
            controlBar5 = document.querySelector('.vp-file-video-container__tools');
            videoElement = document.querySelector('.video-js .vjs-tech');
            videoElement2 = document.querySelector('.vp-video__player');
        }

        function toggleControlBar(display) {
            if (!controlBar || !controlBar2 || !controlBar3 || !controlBar4 || !controlBar5) {
                getElement();
                return;
            }
            const displayValue = display ? 'block' : 'none';
            if (controlBar) controlBar.style.display = displayValue;
            if (controlBar2) controlBar2.style.display = display ? 'flex' : 'none';
            if (controlBar3) controlBar3.style.display = displayValue;
            if (controlBar4) controlBar4.style.display = displayValue;
            if (controlBar5) controlBar5.style.display = displayValue;
        }


        function controlB() {
            timeout = setTimeout(() => {
                toggleControlBar(false);
            }, 1000);
        }

        function controlBDisplay() {
            clearTimeout(timeout);
            toggleControlBar(true);
        }


        let isMouseMoveBound = false;
        let isMouseLeaveBound = false;
        let isControlBarMouseOverBound = false;
        let isControlBarMouseLeave = false;

        function bindEvents() {
            try {

                // 先解绑之前的事件
                if (isMouseMoveBound) {
                    videoElement.removeEventListener('mousemove', onMouseMove);
                    isMouseMoveBound = false;
                }
                if (isMouseLeaveBound) {
                    videoElement2.removeEventListener('mouseleave', onMouseLeave);
                    isMouseLeaveBound = false;
                }
                if (isControlBarMouseOverBound) {
                    controlBar.removeEventListener('mouseover', onControlBarMouseOver);
                    controlBar5.removeEventListener('mouseover', onControlBarMouseOver);
                    isControlBarMouseOverBound = false;
                }
                if (isControlBarMouseLeave) {
                    controlBar5.removeEventListener('mouseleave', onControlBarMouseLeave);
                    isControlBarMouseLeave = false;
                }

                // 重新绑定事件
                videoElement.addEventListener('mousemove', onMouseMove);
                videoElement2.addEventListener('mouseleave', onMouseLeave);
                controlBar.addEventListener('mouseover', onControlBarMouseOver);
                controlBar5.addEventListener('mouseover', onControlBarMouseOver);
                controlBar5.addEventListener('mouseleave', onControlBarMouseLeave);

                // 更新绑定状态
                isMouseMoveBound = true;
                isMouseLeaveBound = true;
                isControlBarMouseOverBound = true;
                isControlBarMouseLeave = true;

            } catch (err) {
                console.error('绑定事件出错:', err);
                // 尝试重新绑定
                setTimeout(() => {
                    getElement();
                    bindEvents();
                }, 1000); // 等待1秒后重试
            }
        }


        function onMouseMove() {
            clearTimeout(timeout);
            controlBDisplay();
            controlB();
        }

        function onMouseLeave() {
            clearTimeout(timeout);
            controlB();
        }

        function onControlBarMouseOver() {
            clearTimeout(timeout);
        }

        function onControlBarMouseLeave() {
            clearTimeout(timeout);
            controlB();
        }

        getElement();
        // 添加事件绑定
        bindEvents();


        let lastUrl = '' // 存储上一个 URL
        // 监听 DOM 变化
        const observer = new MutationObserver(() => {
            const currentUrl = window.location.href;

            // 检查 URL 是否发生变化
            if (currentUrl !== lastUrl) {
                console.log('URL发生变化');
                lastUrl = currentUrl; // 更新上一个 URL
                controlBDisplay();
                controlB();
                //setTimeout(() => {
                //    simulateMouseHoverToButton();
                //}, 0);

                clearInterval(interval); // 停止当前轮询
                // URL 变化后稍微延迟一段时间再检测,确保 DOM 完全更新
                setTimeout(() => {
                    waitForSubtitleButton();
                }, 0);
            }
        });
        // 开始观察 DOM 变化,监听整个页面的变化
        observer.observe(document.body, { childList: true, subtree: true });

        // 修改字幕颜色
        function changeSubtitle() {
            try {
                var subtitleText = document.querySelector('.vp-video__subtitle-text.show')
                //subtitleText.style.background = '#d6d6d6';
                subtitleText.style.background = 'rgba(214, 214, 214, 0.5)'
                subtitleText.style.color = '#ff0000';
            } catch(err) {
                console.error('修改字幕出错:', err);
                setTimeout(() => {
                    changeSubtitle();
                }, 1000);
            }
        }

        function waitForSubtitleButton() {
            const maxAttempts = 100; // 设置最大尝试次数
            let attempts = 0;
            interval = setInterval(function () {
                attempts++;
                if (attempts >= maxAttempts) {
                    console.log('尝试次数过多,停止轮询');
                    console.log('不存在中文字幕');
                    clearInterval(interval);
                }

                simulateMouseHoverToButton();

                // 获取所有符合条件的元素
                const subtitleElements = document.querySelectorAll('li.vp-video__control-bar--video-subtitles-select-item');
                console.log(subtitleElements)

                if (subtitleElements && subtitleElements.length > 0) {
                    // 遍历所有符合条件的元素
                    subtitleElements.forEach(element => {
                        console.log(element.textContent);
                        // 检查元素的文本内容是否为“中文字幕”
                        if (element.textContent.trim() === '中文字幕') {
                            clearInterval(interval); // 停止检测
                            console.log('检测到中文字幕,进行点击...');
                            element.click(); // 模拟点击操作
                            setTimeout(() => {
                                changeSubtitle();
                            }, 1000);
                        }
                    });
                }

            }, 2000);
        }

        function simulateMouseHoverToButton() {
            // 获取需要悬停的按钮
            const buttonElement = document.querySelector('.vp-video__control-bar--button.is-text');
            console.log(buttonElement);

            if (buttonElement) {
                // 创建一个鼠标事件
                const mouseOverEvent = new MouseEvent('mouseenter', {
                    view: window,
                    bubbles: true,
                    cancelable: true
                });

                // 触发鼠标悬停事件
                buttonElement.dispatchEvent(mouseOverEvent);
                console.log('鼠标悬停到按钮上');

                setTimeout(() => {

                    // 创建一个鼠标移开事件
                    const mouseLeaveEvent = new MouseEvent('mouseleave', {
                        view: window,
                        bubbles: true,
                        cancelable: true
                    });

                    // 触发鼠标移开事件
                    buttonElement.dispatchEvent(mouseLeaveEvent);
                    console.log('鼠标移开按钮');
                }, 500);
            } else {
                console.log('未找到需要悬停的按钮');
            }
        }



        // 下载字幕
        function clearResources() {
            performance.clearResourceTimings();
        }

        function sleep(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }

        async function retryOperation(operation, maxRetries = 3, delay = 1000) {
            for (let i = 0; i < maxRetries; i++) {
                try {
                    return await operation();
                } catch (error) {
                    if (i === maxRetries - 1) throw error;
                    console.log(`尝试失败,${maxRetries - i - 1}次重试后重新尝试`);
                    await sleep(delay);
                }
            }
        }

        async function findSubtitleUrl() {
            const resources = performance.getEntriesByType("resource");
            let matchedUrls = resources.filter(resource => resource.name.includes('netdisk-subtitle'));

            if (matchedUrls.length > 0) {
                let url = matchedUrls[matchedUrls.length - 1].name;
                console.log('找到匹配的URL:', url);
                return url;
            } else {
                throw new Error('未找到匹配的URL');
            }
        }

        async function downloadSubtitle() {
            const button = document.querySelector('li.vp-video__control-bar--video-subtitles-select-item.is-checked');
            if (button) {
                clearResources(); // 清理资源
                button.click();

                await sleep(500);

                try {
                    const url = await retryOperation(findSubtitleUrl);
                    const regex = /fn=(.*)\.mp4/;
                    let fileName = decodeURIComponent(url.match(regex)[1]) + '.srt';
                    console.log(fileName);

                    // 使用 Fetch 获取字幕文件内容
                    const response = await fetch(url);
                    if (!response.ok) throw new Error('获取字幕文件失败');

                    const subtitleText = await response.text();

                    // 创建一个 Blob 对象用于下载
                    const blob = new Blob([subtitleText], { type: 'text/plain' });
                    const link = document.createElement('a');
                    link.href = URL.createObjectURL(blob);
                    link.download = fileName;

                    // 自动点击下载链接
                    link.click();
                } catch (error) {
                    console.error('下载失败:', error);
                }
            } else {
                console.log('未找到字幕按钮');
            }
        }

        function addDownloadButton() {
        const controlBar = document.querySelector("#vjs_video_594 > section > div.vp-video__control-bar--setup > div:nth-child(1) > div > div.vp-inner-vontainer > div > div.vp-video__control-bar--video-subtitles > div > ul");
        if (controlBar) {
            let downloadButton = controlBar.querySelector('button.download-subtitle');

            if (!downloadButton) {
                // 如果按钮不存在,则创建一个新的按钮
                downloadButton = document.createElement('button');
                downloadButton.className = 'download-subtitle'; // 添加类名方便识别
                downloadButton.textContent = '下载字幕';
                downloadButton.style.cssText = `
                    background-color: #4CAF50;
                    border: none;
                    color: white;
                    padding: 5px 10px;
                    text-align: center;
                    text-decoration: none;
                    display: inline-block;
                    font-size: 14px;
                    margin: 4px 2px;
                    cursor: pointer;
                    border-radius: 4px;
                `;
                controlBar.appendChild(downloadButton);
            } else {
                // 如果按钮已经存在,更新其文本和事件监听器
                downloadButton.textContent = '下载字幕';
            }

            // 更新按钮的点击事件
            downloadButton.removeEventListener('click', downloadSubtitle); // 移除旧的事件处理器
            downloadButton.addEventListener('click', downloadSubtitle); // 添加新的事件处理器

            return true;
        }
        return false;
    }

        const observer1 = new MutationObserver((mutations, obs) => {
            if (addDownloadButton()) {
                obs.disconnect();
                return;
            }
        });

        const config = {
            childList: true,
            subtree: true
        };
        observer1.observe(document.body, config);

        setInterval(() => {
            if (!document.querySelector("#vjs_video_594 > section > div.vp-video__control-bar--setup > div:nth-child(1) > div > div.vp-inner-vontainer > div > div.vp-video__control-bar--video-subtitles > div > ul > button")) {
                addDownloadButton();
            }
        }, 1000);
    }
})();