// ==UserScript== // @name 雨课堂刷课助手 // @namespace http://tampermonkey.net/ // @version 1.0.4 // @description 针对雨课堂视频进行自动播放 // @author 风之子 // @license MIT // @match *://*.yuketang.cn/* // @icon http://niuwh.cn/favicon.ico // @grant GM_addStyle // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.js // @downloadURL none // ==/UserScript== // 雨课堂刷课脚本 // 添加用户交互窗口 function addWindow() { // 插入的交互HTML窗口 const outerHTML = `
雨课堂刷课助手
`; $('body').append(outerHTML); // 添加css样式 function addStyle() { let css = ` ul, li, p { margin: 0; padding: 0; } body { width: 100vw; height: 100vh; } .n_outer { margin: 0; padding: 0; position: fixed; top: 0; left: 0; min-width: 500px; height: 250px; background-color: #fff; z-index: 99999; box-shadow: 6px 4px 17px 2px #000000; border-radius: 10px; border: 1px solid #a3a3a3; font-family: Avenir, Helvetica, Arial, sans-serif; color: #636363; } .n_header { text-align: center; height: 40px; background-color: #f7f7f7; color: #000; font-size: 18px; line-height: 40px; cursor: move; border-radius: 10px 10px 0 0; border-bottom: 2px solid #eee; } .n_body { font-weight: bold; font-size: 13px; line-height: 26px; height: 183px; } .n_body .n_infoAlert { overflow-y: scroll; height: 100%; } /* 滚动条整体 */ .n_body .n_infoAlert::-webkit-scrollbar { height: 20px; width: 7px; } /* 滚动条轨道 */ .n_body .n_infoAlert::-webkit-scrollbar-track { --webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); border-radius: 10px; background: #ffffff; } /* 滚动条滑块 */ .n_body .n_infoAlert::-webkit-scrollbar-thumb { border-radius: 10px; --webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); background: rgb(20, 19, 19, 0.6); } .n_footer { position: absolute; bottom: 0; left: 0; text-align: right; height: 25px; width: 100%; background-color: #f7f7f7; color: #c5c5c5; font-size: 13px; line-height: 25px; border-radius: 0 0 10px 10px; border-bottom: 2px solid #eee; display: flex; justify-content: space-between; } .n_footer button { border-radius: 6px; border: 0; background-color: blue; color: #fff; cursor: pointer; } .n_footer button:hover { background-color: yellow; color: #000; } .n_footer #n_zanshang { cursor: pointer; position: relative; color: red; } .n_footer #n_zanshang img { position: absolute; top: 30px; left: -130px; display: none; width: 300px; } .n_footer #n_zanshang:hover img { display: block; } `; GM_addStyle(css); } addStyle(); // 窗口的拽拖逻辑 $('.n_header').mousedown(function (e) { let innerLeft = e.offsetX, innerTop = e.offsetY $('body').mousemove(function (e) { let left = e.clientX - innerLeft, top = e.clientY - innerTop; //获取body的页面可视宽高 var clientHeight = document.documentElement.clientHeight || document.body.clientHeight; var clientWidth = document.documentElement.clientWidth || document.body.clientWidth; // 通过判断是否溢出屏幕 if (left <= 0) { left = 0; } else if (left >= clientWidth - $('.n_outer')[0].offsetWidth) { left = clientWidth - $('.n_outer')[0].offsetWidth } if (top <= 0) { top = 0 } else if (top >= clientHeight - $('.n_outer')[0].offsetHeight) { top = clientHeight - $('.n_outer')[0].offsetHeight } $('.n_outer').css({ left: () => { return left + 'px'; }, top: () => { return top + 'px'; } }) }) }) $('.n_header').mouseup(function (e) { $('body').off(); }) $('#n_button').click(function () { main(); $('#n_button').text('刷课中~'); }) $('#n_clear').click(function () { localStorage.removeItem(location.href); localStorage.removeItem('userCount') }) } // 脚本运行核心逻辑 function main() { start(); // 视频播放速率,可选值 [1,1.25,1.5,2],默认为二倍速 const rate = 2; // 向弹窗里追加信息 function alertMessage(message) { $('.n_infoAlert').append(`
  • ${message}
  • `); } setInterval(function () { document.querySelector('.n_infoAlert').lastElementChild.scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest" }); }, 500) // 视频自动加速逻辑 function speed() { let keyt = ''; if (rate === 2 || rate === 1) { keyt = "[keyt='" + rate + ".00']" } else { keyt = "[keyt='" + rate + "']" } function fun(className, selector) { var mousemove = document.createEvent("MouseEvent"); mousemove.initMouseEvent("mousemove", true, true, unsafeWindow, 0, 10, 10, 10, 10, 0, 0, 0, 0, 0, null); console.log(document.getElementsByClassName(className)[0]); document.getElementsByClassName(className)[0].dispatchEvent(mousemove); document.querySelector(selector).click(); alertMessage('已开始两倍速播放'); } fun('xt_video_player_speed', keyt) } // 判断页面类型执行不同的操作 function start() { const url = location.host; const pathName = location.pathname.split('/'); const matchURL = url + pathName[0] + '/' + pathName[1] + '/' + pathName[2]; console.log(matchURL); const changjiangv2 = ['changjiang.yuketang.cn/v2/web', 'yuketang.cn/v2/web', 'www.yuketang.cn/v2/web', 'xxxxx.yuketang.cn/v2/web']; alertMessage(`正在为您匹配${url}的处理逻辑...`); if (changjiangv2.includes(matchURL)) { yuketang_v2(); } } // www.yuketang.cn页面的处理逻辑 function yuketang_v2() { alertMessage('已匹配到www.yuketang.cn,正在处理...'); // 用于判断不同的课程 let baseUrl = location.href; // 根据客户端记录的URL判别刷到那一集了,不影响第一批用户的刷课进度。 if (localStorage.getItem('classIndex')) { localStorage.setItem(baseUrl, +localStorage.getItem('classIndex')); localStorage.removeItem('classIndex'); } let count = +localStorage.getItem(baseUrl) || 0; alertMessage(`检测到已经播放到${count}集...`); let classList = []; // 用于标记视频是否播放完毕 let play = true; // 主函数 function main() { autoSlide(count).then(() => { let list = document.querySelector('.logs-list').childNodes; alertMessage('刷课状态:第' + (count + 1) + '个/' + list.length + '个'); classList[count] = list[count]?.querySelector('.content-box')?.querySelector('section'); let classInfo = classList[count]?.querySelector('.tag')?.querySelector('use')?.getAttribute('xlink:href'); if (classInfo?.includes('shipin') && play === true) { // 视频处理 play = false; classList[count].click(); setTimeout(() => { alertMessage('第' + (count + 1) + '个:进入了视频区'); speed(); let progress = document.querySelector('.progress-wrap').querySelector('.text'); let timer1 = setInterval(() => { if (progress.innerHTML.includes('100%') || progress.innerHTML.includes('99%') || progress.innerHTML.includes('98%')) { count++; localStorage.setItem(baseUrl, count); play = true; history.back(); main(); clearInterval(timer1); } }, 10000); }, 3000) // 批量处理 } else if (classInfo?.includes('piliang') && play === true) { // 批量处理 let zhankai = classList[count].querySelector('.sub-info').querySelector('.gray').querySelector('span'); sync(); async function sync() { await zhankai.click(); setTimeout(() => { alertMessage('第' + (count + 1) + '个:进入了批量区'); localStorage.getItem('userCount') ? localStorage.getItem('userCount') : localStorage.setItem('userCount', 0); // 保存所有视频 let a = list[count].querySelector('.leaf_list__wrap').querySelectorAll('.activity__wrap'); let count1 = localStorage.getItem('userCount'); bofang(); function bofang() { let classInfo1 = a[count1]?.querySelector('.tag').querySelector('use').getAttribute('xlink:href'); let play = true; if (classInfo1?.includes('shipin') && play === true) { play = false; a[count1].click(); alertMessage(`开始播放视频`); // 延迟3秒后加速 setTimeout(() => { speed(); }, 3000); let timer = setInterval(() => { let progress = document.querySelector('.progress-wrap').querySelector('.text'); if (progress.innerHTML.includes('100%') || progress.innerHTML.includes('99%') || progress.innerHTML.includes('98%')) { count1++; localStorage.setItem('userCount', count1); clearInterval(timer); alertMessage(`视频播放完毕`); history.back(); setTimeout(() => { bofang(); }, 2000); } }, 3000) } else if (classInfo1 && !classInfo1.includes('shipin') && play === true) { alertMessage('不是视频'); count1++; localStorage.setItem('userCount', count1); bofang(); } else if (count1 === a.length && play === true) { alertMessage('合集播放完毕'); count++; localStorage.setItem('userCount', count1); localStorage.setItem(baseUrl, count); main(); } } }, 2000) } } else if (classInfo?.includes('ketang') && play === true) { // 课堂处理 alertMessage('第' + (count + 1) + '个:进入了课堂区'); play = false; classList[count].click(); setTimeout(() => { let playBack = document.querySelector('.playback'); if (playBack) { // 存在回放按钮时进入详情页 playBack.click(); setTimeout(() => { // 内容为视频的逻辑 if (document.querySelector('video')) { function isComplate() { let videoTime = document.querySelector('.video__time').innerHTML.toString(); let currentTime = videoTime.split('/')[0]; let totalTime = videoTime.split('/')[1]; if (currentTime == totalTime || currentTime == '00:00' || currentTime == '00:00:00') { count++; localStorage.setItem(baseUrl, count); play = true; history.go(-2); main(); clearInterval(timer); } } let timer = setInterval(() => { isComplate(); }, 10000) } // 内容为音频的逻辑 if (document.querySelector('audio')) { function isComplate() { let mainArea = document.querySelector('.mainArea'); let currentTime = mainArea.querySelectorAll('span')[0].innerHTML.toString(); let totalTime = mainArea.querySelectorAll('span')[1].innerHTML.toString(); if (currentTime == totalTime || currentTime == '00:00' || currentTime == '00:00:00') { count++; localStorage.setItem(baseUrl, count); play = true; history.go(-2); main(); clearInterval(timer); } } let timer = setInterval(() => { isComplate(); }, 10000) } }, 3000) } else { // 不存在回放按钮时退出 count++; localStorage.setItem(baseUrl, count); play = true; history.go(-1); main(); } }, 3000) } else if (classInfo?.includes('kejian') && play === true) { // 课件处理 alertMessage('根据ycj用户的反馈修改新增课件处理,且赞助支持,表示感谢') // 8.8元 alertMessage('第' + (count + 1) + '个:进入了课件区'); play = false; classList[count].click(); let classType; (async function () { await new Promise(function (resolve) { setTimeout(function () { classType = $('.el-card__header')[0].innerText; console.log(classType); $('.check').click(); resolve(); }, 3000) }) // 3秒后执行点击事件 let className = $('.dialog-header')[0].firstElementChild.innerText; console.log(className); if (classType == '课件PPT') { // 课件为ppt let allPPT = $('.swiper-wrapper')[0].children; alertMessage(`开始播放${className}`) for (let i = 0; i < allPPT.length; i++) { await new Promise(function (resolve) { setTimeout(function () { allPPT[i].click(); alertMessage(`第${i}个已经播放`); resolve(); }, 500) }) } alertMessage(`${className} 已经播放完毕`) } else { // 课件为视频 $('.video-box').click(); alertMessage(`开始播放视频:${className}`); await new Promise(function (resolve) { setTimeout(function () { speed(); $('.xt_video_player_common_icon').click(); resolve(); }, 3000) }) // 3秒后加速,静音 alertMessage('已开启二倍速,且自动静音'); await new Promise(function (resolve) { let timer = setInterval(function () { let allTime = $('.xt_video_player_current_time_display')[0].innerText; nowTime = allTime.split(' / ')[0]; totalTime = allTime.split(' / ')[1] console.log(nowTime + totalTime); if (nowTime == totalTime) { clearInterval(timer); resolve(); } }, 500); }) // 等待视频结束 alertMessage(`${className} 视频播放完毕`) } count++; localStorage.setItem(baseUrl, count); play = true; history.back(); main(); })() } else if (count === list.length && play === true) { // 结束 alertMessage('课程刷完了'); $('#n_buttoni').text('刷完了~'); localStorage.setItem(baseUrl, 0); return; } else if (!(classInfo.includes('shipin') || classInfo.includes('piliang') || classInfo.includes('kejian')) && play === true) { // 视频,批量,课件都不是的时候跳过,此处可以优化 alertMessage('第' + (count + 1) + '个:不是视频,已跳过'); count++; localStorage.setItem(baseUrl, count); main(); } }) } // 根据视频集数,自动下拉刷新集数 async function autoSlide(count) { let frequency = parseInt((count + 1) / 20) + 1; for (let i = 0; i < frequency; i++) { await new Promise((resolve, reject) => { setTimeout(() => { document.querySelector('.viewContainer').scrollTop = document.querySelector('.el-tab-pane').scrollHeight; resolve(); }, 1000) }) } } main(); } // bksycsu.yuketang.cn 处理逻辑 // function bksycsu() { // alertMessage(111) // let allClass = $('.leaf-detail'); // let allinfo = { // id: 1, // type: allClass[0].childNodes[0].firstElementChild.className.split(' ')[1], // title: allClass[0].childNodes[0].innerText, // status: allClass[0].childNodes[2].lastElementChild.innerText // } // document.body.addEventListener('mousedown', function (e) { // console.log(e); // }) // } // 其他不同类型的DOM页面的处理逻辑,待完善... } // 油猴执行文件 (function () { 'use strict'; addWindow(); })();