├── gif ├── autoSolve.gif └── getAnswers.gif ├── README.md ├── getAnswers.js └── autosolve.js /gif/autoSolve.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeaveAche/moodle-h5p-solver/HEAD/gif/autoSolve.gif -------------------------------------------------------------------------------- /gif/getAnswers.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeaveAche/moodle-h5p-solver/HEAD/gif/getAnswers.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Moodle H5p Solver 2 | This script was written over a year ago to get answers for H5p quizzes on moodle. The answers to these questions are checked on the client side, making it possible to get the answers. 3 | 4 | ## Usage 5 | 1. Open developer tools window on your browser. 6 | 2. Paste either of the getAnswers.js/autoSolve.js in the console. (getAnswers.js will just open another window with the answers, autoSolve.js will try to solve the quiz automatically, if you are feeling extra lazy) 7 | 3. Press enter. 8 | 9 | ## getAnswers.js 10 | ![getAnswers](/gif/getAnswers.gif) 11 | 12 | ## autoSolve.js 13 | ![autoSolve](/gif/autoSolve.gif) 14 | -------------------------------------------------------------------------------- /getAnswers.js: -------------------------------------------------------------------------------- 1 | let json = H5PIntegration.contents; 2 | let interactions = JSON.parse(json[Object.keys(json)[0]].jsonContent).interactiveVideo.assets.interactions; 3 | 4 | let html = ""; 5 | html += `

Answers

` 6 | 7 | for (let i = 0; i < interactions.length; i++) { 8 | interaction = interactions[i] 9 | q_type=interaction.libraryTitle 10 | params=interaction.action.params 11 | 12 | html += `

Question ${i + 1}

` 13 | 14 | if (q_type=="Single Choice Set") { 15 | answer=params.choices[0].answers[0] 16 | html += `

${answer}

` 17 | console.log(answer) 18 | } else if (q_type=="Multiple Choice") { 19 | answers = params.answers 20 | for (let i = 0; i < answers.length; i++) { 21 | answer = answers[i] 22 | if (answer.correct==true) 23 | html += `

${answer.text}

` 24 | console.log(answer.text) 25 | } 26 | } else if (q_type=="True/False Question") { 27 | console.log(params.correct) 28 | html += `

${params.correct}

` 29 | } else 30 | console.log("wait") 31 | 32 | console.log("\n") 33 | } 34 | 35 | const win = window.open('', 'answers', 'width=400, height=600'); 36 | win.document.write(html); 37 | -------------------------------------------------------------------------------- /autosolve.js: -------------------------------------------------------------------------------- 1 | function getAnswers(){ 2 | var answers = []; 3 | let json = H5PIntegration.contents; 4 | let interactions = JSON.parse(json[Object.keys(json)[0]].jsonContent).interactiveVideo.assets.interactions; 5 | 6 | for (let i = 0; i < interactions.length; i++) { 7 | let currAnswer = []; 8 | let interaction = interactions[i]; 9 | let q_type = interaction.libraryTitle; 10 | let params = interaction.action.params; 11 | 12 | if (q_type=="Single Choice Set") { 13 | currAnswer.push(params.choices.length); 14 | } else if (q_type=="Multiple Choice") { 15 | let options = params.answers; 16 | for (let i = 0; i < options.length; i++) { 17 | let option = options[i] 18 | if (option.correct==true){ 19 | currAnswer.push(option.text); 20 | } 21 | } 22 | } else if (q_type=="True/False Question") { 23 | currAnswer.push(params.correct); 24 | }else{ 25 | alert(`I don't know how to solve question ${i+1}`); 26 | return undefined; 27 | } 28 | 29 | answers.push(currAnswer) 30 | } 31 | 32 | return answers; 33 | } 34 | 35 | 36 | async function autoSolve(answers){ 37 | console.log(answers); 38 | try{ 39 | let frame = document.querySelectorAll("iframe")[0].contentDocument 40 | let interactions = frame.querySelectorAll(".h5p-seekbar-interaction"); 41 | 42 | solver: 43 | for(let i = 0; i < interactions.length ; i++){ 44 | let type = interactions[i].title; 45 | 46 | await interactions[i].click(); 47 | 48 | while(!frame.querySelector(".h5p-interaction-outer")) { 49 | await new Promise(r => setTimeout(r, 500)); 50 | } 51 | 52 | if(type == "Single Choice Set"){ 53 | await frame.querySelectorAll(".h5p-sc-is-correct")[0].click(); 54 | 55 | let k = 1; 56 | let timer = setInterval(async()=>{ 57 | if(k < answers[i][0]){ 58 | await frame.querySelectorAll(".h5p-sc-is-correct")[k].click(); 59 | k++; 60 | }else{ 61 | clearInterval(timer); 62 | } 63 | },2500); 64 | 65 | }else if(type == "True/False Question"){ 66 | let options = frame.querySelectorAll(".h5p-true-false-answer"); 67 | 68 | if(options[0].innerText.toLowerCase() == answers[i][0]){ 69 | await options[0].click(); 70 | }else{ 71 | await options[1].click(); 72 | } 73 | 74 | 75 | }else{ 76 | let options = frame.querySelectorAll(".h5p-answer"); 77 | 78 | for(let j=0; j< options.length; j++){ 79 | if(answers[i].includes(options[j].children[0].children[0].innerHTML)){ 80 | options[j].click(); 81 | } 82 | } 83 | 84 | } 85 | 86 | var annoying_error = false; 87 | 88 | if(frame.querySelector(".h5p-question-check-answer")){ 89 | setTimeout(async ()=>{ 90 | try{ 91 | await frame.querySelector(".h5p-question-check-answer").click(); 92 | }catch(err){ 93 | console.log(err); 94 | annoying_error = true; 95 | } 96 | }, 2000); 97 | } 98 | 99 | while(!frame.querySelector(".h5p-question-iv-continue")) { 100 | if(annoying_error){ 101 | continue solver; 102 | } 103 | await new Promise(r => setTimeout(r, 1000)); 104 | } 105 | 106 | setTimeout(async ()=>{ 107 | await frame.querySelector(".h5p-question-iv-continue").click() 108 | }, 1000); 109 | 110 | 111 | while(frame.querySelector(".h5p-interaction-outer")) { 112 | await new Promise(r => setTimeout(r, 500)); 113 | } 114 | 115 | } 116 | 117 | await frame.querySelector(".h5p-control.h5p-star.h5p-star-foreground").click(); 118 | 119 | }catch(e){ 120 | alert(e) 121 | } 122 | } 123 | 124 | var answers = getAnswers(); 125 | if(answers){ 126 | autoSolve(answers) 127 | } --------------------------------------------------------------------------------