Professional Documents
Culture Documents
Code Duolingo
Code Duolingo
// @name Duolingo-Cheat-Tool
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Auto answer Duolingo script!
// @author Tran Quy <tranphuquy19@gmail.com>
// @match https://www.duolingo.com/skill*
// @icon https://www.google.com/s2/favicons?domain=duolingo.com
// @grant none
// ==/UserScript==
const TIME_OUT = 1;
// Challenge types
const CHARACTER_SELECT_TYPE = 'characterSelect';
const CHARACTER_MATCH_TYPE = 'characterMatch'; // not yet
const TRANSLATE_TYPE = 'translate';
const LISTEN_TAP_TYPE = 'listenTap';
const NAME_TYPE = 'name';
const COMPLETE_REVERSE_TRANSLATION_TYPE = 'completeReverseTranslation';
const LISTEN_TYPE = 'listen';
const SELECT_TYPE = 'select';
const JUDGE_TYPE = 'judge';
const FORM_TYPE = 'form';
const LISTEN_COMPREHENSION_TYPE = 'listenComprehension';
const READ_COMPREHENSION_TYPE = 'readComprehension';
const CHARACTER_INTRO_TYPE = 'characterIntro';
const DIALOGUE_TYPE = 'dialogue';
const SELECT_TRANSCRIPTION_TYPE = 'selectTranscription';
const SPEAK_TYPE = 'speak';
const SELECT_PRONUNCIATION_TYPE = 'selectPronunciation';
function getChallengeObj(theObject) {
let result = null;
if (theObject instanceof Array) {
for (let i = 0; i < theObject.length; i++) {
result = getChallengeObj(theObject[i]);
if (result) {
break;
}
}
}
else {
for (let prop in theObject) {
if (prop == 'challenge') {
if (typeof theObject[prop] == 'object') {
return theObject;
}
}
if (theObject[prop] instanceof Object || theObject[prop] instanceof
Array) {
result = getChallengeObj(theObject[prop]);
if (result) {
break;
}
}
}
}
return result;
}
function getChallenge() {
// const dataTestComponentClassName = 'e4VJZ';
const dataTestDOM = document.getElementsByClassName(dataTestComponentClassName)
[0];
if (!dataTestDOM) {
document.querySelectorAll(PLAYER_NEXT)[0].dispatchEvent(clickEvent);
return null;
} else {
const dataTestAtrr = Object.keys(dataTestDOM).filter(att =>
/^__reactProps/g.test(att))[0];
const childDataTestProps = dataTestDOM[dataTestAtrr];
const { challenge } = getChallengeObj(childDataTestProps);
return challenge;
}
}
function pressEnter() {
document.dispatchEvent(new KeyboardEvent('keydown', { 'keyCode': 13, 'which':
13 }));
}
function classify() {
const challenge = getChallenge();
if (!challenge) return;
if (DEBUG) console.log(`${challenge.type}`, challenge);
switch (challenge.type) {
case SELECT_PRONUNCIATION_TYPE:
case READ_COMPREHENSION_TYPE:
case LISTEN_COMPREHENSION_TYPE:
case FORM_TYPE: { // trắc nghiệm 1 đáp án
const { choices, correctIndex } = challenge;
if (DEBUG) console.log('READ_COMPREHENSION LISTEN_COMPREHENSION FORM',
{ choices, correctIndex });
document.querySelectorAll(CHALLENGE_CHOICE)
[correctIndex].dispatchEvent(clickEvent);
return { choices, correctIndex };
}
case SELECT_TYPE:
case CHARACTER_SELECT_TYPE: { // trắc nghiệm 1 đáp án
const { choices, correctIndex } = challenge;
if (DEBUG) console.log('SELECT CHARACTER_SELECT', { choices,
correctIndex });
document.querySelectorAll(CHALLENGE_CHOICE_CARD)
[correctIndex].dispatchEvent(clickEvent);
return { choices, correctIndex };
}
case TRANSLATE_TYPE: {
const { correctTokens, correctSolutions } = challenge;
if (DEBUG) console.log('TRANSLATE', { correctTokens });
if (correctTokens) {
const tokens = document.querySelectorAll(CHALLENGE_TAP_TOKEN);
let ignoreTokeIndexes = [];
for (let correctTokenIndex in correctTokens) {
for (let tokenIndex in tokens) {
const token = tokens[tokenIndex];
if (ignoreTokeIndexes.includes(tokenIndex)) continue;
if (token.innerText === correctTokens[correctTokenIndex]) {
token.dispatchEvent(clickEvent);
ignoreTokeIndexes.push(tokenIndex);
if(DEBUG) console.log(`correctTokenIndex [$
{correctTokens[correctTokenIndex]}] - tokenIndex [${token.innerText}]`);
break;
};
}
}
} else if (correctSolutions) {
let textInputElement =
document.querySelectorAll(CHALLENGE_TRANSLATE_INPUT)[0];
dynamicInput(textInputElement, correctSolutions[0]);
}
return { correctTokens };
}
case LISTEN_TAP_TYPE: {
const { correctTokens } = challenge;
if (DEBUG) console.log('LISTEN_TAP', { correctTokens });
const tokens = document.querySelectorAll(CHALLENGE_TAP_TOKEN);
for (let wordIndex in correctTokens) {
tokens.forEach((token) => {
if (token.innerText === correctTokens[wordIndex]) {
token.dispatchEvent(clickEvent);
};
});
}
return { correctTokens };
}
case DIALOGUE_TYPE:
case CHARACTER_INTRO_TYPE: { // trắc nghiệm 1 đáp án
const { choices, correctIndex } = challenge;
if (DEBUG) console.log('DIALOGUE CHARACTER_INTRO', { choices,
correctIndex });
document.querySelectorAll(CHALLENGE_JUDGE_TEXT)
[correctIndex].dispatchEvent(clickEvent);
return { choices, correctIndex };
}
case SELECT_TRANSCRIPTION_TYPE: {
const { choices, correctIndex } = challenge;
if (DEBUG) console.log('DIALOGUE CHARACTER_INTRO', { choices,
correctIndex });
document.querySelectorAll(CHALLENGE_JUDGE_TEXT)
[correctIndex].dispatchEvent(clickEvent);
return { choices, correctIndex };
}
case SPEAK_TYPE: {
const { prompt } = challenge;
if (DEBUG) console.log('SPEAK', { prompt });
document.querySelectorAll(PLAYER_SKIP)[0].dispatchEvent(clickEvent);
return { prompt };
}
default:
break;
}
}
function breakWhenIncorrect() {
const isBreak = document.querySelectorAll(BLAME_INCORRECT).length > 0;
if (isBreak) {
console.log('Incorrect, stopped');
clearInterval(mainInterval);
};
}
function main() {
try {
let isPlayerNext = document.querySelectorAll(PLAYER_NEXT)
[0].textContent.toUpperCase();
if (isPlayerNext.valueOf() !== 'CONTINUE') {
classify();
breakWhenIncorrect()
pressEnter();
}
setTimeout(pressEnter, 1);
} catch (e) {
console.log(e);
}
}
function solveChallenge() {
mainInterval = setInterval(main, TIME_OUT);
console.log(`to stop run this command clearInterval(${mainInterval})`);
}
// solveChallenge();
(solveChallenge)();
1