Auto-Duolingo

[Lite Version] Automatically farm experience points, hacking Duolingo is so easy!

Verzia zo dňa 06.11.2024. Pozri najnovšiu verziu.

  1. // ==UserScript==
  2. // @name Auto-Duolingo
  3. // @version 1.0.8
  4. // @author DevX
  5. // @namespace http://tampermonkey.net/
  6. // @description [Lite Version] Automatically farm experience points, hacking Duolingo is so easy!
  7. // @match https://*.duolingo.com/*
  8. // @grant none
  9. // @license MIT
  10. // @icon https://autoduolingo.click/assets/imgs/favicon.ico
  11. // ==/UserScript==
  12.  
  13. (() => {
  14. const AUTODUOLINGO_STORAGE = "autoDuolingoStorage";
  15. const { isSafeMode, isShowUI, isAnimationOff, exp, time, version, isNewNotify, rmNotiVer, rmNotiContent } =
  16. getSession();
  17. const { notifyVersion } = getLocal(AUTODUOLINGO_STORAGE);
  18.  
  19. const autoDuoLite = {
  20. initSignature: function () {
  21. this.signatureElm = document.createElement("div");
  22. Object.assign(this.signatureElm, {
  23. className: "signature-listening",
  24. innerHTML: `
  25. <div>
  26. Auto-Duolingo DevX
  27. <div class="autoduo-lite-version">
  28. LITE VERSION <button class="autoduo-upgrade" title="Upgrade version"></button>
  29. </div>
  30. </div>
  31. `,
  32. });
  33. const upgrade = this.signatureElm.querySelector('.autoduo-upgrade')
  34. upgrade.addEventListener('click', () => this.updateBtn.click())
  35. document.body.appendChild(this.signatureElm);
  36. },
  37.  
  38. initContact: function () {
  39. this.contactWrapper = document.createElement("div");
  40. Object.assign(this.contactWrapper, {
  41. className: "contact-wrapper-listening",
  42. innerHTML: `<a class="contact-item-listening" href="https://t.me/imdevx" target="_blank" style="--data-img: url('https://autoduolingo.click/assets/client/tele-icon.ndx')">
  43. <p class="popup">Chat with DevX</p>
  44. </a>
  45. <a class="contact-item-listening" href="https://t.me/autoduofamily" target="_blank" style="--data-img: url('https://autoduolingo.click/assets/client/tele-gr-icon.ndx')">
  46. <p class="popup">Telegram Community</p>
  47. </a>
  48. <a class="contact-item-listening" href="https://zalo.me/g/lmhfps187" target="_blank" style="--data-img: url('https://autoduolingo.click/assets/client/zalo-icon.ndx')">
  49. <p class="popup">Zalo Community</p>
  50. </a>
  51. <a class="contact-item-listening" href="https://www.youtube.com/@autoduofamily" target="_blank" style="--data-img: url('https://autoduolingo.click/assets/client/youtube-icon.ndx')">
  52. <p class="popup">Youtube Channel</p>
  53. </a>
  54. <a class="contact-item-listening" id="greasyfork" href="https://greasyfork.org/en/scripts/487867-auto-duolingo" target="_blank" style="--data-img: url('https://autoduolingo.click/assets/client/greasyfork-icon.ndx')">
  55. <p class="popup">Greasy Fork</p>
  56. </a>`,
  57. });
  58. },
  59.  
  60. initPopup: function () {
  61. this.updateGuidePopup = document.createElement("div");
  62. Object.assign(this.updateGuidePopup, {
  63. className: "update-guide-popup",
  64. innerHTML: `
  65. <div class="guide-popup-main">
  66. <h2 class="guide-popup-title">UPDATE GUIDE</h2>
  67. <div class="guide-popup-content">
  68. <p class="guide-popup-text" style="color: rgb(0,159,235)">
  69. The full version unlocks all features and receives priority updates for new features and bug fixes.
  70. To upgrade, follow the instructions below:
  71. </p>
  72. <p class="guide-popup-text">
  73. <b>Step 1:</b> Click the "Go update" button below, then proceed to click the "Update" (or maybe "Reinstall", "Override") button
  74. in the popup window to confirm the update process.
  75. </p>
  76. <p class="guide-popup-text">
  77. <b>Step 2</b>: Refresh the Duolingo page to update the interface of the full version of Auto-Duolingo.
  78. </p>
  79. <div class="guide-popup-btn">
  80. <button class="autoduo-btn popup-btn-close">Close</button>
  81. <a class="autoduo-btn btn-green popup-btn-access" href="#">Go Update</a>
  82. </div>
  83. </div>
  84. </div>
  85. `,
  86. });
  87.  
  88. const closePopupBtn = this.updateGuidePopup.querySelector(".popup-btn-close");
  89. closePopupBtn.addEventListener("click", () => {
  90. document.body.contains(this.updateGuidePopup) && this.updateGuidePopup.remove();
  91. });
  92. },
  93.  
  94. initBtn: function () {
  95. this.autoBtn = document.createElement("button");
  96. Object.assign(this.autoBtn, {
  97. className: "autoduo-btn btn-green auto-farm-btn-listening",
  98. innerText: "START FARM XP",
  99. onclick: () => {
  100. this.isAuto ? this.stop() : this.start();
  101. },
  102. });
  103.  
  104. this.updateBtn = document.createElement("button");
  105. Object.assign(this.updateBtn, {
  106. className: "autoduo-btn update-btn-listening",
  107. innerText: "Update to the full version",
  108. onclick: () => {
  109. this.isAuto && this.stop();
  110. document.body.appendChild(this.updateGuidePopup);
  111. },
  112. });
  113.  
  114. this.showHideBtn = document.createElement("button");
  115. Object.assign(this.showHideBtn, {
  116. className: "show-hide-listening",
  117. style: `--data-version: 'V${this.version}'`,
  118. innerHTML: "<i></i>",
  119. });
  120.  
  121. this.showHideBtn.addEventListener("click", () => {
  122. this.isShowUI = !this.isShowUI;
  123. this.handleShowHideUI(true);
  124. });
  125. document.body.append(this.showHideBtn);
  126.  
  127. new Promise((resolve) => {
  128. setTimeout(
  129. resolve.bind(window, notAvailable("aHR0cHM6Ly9pbnN0YWxsLmF1dG9kdW9saW5nby5jbGljaw==")),
  130. 1000
  131. );
  132. }).then((res) => {
  133. this.updateGuidePopup.querySelector(".popup-btn-access").href = res;
  134. });
  135. },
  136.  
  137. initBubbles: function () {
  138. this.notifyBubble = document.createElement("button");
  139. Object.assign(this.notifyBubble, {
  140. className: "bubble-item-listening notify-bubble-listening",
  141. title: "Notification",
  142. });
  143.  
  144. this.superBubble = document.createElement("a");
  145. Object.assign(this.superBubble, {
  146. className: "bubble-item-listening super-bubble-listening",
  147. title: "Duolingo Super Free",
  148. href: "https://t.me/duolingosuperfree",
  149. target: "_blank",
  150. });
  151.  
  152. this.marketerBubble = document.createElement("a");
  153. Object.assign(this.marketerBubble, {
  154. className: "bubble-item-listening marketer-bubble-listening",
  155. title: "AutoDuo Marketer",
  156. href: "https://autoduolingo.click/l/marketer/",
  157. target: "_blank",
  158. });
  159. },
  160.  
  161. initStatistics: function () {
  162. this.statistic = document.createElement("div");
  163. this.keyTypeElm = document.createElement("p");
  164. this.expElm = document.createElement("p");
  165. this.dateElm = document.createElement("p");
  166. const statisticWrapper = document.createElement("div");
  167.  
  168. Object.assign(this.keyTypeElm, {
  169. className: "key-type-listening",
  170. style: `--data-name: "Type"`,
  171. innerHTML: "<b style='color: #009feb'>Auto-Duolingo Lite</b>",
  172. });
  173.  
  174. this.expElm.className = "total-exp-listening";
  175. this.expElm.innerText = this.exp;
  176. this.statistic.className = "statistic-listening";
  177. this.dateElm.className = "time-listening";
  178. statisticWrapper.className = "statistic-wrapper-listening";
  179.  
  180. statisticWrapper.append(this.expElm, this.dateElm);
  181. this.statistic.append(this.keyTypeElm, statisticWrapper);
  182. },
  183.  
  184. initFunctions: function () {
  185. this.animationOffWrapper = document.createElement("div");
  186. this.animationOffWrapper.style = `--data-name: "Hide Animation"`;
  187. const animationOffInfo =
  188. "HIDE ANIMATION MODE:\n" +
  189. "- When this mode is enabled, images and animations on the website will be hidden to optimize performance.\n\n" +
  190. "Suggestion: To achieve the best performance, you should find and disable items related to effects in Duolingo's settings!";
  191. this.autoduoCreateSwitch(
  192. animationOffInfo,
  193. this.animationOffWrapper,
  194. 1,
  195. this.isAnimationOff,
  196. (setSwitch) => {
  197. this.isAnimationOff = !this.isAnimationOff;
  198. this.handleAnimationOff(true);
  199. setSwitch(this.isAnimationOff);
  200. }
  201. );
  202.  
  203. this.safeModeWrapper = document.createElement("div");
  204. this.safeModeWrapper.style = `--data-name: "Safe Mode"`;
  205. const safeModeInfo =
  206. "SAFE MODE:\n" +
  207. "- When this mode is enabled, the system will simulate user actions when using auto. The speed will be more relaxed, " +
  208. "in exchange for the completion time of lessons and the amount of experience will be the most natural, minimizing " +
  209. "the risks of REPORT and account BAN!";
  210. this.autoduoCreateSwitch(safeModeInfo, this.safeModeWrapper, 2, this.isSafeMode, () => {
  211. this.isSafeMode ? this.handleSafeModeOff() : this.handleSafeModeOn();
  212. });
  213.  
  214. this.turboModeWrapper = document.createElement("div");
  215. this.turboModeWrapper.style = `--data-name: "Turbo Mode"`;
  216. const turboModeInfo =
  217. "TURBO MODE:\n" +
  218. "- When enabled, the system will significantly boost the auto speed. It will utilize higher performance and " +
  219. "is not recommended for use on low-performance devices.\n- Turn it off and refresh the page if you encounter " +
  220. "issues while activating this mode!\n\n- Note: This is an experimental feature and requires a VIP Key to use. " +
  221. "Only enable it when you truly require speed and understand its implications!!";
  222. this.autoduoCreateSwitch(turboModeInfo, this.turboModeWrapper, 4, false);
  223.  
  224. this.legendModeWrapper = document.createElement("div");
  225. this.legendModeWrapper.style = `--data-name: "Lesson Pass Mode"`;
  226. const legendModeInfo =
  227. "LESSON PASS MODE:\n" +
  228. "- When activated, the system won't repeat exercises as in the regular mode but will engage in exercises actively selected by the user. " +
  229. "This mode is used for legendary exercises, story exercises, and most other similar exercises.\n- You need to enter the lesson you want to " +
  230. "pass in, and then the system will automatically complete that lesson for you!\n" +
  231. "- When this mode is activated, the basic auto button will be temporarily disabled.";
  232. this.autoduoCreateSwitch(legendModeInfo, this.legendModeWrapper, 5, false);
  233.  
  234. this.targetModeWrapper = document.createElement("div");
  235. this.targetModeWrapper.style = `--data-name: "XP Target Mode"`;
  236. const targetModeInfo =
  237. "EXPERIENCE POINT TARGET MODE:\n" +
  238. "- By setting an experience point target, the system will automatically stop auto mode when the total experience points " +
  239. "obtained equal or exceed the specified target.\n- This helps you better control the auto function, " +
  240. "preventing unintentional accumulation of excess experience points due to forgetting to turn off auto mode!\n\n" +
  241. "- Note: The experience point target must be greater than the current amount of experience points obtained through auto mode!";
  242. this.autoduoCreateSwitch(targetModeInfo, this.targetModeWrapper, 6, false);
  243.  
  244. this.passModeWrapper = document.createElement("div");
  245. this.passModeWrapper.style = `--data-name: "Auto Pass Mode"`;
  246. const passModeInfo =
  247. "AUTO PASS MODE:\n" +
  248. "- By setting the number of lessons you wish to pass, the system will automatically pass the corresponding " +
  249. "number of new lessons as per the value you've set!\n\n" +
  250. "- Note: the lesson value should be within the range of 1 - 1000 (Enter 0 for unlimited auto)!";
  251. this.autoduoCreateSwitch(passModeInfo, this.passModeWrapper, 7, false);
  252.  
  253. this.darkModeWrapper = document.createElement("div");
  254. this.darkModeWrapper.style = `--data-name: "Dark Mode"`;
  255. const darkModeInfo = "DARK MODE\n- Enable/disable website dark mode faster!";
  256. this.autoduoCreateSwitch(darkModeInfo, this.darkModeWrapper, 3, this.isDarkMode, (setSwitch) => {
  257. this.isDarkMode = !this.isDarkMode;
  258. const [theme, value, css] = this.isDarkMode
  259. ? ["dark", "on", "--app-offset: 0px; --color-snow: 19, 31, 36; --color-snow-always-light: 255, 255, 255; --color-snow-always-dark: 19, 31, 36; --color-polar: 32, 47, 54; --color-swan: 55, 70, 79; --color-swan-always-light: 229, 229, 229; --color-swan-always-dark: 55, 70, 79; --color-hare: 82, 101, 109; --color-hare-always-light: 175, 175, 175; --color-wolf: 220, 230, 236; --color-eel: 241, 247, 251; --color-squid: 235, 227, 227; --color-walking-fish: 32, 47, 54; --color-flamingo: 148, 81, 81; --color-pig: 245, 164, 164; --color-crab: 255, 120, 120; --color-cardinal: 238, 85, 85; --color-fire-ant: 216, 72, 72; --color-canary: 32, 47, 54; --color-duck: 251, 229, 109; --color-bee: 255, 199, 0; --color-bee-always-dark: 255, 199, 0; --color-lion: 255, 177, 0; --color-fox: 255, 171, 51; --color-cheetah: 32, 47, 54; --color-monkey: 229, 162, 89; --color-camel: 231, 166, 1; --color-guinea-pig: 215, 148, 51; --color-grizzly: 187, 113, 73; --color-sea-sponge: 32, 47, 54; --color-turtle: 95, 132, 40; --color-owl: 147, 211, 51; --color-tree-frog: 121, 185, 51; --color-peacock: 0, 205, 156; --color-iguana: 32, 47, 54; --color-anchovy: 210, 228, 232; --color-beluga: 187, 242, 255; --color-moon-jelly: 122, 240, 242; --color-blue-jay: 63, 133, 167; --color-macaw: 73, 192, 248; --color-whale: 24, 153, 214; --color-humpback: 43, 112, 201; --color-narwhal: 20, 83, 163; --color-manta-ray: 4, 44, 96; --color-starfish: 255, 134, 208; --color-beetle: 206, 130, 255; --color-betta: 144, 105, 205; --color-butterfly: 111, 78, 161; --color-dragon: 204, 52, 141; --color-starling: 92, 108, 252; --color-martin: 71, 85, 223; --color-grackle: 167, 160, 255; --color-honeycreeper: 193, 187, 255; --color-deep-starling: 34, 33, 81; --color-deep-martin: 16, 15, 62; --color-legendary-foreground: 140, 65, 3; --color-stardust: 199, 255, 254; --color-cosmos: 60, 77, 255; --color-nebula: 63, 34, 236; --color-nova: 207, 23, 200; --color-gamma: 38, 246, 99; --color-starlight: 38, 138, 255; --color-quasar: 252, 85, 255; --color-celestia: 255, 255, 255; --color-eclipse: 0, 4, 55; --color-black: 0, 0, 0; --color-aqua: 43, 164, 176; --color-aqua-always-light: 56, 238, 255; --color-ocean: 56, 238, 255; --color-seafoam: 30, 89, 97; --color-ice: 23, 52, 58; --color-max-shadow: 20, 208, 225; --color-black-white: 255, 255, 255; --color-diamond-stat: 86, 219, 226; --color-mask-green: 144, 220, 72; --color-pearl-stat: 255, 170, 222; --color-snow-dark-swan: 55, 70, 79; --color-black-text: 241, 247, 251; --color-blue-space: 11, 62, 113; --color-juicy-blue-space: 10, 74, 130; --color-juicy-blue-space-light: 35, 83, 144; --color-gold: 250, 169, 25; --color-gray-text: 220, 230, 236; --color-orange: 255, 157, 0; --color-diamond-highlight: 231, 251, 251; --color-diamond: 56, 208, 208; --color-banana: 255, 176, 32; --color-cloud: 207, 207, 207; --color-cloud-light: 221, 221, 221; --color-cloud-lightest: 240, 240, 240; --color-kiwi: 122, 199, 12; --color-kiwi-dark: 93, 151, 9; --color-kiwi-light: 142, 224, 0; --color-facebook: 59, 89, 152; --color-facebook-dark: 45, 67, 115; --color-google: 66, 133, 244; --color-twitter: 29, 161, 242; --color-hv-light-peach: 241, 218, 179; --color-hv-peach: 219, 186, 131; --color-hv-light-orange: 255, 177, 64; --color-hv-orange: 204, 121, 0; --color-hv-brown: 140, 90, 17; --color-streak-panel-extended-background: 205, 121, 0; --color-streak-panel-frozen-background: 43, 112, 201; --color-streak-panel-frozen-flair-background: 73, 192, 248; --color-streak-panel-frozen-subtitle: 255, 255, 255; --color-streak-panel-frozen-text: 255, 255, 255; --color-streak-panel-frozen-topbar-text: 255, 255, 255; --color-streak-panel-streak-society-background: 215, 148, 51; --color-streak-panel-streak-society-text: 255, 255, 255; --color-streak-panel-unextended-heading-text: 82, 101, 109; --color-streak-panel-unextended-heading-background: 32, 47, 54; --color-streak-panel-unextended-topbar-text: 255, 255, 255; --color-streak-panel-milestone-gradient-start: 255, 147, 58; --color-streak-panel-milestone-gradient-end: 255, 200, 0; --color-streak-society-dark-orange: 255, 151, 1; --color-streak-society-light-orange: 255, 179, 1; --color-friends-quest-own-incomplete: 111, 139, 157; --color-friends-quest-friend-incomplete: 79, 100, 113; --color-black-text-always-light: 60, 60, 60; --color-cardinal-always-light: 255, 75, 75; --color-cowbird: 174, 104, 2; --color-eel-always-light: 75, 75, 75; --color-fox-always-light: 255, 150, 0; --color-fire-ant-always-light: 234, 43, 43; --color-grizzly-lite: 220, 143, 71; --color-guinea-pig-always-light: 205, 121, 0; --color-iguana-always-light: 221, 244, 255; --color-macaw-always-light: 28, 176, 246; --color-owl-always-light: 88, 204, 2; --color-polar-always-light: 247, 247, 247; --color-sea-sponge-always-light: 215, 255, 184; --color-tree-frog-always-light: 88, 167, 0; --color-turtle-always-light: 165, 237, 110; --color-walking-fish-always-light: 255, 223, 224; --color-wolf-always-light: 119, 119, 119; --color-cardinal-always-dark: 238, 85, 85; --color-eel-always-dark: 241, 247, 251; --color-hare-always-dark: 82, 101, 109; --color-macaw-always-dark: 73, 192, 248; --color-owl-always-dark: 147, 211, 51; --color-polar-always-dark: 32, 47, 54; --color-wolf-always-dark: 220, 230, 236; --color-rookie: 0, 175, 133; --color-explorer: 255, 100, 191; --color-traveler: 255, 145, 83; --color-trailblazer: 154, 143, 232; --color-adventurer: 96, 12, 199; --color-discoverer: 111, 44, 57; --color-daredevil: 46, 83, 138; --color-navigator: 9, 47, 119; --color-champion: 255, 110, 53; --color-daily_refresh: 0, 148, 255; --color-dark-mode-locked-path-section-text-color: 82, 101, 109; --color-rookie-progress-bar: 0, 198, 150; --color-explorer-progress-bar: 255, 138, 207; --color-traveler-progress-bar: 255, 167, 106; --color-trailblazer-progress-bar: 169, 157, 254; --color-adventurer-progress-bar: 122, 13, 199; --color-discoverer-progress-bar: 131, 50, 65; --color-daredevil-progress-bar: 54, 98, 165; --color-navigator-progress-bar: 12, 57, 141; --color-champion-progress-bar: 255, 129, 80; --color-daily_refresh-progress-bar: 28, 160, 255; --color-course-complete-cta: 120, 219, 224; --color-course-complete-cta-border: 94, 201, 204; --color-bea-secondary: 24, 153, 214; --color-eddy-secondary: 234, 43, 43; --color-gilded-secondary: 231, 166, 1; --color-lily-secondary: 165, 104, 204; --color-vikram-secondary: 163, 42, 113; --color-zari-secondary: 204, 107, 166; --color-oscar-secondary: 0, 164, 125; --color-falstaff-secondary: 150, 90, 58; --color-bea-radio: 20, 123, 172; --color-duo-radio: 62, 143, 1; --color-eddy-radio: 179, 53, 53; --color-falstaff-radio: 131, 79, 51; --color-lin-lucy-radio: 179, 105, 0; --color-lily-radio: 144, 91, 179; --color-vikram-radio: 143, 36, 99; --color-zari-radio: 179, 94, 146; --color-oscar-radio: 0, 144, 109; --color-bea-junior-shine: 67, 190, 248; --color-duo-shine: 114, 214, 39; --color-eddy-shine: 255, 105, 105; --color-falstaff-shine: 227, 165, 108; --color-lily-shine: 214, 150, 255; --color-lin-lucy-shine: 255, 168, 44; --color-oscar-shine: 63, 217, 181; --color-vikram-shine: 214, 90, 162; --color-zari-shine: 255, 158, 217; --color-super-background-secondary: 26, 30, 76; --color-super-gradient-background: 12, 47, 113; --color-super-gradient-top-halo: 12, 76, 70; --color-super-gradient-bottom-halo: 76, 29, 115; --color-gold-shine: 255, 231, 0; --color-legendary-dark-background: 24, 24, 24; --color-roseate: 223, 75, 162; --color-rosefinch: 180, 28, 117; --color-bluebird: 3, 144, 211; --color-cotinga: 121, 58, 227; --color-sabrewing: 165, 112, 255; --color-blueberry: 17, 82, 167; --color-ether: 60, 89, 141; --color-diamond-tournament-purple: 161, 161, 238; --color-diamond-tournament-reaction: 118, 163, 231; --color-yir-page0: 221, 244, 255; --color-yir-page1: 227, 255, 235; --color-yir-page1-shadow: 19, 31, 36; --color-yir-page3-shadow: 187, 172, 252; --color-yir-page4-shadow: 143, 219, 255; --color-yir-page5-shadow: 255, 183, 80; --color-super-gradient-green-variant1: 38, 255, 85; --color-super-gradient-blue-variant1: 38, 139, 255; --color-super-gradient-pink-variant1: 252, 85, 255; --color-super-gradient-purple-variant1: 17, 34, 181; --color-unknown-001e2d: 0, 30, 45; --color-unknown-0047a4: 0, 71, 164; --color-unknown-0087d0: 0, 135, 208; --color-unknown-00aff9: 0, 175, 249; --color-unknown-013047: 1, 48, 71; --color-unknown-048fd1: 4, 143, 209; --color-unknown-0e0f10: 14, 15, 16; --color-unknown-0e3d79: 14, 61, 121; --color-unknown-172071: 23, 32, 113; --color-unknown-280378: 40, 3, 120; --color-unknown-3ebbf6: 62, 187, 246; --color-unknown-655ebb: 101, 94, 187; --color-unknown-696cee: 105, 108, 238; --color-unknown-7c0000: 124, 0, 0; --color-unknown-89e219: 137, 226, 25; --color-unknown-935051: 147, 80, 81; --color-unknown-959595: 149, 149, 149; --color-unknown-a2a2a2: 162, 162, 162; --color-unknown-a3dbeb: 163, 219, 235; --color-unknown-a4dffb: 164, 223, 251; --color-unknown-aaa: 170, 170, 170; --color-unknown-d087ff: 208, 135, 255; --color-unknown-d9d9d9: 217, 217, 217; --color-unknown-ddd: 221, 221, 221; --color-unknown-de8029: 222, 128, 41; --color-unknown-e3e3e3: 227, 227, 227; --color-unknown-e4ffff: 228, 255, 255; --color-unknown-ed8c01: 237, 140, 1; --color-unknown-f3484e: 243, 72, 78; --color-unknown-f4fafe: 244, 250, 254; --color-unknown-fbdec5: 251, 222, 197; --color-unknown-ffc700: 255, 199, 0; --color-unknown-fff2aa: 255, 242, 170; --color-unknown-fffbef: 255, 251, 239;"]
  260. : ["light", "off", "--app-offset: 0px; --color-snow: 255, 255, 255; --color-snow-always-light: 255, 255, 255; --color-snow-always-dark: 19, 31, 36; --color-polar: 247, 247, 247; --color-swan: 229, 229, 229; --color-swan-always-light: 229, 229, 229; --color-swan-always-dark: 55, 70, 79; --color-hare: 175, 175, 175; --color-hare-always-light: 175, 175, 175; --color-wolf: 119, 119, 119; --color-eel: 75, 75, 75; --color-squid: 235, 227, 227; --color-walking-fish: 255, 223, 224; --color-flamingo: 255, 178, 178; --color-pig: 245, 164, 164; --color-crab: 255, 120, 120; --color-cardinal: 255, 75, 75; --color-fire-ant: 234, 43, 43; --color-canary: 255, 245, 211; --color-duck: 251, 229, 109; --color-bee: 255, 200, 0; --color-bee-always-dark: 255, 199, 0; --color-lion: 255, 177, 0; --color-fox: 255, 150, 0; --color-cheetah: 255, 206, 142; --color-monkey: 229, 162, 89; --color-camel: 231, 166, 1; --color-guinea-pig: 205, 121, 0; --color-grizzly: 187, 113, 73; --color-sea-sponge: 215, 255, 184; --color-turtle: 165, 237, 110; --color-owl: 88, 204, 2; --color-tree-frog: 88, 167, 0; --color-peacock: 0, 205, 156; --color-iguana: 221, 244, 255; --color-anchovy: 210, 228, 232; --color-beluga: 187, 242, 255; --color-moon-jelly: 122, 240, 242; --color-blue-jay: 132, 216, 255; --color-macaw: 28, 176, 246; --color-whale: 24, 153, 214; --color-humpback: 43, 112, 201; --color-narwhal: 20, 83, 163; --color-manta-ray: 4, 44, 96; --color-starfish: 255, 134, 208; --color-beetle: 206, 130, 255; --color-betta: 144, 105, 205; --color-butterfly: 111, 78, 161; --color-dragon: 204, 52, 141; --color-starling: 92, 108, 252; --color-martin: 71, 85, 223; --color-grackle: 167, 160, 255; --color-honeycreeper: 193, 187, 255; --color-deep-starling: 34, 33, 81; --color-deep-martin: 16, 15, 62; --color-legendary-foreground: 140, 65, 3; --color-stardust: 199, 255, 254; --color-cosmos: 60, 77, 255; --color-nebula: 63, 34, 236; --color-nova: 207, 23, 200; --color-gamma: 38, 246, 99; --color-starlight: 38, 138, 255; --color-quasar: 252, 85, 255; --color-celestia: 255, 255, 255; --color-eclipse: 0, 4, 55; --color-black: 0, 0, 0; --color-aqua: 56, 238, 255; --color-aqua-always-light: 56, 238, 255; --color-ocean: 0, 124, 143; --color-seafoam: 158, 224, 233; --color-ice: 225, 253, 255; --color-max-shadow: 20, 208, 225; --color-black-white: 0, 0, 0; --color-diamond-stat: 86, 219, 226; --color-mask-green: 137, 226, 25; --color-pearl-stat: 255, 170, 222; --color-snow-dark-swan: 255, 255, 255; --color-black-text: 60, 60, 60; --color-blue-space: 11, 62, 113; --color-juicy-blue-space: 10, 74, 130; --color-juicy-blue-space-light: 35, 83, 144; --color-gold: 250, 169, 25; --color-gray-text: 153, 153, 153; --color-orange: 255, 157, 0; --color-diamond-highlight: 231, 251, 251; --color-diamond: 56, 208, 208; --color-banana: 255, 176, 32; --color-cloud: 207, 207, 207; --color-cloud-light: 221, 221, 221; --color-cloud-lightest: 240, 240, 240; --color-kiwi: 122, 199, 12; --color-kiwi-dark: 93, 151, 9; --color-kiwi-light: 142, 224, 0; --color-facebook: 59, 89, 152; --color-facebook-dark: 45, 67, 115; --color-google: 66, 133, 244; --color-twitter: 29, 161, 242; --color-hv-light-peach: 241, 218, 179; --color-hv-peach: 219, 186, 131; --color-hv-light-orange: 255, 177, 64; --color-hv-orange: 204, 121, 0; --color-hv-brown: 140, 90, 17; --color-streak-panel-extended-background: 255, 150, 0; --color-streak-panel-frozen-background: 221, 244, 255; --color-streak-panel-frozen-flair-background: 132, 216, 255; --color-streak-panel-frozen-subtitle: 28, 176, 246; --color-streak-panel-frozen-text: 132, 216, 255; --color-streak-panel-frozen-topbar-text: 24, 153, 214; --color-streak-panel-streak-society-background: 255, 200, 0; --color-streak-panel-streak-society-text: 205, 121, 0; --color-streak-panel-unextended-heading-text: 235, 195, 127; --color-streak-panel-unextended-heading-background: 255, 245, 211; --color-streak-panel-unextended-topbar-text: 235, 195, 127; --color-streak-panel-milestone-gradient-start: 255, 147, 58; --color-streak-panel-milestone-gradient-end: 255, 200, 0; --color-streak-society-dark-orange: 255, 151, 1; --color-streak-society-light-orange: 255, 179, 1; --color-friends-quest-own-incomplete: 175, 175, 175; --color-friends-quest-friend-incomplete: 145, 145, 145; --color-black-text-always-light: 60, 60, 60; --color-cardinal-always-light: 255, 75, 75; --color-cowbird: 174, 104, 2; --color-eel-always-light: 75, 75, 75; --color-fox-always-light: 255, 150, 0; --color-fire-ant-always-light: 234, 43, 43; --color-grizzly-lite: 220, 143, 71; --color-guinea-pig-always-light: 205, 121, 0; --color-iguana-always-light: 221, 244, 255; --color-macaw-always-light: 28, 176, 246; --color-owl-always-light: 88, 204, 2; --color-polar-always-light: 247, 247, 247; --color-sea-sponge-always-light: 215, 255, 184; --color-tree-frog-always-light: 88, 167, 0; --color-turtle-always-light: 165, 237, 110; --color-walking-fish-always-light: 255, 223, 224; --color-wolf-always-light: 119, 119, 119; --color-cardinal-always-dark: 238, 85, 85; --color-eel-always-dark: 241, 247, 251; --color-hare-always-dark: 82, 101, 109; --color-macaw-always-dark: 73, 192, 248; --color-owl-always-dark: 147, 211, 51; --color-polar-always-dark: 32, 47, 54; --color-wolf-always-dark: 220, 230, 236; --color-rookie: 0, 175, 133; --color-explorer: 255, 100, 191; --color-traveler: 255, 145, 83; --color-trailblazer: 154, 143, 232; --color-adventurer: 96, 12, 199; --color-discoverer: 111, 44, 57; --color-daredevil: 46, 83, 138; --color-navigator: 9, 47, 119; --color-champion: 255, 110, 53; --color-daily_refresh: 0, 148, 255; --color-dark-mode-locked-path-section-text-color: 82, 101, 109; --color-rookie-progress-bar: 0, 198, 150; --color-explorer-progress-bar: 255, 138, 207; --color-traveler-progress-bar: 255, 167, 106; --color-trailblazer-progress-bar: 169, 157, 254; --color-adventurer-progress-bar: 122, 13, 199; --color-discoverer-progress-bar: 131, 50, 65; --color-daredevil-progress-bar: 54, 98, 165; --color-navigator-progress-bar: 12, 57, 141; --color-champion-progress-bar: 255, 129, 80; --color-daily_refresh-progress-bar: 28, 160, 255; --color-course-complete-cta: 120, 219, 224; --color-course-complete-cta-border: 94, 201, 204; --color-bea-secondary: 24, 153, 214; --color-eddy-secondary: 234, 43, 43; --color-gilded-secondary: 231, 166, 1; --color-lily-secondary: 165, 104, 204; --color-vikram-secondary: 163, 42, 113; --color-zari-secondary: 204, 107, 166; --color-oscar-secondary: 0, 164, 125; --color-falstaff-secondary: 150, 90, 58; --color-bea-radio: 20, 123, 172; --color-duo-radio: 62, 143, 1; --color-eddy-radio: 179, 53, 53; --color-falstaff-radio: 131, 79, 51; --color-lin-lucy-radio: 179, 105, 0; --color-lily-radio: 144, 91, 179; --color-vikram-radio: 143, 36, 99; --color-zari-radio: 179, 94, 146; --color-oscar-radio: 0, 144, 109; --color-bea-junior-shine: 67, 190, 248; --color-duo-shine: 114, 214, 39; --color-eddy-shine: 255, 105, 105; --color-falstaff-shine: 227, 165, 108; --color-lily-shine: 214, 150, 255; --color-lin-lucy-shine: 255, 168, 44; --color-oscar-shine: 63, 217, 181; --color-vikram-shine: 214, 90, 162; --color-zari-shine: 255, 158, 217; --color-super-background-secondary: 26, 30, 76; --color-super-gradient-background: 12, 47, 113; --color-super-gradient-top-halo: 12, 76, 70; --color-super-gradient-bottom-halo: 76, 29, 115; --color-gold-shine: 255, 231, 0; --color-legendary-dark-background: 24, 24, 24; --color-roseate: 223, 75, 162; --color-rosefinch: 180, 28, 117; --color-bluebird: 3, 144, 211; --color-cotinga: 121, 58, 227; --color-sabrewing: 165, 112, 255; --color-blueberry: 17, 82, 167; --color-ether: 60, 89, 141; --color-diamond-tournament-purple: 161, 161, 238; --color-diamond-tournament-reaction: 118, 163, 231; --color-yir-page0: 221, 244, 255; --color-yir-page1: 227, 255, 235; --color-yir-page1-shadow: 19, 31, 36; --color-yir-page3-shadow: 187, 172, 252; --color-yir-page4-shadow: 143, 219, 255; --color-yir-page5-shadow: 255, 183, 80; --color-super-gradient-green-variant1: 38, 255, 85; --color-super-gradient-blue-variant1: 38, 139, 255; --color-super-gradient-pink-variant1: 252, 85, 255; --color-super-gradient-purple-variant1: 17, 34, 181; --color-unknown-001e2d: 0, 30, 45; --color-unknown-0047a4: 0, 71, 164; --color-unknown-0087d0: 0, 135, 208; --color-unknown-00aff9: 0, 175, 249; --color-unknown-013047: 1, 48, 71; --color-unknown-048fd1: 4, 143, 209; --color-unknown-0e0f10: 14, 15, 16; --color-unknown-0e3d79: 14, 61, 121; --color-unknown-172071: 23, 32, 113; --color-unknown-280378: 40, 3, 120; --color-unknown-3ebbf6: 62, 187, 246; --color-unknown-655ebb: 101, 94, 187; --color-unknown-696cee: 105, 108, 238; --color-unknown-7c0000: 124, 0, 0; --color-unknown-89e219: 137, 226, 25; --color-unknown-935051: 147, 80, 81; --color-unknown-959595: 149, 149, 149; --color-unknown-a2a2a2: 162, 162, 162; --color-unknown-a3dbeb: 163, 219, 235; --color-unknown-a4dffb: 164, 223, 251; --color-unknown-aaa: 170, 170, 170; --color-unknown-d087ff: 208, 135, 255; --color-unknown-d9d9d9: 217, 217, 217; --color-unknown-ddd: 221, 221, 221; --color-unknown-de8029: 222, 128, 41; --color-unknown-e3e3e3: 227, 227, 227; --color-unknown-e4ffff: 228, 255, 255; --color-unknown-ed8c01: 237, 140, 1; --color-unknown-f3484e: 243, 72, 78; --color-unknown-f4fafe: 244, 250, 254; --color-unknown-fbdec5: 251, 222, 197; --color-unknown-ffc700: 255, 199, 0; --color-unknown-fff2aa: 255, 242, 170; --color-unknown-fffbef: 255, 251, 239;"];
  261.  
  262. document.documentElement.setAttribute("data-duo-theme", theme);
  263. document.documentElement.setAttribute("style", css);
  264.  
  265. const darkModeDataLocal = getLocal("duo.darkMode")
  266. for(const key in darkModeDataLocal){
  267. darkModeDataLocal[key] = value
  268. }
  269.  
  270. localStorage.setItem("duo.darkMode", JSON.stringify(darkModeDataLocal));
  271. setSwitch(this.isDarkMode);
  272. });
  273.  
  274. this.farmingLocationWrapper = document.createElement("div");
  275. this.farmingLocationWrapper.style = `--data-name: "Set XP Farm Location"`;
  276. const farmingLocationInfo =
  277. "SET XP FARM LOCATION\n" +
  278. "- By default, the system can only Farm XP in practice exercises or listening practices. However, with this feature, you can Farm XP " +
  279. "in any lesson you want, even in story lessons!\n" +
  280. "- Usage: Activate the feature and enter the URL of the lesson you want, then enable the XP Farm mode to start farming.\n" +
  281. "- NOTE: The URL to the lesson must be accurate and the lesson must be repeatable. Entering an inaccurate URL may lead " +
  282. "to errors or even pose risks to your account!";
  283. this.autoduoCreateSwitch(farmingLocationInfo, this.farmingLocationWrapper, 8, false);
  284.  
  285. this.autoX2Wrapper = document.createElement("div");
  286. this.autoX2Wrapper.style = `--data-name: "Auto Collect x2 XP"`;
  287. const autoX2Info =
  288. "AUTO COLLECT X2 XP:\n" +
  289. '- This is a supplementary feature for "Auto Farm KN", helping to maintain the x2 KN status during farming. When enabled, ' +
  290. "it will check and automatically do new lessons to get x2 KN rewards if it detects the current state doesn't have x2. " +
  291. "This will help you farm more KN points than usual. \n\n- NOTE: This feature will do new lessons to maintain the x2 status, so " +
  292. "consider before enabling it if you have constraints with these lessons.";
  293. this.autoduoCreateSwitch(autoX2Info, this.autoX2Wrapper, 8, false);
  294.  
  295. this.functionWrapper = document.createElement("div");
  296. this.functionWrapper.className = "function-wrapper-listening";
  297. this.functionWrapper.append(
  298. this.darkModeWrapper,
  299. this.animationOffWrapper,
  300. this.safeModeWrapper,
  301. this.turboModeWrapper
  302. );
  303. },
  304.  
  305. initSetting: function () {
  306. this.settingBtn = document.createElement("button");
  307. Object.assign(this.settingBtn, {
  308. className: "autoduo-btn setting-btn-listening",
  309. innerText: "Other settings",
  310. });
  311. this.settingBtn.addEventListener("click", () => {
  312. this.controlContainer.contains(this.settingOverlay) ||
  313. this.controlContainer.appendChild(this.settingOverlay);
  314. });
  315.  
  316. this.closeSettingBtn = document.createElement("button");
  317. Object.assign(this.closeSettingBtn, {
  318. className: "autoduo-btn close-setting-btn-listening",
  319. innerText: "Close",
  320. });
  321. this.closeSettingBtn.addEventListener("click", () => {
  322. this.controlContainer.contains(this.settingOverlay) &&
  323. this.controlContainer.removeChild(this.settingOverlay);
  324. });
  325.  
  326. this.settingOverlay = document.createElement("div");
  327. Object.assign(this.settingOverlay, {
  328. className: "setting-overlay-listening",
  329. innerHTML: `
  330. <h3>Other settings</h3>
  331. `,
  332. });
  333.  
  334. this.settingFunction = document.createElement("div");
  335. this.settingFunction.className = "setting-function-listening";
  336. this.settingFunction.append(
  337. this.legendModeWrapper,
  338. this.passModeWrapper,
  339. this.targetModeWrapper,
  340. this.farmingLocationWrapper,
  341. this.autoX2Wrapper
  342. );
  343.  
  344. this.settingOverlay.append(this.settingFunction, this.closeSettingBtn);
  345. },
  346.  
  347. initContainer: function () {
  348. this.autoContainer = document.createElement("div");
  349. this.autoContainer.className = "auto-container-listening";
  350. this.autoContainer.append(
  351. this.statistic,
  352. this.functionWrapper,
  353. this.settingBtn,
  354. this.autoBtn,
  355. this.updateBtn
  356. );
  357.  
  358. this.overlayContainer = document.createElement("div");
  359. this.overlayContainer.className = "overlay-listening";
  360.  
  361. this.controlContainer = document.createElement("div");
  362. this.controlContainer.className = "control-container-listening";
  363. this.controlContainer.append(this.autoContainer, this.contactWrapper);
  364.  
  365. this.bubbleContainer = document.createElement("div");
  366. this.bubbleContainer.className = "bubble-container-listening";
  367. this.bubbleContainer.append(this.marketerBubble, this.superBubble, this.notifyBubble);
  368.  
  369. document.body.append(this.controlContainer, this.bubbleContainer);
  370. },
  371.  
  372. fetchNoti: async function () {
  373. try {
  374. const res = await (
  375. await fetch("https://api.autoduolingo.click/super/data/notify/?c7f54a73e6340a16176=91bf0d18b83")
  376. )?.json();
  377. if (res?.code === 200) {
  378. const { notifyVersion: rmVersion, notifyContent: rmContent } = res.data[0];
  379. setDataSession({
  380. isNewNotify: (this.isNewNotify = +rmVersion > this.notifyVersion),
  381. rmNotiVer: (this.rmNotiVer = +rmVersion),
  382. rmNotiContent: (this.rmNotiContent = rmContent.replaceAll("\\n", "\n")),
  383. });
  384. this.setNoti();
  385. }
  386. } catch (e) {}
  387. },
  388.  
  389. setNoti: function () {
  390. if (!this.rmNotiVer) {
  391. return;
  392. }
  393. if (this.isNewNotify) {
  394. this.notifyBubble.classList.add("new");
  395. }
  396. this.notifyBubble.addEventListener("click", () => {
  397. if (this.isNewNotify) {
  398. this.notifyBubble.classList.remove("new");
  399. setDataSession("isNewNotify", (this.isNewNotify = false));
  400. setDataLocal("notifyVersion", this.rmNotiVer);
  401. }
  402. window.alert(this.rmNotiContent);
  403. });
  404. },
  405.  
  406. handleShowHideUI: function (isSave = false) {
  407. if (this.isShowUI) {
  408. this.showHideBtn.classList.remove("hide");
  409. document.body.append(this.controlContainer, this.signatureElm, this.bubbleContainer);
  410. } else {
  411. this.showHideBtn.classList.add("hide");
  412. this.controlContainer.remove();
  413. this.signatureElm.remove();
  414. this.bubbleContainer.remove();
  415. }
  416.  
  417. if (isSave) {
  418. setDataSession("isShowUI", this.isShowUI);
  419. this.controlContainer.classList.contains("autoduo-animate") ||
  420. this.controlContainer.classList.add("autoduo-animate");
  421. }
  422. },
  423.  
  424. handleAnimationOff: function (isSave = false) {
  425. this.isAnimationOff
  426. ? document.head.appendChild(this.animationStyle)
  427. : document.head.removeChild(this.animationStyle);
  428. isSave && setDataSession("isAnimationOff", this.isAnimationOff);
  429. },
  430.  
  431. handleSafeModeOn: function () {
  432. this.safeModeWrapper.setAutoduoSwitch(this.setSafeMode(true));
  433. },
  434.  
  435. handleSafeModeOff: function () {
  436. this.safeModeWrapper.setAutoduoSwitch(this.setSafeMode(false));
  437. },
  438.  
  439. start: function () {
  440. if (this.isAuto || this.isAutoRunning) {
  441. return;
  442. }
  443.  
  444. document.body.appendChild(this.overlayContainer);
  445. this.isAuto = true;
  446. this.autoBtn.classList.add("running");
  447. this.autoBtn.innerText = "STOP FARM XP";
  448. setDataSession("isBasicAuto", this.isAuto);
  449. this.startTm = Date.now();
  450. this.handleLocation();
  451. },
  452.  
  453. stop: function () {
  454. if (!this.isAuto || this.isLegendMode) {
  455. return;
  456. }
  457. document.body.removeChild(this.overlayContainer);
  458. this.isAuto = false;
  459. this.autoBtn.classList.remove("running");
  460. this.autoBtn.innerText = "START FARM XP";
  461. setDataSession("isBasicAuto", this.isAuto);
  462. },
  463.  
  464. handleLocation: function () {
  465. if (!this.isAuto) {
  466. return;
  467. }
  468.  
  469. const currentPath = window.location.pathname;
  470.  
  471. switch (currentPath) {
  472. case this.practiceHubPath:
  473. this.goPracticeHubChallenge();
  474. break;
  475.  
  476. case this.listeningPacticePath:
  477. this.handlePracticeHubChallenge();
  478. break;
  479.  
  480. default:
  481. this.autoduoError(
  482. "[Inappropriate location]: Only enable auto when on the practice page (with the dumbbell icon) of Duolingo Super!" +
  483. "\n- Enabling auto on Duolingo Super's practice page will automatically farm listening exercises (20 XP)." +
  484. "\n- Upgrade to the full version of Auto-Duolingo to use auto farming and many other useful features without needing Super Duolingo!"
  485. , true);
  486. break;
  487. }
  488. },
  489.  
  490. goPracticeHubChallenge: function () {
  491. if (this.isAuto === false) {
  492. return;
  493. }
  494. const challengeBtn = $(
  495. 'img[src="https://d35aaqx5ub95lt.cloudfront.net/images/practiceHub/2ebe830fd55a7f2754d371bcd79faf32.svg"]'
  496. );
  497.  
  498. if (!challengeBtn) {
  499. setTimeout(this.goPracticeHubChallenge.bind(this), 1000);
  500. return;
  501. }
  502.  
  503. challengeBtn.click();
  504. setTimeout(this.handlePracticeHubChallenge.bind(this), 1000);
  505. },
  506.  
  507. handlePracticeHubChallenge: function () {
  508. if (window.location.pathname === this.practiceHubPath) {
  509. this.goPracticeHubChallenge();
  510. return;
  511. }
  512.  
  513. // Flag:BETA
  514. const challengeWrapper = $(".wqSzE");
  515. if (challengeWrapper) {
  516. this.getDataStateNode(challengeWrapper);
  517. this.next();
  518. return;
  519. }
  520. const nextActiveBtn = $('[data-test="player-next"][aria-disabled="false"]');
  521.  
  522. if (nextActiveBtn) {
  523. this.next();
  524. return;
  525. }
  526.  
  527. setTimeout(this.handlePracticeHubChallenge.bind(this), 1000);
  528. },
  529.  
  530. handleChallenge: async function () {
  531. if (this.isSafeMode) {
  532. await this.sleep(500);
  533. }
  534. if (!this.isAuto || this.isAutoRunning) {
  535. return;
  536. }
  537.  
  538. const challengeTypeElm = $('[data-test*="challenge challenge"]');
  539.  
  540. if (!challengeTypeElm) {
  541. return this.autoduoError("Undefined challenge!!");
  542. }
  543.  
  544. const challengeType = challengeTypeElm.dataset.test?.slice(10);
  545.  
  546. this.setAutoRunning(true);
  547. switch (challengeType) {
  548. case "challenge-listenTap":
  549. this.handleChallengeTranslate();
  550. break;
  551.  
  552. case "challenge-gapFill":
  553. case "challenge-listenIsolation":
  554. case "challenge-assist":
  555. case "challenge-selectTranscription":
  556. case "challenge-characterIntro":
  557. case "challenge-characterSelect":
  558. case "challenge-selectPronunciation":
  559. case "challenge-dialogue":
  560. case "challenge-readComprehension":
  561. case "challenge-listenComprehension":
  562. case "challenge-select":
  563. case "challenge-form":
  564. case "challenge-definition":
  565. case "challenge-sameDifferent":
  566. this.handleChallengeChoice();
  567. break;
  568.  
  569. default:
  570. this.autoduoError(
  571. "This exercise is not currently supported in this version. Try updating to the full version of Auto-Duolingo and try again!"
  572. );
  573. break;
  574. }
  575. },
  576.  
  577. handleChallengeTranslate: function () {
  578. if (this.isAuto === false) {
  579. return;
  580. }
  581.  
  582. let data = this.getData("correctTokens");
  583.  
  584. if (this.isAuto === false) {
  585. return;
  586. }
  587.  
  588. if (!data?.length) {
  589. data = this.getData(["challengeResponseTrackingProperties", "best_solution"])?.split(" ");
  590. }
  591.  
  592. if (!data) {
  593. return this.autoduoError("Lesson data not found.");
  594. }
  595.  
  596. const textArea = $('textarea[data-test="challenge-translate-input"]:not([disabled])');
  597. if (textArea) {
  598. const toggleKeyboard = $('[data-test="player-toggle-keyboard"]');
  599. if (toggleKeyboard) {
  600. toggleKeyboard.click();
  601. return setTimeout(this.handleChallengeTranslate.bind(this), 500);
  602. }
  603.  
  604. const inputEvent = new Event("input", {
  605. bubbles: true,
  606. });
  607.  
  608. let answer = "";
  609.  
  610. const inputCaseHandler = () => {
  611. setTimeout(() => {
  612. if (data.length === 0) {
  613. this.setAutoRunning(false);
  614. this.next(true);
  615. return;
  616. }
  617.  
  618. answer += " " + data.shift();
  619. this.nativeTextareaValueSetter.call(textArea, answer);
  620. textArea.dispatchEvent(inputEvent);
  621. inputCaseHandler();
  622. }, this.rmSafeDlTm());
  623. };
  624. inputCaseHandler();
  625. return;
  626. }
  627.  
  628. // Flag:BETA
  629. let options = arr($$('button[data-test*="challenge-tap-token"]'));
  630. if (options.length === 0) {
  631. return setTimeout(this.handleChallengeTranslate.bind(this), 500);
  632. }
  633.  
  634. const getIndexOfOption = (targetData) => {
  635. const index = options.findIndex((option) => option.textContent === targetData);
  636. return index;
  637. };
  638.  
  639. const selectCaseHandler = () => {
  640. setTimeout(() => {
  641. if (data.length === 0) {
  642. this.setAutoRunning(false);
  643. this.next(true);
  644. return;
  645. }
  646.  
  647. const firstValue = data.shift();
  648. const index = getIndexOfOption(firstValue);
  649.  
  650. if (index === -1) {
  651. return this.autoduoLessonError("No suitable option found.");
  652. }
  653.  
  654. options[index].click();
  655. options.splice(index, 1);
  656. selectCaseHandler();
  657. }, this.rmSafeDlTm());
  658. };
  659. selectCaseHandler();
  660. },
  661.  
  662. handleChallengeChoice: function () {
  663. if (!this.isAuto) {
  664. return;
  665. }
  666.  
  667. const optionElm = $$('[data-test="challenge-choice"]');
  668. const correctIndex = this.getData("correctIndex");
  669.  
  670. if (correctIndex === null) {
  671. return this.autoduoError("Lesson data not found.");
  672. }
  673.  
  674. setTimeout(() => {
  675. optionElm[correctIndex].click();
  676. setTimeout(() => {
  677. this.setAutoRunning(false);
  678. this.next();
  679. }, this.rmSafeDlTm());
  680. }, this.rmSafeDlTm());
  681. },
  682.  
  683. next: function () {
  684. if (!this.isAuto) {
  685. return;
  686. }
  687.  
  688. // Flag:BETA
  689. const expWrapper = $('[class="_1XNQX"]');
  690. if (expWrapper) {
  691. const exp = this.getExp(expWrapper);
  692.  
  693. if (exp !== undefined) {
  694. this.exp += exp;
  695. this.expElm.innerText = this.exp;
  696.  
  697. const timeNow = Date.now();
  698. const finishTime = timeNow - this.startTm;
  699. this.totalTime += finishTime;
  700. this.startTm = timeNow;
  701. this.renderTime();
  702.  
  703. setDataSession({
  704. exp: this.exp,
  705. time: this.totalTime,
  706. });
  707.  
  708. const currentPath = window.location.pathname;
  709. if (currentPath === this.listeningPacticePath) {
  710. if ((this.totalReloadTime += finishTime) >= this.reloadTm) {
  711. window.location.reload();
  712. return;
  713. }
  714. }
  715. }
  716. }
  717.  
  718. const nextBtn = $('[data-test="player-next"]');
  719.  
  720. if (!nextBtn) {
  721. setTimeout(this.handleLocation.bind(this), this.goChallengeTm);
  722. return;
  723. }
  724.  
  725. const isDisabled = nextBtn.getAttribute("aria-disabled") === "true";
  726. const isFullProgress = !!$('[aria-valuenow="1"]');
  727.  
  728. if (isDisabled && !isFullProgress) {
  729. boom(this.handleChallenge.bind(this));
  730. return;
  731. }
  732.  
  733. !isDisabled && nextBtn.click();
  734. boom(this.next.bind(this));
  735. },
  736.  
  737. findReactProps: function (wrapperElm) {
  738. this.reactProps = Object.keys(wrapperElm).find((key) => key.startsWith("__reactProps"));
  739.  
  740. if (!this.reactProps) {
  741. return this.autoduoError("ERROR");
  742. }
  743. },
  744.  
  745. getDataStateNode: function (wrapperElm) {
  746. this.reactProps === null && this.findReactProps(wrapperElm);
  747. const childrenData = wrapperElm?.[this.reactProps]?.children;
  748.  
  749. if (Array.isArray(childrenData)) {
  750. this.dataStateNode = childrenData?.[0]?._owner?.stateNode;
  751. } else {
  752. this.dataStateNode = childrenData?._owner?.stateNode;
  753. }
  754. },
  755.  
  756. getData: function (subGenealogy) {
  757. const currentChallenge = this.dataStateNode?.props?.currentChallenge;
  758. if (!currentChallenge) {
  759. return this.autoduoError("There was an error while loading challenge data!");
  760. }
  761.  
  762. if (Array.isArray(subGenealogy)) {
  763. const result = subGenealogy.reduce((acc, currentKey) => {
  764. if (acc === null) {
  765. return null;
  766. }
  767.  
  768. const currentValue = acc[currentKey];
  769. return currentValue || null;
  770. }, currentChallenge);
  771.  
  772. if (result === null) {
  773. return this.autoduoError("There was an error while getting the data!");
  774. }
  775.  
  776. return Array.isArray(result) ? [...result] : result;
  777. } else {
  778. const result = currentChallenge[subGenealogy];
  779. return Array.isArray(result) ? [...result] : result;
  780. }
  781. },
  782.  
  783. getExp: function (expWrapper) {
  784. const keys = Object.keys(expWrapper);
  785. const key = keys.find((key) => key.startsWith("__reactProps"));
  786.  
  787. const exp = expWrapper?.[key]?.children?.props?.slide?.xpGoalSessionProgress?.totalXpThisSession;
  788. return exp;
  789. },
  790.  
  791. renderTime: function () {
  792. const timeString = timeFormat(this.totalTime);
  793. this.dateElm.innerText = timeString;
  794. },
  795.  
  796. setAutoRunning: function (isRunning) {
  797. this.isAutoRunning = isRunning;
  798. },
  799.  
  800. setSafeMode: function (isSafeMode) {
  801. this.isSafeMode = isSafeMode;
  802. setDataSession("isSafeMode", isSafeMode);
  803. return isSafeMode;
  804. },
  805.  
  806. rmSafeDlTm: function () {
  807. if (!this.isSafeMode) {
  808. return 0;
  809. }
  810. return Math.floor(Math.random() * 800 + 100);
  811. },
  812.  
  813. sleep: async function (time) {
  814. await new Promise((resolve) => setTimeout(resolve, time));
  815. },
  816.  
  817. autoduoError: function (message = '', native = false) {
  818. this.isAutoRunning && this.setAutoRunning(false);
  819. this.isAuto && this.stop();
  820. const tips =
  821. "\n- If this message persists, try updating to the full version of Auto-Duolingo. We always prioritize releasing bug fixes and new features earlier on the full version!";
  822. native ? alert(message + tips) : alert("ERROR: " + message + tips);
  823. },
  824.  
  825. autoduoLessonError: function (errorText) {
  826. // Flag:BETA
  827. const settingIcon = $("._2VEsk");
  828. if (settingIcon) {
  829. settingIcon.click();
  830.  
  831. return setTimeout(() => {
  832. this.autoduoError(
  833. `${errorText}. If you are currently displaying the pronunciation guide, please turn it off first, then reload the page, and finally turn on auto again!`
  834. );
  835. }, 800);
  836. }
  837. return this.autoduoError(errorText);
  838. },
  839.  
  840. autoduoCreateSwitch: function (descriptionText = "", wrapperElm, id, isChecked, handleSwitch) {
  841. const infoElm = document.createElement("i");
  842. Object.assign(infoElm, {
  843. className: "switch-info-listening",
  844. title: "Detail",
  845. onclick: () => {
  846. alert(descriptionText);
  847. },
  848. });
  849.  
  850. const checkboxElm = document.createElement("input");
  851. Object.assign(checkboxElm, {
  852. type: "checkbox",
  853. hidden: true,
  854. checked: isChecked,
  855. });
  856.  
  857. const setSwitch = (isEnable) => {
  858. checkboxElm.checked = isEnable;
  859. };
  860.  
  861. const labelElm = document.createElement("label");
  862. labelElm.addEventListener("click", () => {
  863. id > 3 ? notAvailable() : handleSwitch(setSwitch);
  864. });
  865.  
  866. const switchContainer = document.createElement("div");
  867. switchContainer.className = "switch-container-listening";
  868. switchContainer.append(infoElm, checkboxElm, labelElm);
  869.  
  870. wrapperElm.classList.add("switch-wrapper-listening");
  871. if (id > 3) {
  872. wrapperElm.classList.add("unavailable");
  873. }
  874. wrapperElm.append(switchContainer);
  875. wrapperElm.setAutoduoSwitch = setSwitch;
  876. },
  877.  
  878. autoduoCheckUpdate: async function () {
  879. let rmVersion =
  880. version || (await (await fetch("https://api.autoduolingo.click/lite/version/"))?.json())?.version;
  881.  
  882. if (this.version !== rmVersion) {
  883. $("#greasyfork").classList.add("has-update");
  884. $("#greasyfork .popup").innerText = "A new updated version is available!";
  885. }
  886.  
  887. if (!version) {
  888. setDataSession("version", rmVersion);
  889. }
  890. },
  891.  
  892. initStyle: function () {
  893. this.animationStyle = document.createElement("style");
  894. this.animationStyle.innerHTML = `
  895. img, svg, canvas {
  896. visibility: hidden !important;
  897. }
  898. div:not(.autoduo-animate):not(.setting-overlay-listening) {
  899. transition: none !important;
  900. animation-duration: 0s !important;
  901. }
  902. .fSJFz {
  903. display: none !important;
  904. }
  905. `;
  906.  
  907. const listenStyle = document.createElement("style");
  908. listenStyle.innerHTML = `
  909. :root{
  910. --autoduo-bg: 255,255,255;
  911. --autoduo-color: 75,75,75;
  912. --autoduo-h-color: 0,159,235;
  913. }
  914. :root[data-duo-theme="dark"]{
  915. --autoduo-bg: 19,31,36;
  916. --autoduo-color: 241,247,251;
  917. --autoduo-h-color: 241,247,251;
  918. }
  919. .control-container-listening{
  920. position: fixed;
  921. z-index: 9999999;
  922. left: 20px;
  923. bottom: 75px;
  924. padding: 12px 10px;
  925. border: 2px dotted #00b3c1;
  926. border-radius: 20px;
  927. box-shadow: rgba(14, 30, 37, 0.12) 0px 2px 4px 0px, rgba(14, 30, 37, 0.32) 0px 2px 16px 0px;
  928. background-color: rgba(var(--autoduo-bg), 0.4);
  929. backdrop-filter: blur(4px);
  930. }
  931. .autoduo-animate{
  932. animation: autoduo-control-eff .15s;
  933. }
  934. .autoduo-animate::after{
  935. animation: autoduo-control-border-eff .35s .12s backwards;
  936. }
  937. @keyframes autoduo-control-eff {
  938. from {
  939. transform: scale(.8);
  940. opacity: .5;
  941. }
  942. to {
  943. transform: scale(1);
  944. opacity: 1;
  945. }
  946. }
  947. @keyframes autoduo-control-border-eff {
  948. from {
  949. transform: scale(1);
  950. opacity: 1;
  951. }
  952. to {
  953. transform: scale(1.15);
  954. opacity: 0;
  955. }
  956. }
  957. .control-container-listening::after{
  958. content: '';
  959. position: absolute;
  960. z-index: -1;
  961. inset: 0;
  962. border-radius: inherit;
  963. background-color: transparent;
  964. box-shadow: rgb(104 149 199 / 50%) 0px 0px 0px 5px;
  965. opacity: 0;
  966. }
  967. .auto-container-listening{
  968. width: 250px !important;
  969. }
  970. .setting-overlay-listening {
  971. position: absolute;
  972. inset: 0;
  973. display: flex;
  974. flex-direction: column;
  975. padding: inherit;
  976. padding-bottom: 20px;
  977. border-radius: inherit;
  978. backdrop-filter: inherit;
  979. background-color: rgba(var(--autoduo-bg), 0.8);
  980. animation: setting-overlay-eff 0.4s;
  981. }
  982. @keyframes setting-overlay-eff {
  983. from {
  984. opacity: 0;
  985. transform: perspective(450px) rotateY(-90deg);
  986. }
  987. to {
  988. opacity: 1;
  989. transform: perspective(450px) rotateY(0deg);
  990. }
  991. }
  992. .setting-overlay-listening h3 {
  993. padding: 8px 0 12px 0;
  994. text-align: center;
  995. text-transform: uppercase;
  996. }
  997. .setting-function-listening{
  998. flex-grow: 1;
  999. }
  1000. .setting-function-listening .switch-wrapper-listening {
  1001. margin-bottom: 11px;
  1002. font-weight: bold;
  1003. color: #ff4e00;
  1004. }
  1005. .close-setting-btn-listening {
  1006. width: 80%;
  1007. margin: 0 auto;
  1008. }
  1009. .autoduo-btn {
  1010. display: flex;
  1011. justify-content: center;
  1012. align-items: center;
  1013. position: relative;
  1014. height: 46px;
  1015. margin-bottom: 4px;
  1016. background-color: transparent;
  1017. color: rgb(var(--autoduo-bg));
  1018. border: none;
  1019. border-radius: 16px;
  1020. text-transform: uppercase;
  1021. letter-spacing: 1px;
  1022. font-weight: bold;
  1023. font-size: 15px;
  1024. cursor: pointer;
  1025. user-select: none;
  1026. }
  1027. .autoduo-btn::before {
  1028. content: '';
  1029. position: absolute;
  1030. inset: 0;
  1031. z-index: -1;
  1032. background-color: #1cb0f6;
  1033. color: rgb(25, 132, 183);
  1034. border-radius: inherit;
  1035. box-shadow: 0 4px 0;
  1036. }
  1037. .autoduo-btn:hover {
  1038. filter: brightness(1.1);
  1039. }
  1040. .autoduo-btn:active {
  1041. transform: translateY(4px);
  1042. }
  1043. .autoduo-btn:active::before {
  1044. box-shadow: none;
  1045. }
  1046. .btn-green::before {
  1047. background-color: #58CC02;
  1048. color: rgb(81, 151, 4);
  1049. }
  1050. button.setting-btn-listening {
  1051. width: 100% !important;
  1052. margin-top: 10px;
  1053. }
  1054. button.setting-btn-listening::before {
  1055. background-image: url(https://autoduolingo.click/assets/client/setting.svg);
  1056. background-repeat: no-repeat;
  1057. background-size: 22px;
  1058. background-position: 18px;
  1059. }
  1060. button.auto-farm-btn-listening{
  1061. width: 100% !important;
  1062. margin-top: 8px;
  1063. }
  1064. button.auto-farm-btn-listening::before {
  1065. background-image: url(https://autoduolingo.click/assets/client/xp.svg);
  1066. background-repeat: no-repeat;
  1067. background-size: 32px;
  1068. background-position: 12px;
  1069. }
  1070. button.auto-farm-btn-listening.running::before {
  1071. background-color: #FF4B4B;
  1072. color: rgb(234,43,43);
  1073. }
  1074. .statistic-listening {
  1075. color: rgb(var(--autoduo-color));
  1076. font-size: 18px;
  1077. font-weight: bold;
  1078. }
  1079. .statistic-listening p{
  1080. margin-bottom: 8px;
  1081. }
  1082. .statistic-listening > p::before{
  1083. display: inline-block;
  1084. min-width: 60px;
  1085. }
  1086. .statistic-wrapper-listening{
  1087. display: flex;
  1088. justify-content: space-between;
  1089. margin: 16px 0;
  1090. }
  1091. .time-listening, .total-exp-listening{
  1092. display: flex;
  1093. align-items: center;
  1094. margin-bottom: 0 !important;
  1095. }
  1096. .time-listening::before,
  1097. .total-exp-listening::before{
  1098. content: '';
  1099. width: 21px;
  1100. height: 21px;
  1101. margin-right: 4px;
  1102. background-image: url('https://autoduolingo.click/assets/client/clock.svg');
  1103. background-size: cover;
  1104. }
  1105. .total-exp-listening::before{
  1106. width: 16px;
  1107. height: 21px;
  1108. background-image: url('https://autoduolingo.click/assets/client/exp.svg');
  1109. }
  1110. .total-exp-listening::after{
  1111. content: 'XP';
  1112. margin-left: 4px;
  1113. }
  1114. .update-btn-listening{
  1115. width: 100%;
  1116. margin-top: 8px;
  1117. }
  1118. .update-btn-listening::before{
  1119. background-image: url('https://autoduolingo.click/assets/client/twinkle.ndx');
  1120. background-size: 85px auto;
  1121. }
  1122. .notify-bubble-listening::before {
  1123. background-image: url('https://autoduolingo.click/assets/client/notify-icon-lite.png');
  1124. }
  1125. .super-bubble-listening::before {
  1126. background-image: url('https://autoduolingo.click/assets/client/superfree-icon.png');
  1127. }
  1128. .marketer-bubble-listening::before {
  1129. background-image: url('https://autoduolingo.click/assets/client/m-icon.png'), url('https://autoduolingo.click/assets/client/marketer.webp');
  1130. background-size: cover, 250% !important;
  1131. background-position: center;
  1132. }
  1133. .bubble-container-listening {
  1134. position: fixed;
  1135. z-index: 99999;
  1136. right: 8px;
  1137. bottom: 69px;
  1138. display: flex;
  1139. flex-direction: column;
  1140. }
  1141. .bubble-item-listening + .bubble-item-listening {
  1142. margin-top: 16px;
  1143. }
  1144. .bubble-item-listening {
  1145. position: relative;
  1146. width: 48px;
  1147. height: 48px;
  1148. border-radius: 50%;
  1149. border: 1px solid #ccc;
  1150. background-color: #ffffff40;
  1151. backdrop-filter: blur(4px);
  1152. box-shadow: rgba(0, 0, 0, 0.25) 0px 0.0625em 0.0625em, rgba(0, 0, 0, 0.25) 0px 0.125em 0.5em, rgba(255, 255, 255, 0.1) 0px 0px 0px 1px inset;
  1153. cursor: pointer;
  1154. }
  1155. .bubble-item-listening:hover {
  1156. filter: brightness(0.9);
  1157. }
  1158. .bubble-item-listening::before,
  1159. .bubble-item-listening::after {
  1160. content: '';
  1161. position: absolute;
  1162. inset: 0;
  1163. border-radius: inherit;
  1164. pointer-events: none;
  1165. }
  1166. .bubble-item-listening::before {
  1167. background-size: cover;
  1168. }
  1169. .bubble-item-listening::after {
  1170. display: none;
  1171. border: 1px solid #009febdb;
  1172. box-shadow: 2px 2px 5px #ccc, -2px -2px 5px #ccc;
  1173. animation: notify-border-eff 2s infinite;
  1174. }
  1175. .bubble-item-listening.new {
  1176. animation: notify-eff 2s infinite;
  1177. }
  1178. .bubble-item-listening.new::before {
  1179. animation: notify-bell-eff 2s infinite;
  1180. }
  1181. .bubble-item-listening.new::after {
  1182. display: block;
  1183. }
  1184. @keyframes notify-border-eff {
  1185. 70% {
  1186. transform: scale(1.6);
  1187. opacity: 0.1;
  1188. }
  1189. 100% {
  1190. transform: scale(1.6);
  1191. opacity: 0;
  1192. }
  1193. }
  1194. @keyframes notify-eff {
  1195. 0%, 75%, 100% {
  1196. transform: scale(1);
  1197. }
  1198. 10% {
  1199. transform: scale(1.1);
  1200. }
  1201. }
  1202. @keyframes notify-bell-eff {
  1203. 5%, 15% {
  1204. transform: rotate(25deg);
  1205. }
  1206. 10%, 20% {
  1207. transform: rotate(-25deg);
  1208. }
  1209. 25%, 100% {
  1210. transform: rotate(0deg);
  1211. }
  1212. }
  1213. .signature-listening{
  1214. position: fixed;
  1215. z-index: 99999999;
  1216. top: 4px;
  1217. left: 50%;
  1218. transform: translateX(-50%);
  1219. color: rgb(var(--autoduo-h-color));
  1220. background-color: rgba(255, 255, 255, .5);
  1221. font-style: italic;
  1222. font-size: 15px;
  1223. font-weight: 700;
  1224. padding: 2px 8px;
  1225. border-radius: 8px;
  1226. width: max-content;
  1227. display: flex;
  1228. align-items: center;
  1229. }
  1230. .signature-listening::before{
  1231. content: '';
  1232. width: 50px;
  1233. height: 50px;
  1234. background-image: url(https://autoduolingo.click/assets/client/autoduosuperThumb.ndx);
  1235. background-size: cover;
  1236. margin: -4px 0;
  1237. margin-right: 4px;
  1238. }
  1239. .autoduo-lite-version{
  1240. display: flex;
  1241. justify-content: center;
  1242. margin-top: 2px;
  1243. position: relative;
  1244. font-size: 13px;
  1245. font-style: normal;
  1246. text-align: center;
  1247. }
  1248. .autoduo-upgrade {
  1249. margin-left: 6px;
  1250. margin-top: -4px;
  1251. width: 22px;
  1252. height: 22px;
  1253. border: none;
  1254. background-color: transparent;
  1255. background: url('https://autoduolingo.click/assets/client/upgrade.png');
  1256. background-size: cover;
  1257. transition: transform 0.3s;
  1258. }
  1259. .autoduo-upgrade:hover {
  1260. transform: scale(1.2);
  1261. cursor: pointer;
  1262. }
  1263. .key-type-listening::before,
  1264. .key-expired-listening::before {
  1265. content: var(--data-name);
  1266. }
  1267. .show-hide-listening{
  1268. position: fixed;
  1269. right: 8px;
  1270. top: 50%;
  1271. transform: translateY(-50%);
  1272. z-index: 99999999;
  1273. padding: 0;
  1274. width: 50px;
  1275. height: 50px;
  1276. border-radius: 50%;
  1277. color: rgb(var(--autoduo-h-color));
  1278. background-color: #00DBDE;
  1279. background-image: linear-gradient(90deg, #00DBDE 0%, #FC00FF 100%);
  1280. border: 2px solid currentColor;
  1281. display: flex;
  1282. justify-content: center;
  1283. align-items: center;
  1284. font-size: 32px;
  1285. padding-top: 2px;
  1286. cursor: pointer;
  1287. }
  1288. .show-hide-listening.vip::before{
  1289. content: '';
  1290. position: absolute;
  1291. inset: 0;
  1292. background-image: url('https://autoduolingo.click/assets/client/vipCircle.ndx');
  1293. background-size: cover;
  1294. transform: scale(1.2);
  1295. }
  1296. .show-hide-listening::after{
  1297. content: var(--data-version);
  1298. position: absolute;
  1299. left: 50%;
  1300. bottom: 0;
  1301. transform: translate(-50%, 130%);
  1302. font-size: 15px;
  1303. font-weight: bold;
  1304. }
  1305. .show-hide-listening.older::after{
  1306. text-decoration: line-through;
  1307. }
  1308. .show-hide-listening i {
  1309. position: relative;
  1310. flex-shrink: 0;
  1311. width: 35px;
  1312. height: 35px;
  1313. background-image: url('https://autoduolingo.click/assets/client/eye.svg');
  1314. background-size: cover;
  1315. }
  1316. .show-hide-listening.hide i::after{
  1317. content: '';
  1318. position: absolute;
  1319. top: 50%;
  1320. left: 0;
  1321. width: 110%;
  1322. height: 5px;
  1323. transform: rotate(45deg) translateX(-3px);
  1324. background-color: #c0efff;
  1325. border-radius: 7px;
  1326. }
  1327. .overlay-listening{
  1328. position: fixed;
  1329. inset: 0;
  1330. z-index: 9999
  1331. }
  1332.  
  1333. .switch-wrapper-listening{
  1334. display: flex;
  1335. align-items: center;
  1336. margin-bottom: 8px;
  1337. }
  1338. .switch-wrapper-listening::before{
  1339. content: var(--data-name);
  1340. }
  1341. .switch-wrapper-listening.disable{
  1342. opacity: .4;
  1343. pointer-events: none !important;
  1344. user-select: none !important;
  1345. -ms-user-select: none !important;
  1346. -moz-user-select: none !important;
  1347. -webkit-user-select: none !important;
  1348. }
  1349. .switch-wrapper-listening.unavailable{
  1350. color: #808080;
  1351. }
  1352. .switch-wrapper-listening.unavailable label{
  1353. opacity: .6;
  1354. }
  1355. .switch-container-listening{
  1356. flex-grow: 1;
  1357. display: flex;
  1358. justify-content: space-between;
  1359. align-items: center;
  1360. }
  1361. .switch-info-listening{
  1362. width: 18px;
  1363. height: 18px;
  1364. margin-left: 4px;
  1365. margin-right: 8px;
  1366. border-radius: 50%;
  1367. background-image: url('https://autoduolingo.click/assets/client/infomation-icon.ndx');
  1368. background-size: cover;
  1369. cursor: pointer;
  1370. }
  1371. .switch-info-listening:hover{
  1372. filter: brightness(0.8);
  1373. }
  1374.  
  1375. .switch-wrapper-listening label{
  1376. position: relative;
  1377. width: 46px;
  1378. height: 24px;
  1379. background-color: #bbb;
  1380. box-shadow: rgb(104 149 199 / 50%) 0px 0px 0px 3px;
  1381. border-radius: 20px;
  1382. transition: .2s;
  1383. }
  1384. .switch-wrapper-listening label::after{
  1385. content: '';
  1386. position: absolute;
  1387. left: 2px;
  1388. top: 2px;
  1389. width: 20px;
  1390. height: 20px;
  1391. border-radius: 50%;
  1392. background-color: white;
  1393. transition: .2s;
  1394. }
  1395. .switch-wrapper-listening input:checked + label{
  1396. background-color: #1FC2FF;
  1397. }
  1398. .switch-wrapper-listening input:checked + label::after {
  1399. left: 24px;
  1400. }
  1401. .function-wrapper-listening{
  1402. font-weight: bold;
  1403. font-size: 18px;
  1404. color: #ff4e00;
  1405. }
  1406.  
  1407. .contact-wrapper-listening{
  1408. display: flex;
  1409. justify-content: center;
  1410. flex-wrap: wrap;
  1411. margin: 10px 0 -4px 0;
  1412. }
  1413. .contact-item-listening{
  1414. position: relative;
  1415. width: 34px;
  1416. height: 34px;
  1417. margin: 2px 4px;
  1418. border-radius: 50%;
  1419. background-image: var(--data-img);
  1420. background-size: cover;
  1421. transition: .12s;
  1422. color: rgb(var(--autoduo-color));
  1423. }
  1424. .contact-item-listening:hover{
  1425. box-shadow: rgb(104 149 199 / 50%) 0px 0px 0px 3px;
  1426. transform: scale(1.11);
  1427. }
  1428. .contact-item-listening:hover .popup {
  1429. display: block;
  1430. }
  1431. .contact-item-listening .popup {
  1432. display: none;
  1433. position: absolute;
  1434. bottom: 100%;
  1435. left: 50%;
  1436. transform: translateX(-50%);
  1437. margin-bottom: 12px;
  1438. padding: 2px 6px;
  1439. width: max-content;
  1440. font-size: 12px;
  1441. font-weight: bold;
  1442. border: 1px solid #ccc;
  1443. border-radius: 6px;
  1444. background-color: rgb(var(--autoduo-bg));
  1445. box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px, rgba(60, 64, 67, 0.15) 0px 2px 6px 2px;
  1446. animation: contact-popup-eff 0.2s;
  1447. }
  1448. @keyframes contact-popup-eff {
  1449. from {
  1450. opacity: 0;
  1451. bottom: 50%;
  1452. }
  1453. to {
  1454. opacity: 1;
  1455. bottom: 100%;
  1456. }
  1457. }
  1458. @keyframes contact-popup-update-eff {
  1459. 0%, 100% {
  1460. transform: translateY(3px)
  1461. }
  1462. 50% {
  1463. transform: translateY(-3px)
  1464. }
  1465. }
  1466. @keyframes spin-eff {
  1467. 0% {
  1468. transform: scale(var(--scale)) rotate(0deg);
  1469. }
  1470. 100% {
  1471. transform: scale(var(--scale)) rotate(360deg);
  1472. }
  1473. }
  1474. .contact-item-listening .popup::before{
  1475. content: '';
  1476. position: absolute;
  1477. top: calc(100% - 2px);
  1478. left: 50%;
  1479. transform: translateX(-50%);
  1480. border: 10px solid transparent;
  1481. border-top-color: rgb(var(--autoduo-bg));
  1482.  
  1483. }
  1484. .contact-item-listening.has-update {
  1485. transform: scale(1.11) !important;
  1486. box-shadow: rgb(117 117 117 / 50%) 0px 0px 0px 3px;
  1487. }
  1488. .contact-item-listening.has-update::before {
  1489. content: '';
  1490. --scale: 1.05;
  1491. position: absolute;
  1492. inset: 0;
  1493. border-radius: 50%;
  1494. border: 2px solid white;
  1495. border-top-color: transparent;
  1496. border-bottom-color: transparent;
  1497. animation: spin-eff 1.1s linear infinite;
  1498. }
  1499. .contact-item-listening.has-update .popup{
  1500. display: block !important;
  1501. transform: unset;
  1502. right: -70%;
  1503. left: unset;
  1504. animation: contact-popup-update-eff 1.2s infinite;
  1505. }
  1506. .contact-item-listening.has-update .popup::before {
  1507. left: 75%;
  1508. transform: unset;
  1509. }
  1510. .control-container-listening.vip .contact-item-listening:hover{
  1511. box-shadow: rgb(199 138 217 / 50%) 0px 0px 0px 3px;
  1512. }
  1513. .update-guide-popup {
  1514. position: fixed;
  1515. inset: 0;
  1516. z-index: 99999999;
  1517. display: flex;
  1518. justify-content: center;
  1519. align-items: center;
  1520. background-color: rgba(0, 0, 0, 0.4);
  1521. backdrop-filter: blur(4px);
  1522. box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px;
  1523. animation: popup-overlay-eff 0.25s;
  1524. }
  1525. .guide-popup-main {
  1526. display: flex;
  1527. flex-direction: column;
  1528. width: 480px;
  1529. margin: 4px;
  1530. background-color: #009ee9;
  1531. border: 2px solid #fff;
  1532. border-radius: 20px;
  1533. overflow: hidden;
  1534. animation: popup-main-eff 0.25s;
  1535. }
  1536. .guide-popup-title {
  1537. text-align: center;
  1538. padding: 14px 8px 10px 8px;
  1539. margin: 0;
  1540. color: white;
  1541. font-size: 22px;
  1542. }
  1543. .guide-popup-content {
  1544. flex-grow: 1;
  1545. padding: 20px 16px;
  1546. text-align: justify;
  1547. background-color: rgb(var(--autoduo-bg));
  1548. border-top-left-radius: 18px;
  1549. border-top-right-radius: 18px;
  1550. }
  1551. ..guide-popup-text {
  1552. line-height: 24px;
  1553. color: rgb(var(--autoduo-color));
  1554. margin-bottom: 18px;
  1555. }
  1556. .guide-popup-btn {
  1557. display: flex;
  1558. justify-content: space-between;
  1559. margin-top: 26px;
  1560. }
  1561. .guide-popup-btn .autoduo-btn {
  1562. z-index: 1;
  1563. width: calc(50% - 4px);
  1564. }
  1565. @keyframes popup-overlay-eff {
  1566. from {
  1567. opacity: 0;
  1568. }
  1569. to{
  1570. opacity: 1;
  1571. }
  1572. }
  1573. @keyframes popup-main-eff {
  1574. from {
  1575. transform: scale(0.5);
  1576. }
  1577. to{
  1578. transform: scale(1);
  1579. }
  1580. }
  1581. @media (max-height: 550px) {
  1582. .control-container-listening {
  1583. bottom: 4px;
  1584. }
  1585. }
  1586. @media (max-width: 320px) {
  1587. .guide-popup-btn .autoduo-btn {
  1588. width: 100%;
  1589. margin-top: 4px;
  1590. }
  1591. .guide-popup-btn {
  1592. flex-direction: column-reverse;
  1593. }
  1594. }
  1595. `;
  1596. document.head.appendChild(listenStyle);
  1597. const tm = +notAvailable("MjAw");
  1598. window.boom = (cb) => {
  1599. if (Number.isNaN(tm)) return;
  1600. setTimeout(cb, tm);
  1601. };
  1602. },
  1603.  
  1604. setup: function () {
  1605. this.initStyle();
  1606. this.initSignature();
  1607. this.initContact();
  1608. this.initPopup();
  1609. this.initBtn();
  1610. this.initBubbles();
  1611. this.initStatistics();
  1612. this.initFunctions();
  1613. this.initSetting();
  1614. this.initContainer();
  1615. !isShowUI && this.handleShowHideUI();
  1616. isAnimationOff && this.handleAnimationOff();
  1617. this.renderTime();
  1618. getDataSession("isBasicAuto") && this.start();
  1619. this.autoduoCheckUpdate();
  1620. this.rmNotiVer ? this.setNoti() : this.fetchNoti();
  1621. },
  1622.  
  1623. version: "1.0.8",
  1624. isAuto: false,
  1625. isAutoRunning: false,
  1626. isSafeMode: !!isSafeMode,
  1627. isAnimationOff: !!isAnimationOff,
  1628. goChallengeTm: 500,
  1629. reloadTm: 1800000,
  1630. startTm: null,
  1631. isShowUI: isShowUI === undefined || isShowUI,
  1632. exp: exp || 0,
  1633. totalTime: time || 0,
  1634. practiceHubPath: "/practice-hub",
  1635. listeningPacticePath: "/practice-hub/listening-practice",
  1636. lessonWrapper: "._3js2_",
  1637. reactProps: null,
  1638. dataStateNode: null,
  1639. nativeTextareaValueSetter: Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set,
  1640. isDarkMode: document.documentElement.getAttribute("data-duo-theme") === "dark",
  1641. notifyVersion: +notifyVersion || 0,
  1642. isNewNotify: isNewNotify,
  1643. rmNotiVer: rmNotiVer,
  1644. rmNotiContent: rmNotiContent,
  1645. };
  1646.  
  1647. function timeFormat(ms) {
  1648. const h = String(parseInt(ms / 1000 / 60 / 60));
  1649. const m = String(parseInt((ms / 1000 / 60) % 60));
  1650. return `${h.padStart(2, "0")}h:${m.padStart(2, "0")}m`;
  1651. }
  1652.  
  1653. function notAvailable(str) {
  1654. try {
  1655. return str
  1656. ? atob(str)
  1657. : window.alert(
  1658. "The current functionality is not available! To use this feature, please update to the full version of Auto-Duolingo!"
  1659. );
  1660. } catch (e) {
  1661. autoDuoLite.start = () => {};
  1662. }
  1663. }
  1664.  
  1665. const $ = document.querySelector.bind(document);
  1666. const $$ = document.querySelectorAll.bind(document);
  1667.  
  1668. const arr = (nodeList) => {
  1669. return Array.from(nodeList);
  1670. };
  1671.  
  1672. function getSession() {
  1673. const dataStorage = sessionStorage.getItem(AUTODUOLINGO_STORAGE) || "{}";
  1674. return JSON.parse(dataStorage);
  1675. }
  1676. function setDataSession(key, value) {
  1677. const dataStorage = getSession();
  1678. if (key instanceof Object) {
  1679. Object.assign(dataStorage, key);
  1680. } else {
  1681. dataStorage[key] = value;
  1682. }
  1683. sessionStorage.setItem(AUTODUOLINGO_STORAGE, JSON.stringify(dataStorage));
  1684. }
  1685. function getDataSession(key) {
  1686. const dataStorage = getSession();
  1687. return dataStorage[key];
  1688. }
  1689. function getLocal(STORAGE_KEY) {
  1690. const dataStorage = localStorage.getItem(STORAGE_KEY) || "{}";
  1691. try {
  1692. return JSON.parse(dataStorage);
  1693. } catch (e) {
  1694. return {};
  1695. }
  1696. }
  1697. function setDataLocal(key, value) {
  1698. const dataStorage = getLocal(AUTODUOLINGO_STORAGE);
  1699. dataStorage[key] = value;
  1700. localStorage.setItem(AUTODUOLINGO_STORAGE, JSON.stringify(dataStorage));
  1701. }
  1702.  
  1703. autoDuoLite.setup();
  1704. })();