Duolingo automation auto answer script. Include skill leveling up (13.01.2023 update)
// ==UserScript== // @name PWNEDuo (based on DuoHacker). // @description Duolingo automation auto answer script. Include skill leveling up (13.01.2023 update) // @namespace Violentmonkey Scripts // @match https://*.duolingo.com/* // @grant none // @version 1.0.4 // @author hprnv // @license MIT // ==/UserScript== var intervalId; var isAutoMode = false; function addButtons() { if(window.location.pathname == '/learn'){ let button = document.querySelector('a[data-test="global-practice"]'); if(button){ button.click(); return; } } if (document.getElementById("solveAllButton") !== null) { return; } let original = document.querySelectorAll('[data-test="player-next"]')[0]; let wrapper = document.getElementsByClassName('_10vOG')[0]; if (original == undefined) { let startButton = document.querySelector('[data-test="start-button"]'); if (startButton == undefined) { return; } let wrapper = startButton.parentNode; let autoComplete = document.createElement('a'); autoComplete.className = startButton.className; autoComplete.id = "solveAllButton"; autoComplete.innerText = "COMPLETE SKILL"; autoComplete.removeAttribute('href'); autoComplete.onclick = function () { startSolving(); setInterval(function () { let startButton = document.querySelector('[data-test="start-button"]'); if (startButton && startButton.innerText.startsWith("START")) { startButton.click(); } }, 3000); startButton.click(); }; wrapper.appendChild(autoComplete); } else { wrapper.style.display = "flex"; let solveCopy = document.createElement('button'); let pauseCopy = document.createElement('button'); solveCopy.id = 'solveAllButton'; if (intervalId) { solveCopy.innerHTML = 'PAUSE SOLVE'; } else { solveCopy.innerHTML = 'SOLVE ALL'; } solveCopy.disabled = false; pauseCopy.innerHTML = 'SOLVE'; const buttonStyle = ` min-width: 150px; font-size: 17px; border:none; border-bottom: 4px solid #58a700; border-radius: 18px; padding: 13px 16px; transform: translateZ(0); transition: filter .2s; font-weight: 700; letter-spacing: .8px; background: #55CD2E; color:#fff; margin-left:20px; cursor:pointer; `; solveCopy.style.cssText = buttonStyle; pauseCopy.style.cssText = buttonStyle; //Hover effect for buttons function mouseOver(x) { x.style.filter = "brightness(1.1)"; } function mouseLeave(x) { x.style.filter = "none"; } let buttons = [solveCopy, pauseCopy] buttons.forEach(button => { button.addEventListener("mousemove", () => { mouseOver(button); }); }); buttons.forEach(button => { button.addEventListener("mouseleave", () => { mouseLeave(button); }); }); original.parentElement.appendChild(pauseCopy); original.parentElement.appendChild(solveCopy); solveCopy.addEventListener('click', solving); pauseCopy.addEventListener('click', solve); } } setInterval(addButtons, 3000); function solving() { if (intervalId) { pauseSolving(); } else { startSolving(); } } function startSolving() { if (intervalId) { return; } document.getElementById("solveAllButton").innerText = "PAUSE SOLVE"; isAutoMode = true; intervalId = setInterval(solve, 500); } function pauseSolving() { if (!intervalId) { return; } document.getElementById("solveAllButton").innerText = "SOLVE ALL"; isAutoMode = false; clearInterval(intervalId); intervalId = undefined; } function solve() { let selAgain = document.querySelectorAll('[data-test="player-practice-again"]'); if (selAgain.length === 1 && isAutoMode) { // Make sure it's the `practice again` button //if (selAgain[0].innerHTML.toLowerCase() === 'practice again') { // Click the `practice again` button selAgain[0].click(); // Terminate return; //} } try { window.sol = FindReact(document.getElementsByClassName('_3FiYg')[0]).props.currentChallenge; } catch { let next = document.querySelector('[data-test="player-next"]'); if (next) { next.click(); } return; } if (!window.sol) { return; } let btn = null; let selNext = document.querySelectorAll('[data-test="player-next"]'); if (selNext.length === 1) { // Save the button element btn = selNext[0]; if(document.querySelectorAll('[data-test*="challenge-speak"]').length > 0){ let buttonSkip = document.querySelector('button[data-test="player-skip"]'); if(buttonSkip){ buttonSkip.click(); } } if (document.querySelectorAll('[data-test="challenge-choice"]').length > 0) { if (window.sol.correctIndices) { window.sol.correctIndices?.forEach(index => { document.querySelectorAll('[data-test="challenge-choice"]')[index].children[0].click(); }); // Click the first element } else if (window.sol.articles) { var article = ''; for (var i = 0; i < window.sol.articles.length; i++) { if (window.sol.correctSolutions[0].startsWith(window.sol.articles[i])) { Array.from(document.querySelectorAll('[data-test="challenge-choice"]')) .find((elm) => elm.querySelector('[data-test="challenge-judge-text"]').innerText == window.sol.articles[i] ).click(); article = window.sol.articles[i]; break; } } let elm = document.querySelectorAll('[data-test="challenge-text-input"]')[0]; let nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; nativeInputValueSetter.call(elm, window.sol.correctSolutions ? window.sol.correctSolutions[0].replace(article + ' ', '') : (window.sol.displayTokens ? window.sol.displayTokens.find(t => t.isBlank).text : window.sol.prompt)); let inputEvent = new Event('input', { bubbles: true }); elm.dispatchEvent(inputEvent); } else { document.querySelectorAll('[data-test="challenge-choice"]')[window.sol.correctIndex].click(); } // Click the solve button btn.click(); } if (document.querySelectorAll('[data-test="challenge-choice-card"]').length > 0) { // Click the first element if (window.sol.correctIndices) { window.sol.correctIndices?.forEach(index => { document.querySelectorAll('[data-test="challenge-choice-card"]')[index].children[0].click(); }); } else { document.querySelectorAll('[data-test="challenge-choice-card"]')[window.sol.correctIndex].click(); } // Click the solve button btn.click(); } if (window.sol.type == 'listenMatch') { let nl = document.querySelectorAll('[data-test="challenge-tap-token"]'); window.sol.pairs?.forEach((pair) => { for (let i = 0; i < nl.length; i++) { let nlInnerText; if (nl[i].querySelectorAll('[data-test="challenge-tap-token-text"]').length > 1) { nlInnerText = nl[i].querySelector('[data-test="challenge-tap-token-text"]').innerText.toLowerCase().trim(); } else { nlInnerText = FindSubReact(nl[i]).text.toLowerCase().trim(); } if ( ( nlInnerText == pair.learningWord.toLowerCase().trim() || nlInnerText == pair.translation.toLowerCase().trim() ) && !nl[i].disabled ) { nl[i].click(); } } }); } if (window.sol.type == 'listenSpell') { let tokens = window.sol.displayTokens.filter(x => x.damageStart !== undefined); let elms = document.querySelectorAll('._2cjP3._2IKiF'); let nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; var solutionCharacters = []; for (let tok of tokens) { for (let i = tok.damageStart; i < tok.damageEnd; i++) { solutionCharacters.push(tok.text[i]); } } for (var elmIndex = 0; elmIndex < elms.length; elmIndex++) { nativeInputValueSetter.call(elms[elmIndex], solutionCharacters[elmIndex]); let inputEvent = new Event('input', { bubbles: true }); elms[elmIndex].dispatchEvent(inputEvent); } } if (document.querySelectorAll('[data-test="challenge-tap-token"]').length > 0) { // Click the first element if (window.sol.pairs) { let nl = document.querySelectorAll('[data-test="challenge-tap-token"]'); if (document.querySelectorAll('[data-test="challenge-tap-token-text"]').length == document.querySelectorAll('[data-test="challenge-tap-token"]').length) { window.sol.pairs?.forEach((pair) => { for (let i = 0; i < nl.length; i++) { const nlInnerText = nl[i].querySelector('[data-test="challenge-tap-token-text"]').innerText.toLowerCase().trim(); if ( ( nlInnerText == pair.learningToken.toLowerCase().trim() || nlInnerText == pair.fromToken.toLowerCase().trim() ) && !nl[i].disabled ) { nl[i].click(); } } }); } } else if(!window.sol.correctTokens){ let clicked = {} let nl = document.querySelectorAll('[data-test="challenge-tap-token"]'); window.sol.correctIndices?.forEach(index => { let correctAnswer = window.sol.choices[index]; for (let i = 0; i < nl.length; i++) { if ((nl[i].innerText).toLowerCase().trim() == correctAnswer.text.toLowerCase().trim() && !nl[i].disabled && !clicked[i]) { clicked[i] = 1; nl[i].click(); break; } } }); } else { let clicked = {} let nl = document.querySelectorAll('[data-test="challenge-tap-token"]'); window.sol.correctIndices?.forEach(index => { let correctAnswer = window.sol.correctTokens[index]; for (let i = 0; i < nl.length; i++) { if ((nl[i].innerText).toLowerCase().trim() == correctAnswer.toLowerCase().trim() && !nl[i].disabled && !clicked[i]) { clicked[i] = 1; nl[i].click(); break; } } }); } // Click the solve button btn.click(); } if (document.querySelectorAll('[data-test="challenge-text-input"]').length > 0) { let elm = document.querySelectorAll('[data-test="challenge-text-input"]')[0]; let nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; nativeInputValueSetter.call(elm, window.sol.correctSolutions ? window.sol.correctSolutions[0] : (window.sol.displayTokens ? window.sol.displayTokens.find(t => t.isBlank).text : window.sol.prompt)); let inputEvent = new Event('input', { bubbles: true }); elm.dispatchEvent(inputEvent); } if (document.querySelectorAll('[data-test*="challenge-partialReverseTranslate"]').length > 0) { let elm = document.querySelector('[data-test*="challenge-partialReverseTranslate"]')?.querySelector("span[contenteditable]"); 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); } if (document.getElementsByTagName('textarea').length > 0) { let elm = document.getElementsByTagName('textarea')[0] let 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); } // Continue btn.click(); } } function FindSubReact(dom, traverseUp = 0) { const key = Object.keys(dom).find(key => key.startsWith("__reactProps$")); return dom.parentElement[key].children.props; } function FindReact(dom, traverseUp = 0) { const key = Object.keys(dom.parentElement).find(key => key.startsWith("__reactProps$")); return dom.parentElement[key].children[0]._owner.stateNode; } window.findReact = FindReact; window.ss = startSolving;