您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
It solves practice lessons automatically or manually, to increase xp use DuoSolverGrinder.
当前为
// ==UserScript== // @name SolverDuo // @namespace Violentmonkey Scripts // @match https://*.duolingo.com/* // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @require https://cdn.tailwindcss.com // @version 1.0.8 // @author DuoSolverGrinder, has as base DuoPower modified totally. // @description It solves practice lessons automatically or manually, to increase xp use DuoSolverGrinder. // To grind xp automatically visit https://duosolver.is-great.net // ==/UserScript== let solveTimerId; let isAutoMode = GM_getValue('isAutoMode', false); let isPanelShow = GM_getValue('isPanelShow', true); let solveSpeedList = {'speedSlow': 2000, 'speedMedium': 1000, 'speedFast': 500, 'speedFastest': 0 } let solveSpeed = GM_getValue('solveSpeed', 'speedMedium'); const mainLessonFormClass = "[id='root'] > div > div > div > div > div:first-child._3v4ux"; let panelHtml = ` <div id="panelShowBttns" class="flex flex-col gap-y-2 z-[111] fixed xl:bottom-4 right-5 bottom-48 hidden"> <button id="panelShowBttn" class="font-bold text-gray-800 shadow-lg rounded-full px-2 bg-indigo-200 border border-2" >+</button> <a target="_blank"class="px-1" href="https://duosolver.is-great.net/"> <img class="rounded-md w-7 h-7" src="https://duosolvergrinder.github.io/DuoSolverGrinder/dsg.png" > </a> </div> <div id="panelDuoSolver" class="inline-flex flex-col gap-y-4 justify-end rounded-xl fixed xl:bottom-4 right-5 bottom-28 z-[111] border border-1 p-4 bg-indigo-400 dark:bg-gray-900"> <button id="panelHideBttn" title="hide" class="w-6 self-center rounded-lg bg-gray-600 text-gray-200">-</button> <button id="startBttn" class="px-4 py-2 rounded-md border border-2 bg-blue-600 text-gray-200 dark:bg-gray-300 dark:text-gray-800">Start</button> <section class="inline-flex rounded-md shadow-sm" role="group"> <button id="speedSlow" type="button" class="speedSelector px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-s-lg dark:bg-gray-800 dark:border-gray-700 dark:text-white dark:focus:ring-blue-500 dark:focus:text-white"> Slow </button> <button id="speedMedium" type="button" class="speedSelector px-4 py-2 text-sm font-medium text-gray-900 bg-white border-t border-b border-gray-200 dark:bg-gray-800 dark:border-gray-700 dark:text-white dark:focus:ring-blue-500 dark:focus:text-white"> Medium </button> <button id="speedFast" type="button" class="speedSelector px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 dark:bg-gray-800 dark:border-gray-700 dark:text-white dark:focus:ring-blue-500 dark:focus:text-white"> Fast </button> <button id="speedFastest" type="button" class="speedSelector px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-e-lg dark:bg-gray-800 dark:border-gray-700 dark:text-white dark:focus:ring-blue-500 dark:focus:text-white"> Fastest </button> </section> <p class="dark:text-gray-200">To grind higher xp, use next link:</p> <div class="flex justify-center gap-x-2"> <a target="_blank" href="https://github.com/DuoSolverGrinder/DuoSolverGrinder/"> <svg class="dark:hidden text-red-500 w-8 h-8" fill="none" viewBox="0 0 120 120" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/> </svg> <svg class="hidden dark:block w-8 h-8" fill="none" viewBox="0 0 120 120" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#fff"/> </svg> </a> <a target="_blank" href="https://duosolver.is-great.net/"> <img class="rounded-md w-7 h-7" src="https://duosolvergrinder.github.io/DuoSolverGrinder/dsg.png" > </a> </div> </div> `; let solvesBttnHtml = ` <button id="solveBttn" style="--web-ui_button-background-color: rgb(var(--color-gold)); --web-ui_button-border-color: rgb(var(--color-gold))" class="_1rcV8 _1VYyp _1ursp _7jW2t _3DbUj _38g3s lg:block hidden">Solve</button> <button id="solveAllBttn" class="_1rcV8 _1VYyp _1ursp _7jW2t _3DbUj _38g3s _2oGJR">Solve All</button> `; function insertPanelAndBttns() { let panel = document.getElementById('panelDuoSolver'); if(!panel) { document.body.insertAdjacentHTML('beforeend', panelHtml); let bttn = document.getElementById('startBttn'); bttn.addEventListener('click', startStopMain ); const showBttn = document.getElementById('panelShowBttn'); const hideBttn = document.getElementById('panelHideBttn'); showBttn.addEventListener('click', toggleShowHidePanel ); hideBttn.addEventListener('click', toggleShowHidePanel ); document.querySelectorAll('.speedSelector').forEach((element)=> element.addEventListener('click', speedSolveChange)); updatePanelDisplay(); updateSpeedBttnsActive(); } if (window.location.pathname === '/lesson' || window.location.pathname === '/practice') { addButtons(); panel ? panel.children[1].style.display = 'none' : null; return; } panel ? panel.children[1].style.display = '': null; } window.onload = (event) => { GM_addStyle('img { max-width: none}'); } setInterval(insertPanelAndBttns, 1000); function speedSolveChange() { solveSpeed = this.id; GM_setValue('solveSpeed', solveSpeed); updateSpeedBttnsActive(); } function updateSpeedBttnsActive() { const speedBttns = document.querySelectorAll('.speedSelector'); speedBttns.forEach((element)=> element.classList.remove('bg-gray-900','text-white','font-bold')); speedBttns.forEach((element)=> { if(element.id == solveSpeed) { element.classList.remove('bg-white', 'text-gray-900', 'font-semibold', 'dark:bg-gray-800'); element.classList.add('bg-gray-900', 'text-white', 'font-bold', 'dark:bg-black'); return; } element.classList.add('bg-white', 'text-gray-900', 'font-semibold', 'dark:bg-gray-800'); element.classList.remove('bg-gray-900', 'text-white', 'font-bold', 'dark:bg-black'); }); } function updatePanelDisplay(display) { const panelShowBttns = document.getElementById('panelShowBttns'); const panel = document.getElementById('panelDuoSolver'); if(isPanelShow) { panel.classList.remove('collapse'); panelShowBttns.classList.add('hidden'); return; } GM_setValue('isPanelShow', false); panel.classList.add('collapse'); panelShowBttns.classList.remove('hidden'); return; } function toggleShowHidePanel() { isPanelShow = !GM_getValue('isPanelShow'); GM_setValue('isPanelShow', isPanelShow ) updatePanelDisplay(); } function setAutoMode(state) { isAutoMode = state; GM_setValue('isAutoMode', state); } function startStopMain() { setAutoMode(!isAutoMode); updateBttnsCaptions(); if(isAutoMode) { window.location.assign('/practice'); } } function addButtons() { const checkBttn = document.querySelectorAll('[data-test="player-next"]')[0]; if(!checkBttn) { return; } let solveAllBttn = document.getElementById("solveAllBttn"); if (solveAllBttn !== null) { return; } checkBttn.parentElement.classList.add('flex', 'gap-x-8'); checkBttn.parentElement.insertAdjacentHTML('beforeend',solvesBttnHtml); const solveBttn = document.getElementById("solveBttn"); solveAllBttn = document.getElementById("solveAllBttn"); solveBttn.addEventListener('click', solveOne); solveAllBttn.addEventListener('click', solvingAll); updateBttnsCaptions(); resetTimerAutoMode(); } function updateBttnsCaptions() { const solveAllBttn = document.getElementById("solveAllBttn"); const startBttn = document.getElementById("startBttn"); if (isAutoMode) { solveAllBttn ? solveAllBttn.innerText = "PAUSE ALL" : null; startBttn ? startBttn.innerText = "Stop" : null; } else { solveAllBttn ? solveAllBttn.innerText = "SOLVE ALL" : null; startBttn ? startBttn.innerText = "Start" : null; } } function solvingAll() { setAutoMode(!isAutoMode); updateBttnsCaptions(); resetTimerAutoMode(); } function solveOne() { const practiceAgain = document.querySelector('[data-test="player-practice-again"]'); if (practiceAgain !== null && isAutoMode) { practiceAgain.click(); return; } if(document.querySelector('[data-test="session-complete-slide"]') && isAutoMode && !practiceAgain && window.innerWidth <= 768 && window.location.pathname === '/practice') { window.location.assign('/practice'); return; } let subType = ""; try { window.sol = findReact(document.querySelectorAll(mainLessonFormClass)[0]).props.currentChallenge; subType = window.sol.challengeGeneratorIdentifier.specificType; } catch { let next = document.querySelector('[data-test="player-next"]'); if (next) { next.click(); } resetTimerAutoMode(); return; } if (!window.sol) { resetTimerAutoMode(); return; } let nextButton = document.querySelector('[data-test="player-next"]'); if (!nextButton) { resetTimerAutoMode(); return; } switch(window.sol.type) { case "listenMatch": case "listenIsolation": case "listenTap": const buttonSkip = document.querySelector('button[data-test="player-skip"]'); if (buttonSkip) { buttonSkip.click(); } break; case "translate": switch(subType) { case "reverse_translate": const elm = document.querySelector('textarea[data-test="challenge-translate-input"]'); if(elm) { const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set; nativeInputValueSetter.call(elm, window.sol.correctSolutions ? window.sol.correctSolutions[0] : window.sol.prompt); let inputEvent = new Event('input', { bubbles: true }); elm.dispatchEvent(inputEvent); } break; case "tap": case "reverse_tap": translateTapReverseTapSolve(); break; default: null; } break; case "assist": case "gapFill": document.querySelectorAll('[data-test="challenge-choice"]')[window.sol.correctIndex]?.click(); break; case "name": let textInput = document.querySelector('[data-test="challenge-text-input"]'); if(textInput) { if(window.sol.correctSolutions) { let nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; nativeInputValueSetter.call(textInput, window.sol.correctSolutions[0]); let inputEvent = new Event('input', { bubbles: true }); textInput.dispatchEvent(inputEvent); } } break; case "partialReverseTranslate": let elm = document.querySelector('[data-test*="challenge-partialReverseTranslate"]')?.querySelector("span[contenteditable]"); if(elm) { let nativeInputNodeTextSetter = Object.getOwnPropertyDescriptor(Node.prototype, "textContent").set; nativeInputNodeTextSetter.call(elm, window.sol?.displayTokens?.filter(t => t.isBlank)?.map(t => t.text)?.join()?.replaceAll(',', '') ); let inputEvent = new Event('input', { bubbles: true }); elm.dispatchEvent(inputEvent); } break; default: null; } nextButton.click(); resetTimerAutoMode(); } function translateTapReverseTapSolve() { const all_tokens = document.querySelectorAll('[data-test$="challenge-tap-token"]'); const correct_tokens = window.sol.correctTokens; const clicked_tokens = []; correct_tokens.forEach(correct_token => { const matching_elements = Array.from(all_tokens).filter(element => element.textContent.trim() === correct_token.trim()); if (matching_elements.length > 0) { const match_index = clicked_tokens.filter(token => token.textContent.trim() === correct_token.trim()).length; if (match_index < matching_elements.length) { matching_elements[match_index].click(); clicked_tokens.push(matching_elements[match_index]); } else { clicked_tokens.push(matching_elements[0]); } } }); } function resetTimerAutoMode() { if(isAutoMode) { clearTimeout(solveTimerId); solveTimerId = setTimeout(solveOne, solveSpeedList[solveSpeed]); } } function findReact(dom) { let reactProps = Object.keys(dom.parentElement).find((key) => key.startsWith("__reactProps$")); let child = dom?.parentElement?.[reactProps]?.children; return child?.props?.children?._owner?.stateNode ?? child?._owner?.stateNode; }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址