// ==UserScript== // @name 海南干部网络学院学习助手3.2 // @namespace http://tampermonkey.net/ // @version 3.2 // @description 自动检测并播放视频,解除网页快进检测限制,播放到最后60秒 // @author denglao // @match https://www.higbwlxy.gov.cn/#/play* // @grant none // ==/UserScript== (function() { 'use strict'; // 配置参数 const CONFIG = { END_SECONDS: 60, // 播放到最后60秒 CHECK_INTERVAL: 500, // 检查间隔(毫秒) SEEK_INTERVAL: 3000, // 每次快进间隔(毫秒) SEEK_STEP: 10, // 每次快进步长(秒) AUTO_PLAY_DELAY: 1000, // 自动播放延迟(毫秒) }; let videoElement = null; let isProcessing = false; let isFirstSeek = true; let seekTimer = null; let autoPlayAttempts = 0; const MAX_AUTO_PLAY_ATTEMPTS = 10; // 查找视频元素 function findVideo() { const selectors = [ 'video', '#mse video', '.my-video video', 'xg-video video', '[data-xgplayerid] video', '.video-js video', '#video video', 'video[src]' ]; for (const selector of selectors) { const video = document.querySelector(selector); if (video) { return video; } } return null; } // 点击播放按钮 function clickPlayButton() { // 尝试多种选择器找到播放按钮 const playButtonSelectors = [ '.xgplayer-play', '.video-play-btn', '.play-button', '.vjs-big-play-button', '.player-play', 'button[aria-label="播放"]', 'button.play', '.play-btn' ]; for (const selector of playButtonSelectors) { const button = document.querySelector(selector); if (button) { console.log('[自动刷视频] 找到播放按钮,尝试点击'); button.click(); return true; } } return false; } // 自动播放视频 function autoPlayVideo(video) { if (!video) return; // 方法1: 直接调用 play() if (video.paused) { video.play().then(() => { console.log('[自动刷视频] 视频已自动播放'); }).catch((err) => { console.log('[自动刷视频] 自动播放失败,尝试点击播放按钮'); // 方法2: 点击播放按钮 clickPlayButton(); }); } else { console.log('[自动刷视频] 视频已经在播放'); } } // 逐步快进(模拟正常播放进度) function gradualSeek(video) { if (!video || isNaN(video.duration) || video.duration === 0) return; const targetTime = video.duration - CONFIG.END_SECONDS; const currentTime = video.currentTime; // 计算本次快进的目标时间 let newTime = currentTime + CONFIG.SEEK_STEP; // 如果超过目标时间,直接跳到目标时间 if (newTime >= targetTime) { newTime = targetTime; console.log(`[自动刷视频] 已到达目标位置: ${formatTime(targetTime)}`); clearInterval(seekTimer); seekTimer = null; } // 执行快进 video.currentTime = newTime; console.log(`[自动刷视频] 逐步快进: ${formatTime(currentTime)} -> ${formatTime(newTime)}`); // 确保播放 if (video.paused) { video.play().catch(() => {}); } } // 快进到指定时间 function seekToTime(video, seconds) { if (video && !isNaN(video.duration)) { const targetTime = Math.max(0, video.duration - seconds); video.currentTime = targetTime; console.log(`[自动刷视频] 快进到: ${formatTime(targetTime)}`); } } // 格式化时间显示 function formatTime(seconds) { const m = Math.floor(seconds / 60); const s = Math.floor(seconds % 60); return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`; } // 深度拦截 - 覆盖视频元素的属性设置 function deepIntercept(video) { if (!video) return; // 拦截 currentTime 的 setter let _currentTime = video.currentTime; Object.defineProperty(video, 'currentTime', { get: function() { return _currentTime; }, set: function(value) { console.log(`[自动刷视频] currentTime 被设置: ${formatTime(value)}`); _currentTime = value; }, configurable: true }); // 拦截播放速率 Object.defineProperty(video, 'playbackRate', { get: function() { return 1; }, set: function(value) { console.log(`[自动刷视频] 检测到播放速率被设置为: ${value}`); }, configurable: true }); // 拦截 paused 属性 Object.defineProperty(video, 'paused', { get: function() { return false; }, configurable: true }); } // 解除快进检测限制 - 核心功能 function bypassSeekDetection(video) { if (!video) return; // 深度拦截属性 deepIntercept(video); // 方法1: 拦截 timeupdate 事件 video.addEventListener('timeupdate', function(e) { if (!isNaN(video.duration) && video.duration > 0) { const targetTime = video.duration - CONFIG.END_SECONDS; if (video.currentTime < targetTime - 10) { console.log('[自动刷视频] 检测到时间被重置,重新快进'); video.currentTime = targetTime; } } }, false); // 方法2: 拦截 seeked 事件 video.addEventListener('seeked', function(e) { if (!isNaN(video.duration) && video.duration > 0) { const targetTime = video.duration - CONFIG.END_SECONDS; if (video.currentTime < targetTime - 30) { console.log('[自动刷视频] 检测到快进后被重置,重新定位'); video.currentTime = targetTime; } } }, false); // 方法3: 拦截 played 事件 video.addEventListener('play', function(e) { console.log('[自动刷视频] 视频开始播放'); }, false); // 方法4: 拦截 pause 事件 video.addEventListener('pause', function(e) { setTimeout(() => { if (video.paused && !isNaN(video.duration) && video.duration > 0) { const targetTime = video.duration - CONFIG.END_SECONDS; if (video.currentTime >= targetTime - 5) { console.log('[自动刷视频] 视频在末尾被暂停,自动继续播放'); video.play().catch(() => {}); } } }, 100); }, false); // 方法5: 拦截 error 事件 video.addEventListener('error', function(e) { console.log('[自动刷视频] 视频发生错误,尝试恢复'); if (!isNaN(video.duration) && video.duration > 0) { video.currentTime = video.duration - CONFIG.END_SECONDS; video.play().catch(() => {}); } }, false); } // 检查视频是否播放完毕 function isVideoEnded(video) { if (!video || !video.duration) return false; const endTime = video.duration - CONFIG.END_SECONDS; return video.currentTime >= endTime; } // 主循环 function mainLoop() { if (isProcessing) return; isProcessing = true; try { // 查找视频元素 if (!videoElement || !videoElement.src) { videoElement = findVideo(); } if (!videoElement) { console.log('[自动刷视频] 未找到视频元素,继续等待...'); return; } // 确保视频元数据已加载 if (isNaN(videoElement.duration) || videoElement.duration === 0) { console.log('[自动刷视频] 等待视频加载...'); return; } // 如果是第一次运行,启动自动播放和逐步快进 if (isFirstSeek) { console.log('[自动刷视频] 首次运行,尝试自动播放'); isFirstSeek = false; // 尝试自动播放 autoPlayVideo(videoElement); // 清除之前的定时器 if (seekTimer) { clearInterval(seekTimer); } // 启动逐步快进 seekTimer = setInterval(() => gradualSeek(videoElement), CONFIG.SEEK_INTERVAL); return; } // 如果视频已结束,重新开始 if (isVideoEnded(videoElement)) { console.log('[自动刷视频] 视频播放完毕,重新开始'); seekToTime(videoElement, CONFIG.END_SECONDS + 1); videoElement.play().catch(() => {}); return; } // 如果视频暂停,尝试恢复播放 if (videoElement.paused) { console.log('[自动刷视频] 视频暂停,尝试恢复'); videoElement.play().catch(() => {}); } // 检查是否被重置到开头 const targetTime = videoElement.duration - CONFIG.END_SECONDS; if (videoElement.currentTime < targetTime - 30) { console.log('[自动刷视频] 检测到时间被重置,重新快进'); videoElement.currentTime = targetTime; } } catch (error) { console.error('[自动刷视频] 发生错误:', error); } finally { isProcessing = false; } } // 初始化 function init() { console.log('[自动刷视频] 脚本已启动 (自动播放模式 v5 - 最后60秒)'); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', startScript); } else { startScript(); } } function startScript() { // 延迟等待视频元素完全加载 setTimeout(() => { // 查找视频并解除限制 const video = findVideo(); if (video) { console.log('[自动刷视频] 找到视频元素,应用解除限制'); bypassSeekDetection(video); // 监听视频加载事件 video.addEventListener('loadedmetadata', () => { console.log('[自动刷视频] 视频元数据已加载'); isFirstSeek = true; }); // 立即执行一次 mainLoop(); // 设置定时器循环执行 setInterval(mainLoop, CONFIG.CHECK_INTERVAL); } else { console.log('[自动刷视频] 未找到视频,重试中...'); setTimeout(startScript, 2000); } }, CONFIG.AUTO_PLAY_DELAY); } // 启动脚本 init(); // 创建倒计时显示元素 function createCountdownElement() { // 如果已存在则移除,避免重复创建 const existing = document.getElementById('study-countdown'); if (existing) existing.remove(); const div = document.createElement('div'); div.id = 'study-countdown'; div.style.cssText = ` position: fixed; top: 80%; left: 50%; transform: translate(-50%, -50%); z-index: 99999; background: rgba(0, 0, 0, 0.8); color: #fff; padding: 30px 50px; border-radius: 15px; font-size: 28px; font-weight: bold; text-align: center; box-shadow: 0 0 30px rgba(0, 0, 0, 0.5); font-family: 'Microsoft YaHei', sans-serif; line-height: 1.5; pointer-events: none; user-select: none; border: 2px solid rgba(255, 255, 255, 0.2); `; document.body.appendChild(div); return div; } // 启动倒计时 function startCountdown() { const countdownElement = createCountdownElement(); let remainingSeconds = 100; // 更新倒计时显示 function updateDisplay() { if (remainingSeconds > 0) { countdownElement.innerHTML = `本视频距离学习完成还剩 ${remainingSeconds} 秒`; } else { countdownElement.innerHTML = '🎉 已经学完了,可以关闭视频了。如果发现未完成请重新学。'; countdownElement.style.background = 'rgba(0, 128, 0, 0.8)'; countdownElement.style.border = '2px solid rgba(255, 255, 255, 0.4)'; clearInterval(timer); } } // 初始显示 updateDisplay(); // 每秒更新 const timer = setInterval(() => { remainingSeconds--; updateDisplay(); }, 1000); } // 等待DOM加载完成后执行 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', startCountdown); } else { startCountdown(); } })();