Greasy Fork

Greasy Fork is available in English.

国家中小学智慧教育平台助手(修复版)

智慧教育平台功能增强:实际倍速播放、伪装播放速率、自动播放、后台播放、自动切换下一节、保持活跃

// ==UserScript==
// @name         国家中小学智慧教育平台助手(修复版)
// @namespace    http://tampermonkey.net/
// @version      1.0.2
// @description  智慧教育平台功能增强:实际倍速播放、伪装播放速率、自动播放、后台播放、自动切换下一节、保持活跃
// @author       wsbg
// @match        https://basic.smartedu.cn/*
// @grant        none
// @run-at       document-idle
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 用户配置
    const CONFIG = {
        playbackRate: 1.5,      // 实际播放速度
        fakeRate: 1.0,          // 伪装的播放速度
        autoPlay: true,         // 自动播放
        backgroundPlay: true,   // 后台播放
        autoNext: true,         // 自动切换下一节
        keepActive: true,       // 保持活跃
        keepActiveInterval: 60  // 活跃间隔(秒)
    };

    // 全局变量
    let videoPlayer = null;
    let originalPlaybackRateDescriptor = null;

    // 主函数,等待视频元素加载
    const initEnhancement = () => {
        // 查找视频元素
        const video = findVideoElement();
        if (!video) {
            console.log('[智慧教育平台助手] 等待视频元素...');
            setTimeout(initEnhancement, 1000);
            return;
        }

        console.log('[智慧教育平台助手] 视频元素已找到,开始增强功能');
        videoPlayer = video;
        enhanceVideo(video);
    };

    // 查找视频元素
    const findVideoElement = () => {
        // 尝试查找可能的视频元素
        const videoElements = document.querySelectorAll('video');
        if (videoElements.length > 0) {
            return videoElements[0];
        }

        // 寻找可能嵌入在iframe中的视频
        const iframes = document.querySelectorAll('iframe');
        for (const iframe of iframes) {
            try {
                const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                const iframeVideos = iframeDoc.querySelectorAll('video');
                if (iframeVideos.length > 0) {
                    return iframeVideos[0];
                }
            } catch (e) {
                // 跨域iframe无法访问
                console.log('[智慧教育平台助手] 无法访问iframe内容');
            }
        }

        return null;
    };

    // 增强视频功能
    const enhanceVideo = (video) => {
        // 保存视频引用
        videoPlayer = video;

        try {
            // 1. 实际倍速播放与伪装播放速率
            applyPlaybackRateHack(video);

            // 2. 自动播放
            if (CONFIG.autoPlay) {
                applyAutoPlay(video);
            }

            // 3. 后台播放
            if (CONFIG.backgroundPlay) {
                applyBackgroundPlay();
            }

            // 4. 视频播放完自动切换下一节
            if (CONFIG.autoNext) {
                applyAutoNext(video);
            }

            // 5. 保持活跃
            if (CONFIG.keepActive) {
                applyKeepActive();
            }

            // 添加控制面板
            addControlPanel();
        } catch (e) {
            console.error('[智慧教育平台助手] 增强视频功能时出错:', e);
        }
    };

    // 应用播放速率hack
    const applyPlaybackRateHack = (video) => {
        try {
            // 方法1: 直接设置视频元素的播放速率
            const directPlaybackRateSet = () => {
                // 存储原始播放速率
                const originalRate = video.playbackRate;
                console.log(`[智慧教育平台助手] 原始播放速率: ${originalRate}`);

                // 使用原始的setter设置实际播放速率
                video.playbackRate = CONFIG.playbackRate;
                console.log(`[智慧教育平台助手] 已设置播放速率: ${CONFIG.playbackRate}x`);

                // 监听速率变化,保持我们想要的速率
                const playbackObserver = new MutationObserver(function() {
                    if (video.playbackRate !== CONFIG.playbackRate) {
                        console.log(`[智慧教育平台助手] 检测到播放速率被修改为 ${video.playbackRate},重置为 ${CONFIG.playbackRate}`);
                        video.playbackRate = CONFIG.playbackRate;
                    }
                });

                // 定期检查播放速率
                setInterval(() => {
                    if (video.playbackRate !== CONFIG.playbackRate) {
                        console.log(`[智慧教育平台助手] 定期检查: 播放速率被修改为 ${video.playbackRate},重置为 ${CONFIG.playbackRate}`);
                        video.playbackRate = CONFIG.playbackRate;
                    }
                }, 1000);

                // 方法2: 尝试拦截可能的播放速率API
                try {
                    // 为视频播放器添加自定义属性
                    video._originalPlaybackRate = video.playbackRate;
                    video._customPlaybackRate = CONFIG.playbackRate;

                    // 保存原始描述符
                    originalPlaybackRateDescriptor = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'playbackRate');

                    if (originalPlaybackRateDescriptor) {
                        // 重写playbackRate属性
                        Object.defineProperty(video, 'playbackRate', {
                            get: function() {
                                return CONFIG.fakeRate; // 返回伪装的速率
                            },
                            set: function(value) {
                                console.log(`[智慧教育平台助手] 拦截到播放速率设置: ${value},实际使用: ${CONFIG.playbackRate}`);
                                this._originalPlaybackRate = value; // 记录原始请求的速率
                                originalPlaybackRateDescriptor.set.call(this, CONFIG.playbackRate); // 使用我们想要的速率
                            },
                            configurable: true
                        });
                    }
                } catch(e) {
                    console.error('[智慧教育平台助手] 重写playbackRate属性失败:', e);
                }
            };

            // 执行播放速率设置
            directPlaybackRateSet();

            // 视频恢复播放时,确保速率正确
            video.addEventListener('play', function() {
                setTimeout(() => {
                    video.playbackRate = CONFIG.playbackRate;
                }, 100);
            });

            console.log(`[智慧教育平台助手] 已应用播放速率:实际${CONFIG.playbackRate}x,伪装${CONFIG.fakeRate}x`);

        } catch (e) {
            console.error('[智慧教育平台助手] 应用播放速率hack失败:', e);
        }
    };

    // 应用自动播放
    const applyAutoPlay = (video) => {
        try {
            const tryPlay = () => {
                if (video && video.paused) {
                    const playPromise = video.play();
                    if (playPromise !== undefined) {
                        playPromise.catch(error => {
                            console.log('[智慧教育平台助手] 自动播放被阻止,等待用户交互:', error);

                            // 监听用户交互后再播放
                            const playOnInteraction = () => {
                                if (video && video.paused) {
                                    video.play().catch(e => console.log('[智慧教育平台助手] 用户交互后播放失败:', e));
                                }
                                document.removeEventListener('click', playOnInteraction);
                                document.removeEventListener('keydown', playOnInteraction);
                            };
                            document.addEventListener('click', playOnInteraction);
                            document.addEventListener('keydown', playOnInteraction);
                        });
                    }
                }
            };

            // 尝试自动播放
            setTimeout(tryPlay, 1000);

            // 处理可能的暂停事件
            video.addEventListener('pause', () => {
                if (CONFIG.autoPlay && !video.ended) {
                    console.log('[智慧教育平台助手] 视频被暂停,尝试继续播放');
                    setTimeout(() => {
                        if (video && video.paused && !video.ended) {
                            video.play().catch(e => console.log('[智慧教育平台助手] 无法自动恢复播放:', e));
                        }
                    }, 500);
                }
            });

            console.log('[智慧教育平台助手] 已应用自动播放');
        } catch (e) {
            console.error('[智慧教育平台助手] 应用自动播放失败:', e);
        }
    };

    // 应用后台播放
    const applyBackgroundPlay = () => {
        try {
            // 覆盖页面可见性API
            let originalVisibilityState = null;
            try {
                originalVisibilityState = Object.getOwnPropertyDescriptor(Document.prototype, 'visibilityState');
                Object.defineProperty(Document.prototype, 'visibilityState', {
                    get: function() {
                        return 'visible';
                    }
                });
            } catch (e) {
                console.error('[智慧教育平台助手] 覆盖visibilityState失败:', e);
            }

            let originalHidden = null;
            try {
                originalHidden = Object.getOwnPropertyDescriptor(Document.prototype, 'hidden');
                Object.defineProperty(Document.prototype, 'hidden', {
                    get: function() {
                        return false;
                    }
                });
            } catch (e) {
                console.error('[智慧教育平台助手] 覆盖hidden失败:', e);
            }

            // 阻止visibilitychange事件
            const visibilityHandler = (e) => {
                e.stopImmediatePropagation();
            };

            document.addEventListener('visibilitychange', visibilityHandler, true);

            // 定期检查视频是否因为后台而暂停
            setInterval(() => {
                if (CONFIG.backgroundPlay && videoPlayer && videoPlayer.paused && !videoPlayer.ended) {
                    console.log('[智慧教育平台助手] 检测到可能的后台暂停,尝试继续播放');
                    videoPlayer.play().catch(e => {});
                }
            }, 2000);

            console.log('[智慧教育平台助手] 已应用后台播放');
        } catch (e) {
            console.error('[智慧教育平台助手] 应用后台播放失败:', e);
        }
    };

    // 应用自动切换下一节
    const applyAutoNext = (video) => {
        try {
            const endedHandler = () => {
                console.log('[智慧教育平台助手] 视频播放完毕,准备切换下一节');

                // 等待一段时间,确保所有结束处理已完成
                setTimeout(() => {
                    // 查找可能的"下一节"按钮
                    const nextButtons = findNextButton();

                    if (nextButtons.length > 0) {
                        console.log('[智慧教育平台助手] 找到下一节按钮,点击切换');
                        nextButtons[0].click();
                    } else {
                        console.log('[智慧教育平台助手] 未找到下一节按钮,尝试其他方法');

                        // 另一种尝试:查找可能的下一章节链接
                        tryFindNextChapter();
                    }
                }, 2000);
            };

            // 监听视频结束事件
            video.addEventListener('ended', endedHandler);

            console.log('[智慧教育平台助手] 已应用自动切换下一节');
        } catch (e) {
            console.error('[智慧教育平台助手] 应用自动切换下一节失败:', e);
        }
    };

    // 查找下一节按钮
    const findNextButton = () => {
        // 尝试多种可能的选择器和文本内容
        const buttonSelectors = [
            'button', '.btn', '.button', '[class*="next"]', '[id*="next"]',
            '[class*="下一"]', '[id*="下一"]', 'a[href]', '.ant-btn'
        ];

        const possibleNextTexts = ['next', '下一', '下一节', '下一课', '继续学习', '继续', '下一页'];

        // 搜集所有可能的按钮
        const allPossibleButtons = [];
        buttonSelectors.forEach(selector => {
            document.querySelectorAll(selector).forEach(btn => {
                allPossibleButtons.push(btn);
            });
        });

        // 过滤可能的"下一节"按钮
        return allPossibleButtons.filter(el => {
            const text = (el.textContent || '').toLowerCase();
            return possibleNextTexts.some(nextText => text.includes(nextText));
        });
    };

    // 尝试查找下一章节
    const tryFindNextChapter = () => {
        // 尝试查找章节列表中的活跃项,然后点击下一个
        const chapterItems = document.querySelectorAll('.chapter-item, .lesson-item, [class*="chapter"], [class*="lesson"]');
        let activeIndex = -1;

        // 查找当前活跃章节
        for (let i = 0; i < chapterItems.length; i++) {
            if (chapterItems[i].classList.contains('active') ||
                chapterItems[i].querySelector('.active')) {
                activeIndex = i;
                break;
            }
        }

        // 如果找到活跃章节,点击下一个
        if (activeIndex !== -1 && activeIndex < chapterItems.length - 1) {
            console.log('[智慧教育平台助手] 尝试点击下一章节');
            chapterItems[activeIndex + 1].click();
        }
    };

    // 应用保持活跃
    const applyKeepActive = () => {
        try {
            const keepAliveInterval = setInterval(() => {
                if (!CONFIG.keepActive) {
                    clearInterval(keepAliveInterval);
                    return;
                }

                // 模拟鼠标移动
                const eventOptions = {
                    view: window,
                    bubbles: true,
                    cancelable: true,
                    clientX: Math.floor(Math.random() * window.innerWidth),
                    clientY: Math.floor(Math.random() * window.innerHeight)
                };

                const moveEvent = new MouseEvent('mousemove', eventOptions);
                document.dispatchEvent(moveEvent);

                // 额外模拟轻微鼠标移动,更逼真
                setTimeout(() => {
                    const smallMoveEvent = new MouseEvent('mousemove', {
                        ...eventOptions,
                        clientX: eventOptions.clientX + 5,
                        clientY: eventOptions.clientY + 3
                    });
                    document.dispatchEvent(smallMoveEvent);
                }, 100);

                console.log('[智慧教育平台助手] 模拟活跃操作');

                // 检查视频是否播放,如果暂停了就尝试继续播放
                if (videoPlayer && videoPlayer.paused && !videoPlayer.ended && CONFIG.autoPlay) {
                    videoPlayer.play().catch(e => {});
                }

                // 检查并重置播放速率
                if (videoPlayer && videoPlayer.playbackRate !== CONFIG.playbackRate) {
                    videoPlayer.playbackRate = CONFIG.playbackRate;
                }

            }, CONFIG.keepActiveInterval * 1000);

            console.log('[智慧教育平台助手] 已应用保持活跃');
        } catch (e) {
            console.error('[智慧教育平台助手] 应用保持活跃失败:', e);
        }
    };

    // 添加控制面板
    const addControlPanel = () => {
        try {
            // 检查是否已存在面板
            if (document.getElementById('edu-helper-panel')) {
                return;
            }

            const panel = document.createElement('div');
            panel.id = 'edu-helper-panel';
            panel.style.cssText = `
                position: fixed;
                top: 10px;
                right: 10px;
                background: rgba(0, 0, 0, 0.7);
                color: white;
                padding: 10px;
                border-radius: 5px;
                z-index: 9999;
                font-size: 12px;
                transition: opacity 0.3s;
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
            `;

            panel.innerHTML = `
                <div style="text-align: center; margin-bottom: 5px; font-weight: bold;">智慧教育平台助手</div>
                <div>
                    <label>实际倍速:
                        <input type="number" id="edu-helper-rate" min="0.5" max="16" step="0.25" value="${CONFIG.playbackRate}" style="width: 50px; background: rgba(255, 255, 255, 0.2); color: white; border: 1px solid #555;">
                    </label>
                </div>
                <div style="margin-top: 5px;">
                    <label><input type="checkbox" id="edu-helper-autoplay" ${CONFIG.autoPlay ? 'checked' : ''}> 自动播放</label>
                </div>
                <div>
                    <label><input type="checkbox" id="edu-helper-background" ${CONFIG.backgroundPlay ? 'checked' : ''}> 后台播放</label>
                </div>
                <div>
                    <label><input type="checkbox" id="edu-helper-autonext" ${CONFIG.autoNext ? 'checked' : ''}> 自动下一节</label>
                </div>
                <div>
                    <label><input type="checkbox" id="edu-helper-keepactive" ${CONFIG.keepActive ? 'checked' : ''}> 保持活跃</label>
                </div>
                <div style="margin-top: 5px; text-align: center; font-size: 10px; opacity: 0.7;">
                    点击面板外区域隐藏
                </div>
            `;

            // 悬浮效果
            let isPanelVisible = true;
            panel.addEventListener('mouseenter', () => {
                panel.style.opacity = '1';
            });

            panel.addEventListener('mouseleave', () => {
                if (!isPanelVisible) {
                    panel.style.opacity = '0.3';
                }
            });

            document.addEventListener('click', (e) => {
                if (!panel.contains(e.target)) {
                    isPanelVisible = false;
                    panel.style.opacity = '0.3';
                } else {
                    isPanelVisible = true;
                    panel.style.opacity = '1';
                }
            });

            document.body.appendChild(panel);

            // 添加事件监听
            document.getElementById('edu-helper-rate').addEventListener('change', (e) => {
                CONFIG.playbackRate = parseFloat(e.target.value);
                if (videoPlayer) {
                    videoPlayer.playbackRate = CONFIG.playbackRate;
                    console.log(`[智慧教育平台助手] 已更新播放速率: ${CONFIG.playbackRate}x`);
                }
            });

            document.getElementById('edu-helper-autoplay').addEventListener('change', (e) => {
                CONFIG.autoPlay = e.target.checked;
                console.log(`[智慧教育平台助手] 自动播放: ${CONFIG.autoPlay ? '开启' : '关闭'}`);
            });

            document.getElementById('edu-helper-background').addEventListener('change', (e) => {
                CONFIG.backgroundPlay = e.target.checked;
                console.log(`[智慧教育平台助手] 后台播放: ${CONFIG.backgroundPlay ? '开启' : '关闭'}`);
            });

            document.getElementById('edu-helper-autonext').addEventListener('change', (e) => {
                CONFIG.autoNext = e.target.checked;
                console.log(`[智慧教育平台助手] 自动下一节: ${CONFIG.autoNext ? '开启' : '关闭'}`);
            });

            document.getElementById('edu-helper-keepactive').addEventListener('change', (e) => {
                CONFIG.keepActive = e.target.checked;
                console.log(`[智慧教育平台助手] 保持活跃: ${CONFIG.keepActive ? '开启' : '关闭'}`);
            });

            console.log('[智慧教育平台助手] 已添加控制面板');
        } catch (e) {
            console.error('[智慧教育平台助手] 添加控制面板失败:', e);
        }
    };

    // 启动脚本
    setTimeout(initEnhancement, 1500);

    console.log('[智慧教育平台助手] 脚本已加载');
})();