// ==UserScript==
// @name 文才学堂学习插件
// @namespace https://bbs.tampermonkey.net.cn/
// @version 0.1.2
// @description 文才学堂学习的插件,自动播放视频,自动完成作业,自动学习评论
// @author zhou
// @match http://learning.wencaischool.net/openlearning/*
// ==/UserScript==
(function () {
'use strict';
var $ = window.$;
function sleep(t) {
const _t = Date.now()
while(Date.now() - _t < t) {}
}
/**=========================批量评论start==================================== */
let $topciBtn
function initTopic() {
const $btn = window.$('
批量发话题
')
window.$('.btnGroup').append($btn)
$topciBtn = $btn
$btn.on('click', () => {
autoSendTopic()
})
}
function autoSendTopic(len = 5, content = '好好学习,天天向上') {
function addTopic(content, ifAsk = '0', articleImgs = '') {
$topciBtn.text(`正在发表(${len})`)
var params = {
'user_id': getQueryString('userId'),
'course_id': getQueryString('courseId'),
'school_code': getQueryString('schoolCode'),
'grade_code': getQueryString('gradeCode'),
'course_code': getQueryString('courseCode'),
'content': content,
'is_ask': ifAsk,
'img_url': articleImgs,
'time': 0
},
url = urlStart + '/forum_article.action?req=publishArticle', res = getData(url, params);
console.log(len)
len--
setTimeout(() => {
if (len > 0) {
addTopic(content, ifAsk, articleImgs)
} else {
alert('发表完成')
location.reload()
}
}, 1000)
}
addTopic(content)
}
if (location.origin + location.pathname === 'http://learning.wencaischool.net/openlearning/separation/coursePost/index.html')
initTopic()
/**=========================批量评论end==================================== */
/**=========================批量视频start==================================== */
let $videoBtn
function initVideo() {
const $btn = $('一键批量完成
')
$('.lefttop').append($btn).css({ 'text-align': 'center' }).find('.btn').css({ display: 'inline-block', margin: '15px 10px' });
$videoBtn = $btn
$btn.on('click', () => {
autoPlayList()
})
}
let autoPlayed = false
function autoPlayList() {
if (autoPlayed) return alert('程序正在执行,请稍等')
autoPlayed = true
function getChapterList() {
var params = {
'course_id': getQueryString('course_id')
}
var url = urlStart + '/newApp_learn_course.action?req=getCourseScormItemList', res = getData(url, params), str = '';
if (res.code === 1000) {
var resdata = dedata(res.data);
list = resdata.listCourseLesson
}
}
function getPower() {
var url = urlStart + '/newApp_use_energy.action?req=getUserAuthority', res = getData(url);
if (res.code === 1000) {
var data = dedata(res.data)
learning_user_id = data.userId
}
}
var i = 0, learning_user_id = 3518, list = []
function useEnergy(siid, courseId) {
var params = {
'learning_user_id': getQueryString('user_id'),
'course_id': courseId,
'type_code': 'progress',
'item_id': siid
},
url = urlStart + '/newApp_use_energy.action?req=saveUseEnergyInfo', res = getData(url, params), ret = false;
if (res.code == 1000) {
ret = true;
var data = dedata(res.data);
$('#lastEnergy').text(data);
} else {
layer.msg(res.message, { time: 1000 });
}
return ret;
}
function saveSubmit(item) {
var params = {
'user_id': getQueryString('user_id'),
'course_id': item.courseId,
'time': item.timeLen,
'item_id': item.lessonId,
'view_time': item.timeLen,
'last_view_time': item.timeLen - 1,
'video_length': item.timeLen,
'learning_user_id': learning_user_id
},
url = urlStart + '/learning.action?req=submitScormAndHistorySave', res = getData(url, params);
if (res.code == 1000) {
var data = dedata(res.data)
if (data.isFinish) {
console.log(item.lessonName + '完成')
i++
playNext()
}
}
}
function autoPlay(item) {
var energy = true
if (item.useEnergyNum == 1) {
energy = useEnergy(item.lessonId, item.courseId)
}
var t = setTimeout(() => {
if (!energy) return false
saveSubmit(item)
}, 1000)
}
function playNext() {
var item = list[i]
if (!item) return alert('已全部完成,请切换下一个课程')
$videoBtn.text(`已完成(${i+1}/${list.length})`)
if (item.isFinish || item.lessonType != 'scorm_content') {
console.log(`=====${item.lessonName}=====`)
i++
playNext()
} else {
autoPlay(item)
}
}
getChapterList()
getPower()
playNext()
}
if (location.origin + location.pathname === 'http://learning.wencaischool.net/openlearning/separation/courseware/index.html')
initVideo()
/**=========================批量视频end==================================== */
/**=========================批量作业start==================================== */
let $workBtn, worked = false, baseurl, answerObj = {}, sExamStatus, examid
function initWork() {
const $btn = $('一键完成作业')
$('.func').after($btn)
$btn.css('margin-left', '10px')
$workBtn = $btn;
$btn.bind('click', async () => {
if (worked) return alert('正在做题中...')
worked = true
$workBtn.text('正在自动做题中...')
const html = document.body.outerHTML
const contentIds = html.match(/contentId="(\d+)"/gi).map(item => item.match(/\d+/)[0])
const examids = html.match(/examid\s?=\s?"(\d+)"/ig).map(item => /\d+/.exec(item)[0])
baseurl = $fn.getLearningWeb()
// console.log(contentIds, examids)
try {
// examid = examids[0]
// await autoWork(contentIds[0])
for (let i = 0; i < examids.length; i++) {
examid = examids[i]
await autoWork(contentIds[i])
$workBtn.text(`已完成${i+1}/${examids.length}`)
sleep(1000)
}
alert('已全部完成')
} catch(e) {
console.log(e)
}
// location.reload()
})
}
async function autoWork(sContentId) {
const chech = await fetch(`${baseurl}/course/check_pre_index.jsp?content_id=${sContentId}`).then(res => res.text())
if(chech.indexOf('ERROR:') > -1) return alert('数据错误,请手动完成作业')
const sUrl = baseurl + "/exam/portal/exam_info.jsp?content_id="+sContentId+"&type=work&is_make_up=undefined";
let html = await fetch(sUrl).then(res => res.text())
html = html.replace(/\\/g, '')
let scoreId = html.match(/sScoreId\s?=\s?"(\d+)"/)?.[1]
sExamStatus = /sExamStatus\s?=\s?"(\w+)"/.exec(html)[1]
const score = html.match(/(\d+)\(\1\/100\)/)?.[1]
console.log(score, scoreId, sExamStatus)
if (score > 90) return
if (sExamStatus === 'reexamine') {
// 查看答案
const params = $wapper.api.getURLParams($wapper.api.setQueryString("reexamine", '0', sUrl))
const answers = await viewAnswer(scoreId, params)
answerObj[sContentId] = answers
console.log(answers)
if (!answers) return alert(`id=${sContentId}题目获取答案失败,请手动操作`)
await doWork(sContentId)
} else {
// 先做一遍题
await doWork(sContentId)
sleep(1000)
await autoWork(sContentId)
}
}
function disposeAnswer(ans = '') {
if (ans.indexOf('答') === 0) return ans.substring(2)
return /\[参考答案:([^\]]+)\]/i.exec(ans)?.[1] || ''
}
function disposeNames(list) {
const nameM = [...new Set(list.map(name => /\w{28,}/.exec(name)[0]).filter(name => name.split('_').length >= 4))]
let currentName = '', nameSet = new Set()
nameM.forEach(name => {
const cname = strDiff(currentName, name)
cname ? nameSet.add(cname) : nameSet.add(name)
if (cname === name) {
currentName && nameSet.delete(currentName)
}
currentName = name
})
return [...nameSet]
}
function strDiff(str1 = '', str2 = '') {
const arr1 = str1.split('_'), arr2 = str2.split('_')
const maxlen = Math.max(arr1.length, arr2.length)
const minlen = Math.min(arr1.length, arr2.length)
const retArr = []
for(let i = 0; i < maxlen; i++) {
if (arr1[i] === arr2[i]) retArr.push(arr1[i])
}
return retArr.length >= (minlen - 1) ? retArr.join('_') : ''
}
function viewAnswer(scoreId, params) {
return new Promise(async (resolve) => {
const viewUrl = `${baseurl}/exam/portal/view_answer.jsp?exam_id=${examid}&score_id=${scoreId}&${params}`;
let html = await fetch(viewUrl).then(res => res.text())
html = html.replaceAll(/\\/g, '')
const obj = {}
const answerM = html.match(/\[参考答案:[^\]]+\]|答[::][^<]*/gi)
let nameM = html.match(/(name|id)=\\*"?\w{28,}?\\*"?[ >]/gi)
if (!(answerM && nameM)) throw new Error('答案获取失败,请手动做题')
nameM = disposeNames(nameM)
if (nameM.length !== answerM.length) {
console.log(nameM, answerM)
throw new Error('答案解析失败,请联系管理员')
}
let count = 0
nameM.forEach((name, i) => {
obj[name] = disposeAnswer(answerM[i])
count++
})
resolve(count ? obj : null)
})
}
function doWork(sContentId) {
return new Promise(async (resolve) => {
const viewUrl = location.origin + $api.fn.getActionURL(`com.lemon.learning.exam.StudentExamAction?op=before_exam&exam_id=${examid}&reexam=${(sExamStatus=="reexamine"?"1":"0")}&script=parent.afterCheckExam()&type=work`);
// return resolve(console.log(viewUrl))
await fetch(viewUrl)
const params = `exam_id=${examid}&type=work&content_id=${sContentId}&type=work&is_make_up=undefined`
await fetch(`${baseurl}/exam/portal/exam_console.htm?${params}`)
await fetch(`${baseurl}/exam/portal/exam_left.jsp?${params}`)
let html = await fetch(`${baseurl}/exam/portal/exam.jsp?${params}`).then(res => res.text())
html = html.replace(/\\/g, '')
const answers = answerObj[sContentId] || {}
const arr = []
let nameM = html.match(/keylist="\w{28,}"/gi)
// console.log(nameM)
const names = disposeNames(nameM.concat(Object.keys(answers)))
// console.log(names)
names.forEach(name => {
arr.push(`${name}=${answers[name] || 'A'}`)
})
await postWork(arr.join('&'))
resolve()
})
}
function postWork(body) {
return new Promise(async (resolve) => {
const url = location.origin + $api.fn.getActionURL(`com.lemon.learning.exam.StudentExamAction?op=submit_exam&exam_id=${examid}&b_out=1&item_id=&type=work&r=${Math.random()}`)
$.ajax({
url,
type: 'post',
data: body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded;'
},
success(data) {
resolve(true)
},
error(e) {
console.log(e)
}
})
})
}
if(location.origin + location.pathname === 'http://learning.wencaischool.net/openlearning/course/learning/learn_homework.jsp')
initWork()
/**=========================批量作业end==================================== */
})();