yuncourse

屏蔽云课堂挂机检测脚本

  1. // ==UserScript==
  2. // @name yuncourse
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description 屏蔽云课堂挂机检测脚本
  6. // @author Vstay
  7. // @match *://*.yunxuetang.cn/*
  8. // @icon https://yunketang.cn/static/images/xsct-icon-5@2x-87dbb0b9f0.png
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15.  
  16. // 添加防抖函数
  17. function debounce(func, wait) {
  18. let timeout;
  19. return function executedFunction(...args) {
  20. const later = () => {
  21. clearTimeout(timeout);
  22. func(...args);
  23. };
  24. clearTimeout(timeout);
  25. timeout = setTimeout(later, wait);
  26. };
  27. }
  28.  
  29. // 添加错误计数器
  30. let errorCount = 0;
  31. const MAX_ERRORS = 5;
  32.  
  33. var time = getTimes();
  34. var str = "display: none;";
  35. var str2 = "dialog-fade-leave";
  36. var play_btn = 0; var continue_to_learn = 0; var elem = 0; var congratulate_str = 0;
  37. let obj = { 'autoplay': true, 'muted': true };
  38. console.log('It\'s running Now');
  39.  
  40. // 主要检测函数
  41. const mainCheck = async () => {
  42. try {
  43. var i = 0; var j = 0; var RootNode = 0; var finishsign = 0; var next_course = 0; var next_course2 = 0; var begin_to_learn = 0; var lesson_finish = 0; var courses = 0; var courses_length = 0; var lesson_num = 0;
  44. // 开始学习按钮
  45. // v1.0旧版
  46. // begin_to_learn = document.getElementsByClassName("kngpc-playbutton kngpc-playbutton__primary");
  47. // v2.0新版
  48. begin_to_learn = document.getElementsByClassName("yxtf-button yxtf-button--primary yxtf-button--larger");
  49. if (begin_to_learn != 0) {
  50. if (begin_to_learn.length != 0) {
  51. begin_to_learn[0].click();
  52. }
  53. }
  54. play_btn = document.querySelector('video');
  55. finishsign = document.getElementsByClassName("yxtulcdsdk-course-player__countdown standard-size-12 yxtulcdsdk-flex-center");
  56. // 旧版需要判断当前任务完成,关闭评价,点击下一任务
  57. // v2.0新版直接判断剩余时间,学习时间结束,点击下一任务
  58. if (finishsign.length == 0) {
  59. next_course = document.getElementsByClassName("yxtf-button ml12 yxtf-button--default is-plain is-icon")[0];
  60. next_course2 = document.getElementsByClassName("ulcdsdk-nextchapterbutton")[0];
  61. sleep(1000);
  62. next_course.click();
  63. sleep(1000);
  64. next_course2.click();
  65. sleep(1000);
  66. // 发现点击之后需要刷新,v1.1修复bug
  67. location.reload();
  68. }
  69. // 判断当前小节已完成,跳转到下一小节
  70. lesson_finish = document.getElementsByClassName("yxtbiz-language-slot");
  71. // 重新学习按钮不点击,不会显示完成进度。v1.4修复bug
  72. try {
  73. congratulate_str = document.getElementsByClassName("font-size-16 text-bf")[0].innerText;
  74. }
  75. catch (e) { }
  76. // 获取所有小节元素
  77. courses = document.getElementsByClassName("d-in-block ellipsis-2 kng-chapter-title");
  78. courses_length = courses.length;
  79. if (lesson_finish.length === 0) {
  80. // 修复对课程完成的判断,小版本更新v1.3
  81. if (congratulate_str === '恭喜您已完成本课程的学习。') {
  82. console.log("lesson finished");
  83. lesson_num = get_current_lesson_num(courses);
  84. if (lesson_num + 1 < courses_length) {
  85. courses[lesson_num + 1].click();
  86. }
  87. else {
  88. //如果小节看完自动跳转到下一任务,小版本更新v1.2
  89. next_course = document.getElementsByClassName("yxtf-button yxtf-button--primary")[0];
  90. next_course.click();
  91. }
  92. }
  93. }
  94. elem = document.getElementsByClassName("yxt-dialog__wrapper");
  95. // v1.0旧版判断是否有“继续学习”按钮,点击后判断视频是否在播放状态,使视频播放
  96. // continue_to_learn = document.getElementsByClassName("yxtf-button mr8 yxtf-button--primary yxtf-button--larger2");
  97. // v2.0新版
  98. continue_to_learn = document.getElementsByClassName("yxtf-button yxtf-button--primary yxtf-button--large");
  99. // 点击“继续学习”按钮
  100. if (continue_to_learn[0] != undefined) {
  101. continue_to_learn[0].click();
  102. }
  103. // 使视频播放(添加属性,防止chrome报错),使用try...catch丢弃报错
  104. try {
  105. play_btn.setAttribute('autoplay', 'true');
  106. play_btn.setAttribute('muted', 'true');
  107. if (play_btn.paused) {
  108. play_btn.play();
  109. }
  110. }
  111. catch (e) { }
  112.  
  113. // 循环找到挂机检测弹窗节点
  114. for (i = 0; i < elem.length; i++) {
  115. if (elem[i].attributes[2] != undefined) {
  116. if (elem[i].attributes[2].nodeValue.indexOf(str) == -1) {
  117. // 发现bug,添加一个判断
  118. if (elem[i].attributes[1].nodeValue.indexOf(str2) == -1) {
  119. RootNode = elem[i];
  120. console.log(RootNode);
  121. }
  122. }
  123. }
  124. }
  125. if (RootNode === 0) {
  126. console.log("no alert. dialog-center display none.");
  127. return;
  128. }
  129. var btn = RootNode.getElementsByClassName("dialog-footer")[0];
  130. var center = document.getElementsByClassName("dialog-center");
  131. console.log("触发挂机弹窗");
  132. if (!btn) {
  133. console.log("dialog-footer classname elements not found.");
  134. return;
  135. }
  136. var res = btn.innerText;
  137. console.log(res);
  138. if (res != "继续学习") {
  139. btn = document.getElementsByClassName("dialog-footer")[2];
  140. }
  141. console.log("点击继续学习");
  142. // 点击继续学习按钮
  143. btn.getElementsByClassName("yxtf-button yxtf-button--primary yxtf-button--large")[0].click();
  144.  
  145. // 重置错误计数
  146. errorCount = 0;
  147.  
  148. } catch (error) {
  149. console.error('检测过程出错:', error);
  150. errorCount++;
  151.  
  152. // 如果错误次数过多,重新加载页面
  153. if (errorCount >= MAX_ERRORS) {
  154. console.log('错误次数过多,准备重新加载页面...');
  155. location.reload();
  156. return;
  157. }
  158. }
  159. };
  160.  
  161. // 使用防抖包装主检测函数
  162. const debouncedCheck = debounce(mainCheck, 1000);
  163.  
  164. // 修改interval的调用方式
  165. var tm = setInterval(debouncedCheck, time);
  166.  
  167. // 添加清理函数
  168. window.addEventListener('beforeunload', () => {
  169. clearInterval(tm);
  170. });
  171. })();
  172.  
  173. function getTimes() {
  174. var times = Math.random() * 8 + 1;//1-9
  175. times = 5 * 1000 * 1;//+times*10
  176. return times
  177. }
  178.  
  179. function get_current_lesson_num(courses) {
  180. var courses_length = 0;
  181. courses_length = courses.length;
  182. if (courses_length > 0) {
  183. for (var i = 0; i < courses_length; i++) {
  184. if (courses[i].className.indexOf("color-primary-6") != -1) {
  185. return i;
  186. }
  187. }
  188. }
  189. else {
  190. return 0;
  191. }
  192. }
  193.  
  194. // 修改sleep函数
  195. function sleep(time) {
  196. return new Promise((resolve) => {
  197. const timeout = setTimeout(resolve, time);
  198. // 添加清理机制
  199. window.addEventListener('beforeunload', () => {
  200. clearTimeout(timeout);
  201. });
  202. });
  203. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址