KrackMigo

ModMenu para Khan Academy inspirado no design do Khanmigo

  1. // ==UserScript==
  2. // @name KrackMigo
  3. // @namespace https://greasyfork.org/pt-BR/users/1346771-kinjinho
  4. // @version 5.0
  5. // @description ModMenu para Khan Academy inspirado no design do Khanmigo
  6. // @author KIN
  7. // @match https://pt.khanacademy.org/*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. 'use strict';
  14.  
  15. const svgLogo = `<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Abrir Khanmigo</title><circle cx="28" cy="28" r="28" fill="#5f1e5c"></circle><path d="M17.61 12.88H38.45C41.22 12.88 43.47 15.13 43.47 17.89V40.57C43.47 42.76 40.86 43.90 39.25 42.41L37.57 40.85C37.10 40.42 36.49 40.18 35.86 40.18H15.11C13.72 40.18 12.60 39.05 12.60 37.67V17.89C12.60 15.13 14.85 12.88 17.61 12.88Z" fill="#DEAE93"></path><circle cx="21.4178" cy="27.8582" r="6.01791" fill="white"></circle><mask id="mask0" maskUnits="userSpaceOnUse" x="15" y="21" width="13" height="13" style="mask-type: alpha;"><circle cx="21.4178" cy="27.8582" r="6.01791" fill="white"></circle></mask><g mask="url(#mask0)"><circle cx="17.22" cy="23.673" r="5.46" fill="black"></circle></g><circle cx="34.578" cy="27.8579" r="6.01791" fill="white"></circle><mask id="mask1" maskUnits="userSpaceOnUse" x="28" y="21" width="13" height="13" style="mask-type: alpha;"><circle cx="34.578" cy="27.8579" r="6.01791" fill="white"></circle></mask><g mask="url(#mask1)"><circle cx="30.3802" cy="23.6728" r="5.46" fill="black"></circle></g></svg>`;
  16.  
  17. const html = `
  18. <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">
  19. <div id="krakdemy-container">
  20. <div id="krakdemy-toggle">${svgLogo}</div>
  21. <div id="krakdemy-sidebar">
  22. <div id="krakdemy-header">
  23. <span id="krakdemy-title">KrackMigo</span><span id="krakdemy-beta">BETA</span>
  24. </div>
  25. <div id="krakdemy-body">
  26. <p class="info">📖 Respostas Detectadas:</p>
  27. <div id="ansBreak"></div>
  28. <button id="clearList">Limpar Lista</button>
  29. </div>
  30. </div>
  31. </div>
  32.  
  33. <style>
  34. #krakdemy-container {
  35. font-family: 'Inter', sans-serif;
  36. }
  37. #krakdemy-toggle {
  38. position: fixed;
  39. bottom: 20px;
  40. left: 20px;
  41. width: 56px;
  42. height: 56px;
  43. cursor: pointer;
  44. z-index: 99999;
  45. }
  46. #krakdemy-sidebar {
  47. position: fixed;
  48. left: 0;
  49. bottom: 0;
  50. top: 0;
  51. width: 320px;
  52. background-color: #fff;
  53. box-shadow: 2px 0 12px rgba(0,0,0,0.1);
  54. display: none;
  55. flex-direction: column;
  56. border-right: 3px solid #5f1e5c;
  57. z-index: 99998;
  58. }
  59. #krakdemy-header {
  60. padding: 20px;
  61. background: #f4eef5;
  62. display: flex;
  63. justify-content: space-between;
  64. align-items: center;
  65. border-bottom: 1px solid #ddd;
  66. }
  67. #krakdemy-title {
  68. font-size: 20px;
  69. font-weight: 600;
  70. color: #5f1e5c;
  71. }
  72. #krakdemy-beta {
  73. font-size: 12px;
  74. background: #5f1e5c;
  75. color: white;
  76. border-radius: 4px;
  77. padding: 2px 6px;
  78. margin-left: 5px;
  79. }
  80. #krakdemy-body {
  81. padding: 20px;
  82. overflow-y: auto;
  83. height: calc(100% - 80px);
  84. }
  85. #clearList {
  86. background: #5f1e5c;
  87. color: white;
  88. padding: 10px;
  89. border: none;
  90. border-radius: 6px;
  91. margin-top: 15px;
  92. cursor: pointer;
  93. }
  94. .info {
  95. font-weight: bold;
  96. margin-bottom: 10px;
  97. border: 2px solid black;
  98. padding: 10px;
  99. border-radius: 8px;
  100. }
  101. </style>
  102. `;
  103.  
  104. const el = document.createElement('div');
  105. el.innerHTML = html;
  106. document.body.appendChild(el);
  107.  
  108. const sidebar = document.getElementById('krakdemy-sidebar');
  109. document.getElementById('krakdemy-toggle').onclick = () => {
  110. sidebar.style.display = sidebar.style.display === 'flex' ? 'none' : 'flex';
  111. };
  112.  
  113. document.getElementById('clearList').onclick = () => {
  114. document.getElementById('ansBreak').innerHTML = '';
  115. };
  116.  
  117. // Logic do script Krakdemy
  118. let curAns = 1;
  119. const originalFetch = window.fetch;
  120. window.fetch = function () {
  121. return originalFetch.apply(this, arguments).then(async (res) => {
  122. if (res.url.includes("/getAssessmentItem")) {
  123. const clone = res.clone();
  124. const json = await clone.json();
  125. const item = json.data.assessmentItem.item.itemData;
  126. const question = JSON.parse(item).question;
  127.  
  128. Object.keys(question.widgets).map(widgetName => {
  129. switch (widgetName.split(" ")[0]) {
  130. case "numeric-input":
  131. return freeResponseAnswerFrom(question);
  132. case "radio":
  133. return multipleChoiceAnswerFrom(question);
  134. case "expression":
  135. return expressionAnswerFrom(question);
  136. case "dropdown":
  137. return dropdownAnswerFrom(question);
  138. }
  139. });
  140. }
  141. return res;
  142. });
  143. };
  144.  
  145. function addAnswer(answer) {
  146. const el = document.createElement('p');
  147. el.textContent = answer;
  148. document.getElementById('ansBreak').appendChild(el);
  149. }
  150.  
  151. function freeResponseAnswerFrom(question) {
  152. Object.values(question.widgets).forEach((widget) => {
  153. widget.options?.answers?.forEach(answer => {
  154. if (answer.status == "correct") addAnswer(answer.value);
  155. });
  156. });
  157. }
  158.  
  159. function multipleChoiceAnswerFrom(question) {
  160. Object.values(question.widgets).forEach((widget) => {
  161. widget.options?.choices?.forEach(choice => {
  162. if (choice.correct) addAnswer(choice.content);
  163. });
  164. });
  165. }
  166.  
  167. function expressionAnswerFrom(question) {
  168. Object.values(question.widgets).forEach((widget) => {
  169. widget.options?.answerForms?.forEach(answer => {
  170. if (Object.values(answer).includes("correct")) addAnswer(answer.value);
  171. });
  172. });
  173. }
  174.  
  175. function dropdownAnswerFrom(question) {
  176. Object.values(question.widgets).forEach((widget) => {
  177. widget.options?.choices?.forEach(choice => {
  178. if (choice.correct) addAnswer(choice.content);
  179. });
  180. });
  181. }
  182. })();