Greasy Fork

岐黄天使刷课助手 - 视频播放模块

岐黄天使刷课助手的视频播放控制模块,负责视频的自动播放、暂停和状态管理。

当前为 2025-05-24 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/537083/1594828/%E5%B2%90%E9%BB%84%E5%A4%A9%E4%BD%BF%E5%88%B7%E8%AF%BE%E5%8A%A9%E6%89%8B%20-%20%E8%A7%86%E9%A2%91%E6%92%AD%E6%94%BE%E6%A8%A1%E5%9D%97.js

// ==UserScript==
// @name         岐黄天使刷课助手 - 视频播放模块
// @namespace    http://tampermonkey.net/qhtx-modules
// @version      1.3.0
// @description  岐黄天使刷课助手的视频播放控制模块,负责视频的自动播放、暂停和状态管理。
// @author       AI助手
// ==/UserScript==

// 视频播放模块
(function() {
    'use strict';

    // 切换自动学习状态
    window.toggleAutoLearn = function() {
        // 获取当前状态,如果GM_getValue不可用,则使用localStorage
        let isRunning;
        if (typeof GM_getValue !== 'undefined') {
            isRunning = GM_getValue('qh-is-running', false);
        } else {
            isRunning = localStorage.getItem('qh-is-running') === 'true';
        }

        // 切换状态
        isRunning = !isRunning;

        // 保存新状态
        if (typeof GM_setValue !== 'undefined') {
            GM_setValue('qh-is-running', isRunning);
        } else {
            localStorage.setItem('qh-is-running', isRunning.toString());
        }

        console.log('切换自动学习状态:', isRunning ? '开始' : '暂停');

        if (isRunning) {
            // 开始自动学习
            updateStatus('自动学习已开始');

            // 设置定时器,定期检查和播放视频
            if (!window.qh.autoPlayInterval) {
                window.qh.autoPlayInterval = setInterval(autoPlayVideo, 5000);

                // 立即执行一次
                setTimeout(autoPlayVideo, 500);
            }

            // 尝试播放所有视频
            setTimeout(() => {
                try {
                    // 直接调用视频播放函数
                    const videos = document.querySelectorAll('video');
                    if (videos.length > 0) {
                        updateStatus('找到视频,尝试播放');
                        console.log('找到视频,尝试播放');

                        videos.forEach(video => {
                            // 设置视频属性
                            video.loop = true;
                            video.muted = true;
                            video.playbackRate = 2.0;

                            // 尝试播放视频
                            try {
                                const playPromise = video.play();

                                if (playPromise !== undefined) {
                                    playPromise.then(() => {
                                        console.log('视频播放成功');
                                        updateStatus('视频播放成功');
                                    }).catch(error => {
                                        console.error('视频播放失败:', error);
                                        // 尝试使用其他方法播放
                                        setTimeout(() => {
                                            try {
                                                video.play();
                                            } catch (e) {
                                                console.error('重试播放失败:', e);
                                            }
                                        }, 1000);
                                    });
                                }
                            } catch (e) {
                                console.error('播放视频出错:', e);
                            }
                        });
                    }

                    // 检查iframe中的视频
                    const frames = document.querySelectorAll('iframe');
                    for (const frame of frames) {
                        try {
                            const frameDoc = frame.contentDocument || frame.contentWindow.document;
                            const frameVideos = frameDoc.querySelectorAll('video');

                            if (frameVideos.length > 0) {
                                updateStatus('在iframe中找到视频,尝试播放');
                                console.log('在iframe中找到视频,尝试播放');

                                frameVideos.forEach(video => {
                                    // 设置视频属性
                                    video.loop = false; // 不循环播放
                                    video.muted = true;
                                    // 不修改播放速度,使用默认速度

                                    // 尝试播放视频
                                    try {
                                        const playPromise = video.play();

                                        if (playPromise !== undefined) {
                                            playPromise.then(() => {
                                                console.log('iframe视频播放成功');
                                                updateStatus('iframe视频播放成功');
                                            }).catch(error => {
                                                console.error('iframe视频播放失败:', error);
                                                // 尝试使用其他方法播放
                                                setTimeout(() => {
                                                    try {
                                                        video.play();
                                                    } catch (e) {
                                                        console.error('重试播放iframe视频失败:', e);
                                                    }
                                                }, 1000);
                                            });
                                        }
                                    } catch (e) {
                                        console.error('播放iframe视频出错:', e);
                                    }
                                });
                            }
                        } catch (e) {
                            console.error('无法访问iframe内容:', e);
                        }
                    }
                } catch (e) {
                    console.error('播放视频出错:', e);
                }
            }, 1000);
        } else {
            // 暂停自动学习
            updateStatus('自动学习已暂停');

            // 清除定时器
            if (window.qh.autoPlayInterval) {
                clearInterval(window.qh.autoPlayInterval);
                window.qh.autoPlayInterval = null;
            }

            // 暂停所有视频
            pauseAllVideos();
        }

        // 更新按钮状态
        updateButtonStatus();
    };

    // 播放iframe中的视频
    window.playAllVideos = function() {
        // 尝试播放iframe中的视频
        const frames = document.querySelectorAll('iframe');
        frames.forEach(frame => {
            try {
                const frameDoc = frame.contentDocument || frame.contentWindow.document;
                const frameVideos = frameDoc.querySelectorAll('video');
                frameVideos.forEach(video => {
                    // 设置视频属性
                    video.loop = false; // 不循环播放
                    video.muted = true;
                    // 不修改播放速度,使用默认速度

                    // 尝试播放视频
                    try {
                        const playPromise = video.play();

                        // 处理播放承诺
                        if (playPromise !== undefined) {
                            playPromise.then(() => {
                                console.log('iframe视频播放成功');
                            }).catch(error => {
                                console.error('iframe视频播放失败:', error);
                                // 尝试使用其他方法播放
                                setTimeout(() => {
                                    try {
                                        video.play();
                                    } catch (e) {
                                        console.error('重试播放iframe视频失败:', e);
                                    }
                                }, 1000);
                            });
                        }
                    } catch (e) {
                        console.error('播放iframe视频出错:', e);
                    }
                });
            } catch (e) {
                console.error('无法访问iframe内容:', e);
            }
        });
    };

    // 暂停所有视频
    window.pauseAllVideos = function() {
        // 尝试暂停iframe中的视频
        const frames = document.querySelectorAll('iframe');
        frames.forEach(frame => {
            try {
                const frameDoc = frame.contentDocument || frame.contentWindow.document;
                const frameVideos = frameDoc.querySelectorAll('video');
                frameVideos.forEach(video => {
                    try {
                        video.pause();
                    } catch (e) {
                        console.error('暂停iframe视频出错:', e);
                    }
                });
            } catch (e) {
                console.error('无法访问iframe内容:', e);
            }
        });
    };

    // 主要功能:自动播放视频
    window.autoPlayVideo = function() {
        try {
            // 检查是否应该播放视频
            let isRunning;
            if (typeof GM_getValue !== 'undefined') {
                isRunning = GM_getValue('qh-is-running', false);
            } else {
                isRunning = localStorage.getItem('qh-is-running') === 'true';
            }

            if (!isRunning) {
                // 如果不是自动播放状态,则不执行后续操作
                return;
            }

            // 更新状态
            updateStatus('正在检测视频...');
            console.log('正在检测视频...');

            // 尝试查找视频元素
            let foundVideo = false;

            // 2. 检查所有iframe中的视频
            const frames = document.querySelectorAll('iframe');
            for (const frame of frames) {
                try {
                    const frameDoc = frame.contentDocument || frame.contentWindow.document;
                    const frameVideos = frameDoc.querySelectorAll('video');

                    if (frameVideos.length > 0) {
                        updateStatus('在iframe中找到视频,尝试播放');
                        console.log('在iframe中找到视频,尝试播放');

                        frameVideos.forEach(video => {
                            // 设置视频属性
                            video.loop = false; // 不循环播放
                            video.muted = true;

                            // 尝试获取视频标题
                            try {
                                // 尝试从iframe文档中获取标题
                                let videoTitle = '';

                                // 尝试从iframe标题获取
                                if (frameDoc.title && !frameDoc.title.includes('岐黄天使') && !frameDoc.title.includes('登录')) {
                                    videoTitle = frameDoc.title;
                                }

                                // 尝试从视频元素的父元素或周围元素获取标题
                                if (!videoTitle) {
                                    const videoContainer = video.closest('.video-container, .player-container, .course-player');
                                    if (videoContainer) {
                                        const titleElement = videoContainer.querySelector('.title, .video-title, .course-title');
                                        if (titleElement) {
                                            videoTitle = titleElement.textContent.trim();
                                        }
                                    }
                                }

                                // 尝试从iframe中的常见标题元素获取
                                if (!videoTitle) {
                                    const titleSelectors = [
                                        '.video-title', '.course-title', '.title',
                                        'h1.title', 'h2.title', 'h3.title',
                                        '.course-name', '.video-name', '.lesson-title',
                                        '#courseTitle', '#videoTitle', '#lessonTitle'
                                    ];

                                    for (const selector of titleSelectors) {
                                        const titleElement = frameDoc.querySelector(selector);
                                        if (titleElement && titleElement.textContent.trim()) {
                                            videoTitle = titleElement.textContent.trim();
                                            break;
                                        }
                                    }
                                }

                                // 如果找到标题,更新当前课程
                                if (videoTitle) {
                                    updateCurrentCourse(videoTitle);
                                } else {
                                    // 如果没有找到标题,尝试自动检测
                                    updateCurrentCourse(null);
                                }
                            } catch (e) {
                                console.error('获取iframe视频标题出错:', e);
                                // 出错时也尝试自动检测
                                updateCurrentCourse(null);
                            }

                            // 尝试播放视频
                            try {
                                const playPromise = video.play();

                                if (playPromise !== undefined) {
                                    playPromise.then(() => {
                                        console.log('iframe视频播放成功');
                                        updateStatus('iframe视频播放成功');
                                        // 再次尝试更新课程信息
                                        updateCurrentCourse(null);
                                    }).catch(error => {
                                        console.error('iframe视频播放失败:', error);
                                        // 尝试使用其他方法播放
                                        setTimeout(() => {
                                            try {
                                                video.play();
                                            } catch (e) {
                                                console.error('重试播放iframe视频失败:', e);
                                            }
                                        }, 1000);
                                    });
                                }
                            } catch (e) {
                                console.error('播放iframe视频出错:', e);
                            }

                            // 监听进度
                            video.addEventListener('timeupdate', function() {
                                const progress = Math.floor((video.currentTime / video.duration) * 100);
                                updateProgress(progress);
                            });

                            // 监听视频结束事件,自动切换到下一个视频
                            // 移除之前可能存在的事件监听器,避免重复添加
                            video.removeEventListener('ended', window.qh.videoEndedHandler);

                            // 创建新的事件处理函数并保存到全局变量
                            window.qh.videoEndedHandler = function() {
                                // 防止重复触发
                                if (window.qh.isNavigating) {
                                    console.log('导航已在进行中,忽略视频结束事件');
                                    return;
                                }

                                console.log('iframe视频播放完成,准备切换到下一个课程');
                                updateStatus('视频播放完成,准备切换到下一个课程');

                                // 设置导航状态标志
                                window.qh.isNavigating = true;

                                // 延迟一秒后切换到下一课
                                setTimeout(() => {
                                    // 查找当前课程元素
                                    const currentCourse = document.querySelector('.new_bg.active, .course-item.active, .lesson-item.active');
                                    if (currentCourse) {
                                        // 查找下一个课程元素
                                        let nextCourse = currentCourse.nextElementSibling;
                                        while (nextCourse && !(nextCourse.classList.contains('new_bg') || 
                                                             nextCourse.classList.contains('course-item') || 
                                                             nextCourse.classList.contains('lesson-item'))) {
                                            nextCourse = nextCourse.nextElementSibling;
                                        }
                                        
                                        // 如果找到下一个课程,点击它
                                        if (nextCourse) {
                                            nextCourse.click();
                                        } else {
                                            // 如果没有找到,尝试使用navigateToNextCourse函数
                                            if (typeof navigateToNextCourse === 'function') {
                                                navigateToNextCourse();
                                            }
                                        }
                                    } else {
                                        // 如果没有当前课程元素,尝试使用navigateToNextCourse函数
                                        if (typeof navigateToNextCourse === 'function') {
                                            navigateToNextCourse();
                                        }
                                    }

                                    // 5秒后重置导航状态标志,避免卡死
                                    setTimeout(() => {
                                        window.qh.isNavigating = false;
                                    }, 5000);
                                }, 1000);
                            };

                            // 添加新的事件监听器
                            video.addEventListener('ended', window.qh.videoEndedHandler);
                        });

                        foundVideo = true;
                    }
                } catch (e) {
                    console.error('无法访问iframe内容:', e);
                }
            }

            // 3. 如果没有找到视频,尝试查找未完成的课程
            if (!foundVideo) {
                updateStatus('未找到视频,尝试查找未完成的课程');
                console.log('未找到视频,尝试查找未完成的课程');

                // 尝试在当前页面查找未完成的课程
                findAndClickUnfinishedCourse(document);

                // 尝试在iframe中查找未完成的课程
                for (const frame of frames) {
                    try {
                        const frameDoc = frame.contentDocument || frame.contentWindow.document;
                        findAndClickUnfinishedCourse(frameDoc);
                    } catch (e) {
                        console.error('无法访问iframe内容:', e);
                    }
                }
            }

            // 4. 关闭可能出现的弹窗
            closePopups(document);
            for (const frame of frames) {
                try {
                    const frameDoc = frame.contentDocument || frame.contentWindow.document;
                    closePopups(frameDoc);
                } catch (e) {
                    console.error('无法访问iframe内容:', e);
                }
            }

            // 5. 检查进度指示器
            checkProgressIndicator(document);
            for (const frame of frames) {
                try {
                    const frameDoc = frame.contentDocument || frame.contentWindow.document;
                    checkProgressIndicator(frameDoc);
                } catch (e) {
                    console.error('无法访问iframe内容:', e);
                }
            }

            // 6. 收集课程链接
            if (typeof collectCourseLinks === 'function') {
                collectCourseLinks(document);
                for (const frame of frames) {
                    try {
                        const frameDoc = frame.contentDocument || frame.contentWindow.document;
                        collectCourseLinks(frameDoc);
                    } catch (e) {
                        console.error('无法访问iframe内容:', e);
                    }
                }
            }
        } catch (e) {
            console.error('自动播放视频出错:', e);
            updateStatus('自动播放视频出错: ' + e.message);
        }
    };

    // 查找并点击未完成的课程
    window.findAndClickUnfinishedCourse = function(doc) {
        // 查找未完成的视频链接
        const unfinishedLinks = doc.querySelectorAll('.append-plugin-tip > a, .content-unstart a, .content-learning a');
        if (unfinishedLinks.length > 0) {
            updateStatus('找到未完成的课程,即将播放');

            // 收集所有课程链接,用于上一课/下一课导航
            if (typeof collectCourseLinks === 'function') {
                collectCourseLinks(doc);
            }

            // 点击第一个未完成的课程
            try {
                unfinishedLinks[0].click();
            } catch (e) {
                console.error('点击未完成课程失败:', e);
                updateStatus('点击未完成课程失败');
            }
        } else {
            updateStatus('未找到未完成的课程,可能已全部完成');

            // 检查是否有课程列表
            const coursesInList = doc.querySelectorAll('.mycourse-row');
            if (coursesInList.length > 0) {
                // 收集课程列表
                if (typeof collectCoursesFromList === 'function') {
                    collectCoursesFromList(doc);
                }

                // 遍历课程列表,查找未完成的课程
                for (let i = 0; i < coursesInList.length; i++) {
                    const courseRow = coursesInList[i];
                    const courseState = courseRow.innerText.includes('未完成') || courseRow.innerText.includes('未开始');

                    if (courseState) {
                        updateStatus('在课程列表中找到未完成课程,即将打开');

                        try {
                            const courseLink = courseRow.querySelector('a');
                            if (courseLink) {
                                courseLink.click();
                                break;
                            }
                        } catch (e) {
                            console.error('点击课程列表中的未完成课程失败:', e);
                        }
                    }
                }
            }
        }
    };

    // 检查进度指示器
    window.checkProgressIndicator = function(doc) {
        // 首先尝试从<div class="jc_hd w-80">当前视频已观看时长:<span id="schedule">100%</span>获取进度
        const scheduleElement = doc.getElementById('schedule');
        if (scheduleElement) {
            const progressText = scheduleElement.textContent.trim();
            const progressMatch = progressText.match(/(\d+)%/);
            if (progressMatch && progressMatch[1]) {
                const progress = parseInt(progressMatch[1]);
                console.log('从schedule元素获取到进度:', progress + '%');
                updateProgress(progress);

                // 如果进度为100%,自动切换到下一个课程
                if (progress === 100) {
                    // 防止重复触发
                    if (window.qh.isNavigating) {
                        console.log('导航已在进行中,忽略进度100%事件');
                        return;
                    }

                    console.log('当前视频已完成,准备切换到下一个课程');
                    updateStatus('视频播放完成,准备切换到下一个课程');

                    // 设置导航状态标志
                    window.qh.isNavigating = true;

                    // 延迟一秒后切换到下一课
                    setTimeout(() => {
                        // 使用navigateToNextCourse函数切换到下一课
                        if (typeof navigateToNextCourse === 'function') {
                            navigateToNextCourse();
                        }

                        // 5秒后重置导航状态标志,避免卡死
                        setTimeout(() => {
                            window.qh.isNavigating = false;
                        }, 5000);
                    }, 1000);
                }
                return;
            }
        }

        // 如果没有找到schedule元素,尝试其他进度指示器
        const progressIndicator = doc.getElementById('realPlayVideoTime');
        if (progressIndicator) {
            const progress = parseInt(progressIndicator.innerText);
            updateProgress(progress);

            // 如果进度为100%,自动切换到下一个课程
            if (progress === 100) {
                // 防止重复触发
                if (window.qh.isNavigating) {
                    console.log('导航已在进行中,忽略进度100%事件');
                    return;
                }

                console.log('当前视频已完成,准备切换到下一个课程');
                updateStatus('视频播放完成,准备切换到下一个课程');

                // 设置导航状态标志
                window.qh.isNavigating = true;

                // 延迟一秒后切换到下一课
                setTimeout(() => {
                    // 使用navigateToNextCourse函数切换到下一课
                    if (typeof navigateToNextCourse === 'function') {
                        navigateToNextCourse();
                    }

                    // 5秒后重置导航状态标志,避免卡死
                    setTimeout(() => {
                        window.qh.isNavigating = false;
                    }, 5000);
                }, 1000);
            }
        }

        // 尝试查找其他可能的进度指示器
        const jcHdElements = doc.querySelectorAll('.jc_hd');
        for (const jcHd of jcHdElements) {
            if (jcHd.textContent.includes('当前视频已观看时长')) {
                const progressText = jcHd.textContent;
                const progressMatch = progressText.match(/(\d+)%/);
                if (progressMatch && progressMatch[1]) {
                    const progress = parseInt(progressMatch[1]);
                    console.log('从jc_hd元素获取到进度:', progress + '%');
                    updateProgress(progress);

                    // 如果进度为100%,自动切换到下一个课程
                    if (progress === 100) {
                        // 防止重复触发
                        if (window.qh.isNavigating) {
                            console.log('导航已在进行中,忽略进度100%事件');
                            return;
                        }

                        console.log('当前视频已完成,准备切换到下一个课程');
                        updateStatus('视频播放完成,准备切换到下一个课程');

                        // 设置导航状态标志
                        window.qh.isNavigating = true;

                        // 延迟一秒后切换到下一课
                        setTimeout(() => {
                            // 使用navigateToNextCourse函数切换到下一课
                            if (typeof navigateToNextCourse === 'function') {
                                navigateToNextCourse();
                            }

                            // 5秒后重置导航状态标志,避免卡死
                            setTimeout(() => {
                                window.qh.isNavigating = false;
                            }, 5000);
                        }, 1000);
                    }
                    return;
                }
            }
        }
    };
})();