// ==UserScript== // @name 盐城师范学院专业技术人员继续教育平台(盐城人才在线)视频解锁 // @namespace https://yctc.ycrczx.com/ // @version 2.0 // @description 解除视频快进限制、自动播放、秒杀最后3秒 // @author Marvis // @match https://yctc.ycrczx.com/video/* // @grant none // @run-at document-start // @license MIT // ==/UserScript== (function() { 'use strict'; // ========== 策略1:拦截 seeking 事件,阻止网站将播放位置弹回 ========== function unlockSeek() { const videos = document.querySelectorAll('video'); videos.forEach(video => { // 劫持 addEventListener,阻止 seeking 相关的事件监听 const origAddEventListener = EventTarget.prototype.addEventListener; const blockedEvents = ['seeking', 'seeked', 'timeupdate']; EventTarget.prototype.addEventListener = function(type, listener, options) { if (this instanceof HTMLVideoElement && blockedEvents.includes(type)) { console.log('[解锁脚本] 已拦截视频事件监听:', type); return; } return origAddEventListener.call(this, type, listener, options); }; // 直接给已有 video 解除限制 video.addEventListener = function() {}; video.removeAttribute('disableRemotePlayback'); video.controls = true; }); } // ========== 策略2:清除网站的 seeking 限制逻辑 ========== function overrideSeekRestriction() { // 代理 video 的 currentTime setter,阻止被重置 const videoProto = HTMLMediaElement.prototype; const origCurrentTimeDescriptor = Object.getOwnPropertyDescriptor(videoProto, 'currentTime'); Object.defineProperty(videoProto, 'currentTime', { get: function() { return origCurrentTimeDescriptor.get.call(this); }, set: function(value) { // 允许任意设置播放位置 return origCurrentTimeDescriptor.set.call(this, value); }, configurable: true, enumerable: true }); } // ========== 策略3:定时解除视频限制 ========== function keepUnlocking() { setInterval(() => { document.querySelectorAll('video').forEach(video => { // 移除可能限制播放的属性 video.removeAttribute('disableRemotePlayback'); video.controls = true; // 移除内联事件 video.onseeking = null; video.onseeked = null; video.ontimeupdate = null; // 确保播放速率不受限 if (video.playbackRate !== 1) { // 允许用户自行调整倍速 } }); }, 1000); } // ========== 策略4:捕获并阻止限制脚本 ========== function blockRestrictionScripts() { // 使用 MutationObserver 监听新增的 video 元素 const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if (node.nodeName === 'VIDEO') { node.onseeking = null; node.onseeked = null; node.ontimeupdate = null; node.controls = true; } if (node.querySelectorAll) { node.querySelectorAll('video').forEach(v => { v.onseeking = null; v.onseeked = null; v.ontimeupdate = null; v.controls = true; }); } }); }); }); observer.observe(document.documentElement, { childList: true, subtree: true }); } // ========== 策略5:覆盖 HTMLMediaElement 的 onseeking ========== function overrideOnSeeking() { const videoProto = HTMLMediaElement.prototype; let origOnSeekingDescriptor; try { origOnSeekingDescriptor = Object.getOwnPropertyDescriptor(videoProto, 'onseeking'); } catch(e) {} if (origOnSeekingDescriptor && origOnSeekingDescriptor.set) { const origSetter = origOnSeekingDescriptor.set; Object.defineProperty(videoProto, 'onseeking', { get: function() { return null; }, set: function(fn) { console.log('[解锁脚本] 已拦截 onseeking 赋值'); // 不执行任何操作,阻止设置限制 }, configurable: true }); } } // ========== 新增功能:自动播放最后3秒并显示秒杀提示 ========== function autoPlayLast3Seconds() { const videos = document.querySelectorAll('video'); videos.forEach(video => { // 等待视频元数据加载 if (video.readyState < 1) { video.addEventListener('loadedmetadata', () => { playLast3Seconds(video); }); } else { playLast3Seconds(video); } }); } function playLast3Seconds(video) { const duration = video.duration; if (duration > 3) { video.currentTime = duration - 3; video.play().catch(e => console.log('[解锁脚本] 自动播放失败:', e)); console.log(`[解锁脚本] 自动跳转至最后3秒 (${duration-3}s)`); } } // ========== 新增功能:在页面左下角显示秒杀提示 ========== function showKillMessage() { const msgDiv = document.createElement('div'); msgDiv.id = 'video-kill-message'; msgDiv.innerHTML = '秒杀中......'; Object.assign(msgDiv.style, { position: 'fixed', left: '10px', bottom: '10px', zIndex: '999999', background: '#ff4444', color: 'white', padding: '8px 16px', borderRadius: '4px', fontSize: '14px', fontWeight: 'bold', boxShadow: '0 2px 8px rgba(0,0,0,0.3)', opacity: '0.9', fontFamily: 'Arial, sans-serif' }); document.body.appendChild(msgDiv); } // ========== 执行所有策略 ========== function init() { overrideSeekRestriction(); overrideOnSeeking(); showKillMessage(); // 显示秒杀提示 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { unlockSeek(); blockRestrictionScripts(); keepUnlocking(); autoPlayLast3Seconds(); console.log('[解锁脚本] 视频快进与进度条限制已解除,自动播放最后3秒'); }); } else { unlockSeek(); blockRestrictionScripts(); keepUnlocking(); autoPlayLast3Seconds(); console.log('[解锁脚本] 视频快进与进度条限制已解除,自动播放最后3秒'); } // 监听新视频元素 const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if (node.nodeName === 'VIDEO' || (node.querySelectorAll && node.querySelectorAll('video').length > 0)) { autoPlayLast3Seconds(); } }); }); }); observer.observe(document.documentElement, { childList: true, subtree: true }); } init(); })();