// ==UserScript== // @name 江苏开放大学刷课脚本 // @namespace http://tampermonkey.net/ // @version 2.0 // @description 江苏开放大学刷课脚本-二改版,增加手动增加时长功能 | 原作者:Pwn | 二创作者:thanks play // @author Pwn (原作者) / thanks play (二创作者) // @match http://xuexi.jsou.cn/jxpt-web/student/courseuser/courseVersionId=* // @match http://xuexi.jsou.cn/jxpt-web/student/activity/display?courseVersionId=* // @match http://xuexi.jsou.cn/jxpt-web/student/newHomework/showHomeworkByStatus?courseVersionId=* // @icon https://www.google.com/s2/favicons?sz=64&domain=jsou.cn // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== var manualSelectMode = false; var manualMinMinutes = 8; var manualMaxMinutes = 10; var manualSelectRunning = false; var manualSelectButton = null; function StartRunCourse() { for(var i=0;i<300;i++) { sendHeartBeatAjax(); } } function AddTime(seconds) { var secondsPerHeartbeat = 30; var totalHeartbeats = Math.ceil(seconds / secondsPerHeartbeat); console.log('开始按节奏增加时长...'); console.log('需要发送心跳包: ' + totalHeartbeats + '次'); var heartbeatCount = 0; var heartbeatInterval = setInterval(function() { if(heartbeatCount >= totalHeartbeats) { clearInterval(heartbeatInterval); console.log('✓ 已发送 ' + totalHeartbeats + ' 次心跳包'); return; } sendHeartBeatAjax(); heartbeatCount++; console.log('已发送第 ' + heartbeatCount + '/' + totalHeartbeats + ' 次心跳包'); }, 30000); } function toggleSettingsPanel() { var panel = document.getElementById('settingsPanel'); if(panel.style.display === 'none') { panel.style.display = 'block'; } else { panel.style.display = 'none'; } } function ManualSelectAuto(minMinutes, maxMinutes) { console.log('=== ManualSelectAuto 函数开始执行 ==='); console.log('参数:minMinutes=' + minMinutes + ', maxMinutes=' + maxMinutes); var allActivities = []; if(typeof units !== 'undefined' && units && units.length > 0) { console.log('使用 units 变量获取课程列表'); for(var i=0;i 0) { for(var j=0;j= allActivities.length) { console.log('✓ 全部刷课完成!'); if(manualSelectButton) { manualSelectButton.textContent = '已完成'; manualSelectButton.style.backgroundColor = '#4CAF50'; } manualSelectRunning = false; GM_setValue('manualSelectMode', false); alert('全部刷课完成!'); return; } var activityId = allActivities[currentIndex]; var randomMinutes = Math.floor(Math.random() * (maxMinutes - minMinutes + 1)) + minMinutes; var randomSeconds = randomMinutes * 60; var secondsPerHeartbeat = 30; var totalHeartbeats = Math.ceil(randomSeconds / secondsPerHeartbeat); console.log('课程信息:'); console.log(' - ID: ' + activityId); console.log(' - 随机时长: ' + randomMinutes + '分钟'); console.log(' - 需要发送心跳包: ' + totalHeartbeats + '次'); if(manualSelectButton) { manualSelectButton.textContent = '正在刷课: ' + (currentIndex + 1) + '/' + allActivities.length; manualSelectButton.style.backgroundColor = '#FF9800'; } console.log('开始按节奏发送心跳包...'); var heartbeatCount = 0; var heartbeatInterval = setInterval(function() { if(!manualSelectRunning) { clearInterval(heartbeatInterval); console.log('手动选课已停止,停止发送心跳包'); return; } if(heartbeatCount >= totalHeartbeats) { clearInterval(heartbeatInterval); console.log('✓ 已发送 ' + totalHeartbeats + ' 次心跳包'); currentIndex++; if(currentIndex < allActivities.length && manualSelectRunning) { console.log('立即处理下一个课程...'); processNextCourse(); } return; } sendHeartBeatAjax(); heartbeatCount++; console.log('已发送第 ' + heartbeatCount + '/' + totalHeartbeats + ' 次心跳包'); }, 30000); } console.log('启动第一个课程处理...'); processNextCourse(); } function AllCourseAuto(minMinutes, maxMinutes) { console.log('=== AllCourseAuto 函数开始执行 ==='); console.log('参数:minMinutes=' + minMinutes + ', maxMinutes=' + maxMinutes); var allCourses = []; var savedProgress = GM_getValue('autoJumpProgress', null); var startIndex = 0; if(typeof units !== 'undefined' && units && units.length > 0) { console.log('使用 units 变量获取课程列表'); for(var i=0;i 0) { for(var j=0;j= allCourses.length) { console.log('✓ 全部课程跳转完成!'); GM_setValue('autoJumpProgress', null); alert('全部课程跳转完成!'); return; } var course = allCourses[currentIndex]; console.log('课程信息:'); console.log(' - ID: ' + course.id); console.log(' - 名称: ' + course.name); console.log(' - URL: ' + course.url); GM_setValue('autoJumpProgress', currentIndex); console.log('等待3秒后跳转...'); setTimeout(function() { console.log('跳转到课程: ' + course.name); window.location.href = course.url; }, 3000); } console.log('启动第一个课程跳转...'); processNextCourse(); } function InjectClickButton() { var StartTree = document.evaluate('//*[@id="courseContent_1_switch"]',document).iterateNext(); var ShowText =document.evaluate('//*[@id="courseContent_1_a"]',document).iterateNext(); ShowText.textContent = "点击一键完成本课"; ShowText.style.color="red"; StartTree.removeAttribute("treenode_switch"); StartTree.onclick=()=>{StartRunCourse()} var savedLeft = GM_getValue('buttonLeft', '20px'); var savedTop = GM_getValue('buttonTop', null); var savedBottom = GM_getValue('buttonBottom', '20px'); var buttonContainer = document.createElement('div'); buttonContainer.style.cssText = 'position: fixed; bottom: ' + savedBottom + '; left: ' + savedLeft + '; z-index: 9999; background: white; padding: 10px; border: 2px solid #4CAF50; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.3); cursor: move;'; if(savedTop) { buttonContainer.style.top = savedTop; buttonContainer.style.bottom = 'auto'; } var title = document.createElement('div'); title.textContent = '手动增加时长(可拖拽)(thanks play build)'; title.style.cssText = 'font-weight: bold; margin-bottom: 10px; color: #333; user-select: none;'; buttonContainer.appendChild(title); var buttons = [ { text: '+30秒', seconds: 30, color: '#2196F3' }, { text: '+1分钟', seconds: 60, color: '#4CAF50' }, { text: '+5分钟', seconds: 300, color: '#FF9800' } ]; buttons.forEach(btn => { var button = document.createElement('button'); button.textContent = btn.text; button.style.cssText = `margin: 5px; padding: 8px 15px; background-color: ${btn.color}; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 14px;`; button.onclick = (e) => { e.stopPropagation(); AddTime(btn.seconds); }; buttonContainer.appendChild(button); }); var divider2 = document.createElement('div'); divider2.style.cssText = 'border-top: 1px solid #ddd; margin: 10px 0;'; buttonContainer.appendChild(divider2); var secondRow = document.createElement('div'); secondRow.style.cssText = 'display: flex; align-items: center; gap: 5px;'; var tenMinButton = document.createElement('button'); tenMinButton.textContent = '+10分钟'; tenMinButton.style.cssText = 'margin: 5px; padding: 8px 15px; background-color: #E91E63; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 14px;'; tenMinButton.onclick = (e) => { e.stopPropagation(); AddTime(600); }; secondRow.appendChild(tenMinButton); var randomButton = document.createElement('button'); randomButton.textContent = '+随机'; randomButton.style.cssText = 'margin: 5px; padding: 8px 10px; background-color: #00BCD4; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 14px; width: 80px;'; randomButton.onclick = (e) => { e.stopPropagation(); var minMin = parseInt(document.getElementById('randomMin').value) || 8; var maxMin = parseInt(document.getElementById('randomMax').value) || 10; GM_setValue('randomMin', minMin); GM_setValue('randomMax', maxMin); var randomMinutes = Math.floor(Math.random() * (maxMin - minMin + 1)) + minMin; AddTime(randomMinutes * 60); }; secondRow.appendChild(randomButton); var settingsIcon = document.createElement('span'); settingsIcon.innerHTML = '⚙️'; settingsIcon.style.cssText = 'cursor: pointer; font-size: 18px; margin-left: 5px;'; settingsIcon.onclick = (e) => { e.stopPropagation(); toggleSettingsPanel(); }; secondRow.appendChild(settingsIcon); buttonContainer.appendChild(secondRow); var settingsPanel = document.createElement('div'); settingsPanel.id = 'settingsPanel'; settingsPanel.style.cssText = 'display: none; margin-top: 10px; padding: 10px; background: #f5f5f5; border-radius: 3px;'; var randomTitle = document.createElement('div'); randomTitle.textContent = '随机时间设置'; randomTitle.style.cssText = 'font-weight: bold; margin-bottom: 8px; color: #333; font-size: 12px;'; settingsPanel.appendChild(randomTitle); var randomSettings = document.createElement('div'); randomSettings.style.cssText = 'display: flex; align-items: center; gap: 5px;'; var randomMinLabel = document.createElement('span'); randomMinLabel.textContent = '最小:'; randomMinLabel.style.cssText = 'font-size: 12px;'; randomSettings.appendChild(randomMinLabel); var randomMinInput = document.createElement('input'); randomMinInput.type = 'number'; randomMinInput.value = GM_getValue('randomMin', '8'); randomMinInput.id = 'randomMin'; randomMinInput.style.cssText = 'width: 50px; padding: 3px;'; randomSettings.appendChild(randomMinInput); var randomMaxLabel = document.createElement('span'); randomMaxLabel.textContent = '最大:'; randomMaxLabel.style.cssText = 'font-size: 12px;'; randomSettings.appendChild(randomMaxLabel); var randomMaxInput = document.createElement('input'); randomMaxInput.type = 'number'; randomMaxInput.value = GM_getValue('randomMax', '10'); randomMaxInput.id = 'randomMax'; randomMaxInput.style.cssText = 'width: 50px; padding: 3px;'; randomSettings.appendChild(randomMaxInput); var unitLabel = document.createElement('span'); unitLabel.textContent = '分钟'; unitLabel.style.cssText = 'font-size: 12px;'; randomSettings.appendChild(unitLabel); settingsPanel.appendChild(randomSettings); buttonContainer.appendChild(settingsPanel); var divider = document.createElement('div'); divider.style.cssText = 'border-top: 1px solid #ddd; margin: 10px 0;'; buttonContainer.appendChild(divider); var allCourseTitle = document.createElement('div'); allCourseTitle.textContent = '全部刷课'; allCourseTitle.style.cssText = 'font-weight: bold; margin-bottom: 5px; color: #333; font-size: 12px;'; buttonContainer.appendChild(allCourseTitle); var timeContainer = document.createElement('div'); timeContainer.style.cssText = 'margin: 5px 0;'; var minLabel = document.createElement('span'); minLabel.textContent = '最小(分钟):'; minLabel.style.cssText = 'font-size: 12px;'; timeContainer.appendChild(minLabel); var minInput = document.createElement('input'); minInput.type = 'number'; minInput.value = GM_getValue('allCourseMin', '8'); minInput.id = 'minMinutes'; minInput.style.cssText = 'width: 50px; margin: 0 5px; padding: 3px;'; timeContainer.appendChild(minInput); var maxLabel = document.createElement('span'); maxLabel.textContent = '最大(分钟):'; maxLabel.style.cssText = 'font-size: 12px;'; timeContainer.appendChild(maxLabel); var maxInput = document.createElement('input'); maxInput.type = 'number'; maxInput.value = GM_getValue('allCourseMax', '10'); maxInput.id = 'maxMinutes'; maxInput.style.cssText = 'width: 50px; margin: 0 5px; padding: 3px;'; timeContainer.appendChild(maxInput); buttonContainer.appendChild(timeContainer); var allCourseButton = document.createElement('button'); allCourseButton.textContent = '全部刷课'; allCourseButton.style.cssText = 'margin: 5px; padding: 8px 15px; background-color: #9C27B0; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 14px; width: 100%;'; allCourseButton.onclick = (e) => { e.stopPropagation(); console.log('=== 全部刷课按钮被点击 ==='); var minMin = parseInt(document.getElementById('minMinutes').value) || 8; var maxMin = parseInt(document.getElementById('maxMinutes').value) || 10; GM_setValue('allCourseMin', minMin); GM_setValue('allCourseMax', maxMin); console.log('获取到的参数:最小=' + minMin + '分钟,最大=' + maxMin + '分钟'); AllCourseAuto(minMin, maxMin); }; buttonContainer.appendChild(allCourseButton); var divider2 = document.createElement('div'); divider2.style.cssText = 'border-top: 1px solid #ddd; margin: 10px 0;'; buttonContainer.appendChild(divider2); var manualTitle = document.createElement('div'); manualTitle.textContent = '手动选课模式'; manualTitle.style.cssText = 'font-weight: bold; margin-bottom: 5px; color: #333; font-size: 12px;'; buttonContainer.appendChild(manualTitle); var manualTimeContainer = document.createElement('div'); manualTimeContainer.style.cssText = 'margin: 5px 0;'; var manualMinLabel = document.createElement('span'); manualMinLabel.textContent = '最小(分钟):'; manualMinLabel.style.cssText = 'font-size: 12px;'; manualTimeContainer.appendChild(manualMinLabel); var manualMinInput = document.createElement('input'); manualMinInput.type = 'number'; manualMinInput.value = GM_getValue('manualMin', '8'); manualMinInput.id = 'manualMin'; manualMinInput.style.cssText = 'width: 50px; margin: 0 5px; padding: 3px;'; manualTimeContainer.appendChild(manualMinInput); var manualMaxLabel = document.createElement('span'); manualMaxLabel.textContent = '最大(分钟):'; manualMaxLabel.style.cssText = 'font-size: 12px;'; manualTimeContainer.appendChild(manualMaxLabel); var manualMaxInput = document.createElement('input'); manualMaxInput.type = 'number'; manualMaxInput.value = GM_getValue('manualMax', '10'); manualMaxInput.id = 'manualMax'; manualMaxInput.style.cssText = 'width: 50px; margin: 0 5px; padding: 3px;'; manualTimeContainer.appendChild(manualMaxInput); buttonContainer.appendChild(manualTimeContainer); var manualButtonContainer = document.createElement('div'); manualButtonContainer.style.cssText = 'display: flex; gap: 5px; margin: 5px 0;'; var manualButton = document.createElement('button'); manualButton.textContent = '启动手动选课'; manualButton.style.cssText = 'flex: 1; padding: 8px 15px; background-color: #FF5722; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 14px;'; manualButton.onclick = (e) => { e.stopPropagation(); console.log('=== 手动选课按钮被点击 ==='); var minMin = parseInt(document.getElementById('manualMin').value) || 8; var maxMin = parseInt(document.getElementById('manualMax').value) || 10; GM_setValue('manualMin', minMin); GM_setValue('manualMax', maxMin); GM_setValue('manualSelectMode', true); manualSelectMode = true; manualMinMinutes = minMin; manualMaxMinutes = maxMin; manualSelectButton = manualButton; console.log('手动选课模式已启动,随机时间:' + minMin + '~' + maxMin + '分钟'); ManualSelectAuto(minMin, maxMin); }; manualButtonContainer.appendChild(manualButton); var stopManualButton = document.createElement('button'); stopManualButton.textContent = '停止手动选课'; stopManualButton.style.cssText = 'flex: 1; padding: 8px 15px; background-color: #607D8B; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 14px;'; stopManualButton.onclick = (e) => { e.stopPropagation(); console.log('=== 停止手动选课按钮被点击 ==='); GM_setValue('manualSelectMode', false); manualSelectMode = false; manualSelectRunning = false; if(manualSelectButton) { manualSelectButton.textContent = '启动手动选课'; manualSelectButton.style.backgroundColor = '#FF5722'; } console.log('手动选课模式已停止'); alert('手动选课模式已停止!'); }; manualButtonContainer.appendChild(stopManualButton); buttonContainer.appendChild(manualButtonContainer); document.body.appendChild(buttonContainer); var isDragging = false; var offsetX, offsetY; buttonContainer.addEventListener('mousedown', function(e) { if (e.target.tagName === 'BUTTON' || e.target.tagName === 'INPUT') return; isDragging = true; offsetX = e.clientX - buttonContainer.offsetLeft; offsetY = e.clientY - buttonContainer.offsetTop; buttonContainer.style.cursor = 'grabbing'; }); document.addEventListener('mousemove', function(e) { if (!isDragging) return; buttonContainer.style.left = (e.clientX - offsetX) + 'px'; buttonContainer.style.top = (e.clientY - offsetY) + 'px'; buttonContainer.style.bottom = 'auto'; buttonContainer.style.right = 'auto'; }); document.addEventListener('mouseup', function() { if(isDragging) { GM_setValue('buttonLeft', buttonContainer.style.left); GM_setValue('buttonTop', buttonContainer.style.top); GM_setValue('buttonBottom', 'auto'); } isDragging = false; buttonContainer.style.cursor = 'move'; }); manualSelectMode = GM_getValue('manualSelectMode', false); manualMinMinutes = GM_getValue('manualMin', 8); manualMaxMinutes = GM_getValue('manualMax', 10); if(manualSelectMode) { console.log('检测到手动选课模式已激活,但需要手动启动'); GM_setValue('manualSelectMode', false); manualSelectMode = false; if(manualSelectButton) { manualSelectButton.textContent = '启动手动选课'; manualSelectButton.style.backgroundColor = '#FF5722'; } } } function GetDocId() { var DocActivy = document.getElementsByClassName('activity doc'); var DocIds = [] for(var i=0;i { e.stopPropagation(); CrackCopyPaste(); }; buttonContainer.appendChild(crackButton); var statusText = document.createElement('div'); statusText.id = 'crackStatus'; statusText.textContent = '未破解'; statusText.style.cssText = 'margin-top: 10px; padding: 5px; background: #f5f5f5; border-radius: 3px; font-size: 12px; color: #666; text-align: center;'; buttonContainer.appendChild(statusText); document.body.appendChild(buttonContainer); var isDragging = false; var offsetX, offsetY; buttonContainer.addEventListener('mousedown', function(e) { if (e.target.tagName === 'BUTTON') return; isDragging = true; offsetX = e.clientX - buttonContainer.offsetLeft; offsetY = e.clientY - buttonContainer.offsetTop; buttonContainer.style.cursor = 'grabbing'; }); document.addEventListener('mousemove', function(e) { if (!isDragging) return; buttonContainer.style.left = (e.clientX - offsetX) + 'px'; buttonContainer.style.top = (e.clientY - offsetY) + 'px'; buttonContainer.style.bottom = 'auto'; buttonContainer.style.right = 'auto'; }); document.addEventListener('mouseup', function() { isDragging = false; buttonContainer.style.cursor = 'move'; }); } function CrackCopyPaste() { console.log('=== 开始破解复制粘贴限制 ==='); var allElements = document.querySelectorAll('*'); var count = 0; allElements.forEach(function(element) { var originalStyle = element.style.cssText; element.style.userSelect = 'auto'; element.style.webkitUserSelect = 'auto'; element.style.mozUserSelect = 'auto'; element.style.msUserSelect = 'auto'; element.oncopy = null; element.oncut = null; element.onpaste = null; element.removeAttribute('oncopy'); element.removeAttribute('oncut'); element.removeAttribute('onpaste'); element.removeEventListener('copy', function(e) { e.preventDefault(); }); element.removeEventListener('cut', function(e) { e.preventDefault(); }); element.removeEventListener('paste', function(e) { e.preventDefault(); }); count++; }); document.oncopy = null; document.oncut = null; document.onpaste = null; document.removeEventListener('copy', function(e) { e.preventDefault(); }); document.removeEventListener('cut', function(e) { e.preventDefault(); }); document.removeEventListener('paste', function(e) { e.preventDefault(); }); var style = document.createElement('style'); style.innerHTML = ` * { user-select: auto !important; -webkit-user-select: auto !important; -moz-user-select: auto !important; -ms-user-select: auto !important; } `; document.head.appendChild(style); console.log('✓ 已处理 ' + count + ' 个元素'); console.log('✓ 复制粘贴限制已破解!'); var statusText = document.getElementById('crackStatus'); if(statusText) { statusText.textContent = '✓ 已破解 - 可以自由复制粘贴'; statusText.style.color = '#4CAF50'; statusText.style.background = '#E8F5E9'; } alert('复制粘贴限制已破解!现在可以自由复制粘贴了。'); } function MainRun() { if(location.href.includes("display")) { InjectClickButton(); } else if(location.href.includes("showHomeworkByStatus")) { InjectCopyButton(); } else { unsafeWindow.DocHeart_Send = DocHeart_Send; unsafeWindow.VideoHeart_Send = VideoHeart_Send; unsafeWindow.AudioHeart_Send = AudioHeart_Send; console.info(`%c+`,`background-image:url(https://s3.bmp.ovh/imgs/2022/03/5e6d432c16060d22.jpg);background-size: contain; background-repeat: no-repeat; color: transparent;padding: 122px 217px;`) console.info("%c当你打开控制台的时候,请记住以下几个规则:\n1.DocHeart_Send函数可以帮你刷全部的文档课程\n2.VideoHeart_Send函数可以帮你刷全部的视频课程\n3.AudioHeart_Send函数可以帮你刷全部的音频课程\n4.在课程页面右上角有手动增加时长的按钮(+30秒、+1分钟、+5分钟)\n按需使用,不要一次性全部输入,不然程序会混乱,使用过程中感觉浏览器有点卡顿是正常现象,程序在无延迟的发送网络请求,所以会发生卡顿\n当你发现一排红报错的时候,请不要犹豫,立马刷新页面,重新开始刷课。\n\n二改说明:本脚本基于原作者Pwn的开源脚本进行二次开发,增加了手动增加时长的功能。","color:red;margin-top:10px"); } } MainRun();