// ==UserScript== // @name 超星学习通+AI自动答题脚本(支持考试,作业,章节测试,支持新版学习通,一键最小化,多种AI) // @namespace http://tampermonkey.net/ // @version 1.21 // @description 超星学习通+ChatGPT自动答题脚本(支持考试和作业和章节测试,支持新版学习通)。直接获取到答案,可以复制答案到剪切板。 // @author Cwyu // @license MIT // @supportURL 1441577495@qq.com // @contributionURL https://ifdian.net/a/cwyuu // @match *://mooc1.chaoxing.com/exam-ans/mooc2/exam/preview?* // @match *://mooc1.chaoxing.com/mooc2/work/dowork?* // @match *://mooc1.chaoxing.com/mycourse/studentstudy?* // @match *://mooc1.chaoxing.com/mycourse/studentstudy* // @match *://mooc1.chaoxing.com/mooc-ans/mooc2/work/dowork* // @icon https://www.google.com/s2/favicons?sz=64&domain=chaoxing.com // @grant unsafeWindow // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @run-at document-end // @downloadURL none // ==/UserScript== (function() { 'use strict'; GM_addStyle(` #my-window { position: fixed; top: 10px; left: 10px; width: 500px; height: 400px; background-color: rgba(255, 255, 255, 0.95); border: 1px solid #e2e8f0; border-radius: 8px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); z-index: 9999; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; resize: both; min-width: 300px; min-height: 200px; } #my-window .header { background-color: #1a202c; color: white; padding: 8px 12px; font-size: 14px; font-weight: 600; border-radius: 8px 8px 0 0; cursor: move; display: flex; justify-content: space-between; align-items: center; } #my-window .xxt-content { padding: 12px; display: flex; flex-direction: column; overflow: hidden; width: auto; min-height: 0; } #my-window .question-section, #my-window .answer-section { background-color: #fff; border: 1px solid #e2e8f0; padding: 12px; border-radius: 4px; margin-bottom: 8px; word-break: break-word; overflow-wrap: break-word; } #my-window .answer-section { flex: 1; overflow-y: auto; } #my-window .controls { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; } #my-window .settings-row { display: flex; align-items: center; gap: 12px; } #my-window .button-row { display: flex; gap: 8px; } #my-window button { padding: 4px 8px; border-radius: 4px; font-size: 12px; cursor: pointer; border: none; background: #e2e8f0; transition: background-color 0.2s; } #my-window button:hover { background: #cbd5e1; } #my-window button#refresh-btn { background: #3b82f6; color: white; } #my-window button#refresh-btn:hover { background: #2563eb; } #my-window button#copy-btn { background: #10b981; color: white; } #my-window button#copy-btn:hover { background: #059669; } #my-window select { padding: 4px; border-radius: 4px; font-size: 12px; border: 1px solid #e2e8f0; flex: 1; } #my-window input[type="text"] { padding: 4px 8px; border-radius: 4px; font-size: 12px; border: 1px solid #e2e8f0; flex: 1; } #floating-button { position: fixed; top: 20px; left: -45px; width: 50px; height: 50px; background-color: #1a202c; color: white; border-radius: 25px; text-align: center; line-height: 50px; cursor: pointer; transition: all 0.3s ease; z-index: 9999; font-size: 12px; } #floating-button:hover { left: 0; } #my-window .label { color: #64748b; font-size: 12px; margin-bottom: 4px; } #my-window .subscription-row { display: flex; gap: 8px; width: 100%; } #my-window .subscription-row input { flex: 1; } #my-window .subscription-row button { white-space: nowrap; } #my-window button svg { display: inline-block; vertical-align: middle; margin-right: 4px; } #my-window #prev-btn svg, #my-window #next-btn svg { margin-right: 0; } #my-window .status-info-row { display: flex; justify-content: space-between; align-items: center; padding: 4px 8px; border-top: 1px solid #e2e8f0; font-size: 12px; color: #64748b; } `); const windowHTML = `
AI答题(Alt+Z 快速隐藏)
当前题目:
答案:
状态内容
by: cwyu
显示
`; document.body.insertAdjacentHTML('beforeend', windowHTML); const myWindow = document.getElementById('my-window'); const floatingButton = document.getElementById('floating-button'); const hideBtn = document.getElementById('hide-btn'); const header = document.querySelector('.header'); const answerEl = document.getElementById('answer'); const questionEl = document.getElementById('question'); const subscriptionKey = document.getElementById('subscription-key'); let answerCache = {}; let currentIndex = 0; let timu = ["正在获取题目"]; let isDragging = false; let currentX; let currentY; let initialX; let initialY; let xOffset = 0; let yOffset = 0; header.addEventListener('mousedown', dragStart); document.addEventListener('mousemove', drag); document.addEventListener('mouseup', dragEnd); function dragStart(e) { initialX = e.clientX - xOffset; initialY = e.clientY - yOffset; if (e.target === header) { isDragging = true; } } function drag(e) { if (isDragging) { e.preventDefault(); currentX = e.clientX - initialX; currentY = e.clientY - initialY; xOffset = currentX; yOffset = currentY; myWindow.style.transform = `translate(${currentX}px, ${currentY}px)`; } } function dragEnd() { isDragging = false; } function toggleWindow() { if (myWindow.style.display === 'none') { myWindow.style.display = 'block'; floatingButton.style.display = 'none'; } else { myWindow.style.display = 'none'; floatingButton.style.display = 'block'; } } document.addEventListener('keydown', function(e) { if (e.altKey && e.key.toLowerCase() === 'z') { toggleWindow(); } }); hideBtn.addEventListener('click', toggleWindow); floatingButton.addEventListener('click', toggleWindow); floatingButton.style.display = 'none'; const savedKey = GM_getValue('subscription_key'); if (savedKey) { subscriptionKey.value = savedKey; (async () => { const data = { serial: savedKey }; try { const response = await fetch('https://xxt.uycc.xyz/api/v1/serial/check', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const result = await response.json(); document.getElementById('card_status').textContent = "可用的token余额:" + result.balances; } catch (error) { console.error('Serial check API error:', error); document.getElementById('card_status').textContent = "卡密验证失败,请检查卡密是否正确"; } })(); } async function fetchAnswer() { const currentQuestion = timu[currentIndex]; answerEl.textContent = "获取答案中..."; const data = { serial: subscriptionKey.value, question: currentQuestion, model: document.getElementById('ai-model').value, use_tiku: document.getElementById('use-tiku').checked, have_analyze: document.getElementById('need-analysis').checked }; try { const response = await fetch('https://xxt.uycc.xyz/api/v1/search', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const result = await response.json(); if (result.answer) { answerCache[currentIndex] = result.answer; answerEl.textContent = result.answer; if (result.cost===0) { document.getElementById('card_status').textContent = `题库中包含此题,不花费token`; } if (result.cost && result.balances) { document.getElementById('card_status').textContent = `本次花费: ${result.cost} | 剩余余额: ${result.balances}`; } } } catch (error) { console.error('Search API error:', error); answerEl.textContent = "请求失败,请检查卡密或网络连接"; } } function updateDisplay(index) { questionEl.textContent = timu[index]; answerEl.textContent = answerCache[index] || ''; } document.getElementById('prev-btn').addEventListener('click', () => { if (currentIndex > 0) { currentIndex--; updateDisplay(currentIndex); } }); document.getElementById('next-btn').addEventListener('click', () => { if (currentIndex < timu.length - 1) { currentIndex++; updateDisplay(currentIndex); } }); document.getElementById('refresh-btn').addEventListener('click', fetchAnswer); document.getElementById('copy-btn').addEventListener('click', () => { const answerText = answerEl.textContent; navigator.clipboard.writeText(answerText) .catch(err => console.error('复制失败:', err)); }); document.getElementById('save-btn').addEventListener('click', async () => { const key = subscriptionKey.value; GM_setValue('subscription_key', key); const data = { serial: key }; try { const response = await fetch('https://xxt.uycc.xyz/api/v1/serial/check', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const result = await response.json(); document.getElementById('card_status').textContent = "可用的token余额:" + result.balances; } catch (error) { console.error('Serial check API error:', error); document.getElementById('card_status').textContent = "卡密验证失败,请检查卡密是否正确"; } }); if (document.title === "学生学习页面") { queryElements(); } if (document.title == "作业作答") { const divs = document.querySelectorAll('.padBom50.questionLi:not(script)'); const texts = []; divs.forEach(div => { const text = div.textContent.trim().replace(/\s+/g, ' '); texts.push(text); }); timu = texts.map((text) => text.replace(/var\s+wordNum\s*=.*$/gm, "").trim() ); updateDisplay(0); } if (document.title == "整卷预览") { const elements = document.querySelectorAll('div.questionLi:not(script)'); const texts = []; for (let i = 0; i < elements.length; i++) { const element = elements[i]; const text = element.textContent.trim().replace(/\s+/g, ' '); texts.push(text); } timu = texts.map((text) => text.replace(/window\.UEDITOR_CONFIG\.initialFrameWidth.*保存/g, "").trim() ); updateDisplay(0); } async function queryElements() { const iframe = document.getElementById('iframe'); if (!iframe) { setTimeout(queryElements, 3000); return; } const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; const second = iframeDoc.querySelector('iframe'); if (!second) { setTimeout(queryElements, 3000); return; } const secondDoc = second.contentDocument || second.contentWindow.document; const third = secondDoc.getElementById('frame_content'); if (!third) { setTimeout(queryElements, 3000); return; } const thirdDoc = third.contentDocument || third.contentWindow.document; const elements = thirdDoc.querySelectorAll('div.TiMu:not(script)'); if (elements.length > 0) { const texts = []; elements.forEach(element => { const text = element.textContent.trim().replace(/\s+/g, ' '); texts.push(text); }); const style = $("style[type='text/css']", thirdDoc); const fontData = style.text().match(/'(data:application\/font-ttf;.*?)'/)[1]; const fontBase64 = fontData.split(",")[1]; timu = texts.map((text) => text .replace(/var\s+wordNum\s*=.*$/gm, "") .replace(/点击上传x[^}]*}/gm, "") .replace(/填写答案[^x]*x/gm, "") .trim() ); await decrypt(fontBase64); } else { setTimeout(queryElements, 3000); } } async function decrypt(b64) { const data = { text: timu, b64: b64 }; try { const response = await fetch("https://xxt.uycc.xyz/api/v1/decrypt", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const result = await response.json(); timu = result.text; updateDisplay(0); } catch (error) { console.error('Decrypt API error:', error); answerEl.textContent = "解密失败,请稍后重试"; } } questionEl.addEventListener('dblclick', function(e) { e.preventDefault(); const editableDiv = document.createElement('div'); editableDiv.setAttribute('contenteditable', true); editableDiv.textContent = questionEl.textContent; editableDiv.style.background = '#fff'; editableDiv.style.padding = '4px'; editableDiv.style.border = '1px solid #3b82f6'; editableDiv.style.borderRadius = '4px'; editableDiv.style.minHeight = '50px'; questionEl.replaceWith(editableDiv); editableDiv.focus(); function saveEdit() { timu[currentIndex] = editableDiv.textContent; questionEl.textContent = editableDiv.textContent; editableDiv.replaceWith(questionEl); } editableDiv.addEventListener('blur', saveEdit); editableDiv.addEventListener('keydown', function(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); saveEdit(); } }); }); const resizeObserver = new ResizeObserver(entries => { for (const entry of entries) { const { width, height } = entry.contentRect; const content = myWindow.querySelector('.xxt-content'); if (content) { content.style.height = `${height - 40}px`; } } }); resizeObserver.observe(myWindow); })();