- // ==UserScript==
- // @name Auto-Duolingo
- // @version 1.0.2
- // @author DevX
- // @namespace http://tampermonkey.net/
- // @description [Lite Version] Automatically farm experience points, hacking Duolingo is so easy!
- // @match https://*.duolingo.com/*
- // @grant none
- // @license MIT
- // @icon https://api.autoduolingo.click/assets/favicon.ico
- // ==/UserScript==
-
- (() => {
- const AUTODUOLINGO_STORAGE_KEY = "autoDuolingoStorageKey";
- const { isSafeMode, isShowUI, isAnimationOff, exp, time } = getSession();
-
- const autoDuoLite = {
- version: "1.0.2",
- isAuto: false,
- isAutoRunning: false,
- isSafeMode: !!isSafeMode,
- isAnimationOff: !!isAnimationOff,
- goChallengeTm: 500,
- reloadTm: 1800000,
- startTm: null,
- isShowUI: isShowUI === undefined || isShowUI,
- exp: exp || 0,
- totalTime: time || 0,
- practiceHubPath: "/practice-hub",
- listeningPacticePath: "/practice-hub/listening-practice",
- lessonWrapper: "._3js2_",
- reactProps: null,
- dataStateNode: null,
- nativeTextareaValueSetter: Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set,
-
- setup: function () {
- this.createStyle();
- this.createSignature();
- this.createContact();
- this.createBtn();
- this.createStatistics();
- this.createFunctions();
- this.createContainer();
- !isShowUI && this.handleShowHideUI();
- isAnimationOff && this.handleAnimationOff();
- this.renderTime();
- getDataSession("isBasicAuto") && this.start();
- },
-
- createSignature: function () {
- this.signatureElm = document.createElement("div");
- Object.assign(this.signatureElm, {
- className: "signature-listening",
- innerHTML: `
- <div>
- Auto-Duolingo DevX
- <div class="autoduo-lite-version">
- LITE VERSION
- </div>
- </div>
- `,
- });
- document.body.appendChild(this.signatureElm);
- },
-
- createContact: function () {
- this.contactWrapper = document.createElement("div");
- Object.assign(this.contactWrapper, {
- className: "contact-wrapper-listening",
- innerHTML: `<a class="contact-item-listening" href="https://t.me/imdevx" target="_blank" style="--data-img: url('https://api.autoduolingo.click/assets/tele-icon.ndx')"></a>
- <a class="contact-item-listening" href="https://t.me/autoduolingo" target="_blank" style="--data-img: url('https://api.autoduolingo.click/assets/tele-gr-icon.ndx')"></a>
- <a class="contact-item-listening" href="https://zalo.me/g/lmhfps187" target="_blank" style="--data-img: url('https://api.autoduolingo.click/assets/zalo-icon.ndx')"></a>
- <a class="contact-item-listening" href="https://www.youtube.com/@autoduofamily" target="_blank" style="--data-img: url('https://api.autoduolingo.click/assets/youtube-icon.ndx')"></a>
- <a class="contact-item-listening" href="https://gf.qytechs.cn/en/scripts/487867-auto-duolingo" target="_blank" style="--data-img: url('https://api.autoduolingo.click/assets/greasyfork-icon.ndx')"></a>
- `,
- });
- },
-
- createBtn: function () {
- this.autoBtn = document.createElement("button");
- Object.assign(this.autoBtn, {
- className: "_2N_A5 _36Vd3 _16r-S auto-farm-btn-listening",
- innerText: "START FARM XP",
- onclick: () => {
- this.isAuto ? this.stop() : this.start();
- },
- });
-
- this.updateBtn = document.createElement("a");
- Object.assign(this.updateBtn, {
- className: "_2N_A5 _36Vd3 _16r-S update-btn-listening",
- innerText: "Update to the full version",
- target: "_blank",
- onclick: () => {
- this.isAuto && this.stop();
- },
- });
-
- this.showHideBtn = document.createElement("button");
- Object.assign(this.showHideBtn, {
- className: "show-hide-listening",
- style: `--data-version: 'V${this.version}'`,
- innerHTML: "<i></i>",
- });
-
- this.showHideBtn.addEventListener("click", () => {
- this.isShowUI = !this.isShowUI;
- this.handleShowHideUI(true);
- });
- document.body.append(this.showHideBtn);
-
- new Promise((resolve) => {
- setTimeout(
- resolve.bind(window, notAvailable("aHR0cHM6Ly9pbnN0YWxsLmF1dG9kdW9saW5nby5jbGljaw==")),
- 1000
- );
- }).then((res) => (this.updateBtn.href = res));
- },
-
- createStatistics: function () {
- this.statistic = document.createElement("div");
- this.keyTypeElm = document.createElement("p");
- this.keyExpiredElm = document.createElement("p");
- this.expElm = document.createElement("p");
- this.dateElm = document.createElement("p");
- const statisticWrapper = document.createElement("div");
-
- Object.assign(this.keyTypeElm, {
- className: "key-type-listening",
- style: `--data-name: "Type"`,
- innerHTML: "<b style='color: #009feb'>Auto-Duolingo LITE</b>",
- });
- Object.assign(this.keyExpiredElm, {
- className: "key-expired-listening",
- style: `--data-name: "EXP"`,
- innerHTML: "<b style='color: #009feb'>∞</b>",
- });
-
- this.expElm.className = "total-exp-listening";
- this.expElm.innerText = this.exp;
- this.statistic.className = "statistic-listening";
- this.dateElm.className = "time-listening";
- statisticWrapper.className = "statistic-wrapper-listening";
-
- statisticWrapper.append(this.expElm, this.dateElm);
- this.statistic.append(this.keyTypeElm, this.keyExpiredElm, statisticWrapper);
- },
-
- createFunctions: function () {
- this.animationOffWrapper = document.createElement("div");
- this.animationOffWrapper.style = `--data-name: "Hide Animation"`;
- const animationOffInfo =
- "- HIDE ANIMATION MODE:\n" +
- "When this mode is enabled, images and animations on the website will be hidden to optimize performance.";
- this.autoduoCreateSwitch(
- animationOffInfo,
- this.animationOffWrapper,
- 1,
- this.isAnimationOff,
- (setSwitch) => {
- this.isAnimationOff = !this.isAnimationOff;
- this.handleAnimationOff(true);
- setSwitch(this.isAnimationOff);
- }
- );
-
- this.safeModeWrapper = document.createElement("div");
- this.safeModeWrapper.style = `--data-name: "Safe Mode"`;
- const safeModeInfo =
- "- SAFE MODE:\n" +
- "When this mode is enabled, the system will simulate user actions when using auto. The speed will be more relaxed, " +
- "in exchange for the completion time of lessons and the amount of experience will be the most natural, minimizing " +
- "the risks of REPORT and account BAN!";
- this.autoduoCreateSwitch(safeModeInfo, this.safeModeWrapper, 2, this.isSafeMode, () => {
- this.isSafeMode ? this.handleSafeModeOff() : this.handleSafeModeOn();
- });
-
- this.turboModeWrapper = document.createElement("div");
- this.turboModeWrapper.style = `--data-name: "Turbo Mode"`;
- const turboModeInfo =
- "- TURBO MODE:\n" +
- "When enabled, the system will significantly boost the auto speed. It will utilize higher performance and " +
- "is not recommended for use on low-performance devices.\nTurn it off and refresh the page if you encounter " +
- "issues while activating this mode!\n\nNote: This is an experimental feature and requires a VIP Key to use. " +
- "Only enable it when you truly require speed and understand its implications!!";
- this.autoduoCreateSwitch(turboModeInfo, this.turboModeWrapper, 3, false);
-
- this.legendModeWrapper = document.createElement("div");
- this.legendModeWrapper.style = `--data-name: "Lesson Pass Mode"`;
- const legendModeInfo =
- "- LESSON PASS MODE:\n" +
- "When activated, the system won't repeat exercises as in the regular mode but will engage in exercises actively selected by the user. " +
- "This mode is used for legendary exercises, story exercises, and most other similar exercises. You need to enter the lesson you want to " +
- "pass in, and then the system will automatically complete that lesson for you!\n" +
- "When this mode is activated, the basic auto button will be temporarily disabled.";
- this.autoduoCreateSwitch(legendModeInfo, this.legendModeWrapper, 4, false);
-
- this.targetModeWrapper = document.createElement("div");
- this.targetModeWrapper.style = `--data-name: "XP Target Mode"`;
- const targetModeInfo =
- "- EXPERIENCE POINT TARGET MODE:\n" +
- "By setting an experience point target, the system will automatically stop auto mode when the total experience points " +
- "obtained equal or exceed the specified target.\nThis helps you better control the auto function, " +
- "preventing unintentional accumulation of excess experience points due to forgetting to turn off auto mode!\n\n" +
- "- Note: The experience point target must be greater than the current amount of experience points obtained through auto mode!";
- this.autoduoCreateSwitch(targetModeInfo, this.targetModeWrapper, 5, false);
-
- this.passModeWrapper = document.createElement("div");
- this.passModeWrapper.style = `--data-name: "Auto Pass Mode"`;
- const passModeInfo =
- "- AUTO PASS MODE:\n" +
- "By setting the number of lessons you wish to pass, the system will automatically pass the corresponding " +
- "number of new lessons as per the value you've set!\n\n" +
- "- Note: the lesson value should be within the range of 1 - 1000 (Enter 0 for unlimited auto)!";
- this.autoduoCreateSwitch(passModeInfo, this.passModeWrapper, 6, false);
-
- this.functionWrapper = document.createElement("div");
- this.functionWrapper.className = "function-wrapper-listening";
- this.functionWrapper.append(
- this.animationOffWrapper,
- this.safeModeWrapper,
- this.turboModeWrapper,
- this.legendModeWrapper,
- this.passModeWrapper,
- this.targetModeWrapper
- );
- },
-
- createContainer: function () {
- this.autoContainer = document.createElement("div");
- this.autoContainer.className = "auto-container-listening";
- this.autoContainer.append(this.statistic, this.functionWrapper, this.autoBtn, this.updateBtn);
-
- this.overlayContainer = document.createElement("div");
- this.overlayContainer.className = "overlay-listening";
-
- this.controlContainer = document.createElement("div");
- this.controlContainer.className = "control-container-listening";
- this.controlContainer.append(this.autoContainer, this.contactWrapper);
- document.body.append(this.controlContainer);
- },
-
- handleShowHideUI: function (isSave = false) {
- if (this.isShowUI) {
- this.showHideBtn.classList.remove("hide");
- document.body.append(this.controlContainer, this.signatureElm);
- } else {
- this.showHideBtn.classList.add("hide");
- this.controlContainer.remove();
- this.signatureElm.remove();
- }
-
- if (isSave) {
- setDataSession("isShowUI", this.isShowUI);
- this.controlContainer.classList.contains("autoduo-animate") ||
- this.controlContainer.classList.add("autoduo-animate");
- }
- },
-
- handleAnimationOff: function (isSave = false) {
- this.isAnimationOff
- ? document.head.appendChild(this.animationStyle)
- : document.head.removeChild(this.animationStyle);
- isSave && setDataSession("isAnimationOff", this.isAnimationOff);
- },
-
- handleSafeModeOn: function () {
- this.safeModeWrapper.setAutoduoSwitch(this.setSafeMode(true));
- },
-
- handleSafeModeOff: function () {
- this.safeModeWrapper.setAutoduoSwitch(this.setSafeMode(false));
- },
-
- start: function () {
- if (this.isAuto || this.isAutoRunning) {
- return;
- }
-
- document.body.appendChild(this.overlayContainer);
- this.isAuto = true;
- this.autoBtn.classList.add("running");
- this.autoBtn.innerText = "STOP FARM XP";
- setDataSession("isBasicAuto", this.isAuto);
- this.startTm = Date.now();
- this.handleLocation();
- },
-
- stop: function () {
- if (!this.isAuto || this.isLegendMode) {
- return;
- }
- document.body.removeChild(this.overlayContainer);
- this.isAuto = false;
- this.autoBtn.classList.remove("running");
- this.autoBtn.innerText = "START FARM XP";
- setDataSession("isBasicAuto", this.isAuto);
- },
-
- handleLocation: function () {
- if (!this.isAuto) {
- return;
- }
-
- const currentPath = window.location.pathname;
-
- switch (currentPath) {
- case this.practiceHubPath:
- this.goPracticeHubChallenge();
- break;
-
- case this.listeningPacticePath:
- this.handlePracticeHubChallenge();
- break;
-
- default:
- this.autoduoError(
- "Inappropriate location: Only enable auto when on the practice page (with the dumbbell icon) of Duolingo Super!" +
- "\n- Enabling auto on Duolingo Super's practice page will automatically farm listening exercises (20 XP)." +
- "\n- If you want to auto farm practice exercises without needing Super or automatically complete most other exercises, please update to the full version of Auto-Duolingo!"
- );
- break;
- }
- },
-
- goPracticeHubChallenge: function () {
- if (this.isAuto === false) {
- return;
- }
- const challengeBtn = $(
- 'img[src="https://d35aaqx5ub95lt.cloudfront.net/images/practiceHub/2ebe830fd55a7f2754d371bcd79faf32.svg"]'
- );
-
- if (!challengeBtn) {
- setTimeout(this.goPracticeHubChallenge.bind(this), 1000);
- return;
- }
-
- challengeBtn.click();
- setTimeout(this.handlePracticeHubChallenge.bind(this), 1000);
- },
-
- handlePracticeHubChallenge: function () {
- if (window.location.pathname === this.practiceHubPath) {
- this.goPracticeHubChallenge();
- return;
- }
-
- const challengeWrapper = $(this.lessonWrapper);
- if (challengeWrapper) {
- this.getDataStateNode(challengeWrapper);
- this.next();
- return;
- }
- const nextActiveBtn = $('[data-test="player-next"][aria-disabled="false"]');
-
- if (nextActiveBtn) {
- this.next();
- return;
- }
-
- setTimeout(this.handlePracticeHubChallenge.bind(this), 1000);
- },
-
- handleChallenge: async function () {
- if (this.isSafeMode) {
- await this.sleep(500);
- }
- if (!this.isAuto || this.isAutoRunning) {
- return;
- }
-
- const challengeTypeElm = $('[data-test*="challenge challenge"]');
-
- if (!challengeTypeElm) {
- return this.autoduoError("Undefined challenge!!");
- }
-
- const challengeType = challengeTypeElm.dataset.test?.slice(10);
-
- this.setAutoRunning(true);
- switch (challengeType) {
- case "challenge-listenTap":
- this.handleChallengeTranslate();
- break;
-
- case "challenge-gapFill":
- case "challenge-listenIsolation":
- case "challenge-assist":
- case "challenge-selectTranscription":
- case "challenge-characterIntro":
- case "challenge-characterSelect":
- case "challenge-selectPronunciation":
- case "challenge-dialogue":
- case "challenge-readComprehension":
- case "challenge-listenComprehension":
- case "challenge-select":
- case "challenge-form":
- case "challenge-definition":
- case "challenge-sameDifferent":
- this.handleChallengeChoice();
- break;
-
- default:
- this.autoduoError(
- "This exercise is not currently supported in this version. Try updating to the full version of Auto-Duolingo and try again!"
- );
- break;
- }
- },
-
- handleChallengeTranslate: function () {
- if (this.isAuto === false) {
- return;
- }
-
- let data = this.getData("correctTokens");
-
- if (!data?.length) {
- data = this.getData(["challengeResponseTrackingProperties", "best_solution"])?.split(" ");
- }
-
- if (!data) {
- return this.autoduoError("Lesson data not found.");
- }
-
- const textArea = $('textarea[data-test="challenge-translate-input"]:not([disabled])');
- if (textArea) {
- const toggleKeyboard = $('[data-test="player-toggle-keyboard"]');
- if (toggleKeyboard) {
- toggleKeyboard.click();
- return setTimeout(this.handleChallengeTranslate.bind(this), 500);
- }
-
- const inputEvent = new Event("input", {
- bubbles: true,
- });
-
- let answer = "";
-
- const inputCaseHandler = () => {
- setTimeout(() => {
- if (data.length === 0) {
- this.setAutoRunning(false);
- this.next(true);
- return;
- }
-
- answer += " " + data.shift();
- this.nativeTextareaValueSetter.call(textArea, answer);
- textArea.dispatchEvent(inputEvent);
- inputCaseHandler();
- }, this.rmSafeDelayTm());
- };
- inputCaseHandler();
- return;
- }
-
- let options = arr($$('[class="_1vkDo"] button[data-test*="challenge-tap-token"]'));
- if (options.length === 0) {
- return setTimeout(this.handleChallengeTranslate.bind(this), 500);
- }
-
- const getIndexOfOption = (targetData) => {
- const index = options.findIndex((option) => option.textContent === targetData);
- return index;
- };
-
- const selectCaseHandler = () => {
- setTimeout(() => {
- if (data.length === 0) {
- this.setAutoRunning(false);
- this.next(true);
- return;
- }
-
- const firstValue = data.shift();
- const index = getIndexOfOption(firstValue);
-
- if (index === -1) {
- return this.autoduoLessonError("No suitable option found.");
- }
-
- options[index].click();
- options.splice(index, 1);
- selectCaseHandler();
- }, this.rmSafeDelayTm());
- };
- selectCaseHandler();
- },
-
- handleChallengeChoice: function () {
- if (!this.isAuto) {
- return;
- }
-
- const optionElm = $$('[data-test="challenge-choice"]');
- const correctIndex = this.getData("correctIndex");
-
- if (correctIndex === null) {
- return this.autoduoError("Lesson data not found.");
- }
-
- setTimeout(() => {
- optionElm[correctIndex].click();
- setTimeout(() => {
- this.setAutoRunning(false);
- this.next();
- }, this.rmSafeDelayTm());
- }, this.rmSafeDelayTm());
- },
-
- next: function () {
- if (!this.isAuto) {
- return;
- }
-
- const expWrapper = $('[class="i6eR4"]');
- if (expWrapper) {
- const exp = this.getExp(expWrapper);
-
- if (exp !== undefined) {
- this.exp += exp;
- this.expElm.innerText = this.exp;
-
- const timeNow = Date.now();
- const finishTime = timeNow - this.startTm;
- this.totalTime += finishTime;
- this.startTm = timeNow;
- this.renderTime();
-
- setDataSession("exp", this.exp);
- setDataSession("time", this.totalTime);
-
- const currentPath = window.location.pathname;
- if (currentPath === this.listeningPacticePath) {
- if ((this.totalReloadTime += finishTime) >= this.reloadTm) {
- window.location.reload();
- return;
- }
- }
- }
- }
-
- const nextBtn = $('[data-test="player-next"]');
-
- if (!nextBtn) {
- setTimeout(this.handleLocation.bind(this), this.goChallengeTm);
- return;
- }
-
- const isDisable = nextBtn.getAttribute("aria-disabled");
- const isLoadingBtn = nextBtn.classList.contains("_3CBig");
-
- if (isDisable === "true" && !isLoadingBtn) {
- boom(this.handleChallenge.bind(this));
- return;
- }
-
- !isLoadingBtn && nextBtn.click();
- boom(this.next.bind(this));
- },
-
- findReactProps: function (wrapperElm) {
- this.reactProps = Object.keys(wrapperElm).find((key) => key.startsWith("__reactProps"));
-
- if (!this.reactProps) {
- return this.autoduoError("ERROR");
- }
- },
-
- getDataStateNode: function (wrapperElm) {
- this.reactProps === null && this.findReactProps(wrapperElm);
- const childrenData = wrapperElm?.[this.reactProps]?.children;
-
- if (Array.isArray(childrenData)) {
- this.dataStateNode = childrenData?.[0]?._owner?.stateNode;
- } else {
- this.dataStateNode = childrenData?._owner?.stateNode;
- }
- },
-
- getData: function (subGenealogy) {
- const currentChallenge = this.dataStateNode?.props?.currentChallenge;
- if (!currentChallenge) {
- return this.autoduoError("There was an error while loading challenge data!");
- }
-
- if (Array.isArray(subGenealogy)) {
- const result = subGenealogy.reduce((acc, currentKey) => {
- if (acc === null) {
- return null;
- }
-
- const currentValue = acc[currentKey];
- return currentValue || null;
- }, currentChallenge);
-
- if (result === null) {
- return this.autoduoError("There was an error while getting the data!");
- }
-
- return Array.isArray(result) ? [...result] : result;
- } else {
- const result = currentChallenge[subGenealogy];
- return Array.isArray(result) ? [...result] : result;
- }
- },
-
- getExp: function (expWrapper) {
- const keys = Object.keys(expWrapper);
- const key = keys.find((key) => key.startsWith("__reactProps"));
-
- const exp = expWrapper?.[key]?.children?.props?.slide?.xpGoalSessionProgress?.totalXpThisSession;
- return exp;
- },
-
- renderTime: function () {
- const timeString = timeFormat(this.totalTime);
- this.dateElm.innerText = timeString;
- },
-
- setAutoRunning: function (isRunning) {
- this.isAutoRunning = isRunning;
- },
-
- setSafeMode: function (isSafeMode) {
- this.isSafeMode = isSafeMode;
- setDataSession("isSafeMode", isSafeMode);
- return isSafeMode;
- },
-
- rmSafeDelayTm: function () {
- if (!this.isSafeMode) {
- return 0;
- }
-
- return Math.floor(Math.random() * 550 + 50);
- },
-
- sleep: async function (time) {
- await new Promise((resolve) => setTimeout(resolve, time));
- },
-
- autoduoError: function (message) {
- this.isAutoRunning && this.setAutoRunning(false);
- this.isAuto && this.stop();
- alert("ERROR: " + message + ". Try updating to the full version if this issue persists!");
- },
-
- autoduoLessonError: function (errorText) {
- const settingIcon = $("._7X9XV");
- if (settingIcon) {
- settingIcon.click();
-
- return setTimeout(() => {
- this.autoduoError(
- `${errorText}. If you are currently displaying the pronunciation guide, please turn it off first, then reload the page, and finally turn on auto again!`
- );
- }, 800);
- }
- return this.autoduoError(errorText);
- },
-
- autoduoCreateSwitch: function (descriptionText = "", wrapperElm, id, isChecked, handleSwitch) {
- const infoElm = document.createElement("i");
- Object.assign(infoElm, {
- className: "switch-info-listening",
- title: "Detail",
- onclick: () => {
- alert(descriptionText);
- },
- });
-
- const checkboxElm = document.createElement("input");
- Object.assign(checkboxElm, {
- type: "checkbox",
- hidden: true,
- checked: isChecked,
- });
-
- const setSwitch = (isEnable) => {
- checkboxElm.checked = isEnable;
- };
-
- const labelElm = document.createElement("label");
- labelElm.addEventListener("click", () => {
- id > 2 ? notAvailable() : handleSwitch(setSwitch);
- });
-
- const switchContainer = document.createElement("div");
- switchContainer.className = "switch-container-listening";
- switchContainer.append(infoElm, checkboxElm, labelElm);
-
- wrapperElm.classList.add("switch-wrapper-listening");
- if ([3, 4, 5, 6].includes(id)) {
- wrapperElm.classList.add("unavailable");
- }
- wrapperElm.append(switchContainer);
- wrapperElm.setAutoduoSwitch = setSwitch;
- },
-
- createStyle: function () {
- this.animationStyle = document.createElement("style");
- this.animationStyle.innerHTML = `
- img, svg, canvas {
- visibility: hidden !important;
- }
- div:not(.autoduo-animate) {
- transition: none !important;
- animation-duration: 0s !important;
- }
- .fSJFz {
- display: none !important;
- }
- `;
-
- const listenStyle = document.createElement("style");
- listenStyle.innerHTML = `
- .control-container-listening{
- position: fixed;
- z-index: 9999999;
- left: 20px;
- bottom: 75px;
- padding: 12px 10px;
- border: 2px dotted #00b3c1;
- border-radius: 20px;
- box-shadow: rgba(14, 30, 37, 0.12) 0px 2px 4px 0px, rgba(14, 30, 37, 0.32) 0px 2px 16px 0px;
- background-color: rgba(var(--color-snow), 0.4);
- backdrop-filter: blur(4px);
- }
- .autoduo-animate{
- animation: autoduo-control-eff .15s;
- }
- .autoduo-animate::after{
- animation: autoduo-control-border-eff .35s .12s backwards;
- }
- @keyframes autoduo-control-eff {
- from {
- transform: scale(.8);
- opacity: .5;
- }
- to {
- transform: scale(1);
- opacity: 1;
- }
- }
- @keyframes autoduo-control-border-eff {
- from {
- transform: scale(1);
- opacity: 1;
- }
- to {
- transform: scale(1.15);
- opacity: 0;
- }
- }
- .control-container-listening::after{
- content: '';
- position: absolute;
- z-index: -1;
- inset: 0;
- border-radius: inherit;
- background-color: transparent;
- box-shadow: rgb(104 149 199 / 50%) 0px 0px 0px 5px;
- opacity: 0;
- }
-
- .auto-container-listening{
- width: 250px !important;
- }
- button.auto-farm-btn-listening{
- width: 100% !important;
- margin-top: 4px;
- }
- button.auto-farm-btn-listening::before {
- background-color: #58CC02;
- color: rgb(88,167,0);
- }
- button.auto-farm-btn-listening.running::before {
- background-color: #FF4B4B;
- color: rgb(234,43,43);
- }
- .statistic-listening {
- color: rgb(var(--color-black-text));
- font-size: 18px;
- font-weight: bold;
- }
- .statistic-listening p{
- margin-bottom: 8px;
- }
- .statistic-listening > p::before{
- display: inline-block;
- min-width: 60px;
- }
- .statistic-wrapper-listening{
- display: flex;
- justify-content: space-between;
- margin: 14px 0;
- }
- .time-listening, .total-exp-listening{
- display: flex;
- align-items: center;
- margin-bottom: 0 !important;
- }
- .time-listening::before,
- .total-exp-listening::before{
- content: '';
- width: 21px;
- height: 21px;
- margin-right: 4px;
- background-image: url('https://api.autoduolingo.click/assets/clock.svg');
- background-size: cover;
- }
- .total-exp-listening::before{
- width: 16px;
- height: 21px;
- background-image: url('https://api.autoduolingo.click/assets/exp.svg');
- }
-
- .total-exp-listening::after{
- content: 'XP';
- margin-left: 4px;
- }
-
- .update-btn-listening{
- width: 100%;
- margin-top: 4px;
- }
- .update-btn-listening::before{
- background-image: url('https://api.autoduolingo.click/assets/twinkle.ndx');
- background-size: 85px auto;
- }
- .signature-listening{
- position: fixed;
- z-index: 99999999;
- top: 4px;
- left: 50%;
- transform: translateX(-50%);
- color: #aa00b0;
- background-color: rgba(255, 255, 255, .5);
- font-style: italic;
- font-size: 15px;
- font-weight: 700;
- padding: 2px 8px;
- border-radius: 8px;
- width: max-content;
- display: flex;
- align-items: center;
- }
- .signature-listening::before{
- content: '';
- width: 50px;
- height: 50px;
- background-image: url(https://api.autoduolingo.click/assets/autoduosuperThumb.ndx);
- background-size: cover;
- margin: -4px 0;
- margin-right: 4px;
- }
- .autoduo-lite-version{
- position: relative;
- font-size: 13px;
- font-style: normal;
- text-align: center;
- }
- .key-type-listening::before,
- .key-expired-listening::before {
- content: var(--data-name);
- }
- .show-hide-listening{
- position: fixed;
- right: 8px;
- top: 50%;
- transform: translateY(-50%);
- z-index: 999999999;
- width: 50px;
- height: 50px;
- border-radius: 50%;
- background-color: #00DBDE;
- background-image: linear-gradient(90deg, #00DBDE 0%, #FC00FF 100%);
- border-color: #b800c8;
-
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 32px;
- padding-top: 2px;
- cursor: pointer;
- }
- .show-hide-listening.vip::before{
- content: '';
- position: absolute;
- inset: 0;
- background-image: url('https://api.autoduolingo.click/assets/vipCircle.ndx');
- background-size: cover;
- transform: scale(1.2);
- }
- .show-hide-listening::after{
- content: var(--data-version);
- position: absolute;
- left: 50%;
- bottom: 0;
- transform: translate(-50%, 130%);
- font-size: 15px;
- font-weight: bold;
- color: #b800c8;
- }
- .show-hide-listening.older::after{
- text-decoration: line-through;
- }
- .show-hide-listening i {
- position: relative;
- flex-shrink: 0;
- width: 35px;
- height: 35px;
- background-image: url('https://api.autoduolingo.click/assets/eye.svg');
- background-size: cover;
- }
- .show-hide-listening.hide i::after{
- content: '';
- position: absolute;
- top: 50%;
- left: 0;
- width: 110%;
- height: 5px;
- transform: rotate(45deg) translateX(-3px);
- background-color: #c0efff;
- border-radius: 7px;
- }
- .overlay-listening{
- position: fixed;
- inset: 0;
- z-index: 9999
- }
-
- .switch-wrapper-listening{
- display: flex;
- align-items: center;
- margin-bottom: 8px;
- }
- .switch-wrapper-listening::before{
- content: var(--data-name);
- }
- .switch-wrapper-listening.disable{
- opacity: .4;
- pointer-events: none !important;
- user-select: none !important;
- -ms-user-select: none !important;
- -moz-user-select: none !important;
- -webkit-user-select: none !important;
- }
- .switch-wrapper-listening.unavailable{
- color: #808080;
- }
- .switch-wrapper-listening.unavailable label{
- opacity: .6;
- }
- .switch-container-listening{
- flex-grow: 1;
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .switch-info-listening{
- width: 18px;
- height: 18px;
- margin-left: 4px;
- margin-right: 8px;
- border-radius: 50%;
- background-image: url('https://api.autoduolingo.click/assets/infomation-icon.ndx');
- background-size: cover;
- cursor: pointer;
- }
- .switch-info-listening:hover{
- filter: brightness(0.8);
- }
-
- .switch-wrapper-listening label{
- position: relative;
- width: 46px;
- height: 24px;
- background-color: #bbb;
- box-shadow: rgb(104 149 199 / 50%) 0px 0px 0px 3px;
- border-radius: 20px;
- transition: .2s;
- }
-
- .switch-wrapper-listening label::after{
- content: '';
- position: absolute;
- left: 2px;
- top: 2px;
- width: 20px;
- height: 20px;
- border-radius: 50%;
- background-color: white;
- transition: .2s;
- }
- .switch-wrapper-listening input:checked + label{
- background-color: #1FC2FF;
- }
- .switch-wrapper-listening input:checked + label::after {
- left: 24px;
- }
-
- .function-wrapper-listening{
- font-weight: bold;
- font-size: 18px;
- color: #ff4e00;
- }
-
- .contact-wrapper-listening{
- display: flex;
- justify-content: center;
- flex-wrap: wrap;
- margin: 8px 0 -4px 0;
- }
- .contact-item-listening{
- width: 34px;
- height: 34px;
- margin: 2px 4px;
- border-radius: 50%;
- background-image: var(--data-img);
- background-size: cover;
- transition: .18s;
- }
- .contact-item-listening:hover{
- box-shadow: rgb(104 149 199 / 50%) 0px 0px 0px 3px;
- transform: scale(1.11);
- }
- .control-container-listening.vip .contact-item-listening:hover{
- box-shadow: rgb(199 138 217 / 50%) 0px 0px 0px 3px;
- }
-
- @media (max-height: 550px) {
- .control-container-listening {
- bottom: 4px;
- }
- }
- `;
- document.head.appendChild(listenStyle);
- const tm = +notAvailable("MjAw");
- window.boom = (cb) => {
- if (Number.isNaN(tm)) return;
- setTimeout(cb, tm);
- };
- },
- };
-
- function timeFormat(ms) {
- const h = String(parseInt(ms / 1000 / 60 / 60));
- const m = String(parseInt((ms / 1000 / 60) % 60));
- return `${h.padStart(2, "0")}h:${m.padStart(2, "0")}m`;
- }
-
- function notAvailable(str) {
- try {
- return str
- ? atob(str)
- : window.alert(
- "The current functionality is not available! To use this feature, please update to the full version of Auto-Duolingo!"
- );
- } catch (e) {
- autoDuoLite.start = () => {};
- }
- }
-
- const $ = document.querySelector.bind(document);
- const $$ = document.querySelectorAll.bind(document);
-
- const arr = (nodeList) => {
- return Array.from(nodeList);
- };
-
- function getSession() {
- const dataStorage = sessionStorage.getItem(AUTODUOLINGO_STORAGE_KEY) || "{}";
- return JSON.parse(dataStorage);
- }
- function setDataSession(key, value) {
- const dataStorage = getSession();
- dataStorage[key] = value;
- sessionStorage.setItem(AUTODUOLINGO_STORAGE_KEY, JSON.stringify(dataStorage));
- }
- function getDataSession(key) {
- const dataStorage = getSession();
- return dataStorage[key];
- }
-
- // SETUP AUTO
- autoDuoLite.setup();
- })();