// ==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==================================== */ })();