// ==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();
})();