您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
【使用前先看介绍/有问题可反馈】【欢迎一键三连(好评+打赏+收藏),你的支持是作者维护下去的最大动力!】UOOC优课联盟助手(UOOC assistant):可选是否倍速(若取消勾选则一倍速播放),可选是否静音(若取消勾选则恢复原音量),可选是否播放(若取消勾选则暂停播放),可选是否连播(若取消勾选则循环播放),离开页面保持状态,自动回答视频中途弹出问题;键盘左右方向键可以控制视频快进/快退,上下方向键可以控制音量增大/减小,空格键可以控制播放/暂停;自动签到慕课;如果视频标题下面出现 倍速/静音/播放/连播 选项说明脚本正常启动运行。
当前为
- // ==UserScript==
- // @name UOOC assistant
- // @name:en UOOC assistant
- // @namespace http://tampermonkey.net/
- // @version 0.9.5
- // @description 【使用前先看介绍/有问题可反馈】【欢迎一键三连(好评+打赏+收藏),你的支持是作者维护下去的最大动力!】UOOC优课联盟助手(UOOC assistant):可选是否倍速(若取消勾选则一倍速播放),可选是否静音(若取消勾选则恢复原音量),可选是否播放(若取消勾选则暂停播放),可选是否连播(若取消勾选则循环播放),离开页面保持状态,自动回答视频中途弹出问题;键盘左右方向键可以控制视频快进/快退,上下方向键可以控制音量增大/减小,空格键可以控制播放/暂停;自动签到慕课;如果视频标题下面出现 倍速/静音/播放/连播 选项说明脚本正常启动运行。
- // @description:en 【使用前先看介绍/有问题可反馈】【欢迎一键三连(好评+打赏+收藏),你的支持是作者维护下去的最大动力!】UOOC优课联盟助手(UOOC assistant):可选是否倍速(若取消勾选则一倍速播放),可选是否静音(若取消勾选则恢复原音量),可选是否播放(若取消勾选则暂停播放),可选是否连播(若取消勾选则循环播放),离开页面保持状态,自动回答视频中途弹出问题;键盘左右方向键可以控制视频快进/快退,上下方向键可以控制音量增大/减小,空格键可以控制播放/暂停;自动签到慕课;如果视频标题下面出现 倍速/静音/播放/连播 选项说明脚本正常启动运行。
- // @author cc
- // @include http://www.uooc.net.cn/*
- // @grant none
- // ==/UserScript==
- (function () {
- 'use strict';
- const jsName = 'UOOC-assistant.js';
- const RECURSION_DURATION = 500;
- if (location.host == 'www.uooc.net.cn') {
- console.log(`excute ${jsName}`);
- let recursive = () => {
- let extraTime = 0;
- try {
- let done = false;
- let video = document.querySelector('#player_html5_api');
- if (video) {
- if (document.getElementById('rate').checked)
- video.playbackRate = 2;
- else
- video.playbackRate = 1;
- if (document.getElementById('volume').checked)
- video.muted = true;
- else
- video.muted = false;
- if (document.getElementById('play').checked && !video.ended)
- video.play();
- else
- video.pause();
- if (video.ended) {
- done = true;
- };
- let quizLayer = document.querySelector('#quizLayer');
- if (quizLayer && quizLayer.style.display != 'none') {
- if (done) {
- setTimeout(() => {
- document.querySelectorAll('.layui-layer-shade').forEach(e => e.style.display = 'none');
- }, RECURSION_DURATION << 1);
- };
- let source = JSON.parse(document.querySelector('div[uooc-video]').getAttribute('source'));
- let quizList = source.quiz;
- let quizIndex = 0;
- let quizQuestion = document.querySelector('.smallTest-view .ti-q-c').innerHTML;
- for (let i = 0; i < quizList.length; i++) {
- if (quizList[i].question == quizQuestion) {
- quizIndex = i;
- break;
- };
- };
- let quizAnswer = eval(quizList[quizIndex].answer);
- let quizOptions = quizLayer.querySelector('div.ti-alist');
- for (let ans of quizAnswer) {
- let labelIndex = ans.charCodeAt() - 'A'.charCodeAt();
- quizOptions.children[labelIndex].click();
- }; // end for
- quizLayer.querySelector('button').click();
- extraTime = 1000;
- }; // end if
- if (!done) {
- if (video.paused && document.getElementById('play').checked) {
- video.play();
- } else {
- document.querySelectorAll('.layui-layer-shade, #quizLayer').forEach(e => e.style.display = 'none');
- };
- };
- }; // end if (video)
- if (!done) {
- setTimeout(recursive, RECURSION_DURATION + extraTime);
- } else if (video) {
- if (!document.getElementById('continue').checked) {
- video.currentTime = 0;
- // video.ended = false;
- setTimeout(recursive, RECURSION_DURATION + extraTime);
- } else {
- let current_video = document.querySelector('.basic.active');
- let next_part = current_video.parentNode;
- let next_video = current_video;
- // 定义判断是否视频的函数
- let isVideo = node => Boolean(node.querySelector('span.icon-video'));
- // 定义是否可返回上一级目录的函数
- let canBack = () => {
- return Boolean(next_part.parentNode.parentNode.tagName == 'LI');
- };
- // 定义更新至后续视频的函数
- let toNextVideo = () => {
- next_video = next_video.nextElementSibling;
- while (next_video && !isVideo(next_video)) {
- next_video = next_video.nextElementSibling;
- };
- };
- // 定义判断是否存在视频的函数
- let isExistsVideo = () => {
- let _video = next_part.firstElementChild;
- while (_video && !isVideo(_video)) {
- _video = _video.nextElementSibling;
- };
- return Boolean(_video && isVideo(_video));
- };
- // 定义判断是否存在后续视频的函数
- let isExistsNextVideo = () => {
- let _video = current_video.nextElementSibling;
- while (_video && !isVideo(_video)) {
- _video = _video.nextElementSibling;
- };
- return Boolean(_video && isVideo(_video));
- };
- // 定义检查文件后是否存在后续目录的函数
- let isExistsNextListAfterFile = () => {
- let part = current_video.parentNode.nextElementSibling;
- return Boolean(part && part.childElementCount > 0);
- };
- // 定义更新文件后的后续目录的函数
- let toNextListAfterFile = () => {
- next_part = next_part.nextElementSibling;
- };
- // 定义返回上一级的函数
- let toOuterList = () => {
- next_part = next_part.parentNode.parentNode;
- };
- // 定义返回主条目的函数
- let toOuterItem = () => {
- next_part = next_part.parentNode;
- };
- // 定义检查列表后是否存在后续目录的函数
- let isExistsNextListAfterList = () => {
- return Boolean(next_part.nextElementSibling);
- };
- // 定义进入列表后的后续目录的函数
- let toNextListAfterList = () => {
- next_part = next_part.nextElementSibling;
- };
- // 定义展开目录的函数
- let expandList = () => {
- next_part.firstElementChild.click();
- };
- // 定义进入展开目录的第一个块级元素的函数
- let toExpandListFirstElement = () => {
- next_part = next_part.firstElementChild.nextElementSibling;
- if (next_part.classList.contains('unfoldInfo')) {
- next_part = next_part.nextElementSibling;
- };
- };
- // 定义判断块级元素是否目录列表的函数
- let isList = () => {
- return Boolean(next_part.tagName == 'UL');
- };
- // 定义目录列表的第一个目录的函数
- let toInnerList = () => {
- next_part = next_part.firstElementChild;
- };
- // 定义进入文件列表的第一个视频的函数
- let toFirstVideo = () => {
- next_video = next_part.firstElementChild;
- while (next_video && !isVideo(next_video)) {
- next_video = next_video.nextElementSibling;
- };
- };
- // 定义模式
- let mode = {
- FIRST_VIDEO: 'FIRST_VIDEO',
- NEXT_VIDEO: 'NEXT_VIDEO',
- LAST_LIST: 'LAST_LIST',
- NEXT_LIST: 'NEXT_LIST',
- INNER_LIST: 'INNER_LIST',
- OUTER_LIST: 'OUTER_LIST',
- OUTER_ITEM: 'OUTER_ITEM',
- }
- // 定义搜索函数
- let search = (_mode) => {
- switch (_mode) {
- case mode.FIRST_VIDEO: // mode = 0
- if (isExistsVideo()) {
- toFirstVideo();
- next_video.click();
- setTimeout(recursive, RECURSION_DURATION);
- } else {
- // perhaps there is an exam, end recursion
- };
- break;
- case mode.NEXT_VIDEO: // mode == 1
- if (isExistsNextVideo()) {
- toNextVideo();
- next_video.click();
- setTimeout(recursive, RECURSION_DURATION);
- } else if (isExistsNextListAfterFile()) {
- search(mode.LAST_LIST);
- } else {
- search(mode.OUTER_ITEM);
- };
- break;
- case mode.LAST_LIST: // mode == 2
- toNextListAfterFile();
- toInnerList();
- search(mode.INNER_LIST);
- break;
- case mode.NEXT_LIST: // mode == 3
- toNextListAfterList();
- search(mode.INNER_LIST);
- break;
- case mode.INNER_LIST: // mode == 4
- expandList();
- (function waitForExpand () {
- if (next_part.firstElementChild.nextElementSibling) {
- toExpandListFirstElement();
- if (isList()) {
- toInnerList();
- search(mode.INNER_LIST);
- } else {
- search(mode.FIRST_VIDEO);
- };
- } else {
- setTimeout(waitForExpand, RECURSION_DURATION);
- };
- })();
- break;
- case mode.OUTER_LIST: // mode == 5
- toOuterList();
- if (isExistsNextListAfterList()) {
- search(mode.NEXT_LIST);
- } else if (canBack()) {
- search(mode.OUTER_LIST);
- } else {
- // perhaps there is no next list
- };
- break;
- case mode.OUTER_ITEM: // mode == 6
- toOuterItem();
- if (isExistsNextListAfterList()) {
- toNextListAfterList();
- search(mode.INNER_LIST);
- } else if (canBack()){
- search(mode.OUTER_LIST);
- } else {
- // perhaps there is no list
- };
- break;
- default:
- break;
- };
- };
- try {
- search(mode.NEXT_VIDEO);
- } catch (e) {
- console.log(e);
- };
- };
- };
- } catch (e) {
- console.log(e);
- };
- }; // end recursive
- let wait = () => {
- if (document.readyState == 'complete') {
- console.log('ready to set checkboxes.');
- let getCheckbox = (name, text) => {
- let p = document.createElement('p');
- p.style.color = '#cccccc';
- let checkbox = document.createElement('input');
- checkbox.id = name;
- checkbox.type = 'checkbox';
- checkbox.checked = true;
- checkbox.name = name;
- checkbox.value = name;
- checkbox.style.marginLeft = '25px';
- p.append(checkbox);
- let label = document.createElement('label');
- label.setAttribute('for', name);
- label.innerText = text;
- label.style.marginLeft = '15px';
- p.append(label);
- p.style.margin = '5px';
- return p;
- };
- let rateCheckbox = getCheckbox('rate', '倍速');
- let volumeCheckbox = getCheckbox('volume', '静音');
- let playCheckbox = getCheckbox('play', '播放');
- let continueCheckbox = getCheckbox('continue', '连播');
- let head = document.querySelector('.learn-head');
- let container = document.createElement('div');
- container.id = 'container';
- container.style.display = 'flex';
- container.style.flexDirection = 'row';
- container.style.alignItems = 'center';
- container.append(rateCheckbox);
- container.append(volumeCheckbox);
- container.append(playCheckbox);
- container.append(continueCheckbox);
- let div = document.createElement('div');
- div.innerHTML = '( 提示:键盘的 \u2190 和 \u2192 可以控制快进/快退,\u2191 和 \u2193 可以控制音量增大/减小,空格键可以控制播放/暂停 )';
- div.style.color = '#cccccc';
- div.style.fontWeight = 'bold';
- div.style.height = 'min-height';
- div.style.margin = '0px 20px 0px';
- div.style.padding = '2px 5px 2px';
- div.style.bordRadius = '5px';
- div.style.fontSize = '13px';
- container.appendChild(div);
- let a = document.createElement('a');
- a.href = 'https://s1.ax1x.com/2020/11/08/BTeRqe.png';
- a.target = '_blank';
- a.innerHTML = '<u>本脚本使用完全免费,您的打赏是作者维护下去的最大动力!点此打赏作者😊</u>';
- a.style.color = '#cccccc';
- a.style.fontWeight = 'bold';
- a.style.height = 'min-height';
- a.style.margin = '0px 20px 0px';
- a.style.padding = '2px 5px 2px';
- a.style.bordRadius = '5px';
- a.style.fontSize = '13px';
- container.appendChild(a);
- head.append(container);
- console.log('checkboxes have been set.');
- let cid = location.href.match(/\d+/g)[0];
- let httpRequest = new XMLHttpRequest();
- httpRequest.open('GET', `http://www.uooc.net.cn/home/course/info?cid=${cid}`, true);
- httpRequest.send();
- httpRequest.onreadystatechange = function () {
- if (httpRequest.readyState == 4 && httpRequest.status == 200) {
- console.log('Automatic sign-in succeeded.');
- };
- };
- document.onkeydown = (event) => {
- let k = event.key;
- let complete = false;
- let div = document.querySelector('div.basic.active');
- if (div && div.classList.contains('complete'))
- complete = true;
- let video = document.getElementById('player_html5_api');
- if (video) {
- switch (k) {
- case 'ArrowLeft':
- video.currentTime -= 10;
- break;
- case 'ArrowRight':
- if (complete)
- video.currentTime += 10;
- break;
- case 'ArrowUp':
- if (video.volume + 0.1 <= 1.0)
- video.volume += 0.1;
- else
- video.volume = 1.0;
- break;
- case 'ArrowDown':
- if (video.volume - 0.1 >= 0.0)
- video.volume -= 0.1;
- else
- video.volume = 0.0;
- break;
- case ' ':
- let continueCheckbox = document.getElementById('play');
- continueCheckbox.checked = !continueCheckbox.checked;
- break;
- };
- };
- };
- recursive();
- } else {
- setTimeout(wait, RECURSION_DURATION);
- };
- }; // end wait
- wait();
- }
- })();