// ==UserScript== // @name Auto-Duolingo // @version 1.0.1 // @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 // @downloadURL none // ==/UserScript== (() => { const AUTODUOLINGO_STORAGE_KEY = "autoDuolingoStorageKey"; const { isSafeMode, isShowUI, isAnimationOff, exp, time } = getSession(); const autoDuoLite = { version: "1.0.1", 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: "._3FiYg", 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: `
Auto-Duolingo DevX
LITE VERSION
`, }); document.body.appendChild(this.signatureElm); }, createContact: function () { this.contactWrapper = document.createElement("div"); Object.assign(this.contactWrapper, { className: "contact-wrapper-listening", innerHTML: ` `, }); }, createBtn: function () { this.autoBtn = document.createElement("button"); Object.assign(this.autoBtn, { className: "_2N_A5 _36Vd3 _16r-S _108yV 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: "", }); 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: "Auto-Duolingo LITE", }); Object.assign(this.keyExpiredElm, { className: "key-expired-listening", style: `--data-name: "EXP"`, innerHTML: "31/12/2099", }); 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("NAidc", "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("NAidc", "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 = $(".FQpeZ"); if (!challengeTypeElm) { return this.autoduoError("Undefined challenge!!"); } const challengeType = challengeTypeElm.dataset.test?.slice(10); this.setAutoRunning(true); switch (challengeType) { case "challenge-listenTap": this.handleChallengeTranslate(challengeType); 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 (challengeType) { 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 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="_3Lqi-"] button[data-test*="challenge-tap-token"]')); if (options.length === 0) { return setTimeout(this.handleChallengeTranslate.bind(this, challengeType), 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(); }, next: function () { if (!this.isAuto) { return; } const expWrapper = $('[class="_863KE"]'); 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); }, 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; } .auto-farm-btn-listening{ width: 100% !important; margin-top: 4px; } .auto-farm-btn-listening.disable { opacity: 0.8 !important; pointer-events: none !important; user-select: none !important; -ms-user-select: none !important; -moz-user-select: none !important; -webkit-user-select: none !important; } .auto-farm-btn-listening.disable::before{ background-color: #9c9c9c !important; color: #686868 !important; } .auto-farm-btn-listening.turbo.running::before{ background-image: url('https://api.autoduolingo.click/assets/vip.ndx'), url('https://api.autoduolingo.click/assets/thunder.ndx'); background-size: contain, cover; background-position: left, right; } .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{ --web-ui_button-background-color: #e800ff; --web-ui_button-border-color: pink; color: yellow; 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(); })();