Auto Mooc (Script Only)

欢迎使用Auto Mooc的内置脚本, 如需服务端运行请访问Github - skye-z/auto-mooc

  1. // ==UserScript==
  2. // @name Auto Mooc (Script Only)
  3. // @namespace Violentmonkey Scripts
  4. // @description 欢迎使用Auto Mooc的内置脚本, 如需服务端运行请访问Github - skye-z/auto-mooc
  5. // @match http://www.uooc.net.cn/home/learn/index*
  6. // @match https://www.uooc.net.cn/home/learn/index*
  7. // @match http://www.uooconline.com/home/learn/index*
  8. // @match https://www.uooconline.com/home/learn/index*
  9. // @match http://cce.org.uooconline.com/home/learn/index*
  10. // @match https://cce.org.uooconline.com/home/learn/index*
  11. // @grant none
  12. // @license GPL v3.0
  13. // @version 2.0.2
  14. // @author Skye
  15. // @description 2024/03/13 21:00:29
  16. // ==/UserScript==
  17.  
  18. (function () {
  19. 'use strict';
  20. const GT = 500;
  21. let runWork = () => {
  22. let extraTime = 0;
  23. try {
  24. let done = false;
  25. let video = document.querySelector('#player_html5_api');
  26. if (video) {
  27. video.playbackRate = 2;
  28. video.muted = true;
  29. if (!video.ended) video.play();
  30. else video.pause();
  31. if (video.ended) done = true;
  32. let quizLayer = document.querySelector('#quizLayer');
  33. if (quizLayer && quizLayer.style.display != 'none') {
  34. if (done) {
  35. setTimeout(() => {
  36. document.querySelectorAll('.layui-layer-shade').forEach(e => e.style.display = 'none');
  37. }, GT << 1);
  38. };
  39. let source = JSON.parse(document.querySelector('div[uooc-video]').getAttribute('source'));
  40. let quizList = source.quiz;
  41. let quizIndex = 0;
  42. let quizQuestion = document.querySelector('.smallTest-view .ti-q-c').innerHTML;
  43. for (let i = 0; i < quizList.length; i++) {
  44. if (quizList[i].question == quizQuestion) {
  45. quizIndex = i;
  46. break;
  47. };
  48. };
  49. let quizAnswer = eval(quizList[quizIndex].answer);
  50. let quizOptions = quizLayer.querySelector('div.ti-alist');
  51. for (let ans of quizAnswer) {
  52. let labelIndex = ans.charCodeAt() - 'A'.charCodeAt();
  53. quizOptions.children[labelIndex].click();
  54. };
  55. quizLayer.querySelector('button').click();
  56. extraTime = 1000;
  57. };
  58. if (!done) {
  59. if (video.paused) video.play();
  60. else document.querySelectorAll('.layui-layer-shade, #quizLayer').forEach(e => e.style.display = 'none');
  61. };
  62. };
  63. if (!done) setTimeout(runWork, GT + extraTime);
  64. else if (video) {
  65. let current_video = document.querySelector('.basic.active');
  66. let next_part = current_video.parentNode;
  67. let next_video = current_video;
  68. let isVideo = node => Boolean(node.querySelector('span.icon-video'));
  69. let canBack = () => {
  70. return Boolean(next_part.parentNode.parentNode.tagName === 'LI');
  71. };
  72. let toNextVideo = () => {
  73. next_video = next_video.nextElementSibling;
  74. while (next_video && !isVideo(next_video)) {
  75. next_video = next_video.nextElementSibling;
  76. };
  77. };
  78. let isExistsVideo = () => {
  79. let _video = next_part.firstElementChild;
  80. while (_video && !isVideo(_video)) {
  81. _video = _video.nextElementSibling;
  82. };
  83. return Boolean(_video && isVideo(_video));
  84. };
  85. let isExistsNextVideo = () => {
  86. let _video = current_video.nextElementSibling;
  87. while (_video && !isVideo(_video)) {
  88. _video = _video.nextElementSibling;
  89. };
  90. return Boolean(_video && isVideo(_video));
  91. };
  92. let isExistsNextListAfterFile = () => {
  93. let part = next_part.nextElementSibling;
  94. return Boolean(part && part.childElementCount > 0);
  95. };
  96. let toNextListAfterFile = () => {
  97. next_part = next_part.nextElementSibling;
  98. };
  99. let toOuterList = () => {
  100. next_part = next_part.parentNode.parentNode;
  101. };
  102. let toOuterItem = () => {
  103. next_part = next_part.parentNode;
  104. };
  105. let isExistsNextListAfterList = () => {
  106. return Boolean(next_part.nextElementSibling);
  107. };
  108. let toNextListAfterList = () => {
  109. next_part = next_part.nextElementSibling;
  110. };
  111. let expandList = () => {
  112. next_part.firstElementChild.click();
  113. };
  114. let toExpandListFirstElement = () => {
  115. next_part = next_part.firstElementChild.nextElementSibling;
  116. if (next_part.classList.contains('unfoldInfo')) {
  117. next_part = next_part.nextElementSibling;
  118. };
  119. };
  120. let isList = () => {
  121. return Boolean(next_part.tagName === 'UL');
  122. };
  123. let toInnerList = () => {
  124. next_part = next_part.firstElementChild;
  125. };
  126. let toFirstVideo = () => {
  127. next_video = next_part.firstElementChild;
  128. while (next_video && !isVideo(next_video)) {
  129. next_video = next_video.nextElementSibling;
  130. };
  131. };
  132. let mode = {
  133. FIRST_VIDEO: '1',
  134. NEXT_VIDEO: '2',
  135. LAST_LIST: '3',
  136. NEXT_LIST: '4',
  137. INNER_LIST: '5',
  138. OUTER_LIST: '6',
  139. OUTER_ITEM: '7',
  140. }
  141. let search = (_mode) => {
  142. switch (_mode) {
  143. case mode.FIRST_VIDEO:
  144. if (isExistsVideo()) {
  145. toFirstVideo();
  146. next_video.click();
  147. setTimeout(runWork, GT);
  148. } else if (isExistsNextListAfterFile()) search(mode.LAST_LIST);
  149. break;
  150. case mode.NEXT_VIDEO:
  151. if (isExistsNextVideo()) {
  152. toNextVideo();
  153. next_video.click();
  154. setTimeout(runWork, GT);
  155. } else if (isExistsNextListAfterFile()) search(mode.LAST_LIST);
  156. else search(mode.OUTER_ITEM);
  157. break;
  158. case mode.LAST_LIST:
  159. toNextListAfterFile();
  160. toInnerList();
  161. search(mode.INNER_LIST);
  162. break;
  163. case mode.NEXT_LIST:
  164. toNextListAfterList();
  165. search(mode.INNER_LIST);
  166. break;
  167. case mode.INNER_LIST:
  168. expandList();
  169. (function waitForExpand() {
  170. if (next_part.firstElementChild.nextElementSibling) {
  171. toExpandListFirstElement();
  172. if (isList()) {
  173. toInnerList();
  174. search(mode.INNER_LIST);
  175. } else search(mode.FIRST_VIDEO);
  176. } else setTimeout(waitForExpand, GT);
  177. })();
  178. break;
  179. case mode.OUTER_LIST:
  180. toOuterList();
  181. if (isExistsNextListAfterList()) search(mode.NEXT_LIST);
  182. else if (canBack()) search(mode.OUTER_LIST);
  183. break;
  184. case mode.OUTER_ITEM:
  185. toOuterItem();
  186. if (isExistsNextListAfterList()) {
  187. toNextListAfterList();
  188. search(mode.INNER_LIST);
  189. } else if (canBack()) search(mode.OUTER_LIST);
  190. break;
  191. default:
  192. break;
  193. };
  194. };
  195. try {
  196. search(mode.NEXT_VIDEO);
  197. } catch (err) {
  198. console.error(err);
  199. };
  200. };
  201. } catch (err) {
  202. console.error(err);
  203. };
  204. };
  205. runWork();
  206. console.info('Auto Mooc Init');
  207. })();
  208.  
  209. function openClass(top, dom) {
  210. if (dom == null) {
  211. playerClass(top)
  212. } else {
  213. let obj = dom.querySelector('.basic.uncomplete');
  214. let res = (obj && obj.parentNode) ? obj.parentNode.querySelector('.resourcelist'):null;
  215. if (res != null) {
  216. playerClass(obj)
  217. } else if (obj == null) {
  218. playerClass(top)
  219. } else {
  220. let part = obj.parentNode;
  221. let sub = part.querySelector('ul');
  222. if (sub == null) {
  223. obj.click();
  224. setTimeout(() => {
  225. sub = part.querySelector('ul');
  226. openClass(part, sub)
  227. }, 1000)
  228. } else {
  229. openClass(part, sub)
  230. }
  231. }
  232. }
  233. }
  234.  
  235. function playerClass(top) {
  236. let res = top.parentNode.querySelector('.resourcelist');
  237. if (res == null) return
  238. res = res.querySelector('div:not(.complete)')
  239. if (res == null) return
  240. res = jumpNotTask(res)
  241. res.click()
  242. }
  243.  
  244. function jumpNotTask(res){
  245. if (res.querySelector('span.taskpoint') == null){
  246. return jumpNotTask(res.nextElementSibling)
  247. } else return res
  248. }
  249.  
  250. function selectClass() {
  251. openClass(null, document)
  252. }