// ==UserScript==
// @name 超星网课助手
// @namespace wyn665817@163.com
// @version 1.5.1
// @description 自动挂机看尔雅MOOC,支持后台、切换窗口不暂停,视频自动切换,屏蔽视频内的题目,倍速播放、进度条拖动、快进快退
// @author wyn665817
// @match *://*.chaoxing.com/*
// @run-at document-end
// @grant unsafeWindow
// @license MIT
// @downloadURL none
// ==/UserScript==
// 设置修改后,需要刷新或重新打开网课页面才会生效
var setting = {
// 5E3 == 5000,表示毫秒数
time: 5E3 // 默认响应速度为5秒,不建议小于3秒
// 1代表开启,0代表关闭
,video: 1 // 视频支持后台、切换窗口不暂停,支持多视频,默认开启
,work: 1 // 自动答题功能(章节测验),高准确率,默认开启
,jump: 1 // 自动切换任务点、章节,默认开启
,test: 1 // 自动答题功能(考试),高准确率,默认开启
,proxy: 0 // 自动答题功能的代理服务器,建议仅在自动答题功能无法加载时开启,默认关闭
// 仅开启video时,修改此处才会生效
,line: '公网1' // 视频播放的默认资源线路,支持选择清晰度,例如'公网1标清',默认'公网1'
,drag: 0 // 倍速播放、进度条拖动、快进快退,使用此功能会出现不良记录(慎用),默认关闭
// 仅开启work时,修改此处才会生效
,retry: 0 // 自动答题失败后进行重试,如果网课是需要每章解锁的建议开启,默认关闭
// 仅开启jump时,修改此处才会生效
,check: 1 // 任务点无法自动完成时暂停切换,如果网课已全部解锁的建议关闭,默认开启
},
_self = unsafeWindow,
$ = _self.$ || top.$,
url = location.pathname;
if (url.indexOf('ananas/modules/video/index.html') > 0) {
if (setting.video) {
hookJQuery();
} else {
reviseTip(0);
}
} else if (url.indexOf('work/doHomeWorkNew') > 0) {
if (setting.work && $('.Btn_blue_1').length) {
addStyle();
} else {
reviseTip(1);
}
} else if (url.indexOf('exam/test/reVersionTestStartNew') > 0 && setting.test) {
addStyle('test');
} else if (url.indexOf('knowledge/cards') > 0) {
checkToNext();
}
function toNext() {
var $tip = $('.currents ~ span');
if (!setting.jump) {
} else if ($('.lock, .blue', '.currents').length || !$tip.length) {
$tip = $('.roundpointStudent, .roundpoint').parent();
var index = $tip.index($tip.filter('.currents'));
$tip.filter(':gt(' + index + ')').not(':has(.lock, .blue)').eq(0).click();
} else {
$tip.eq(0).click();
}
}
function hookJQuery() {
var Hooks = varHooks(),
$video = $('.ans-job-icon + iframe[src*="/video/index.html"]', parent.document),
$job = $video.not('.ans-job-finished > iframe');
setting.tip = false;
if (!$job.length) {
} else if ($job[0].contentWindow == _self) {
setting.tip = true;
} else {
setInterval(function() {
if ($video.not('.ans-job-finished > iframe')[0].contentWindow == _self) {
location.reload();
}
}, setting.time);
}
Hooks.set(_self, 'jQuery', function(target, propertyName, ignored, jQuery) {
Hooks.set(jQuery.fn, 'cxplayer', function(target, propertyName, oldValue, newValue) {
return Hooks.apply(newValue, function(target, thisArg, args) {
var config = args[0];
config.datas.isDefaultPlay = setting.tip;
config.enableSwitchWindow = 1;
config.datas.currVideoInfo.resourceUrl = '/richvideo/initdatawithviewer?';
config.datas.currVideoInfo.dftLineIndex = config.datas.currVideoInfo.getVideoUrl.match(/{.+?}/g).findIndex(function(currentValue) {
return currentValue.indexOf(setting.line) > 1;
});
if (setting.drag) {
config.datas.currVideoInfo.getVideoUrl = config.datas.currVideoInfo.getVideoUrl.replace(/&drag=false&/, '&drag=true&');
}
return Hooks.Reply.apply(arguments);
});
});
return Hooks.Reply.set(arguments);
});
}
function varHooks() {
/**
* Hooks.js v1.1.3 | xymopen
* xuyiming.open@outlook.com
* https://github.com/xymopen/JS_Utilities/blob/master/Hooks.js
*/
var Hooks = {
apply: function apply(target, onApply) {
if ('function' === typeof target && 'function' === typeof onApply) {
return function() {
return onApply.call(this, target, this, arguments);
};
} else {
throw new TypeError();
}
},
property: function property(target, propertyName, onGet, onSet) {
var descriptor, oldValue;
if (Object.prototype.hasOwnProperty.call(target, propertyName)) {
descriptor = Object.getOwnPropertyDescriptor(target, propertyName);
if (Object.prototype.hasOwnProperty.call(descriptor, 'value')) {
oldValue = descriptor.value;
delete descriptor.value;
delete descriptor.writable;
} else if (Object.prototype.hasOwnProperty.call(descriptor, 'get')) {
oldValue = descriptor.get.call(target);
} else {
oldValue = undefined;
}
} else {
descriptor = {
'configurable': true,
'enumerable': true
};
oldValue = undefined;
}
descriptor.get = function get() {
return onGet.call(this, target, propertyName, oldValue);
};
descriptor.set = function set(newValue) {
oldValue = onSet.call(this, target, propertyName, oldValue, newValue);
return oldValue;
};
Object.defineProperty(target, propertyName, descriptor);
},
set: function set(target, propertyName, onSet) {
return Hooks.property(target, propertyName, function(target, propertyName, oldValue) {
return Hooks.Reply.set(arguments);
}, onSet);
}
};
Hooks.Reply = {
apply: function apply(param) {
return param[0].apply(param[1], param[2]);
},
set: function(param) {
return param[param.length - 1];
}
};
return Hooks;
}
function addStyle(obj) {
$('head').append(
''
);
addNanayun(obj);
}
function addNanayun(obj) {
/**
* api | nanayun.com
* https://freejs19.nanayun.com/
*/
var date = new Date(),
xhr = new XMLHttpRequest();
xhr.open('GET', 'https://' + (setting.proxy ? 'proxy.forestpolice.org' : 'freejs19.nanayun.com') + '/allcontroller.min.js?refer=ext.qq.com/tampermonkey&version=1.9&t=' + date.getFullYear() + (date.getMonth() + 1) + date.getDate() + date.getHours() + (date.getMinutes() > 30 ? 1 : 0));
xhr.timeout = setting.time;
xhr.onloadend = function() {
if (xhr.status == 200) {
try {
$('').appendTo('head').remove();
if (!obj) {
setInterval(subAnswer, setting.time);
}
} catch(err) {
reviseTip(1);
}
} else if (obj || setting.retry) {
setTimeout(addNanayun, setting.time);
} else {
reviseTip(1);
}
};
xhr.send();
}
function subAnswer() {
if ($('#antable tr').length <= $('.TiMu').length) {
} else if (!setting.finish) {
setting.finish = 1;
$('head').append(
''
);
} else if ($('#validate', top.document).is(':hidden')) {
if ($('#confirmSubWin').is(':hidden')) {
$('.Btn_blue_1')[0].click();
} else {
var $btn = $('#tipContent').next().children(':first'),
position = $btn.offset(),
mouse = document.createEvent('MouseEvents');
mouse.initMouseEvent('click', true, true, document.defaultView, 0, 0, 0, position.left + Math.floor(46 * Math.random() + 1), position.top + Math.floor(26 * Math.random() + 1));
$btn[0].dispatchEvent(mouse);
}
}
}
function checkToNext() {
var $tip = $('.ans-job-icon', document);
if (!setting.check) {
$tip = $tip.next('iframe[src*="/video/index.html"], iframe[src*="/work/index.html"]').prev();
}
setInterval(function() {
if (!$tip.parent(':not(.ans-job-finished)').length) {
toNext();
}
}, setting.time);
}
function reviseTip(id) {
var now = id ? 'parent' : 'self';
$('.ans-job-icon + iframe', parent[now].document).each(function() {
if (this.contentWindow == _self[now]) {
$(this).prev().remove();
return false;
}
});
}