// ==UserScript==
// @name Duolingo SM
// @version 2.1.0
// @author MeowWoof
// @namespace http://tampermonkey.net/
// @description DuolingoSM helps you enhance your Duolingo experience with advanced features
// @match https://*.duolingo.com/*
// @grant none
// @license MIT
// @icon https://d35aaqx5ub95lt.cloudfront.net/vendor/a0ee30fa22ca3d00e9e5db913b1965b5.svg
// ==/UserScript==
(function() {
'use strict';
// Đừng đọc code bạn ơi DITME =(((
const sessionUrl = "https://www.duolingo.com/2017-06-30/sessions";
let isFarming = false, isVisible = true;
let currentLanguage = "en";
const getJwtToken = () => document.cookie.split(';').find(c => c.trim().startsWith('jwt_token='))?.split('=')[1] || null;
const decodeJwtToken = token => JSON.parse(atob(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));
const formatHeaders = jwtToken => ({ "Content-Type": "application/json", "Authorization": `Bearer ${jwtToken}`, "User-Agent": navigator.userAgent });
const getUserInfo = async (sub, headers) => (await fetch(`https://www.duolingo.com/2017-06-30/users/${sub}?fields=username,fromLanguage,learningLanguage`, { headers })).json();
const farmXp = async (headers, sessionPayload, updateSessionPayload) => {
while (isFarming) {
try {
const session = await (await fetch(sessionUrl, { method: 'POST', headers, body: JSON.stringify(sessionPayload) })).json();
const updatedSession = await (await fetch(`${sessionUrl}/${session.id}`, { method: 'PUT', headers, body: JSON.stringify({ ...session, ...updateSessionPayload }) })).json();
document.getElementById("_xpAmount").innerText = parseInt(document.getElementById("_xpAmount").innerText) + updatedSession.xpGain;
} catch (error) {
alert(currentLanguage === "en" ? "An error occurred while farming XP. Please try again!" : "Đã xảy ra lỗi khi farm XP. Vui lòng thử lại!");
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
};
const translations = {
en: {
title: "DuolingoSM",
welcome: "Welcome to SuperDuolingo!",
notLoggedIn: "You are not logged in! (if you are logged in, please refresh the page)",
hello: "Hello",
farmXp: "FARM XP",
farmGems: "FARM GEMS",
upgrade: "UPGRADE TO PRO",
start: "Start",
stop: "Stop",
xpGained: "XP Gained",
warning: "Please use this tool responsibly.",
loading: "Processing...",
switchLang: "Tiếng Việt"
},
vi: {
title: "Super-Duo",
welcome: "Chào mừng đến với SuperDuolingo!",
notLoggedIn: "Bạn chưa đăng nhập! (nếu bạn đã đăng nhập, vui lòng tải lại trang)",
hello: "Xin chào",
farmXp: "FARM XP",
farmGems: "FARM GEMS",
upgrade: "NÂNG CẤP PRO",
start: "Bắt đầu",
stop: "Dừng lại",
xpGained: "XP Đã Nhận",
warning: "Vui lòng sử dụng công cụ này một cách có trách nhiệm.",
loading: "Đang xử lý...",
switchLang: "English"
}
};
const initSuperDuolingo = async () => {
const style = document.createElement('style');
style.innerHTML = `
:root {
--primary: #141436;
--secondary: #00e2c3;
--accent: #ff7e47;
--light: #ffffff;
--dark: #0f0f28;
--darker: #070718;
--gradient-primary: linear-gradient(135deg, #00e2c3 0%, #00b8d4 50%, #0091ea 100%);
--gradient-accent: linear-gradient(135deg, #ff7e47 0%, #ff5252 100%);
--gradient-dark: linear-gradient(135deg, #141436 0%, #0f0f28 100%);
--glass: rgba(255, 255, 255, 0.08);
--glass-dark: rgba(15, 15, 40, 0.65);
--border: rgba(255, 255, 255, 0.18);
--border-glow: rgba(0, 226, 195, 0.3);
--shadow-sm: 0 4px 6px rgba(0, 0, 0, 0.1);
--shadow-md: 0 10px 20px rgba(0, 0, 0, 0.15);
--shadow-lg: 0 15px 30px rgba(0, 0, 0, 0.25);
--shadow-xl: 0 20px 40px rgba(0, 0, 0, 0.3);
--shadow-inner: inset 0 2px 6px rgba(0, 0, 0, 0.15);
--shadow-glow: 0 0 20px rgba(0, 226, 195, 0.25);
--text-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
--text-glow: 0 0 10px rgba(0, 226, 195, 0.5);
--transition-fast: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
--transition-bounce: all 0.5s cubic-bezier(0.17, 0.89, 0.32, 1.49);
}
._sd_container {
position: fixed;
right: 24px;
top: 240px;
width: 320px;
background: var(--dark);
background-image:
radial-gradient(circle at top right, rgba(0, 226, 195, 0.1), transparent 80%),
radial-gradient(circle at bottom left, rgba(255, 126, 71, 0.05), transparent 70%);
border-radius: 16px;
box-shadow:
var(--shadow-xl),
0 0 0 1px var(--border),
0 0 40px rgba(0, 226, 195, 0.15);
z-index: 9999;
overflow: hidden;
transition: transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.4s;
backdrop-filter: blur(10px);
transform-origin: top left;
}
._sd_container::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background:
linear-gradient(
to right,
transparent,
rgba(255, 255, 255, 0.03),
transparent
);
transform: rotate(45deg);
animation: _sd_light_sweep 8s infinite linear;
pointer-events: none;
}
._sd_container::after {
content: '';
position: absolute;
inset: 0;
border-radius: 16px;
padding: 1px;
background: linear-gradient(135deg, var(--secondary), transparent 50%, var(--accent));
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
pointer-events: none;
}
._sd_container.hidden {
transform: translateY(-120%) scale(0.95);
opacity: 0;
}
._sd_header {
background: var(--gradient-dark);
padding: 20px;
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border);
box-shadow: var(--shadow-inner);
overflow: hidden;
}
._sd_header::before {
content: '';
position: absolute;
right: -20px;
top: -20px;
width: 100px;
height: 100px;
background: radial-gradient(circle, rgba(0, 226, 195, 0.15), transparent 70%);
border-radius: 50%;
filter: blur(8px);
pointer-events: none;
}
._sd_title {
font-size: 1.25rem;
font-weight: 800;
color: var(--secondary);
margin: 0;
letter-spacing: 1.5px;
text-shadow: var(--text-shadow);
position: relative;
display: inline-block;
background: linear-gradient(to right, var(--secondary), #64ffda);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.3));
}
._sd_title::after {
content: '';
position: absolute;
left: 0;
bottom: -4px;
width: 50%;
height: 2px;
background: var(--gradient-primary);
border-radius: 2px;
transition: var(--transition);
}
._sd_body {
padding: 24px;
background: var(--dark);
position: relative;
z-index: 1;
}
._sd_welcome {
font-size: 0.95rem;
color: var(--light);
margin-bottom: 20px;
opacity: 0.95;
line-height: 1.6;
border-left: 3px solid var(--secondary);
padding: 14px 16px;
background: var(--glass);
border-radius: 0 12px 12px 0;
box-shadow: var(--shadow-sm);
position: relative;
overflow: hidden;
}
._sd_welcome::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 3px;
height: 100%;
background: var(--gradient-primary);
opacity: 0.8;
animation: _sd_pulse 2s infinite;
}
._sd_tabs {
display: flex;
flex-direction: column;
gap: 12px;
margin-bottom: 28px;
position: relative;
}
._sd_tabs::after {
content: '';
position: absolute;
bottom: -14px;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(to right, transparent, var(--border), transparent);
}
._sd_tab {
padding: 14px 18px;
border-radius: 12px;
background: rgba(20, 20, 54, 0.6);
color: var(--light);
cursor: pointer;
transition: var(--transition-bounce);
font-weight: 600;
font-size: 0.95rem;
border-left: 3px solid transparent;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: var(--shadow-sm);
backdrop-filter: blur(4px);
position: relative;
overflow: hidden;
}
._sd_tab::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.03));
opacity: 0;
transition: var(--transition);
}
._sd_tab:hover::before {
opacity: 1;
}
._sd_tab.active {
color: var(--accent);
border-left: 3px solid var(--accent);
background: rgba(42, 42, 96, 0.8);
box-shadow:
var(--shadow-md),
0 0 0 1px rgba(255, 126, 71, 0.2),
0 0 15px rgba(255, 126, 71, 0.1);
transform: translateX(5px);
}
._sd_tab:hover:not(.active) {
background: rgba(42, 42, 96, 0.5);
transform: translateX(5px);
box-shadow:
var(--shadow-md),
0 0 0 1px rgba(255, 255, 255, 0.1);
}
._sd_tab::after {
content: "›";
opacity: 0;
transform: translateX(-10px);
transition: var(--transition);
font-size: 1.4rem;
text-shadow: var(--text-shadow);
}
._sd_tab:hover::after {
opacity: 0.7;
transform: translateX(0);
}
._sd_tab.active::after {
content: "›";
opacity: 1;
transform: translateX(0);
color: var(--accent);
}
._sd_farm_controls {
display: grid;
grid-template-columns: 1fr;
gap: 18px;
position: relative;
}
._sd_start_btn {
padding: 16px;
background: var(--gradient-primary);
border: none;
border-radius: 12px;
color: var(--light);
font-weight: 700;
cursor: pointer;
transition: var(--transition-bounce);
width: 100%;
font-size: 1rem;
text-transform: uppercase;
letter-spacing: 2px;
box-shadow:
var(--shadow-lg),
0 0 20px rgba(0, 226, 195, 0.2);
position: relative;
overflow: hidden;
text-shadow: var(--text-shadow);
}
._sd_start_btn::before {
content: "";
position: absolute;
top: -10px;
left: -100%;
width: 100%;
height: 200%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.3),
transparent
);
transform: rotate(25deg);
transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
._sd_start_btn:hover::before {
left: 200%;
transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
._sd_start_btn:hover {
transform: translateY(-3px);
box-shadow:
var(--shadow-xl),
0 0 30px rgba(0, 226, 195, 0.4);
background-image: linear-gradient(135deg, #00e2c3 0%, #00cbde 50%, #00a6ea 100%);
letter-spacing: 2.5px;
}
._sd_start_btn:active {
transform: translateY(1px);
box-shadow:
var(--shadow-sm),
0 0 10px rgba(0, 226, 195, 0.4);
background-image: linear-gradient(135deg, #00cbb0 0%, #00b8c9 50%, #0091d1 100%);
}
._sd_start_btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
box-shadow: none;
filter: grayscale(0.8);
}
._sd_toggle_btn {
position: fixed;
left: 24px;
bottom: 24px;
width: 54px;
height: 54px;
border-radius: 14px;
background: var(--gradient-primary);
border: none;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
z-index: 10000;
transition: var(--transition-bounce);
color: var(--light);
font-weight: bold;
font-size: 1.5rem;
box-shadow:
var(--shadow-lg),
0 0 20px rgba(0, 226, 195, 0.3);
text-shadow: var(--text-shadow);
overflow: hidden;
}
._sd_toggle_btn::before {
content: "";
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.2), transparent 70%);
opacity: 0;
transition: var(--transition);
pointer-events: none;
}
._sd_toggle_btn:hover::before {
opacity: 1;
transform: scale(0.5);
}
._sd_toggle_btn:hover {
transform: scale(1.15) rotate(5deg);
box-shadow:
var(--shadow-xl),
0 0 30px rgba(0, 226, 195, 0.5);
}
._sd_toggle_btn:active {
transform: scale(0.95);
}
._sd_overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(7, 7, 24, 0.85);
backdrop-filter: blur(10px);
display: none;
align-items: center;
justify-content: center;
z-index: 9999;
animation: _sd_fadeIn 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
._sd_modal {
background: var(--primary);
border-left: 5px solid var(--secondary);
border-radius: 14px;
padding: 35px;
width: 90%;
max-width: 450px;
animation: _sd_slideIn 0.6s cubic-bezier(0.17, 0.89, 0.32, 1.49);
box-shadow:
var(--shadow-xl),
0 0 0 1px var(--border),
0 0 40px rgba(0, 226, 195, 0.15);
position: relative;
overflow: hidden;
}
._sd_modal::before {
content: '';
position: absolute;
inset: 0;
border-radius: 14px;
padding: 1px;
background: linear-gradient(135deg, var(--secondary), transparent 50%, var(--accent));
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
pointer-events: none;
}
._sd_modal::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
radial-gradient(circle at top right, rgba(0, 226, 195, 0.1), transparent 70%),
radial-gradient(circle at bottom left, rgba(255, 126, 71, 0.05), transparent 70%);
pointer-events: none;
}
._sd_modal_title {
font-size: 1.8rem;
font-weight: 800;
margin-bottom: 28px;
background: linear-gradient(to right, var(--secondary), #64ffda);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-transform: uppercase;
letter-spacing: 2px;
filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.3));
position: relative;
display: inline-block;
}
._sd_modal_title::after {
content: "";
position: absolute;
left: 0;
bottom: -8px;
width: 60px;
height: 3px;
background: var(--gradient-primary);
border-radius: 3px;
}
._sd_spinner {
display: inline-block;
width: 80px;
height: 80px;
margin: 30px auto;
position: relative;
}
._sd_spinner::before {
content: '';
position: absolute;
inset: -5px;
border-radius: 50%;
background: rgba(0, 226, 195, 0.05);
box-shadow: 0 0 30px rgba(0, 226, 195, 0.3);
animation: _sd_pulse 2s infinite;
}
._sd_spinner:after {
content: " ";
display: block;
width: 64px;
height: 64px;
margin: 8px;
border-radius: 50%;
border: 4px solid transparent;
border-top: 4px solid var(--secondary);
border-right: 4px solid var(--accent);
border-bottom: 4px solid var(--secondary);
border-left: 4px solid var(--accent);
animation: _sd_spin 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
box-shadow: 0 0 10px rgba(0, 226, 195, 0.2);
}
._sd_xp_info {
font-size: 1rem;
background: linear-gradient(to right, var(--accent), #ffae70);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 30px 0;
font-weight: 800;
letter-spacing: 1.5px;
filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.3));
text-align: center;
position: relative;
}
._sd_xp_info::before {
content: '';
position: absolute;
top: -15px;
left: 50%;
transform: translateX(-50%);
width: 100px;
height: 2px;
background: linear-gradient(to right, transparent, var(--accent), transparent);
}
._sd_xp_info::after {
content: '';
position: absolute;
bottom: -15px;
left: 50%;
transform: translateX(-50%);
width: 100px;
height: 2px;
background: linear-gradient(to right, transparent, var(--accent), transparent);
}
._sd_warning {
font-size: 0.95rem;
color: var(--light);
opacity: 0.85;
margin-bottom: 28px;
line-height: 1.7;
border-left: 3px solid var(--accent);
padding: 14px 16px;
background: rgba(255, 126, 71, 0.08);
border-radius: 0 12px 12px 0;
box-shadow: var(--shadow-sm);
position: relative;
}
._sd_warning::before {
content: '!';
position: absolute;
left: -15px;
top: 50%;
transform: translateY(-50%);
width: 26px;
height: 26px;
background: var(--accent);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 16px;
color: var(--primary);
box-shadow: var(--shadow-sm);
}
._sd_stop_btn {
padding: 14px 30px;
background: var(--gradient-accent);
border: none;
border-radius: 12px;
color: var(--light);
font-weight: 700;
cursor: pointer;
transition: var(--transition-bounce);
font-size: 1rem;
text-transform: uppercase;
letter-spacing: 2px;
box-shadow:
var(--shadow-lg),
0 0 20px rgba(255, 126, 71, 0.3);
position: relative;
overflow: hidden;
text-shadow: var(--text-shadow);
}
._sd_stop_btn::before {
content: "";
position: absolute;
top: -10px;
left: -100%;
width: 100%;
height: 200%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.3),
transparent
);
transform: rotate(25deg);
transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
._sd_stop_btn:hover::before {
left: 200%;
transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
._sd_stop_btn:hover {
background: linear-gradient(135deg, #ff8e5e 0%, #ff5252 100%);
transform: translateY(-3px);
box-shadow:
var(--shadow-xl),
0 0 30px rgba(255, 126, 71, 0.4);
letter-spacing: 2.5px;
}
._sd_stop_btn:active {
transform: translateY(1px);
box-shadow:
var(--shadow-sm),
0 0 10px rgba(255, 126, 71, 0.4);
}
._sd_language_switcher {
position: relative;
background: transparent;
border: 1px solid var(--secondary);
border-radius: 10px;
padding: 6px 14px;
font-size: 0.8rem;
background: linear-gradient(to right, var(--secondary), #64ffda);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
cursor: pointer;
transition: var(--transition-bounce);
text-transform: uppercase;
letter-spacing: 1.5px;
font-weight: 600;
}
._sd_language_switcher:hover {
border-color: var(--accent);
background: linear-gradient(to right, var(--accent), #ffae70);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
box-shadow: 0 0 15px rgba(0, 226, 195, 0.2);
transform: translateY(-2px);
}
._sd_language_switcher:active {
transform: translateY(1px);
}
@keyframes _sd_spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes _sd_fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes _sd_slideIn {
0% {
opacity: 0;
transform: translateY(-30px) scale(0.95);
}
100% {
opacity: 1;
transform: translateY(0) scale(1);
}
}
@keyframes _sd_pulse {
0% {
opacity: 0.7;
}
50% {
opacity: 1;
}
100% {
opacity: 0.7;
}
}
@keyframes _sd_light_sweep {
0% {
transform: rotate(45deg) translateY(0%);
}
100% {
transform: rotate(45deg) translateY(100%);
}
}
._sd_container::before, ._sd_modal::before {
animation: _sd_float 8s ease-in-out infinite alternate;
}
@keyframes _sd_float {
0% {
background-position: 0% 0%;
}
100% {
background-position: 100% 100%;
}
}
._sd_container, ._sd_modal, ._sd_tab, ._sd_welcome, ._sd_warning {
backdrop-filter: blur(10px);
}
._sd_body::-webkit-scrollbar {
width: 5px;
}
._sd_body::-webkit-scrollbar-track {
background: rgba(15, 15, 40, 0.5);
border-radius: 10px;
}
._sd_body::-webkit-scrollbar-thumb {
background: var(--secondary);
border-radius: 10px;
}
._sd_container:hover {
box-shadow:
var(--shadow-xl),
0 0 0 1px var(--border-glow),
0 0 50px rgba(0, 226, 195, 0.2);
}
`;
document.head.appendChild(style);
const containerHTML = `
<div class="_sd_container" id="_sd_container">
<div class="_sd_header">
<h2 class="_sd_title" id="_sd_title">${translations[currentLanguage].title}</h2>
<button class="_sd_language_switcher" id="_sd_language_switcher">${translations[currentLanguage].switchLang}</button>
</div>
<div class="_sd_body">
<div class="_sd_welcome" id="_sd_welcome">${translations[currentLanguage].welcome}</div>
<div class="_sd_tabs">
<div class="_sd_tab active" id="_sd_tab_farm_xp">${translations[currentLanguage].farmXp}</div>
<div class="_sd_tab" id="_sd_tab_farm_gems">${translations[currentLanguage].farmGems}</div>
<div class="_sd_tab" id="_sd_tab_upgrade">${translations[currentLanguage].upgrade}</div>
</div>
<div class="_sd_farm_controls">
<button class="_sd_start_btn" id="_sd_start_btn">${translations[currentLanguage].start}</button>
</div>
</div>
</div>
<button class="_sd_toggle_btn" id="_sd_toggle_btn">→</button>
<div class="_sd_overlay" id="_sd_overlay">
<div class="_sd_modal">
<h2 class="_sd_modal_title" id="_sd_modal_title">${translations[currentLanguage].title}</h2>
<p id="_sd_loading_message">${translations[currentLanguage].loading}</p>
<div class="_sd_spinner" id="_sd_spinner"></div>
<div class="_sd_warning" id="_sd_warning">${translations[currentLanguage].warning}</div>
<div class="_sd_xp_info"><span id="_sd_xp_label">${translations[currentLanguage].xpGained}:</span> <span id="_xpAmount">0</span> XP</div>
<button id="_sd_stop_btn" class="_sd_stop_btn">${translations[currentLanguage].stop}</button>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', containerHTML);
const JWT = getJwtToken();
if (!JWT) {
document.getElementById("_sd_start_btn").disabled = true;
document.getElementById("_sd_welcome").innerText = translations[currentLanguage].notLoggedIn;
return;
}
const HEADERS = formatHeaders(JWT);
try {
const { username, fromLanguage, learningLanguage } = await getUserInfo(decodeJwtToken(JWT).sub, HEADERS);
document.getElementById("_sd_welcome").innerHTML = `${translations[currentLanguage].hello} <strong>${username}</strong>!`;
const sessionPayload = {
challengeTypes: ["assist", "characterIntro", "characterMatch", "characterPuzzle", "characterSelect", "characterTrace", "characterWrite", "completeReverseTranslation", "definition", "dialogue", "extendedMatch", "extendedListenMatch", "form", "freeResponse", "gapFill", "judge", "listen", "listenComplete", "listenMatch", "match", "name", "listenComprehension", "listenIsolation", "listenSpeak", "listenTap", "orderTapComplete", "partialListen", "partialReverseTranslate", "patternTapComplete", "radioBinary", "radioImageSelect", "radioListenMatch", "radioListenRecognize", "radioSelect", "readComprehension", "reverseAssist", "sameDifferent", "select", "selectPronunciation", "selectTranscription", "svgPuzzle", "syllableTap", "syllableListenTap", "speak", "tapCloze", "tapClozeTable", "tapComplete", "tapCompleteTable", "tapDescribe", "translate", "transliterate", "transliterationAssist", "typeCloze", "typeClozeTable", "typeComplete", "typeCompleteTable", "writeComprehension"],
fromLanguage,
learningLanguage,
type: "GLOBAL_PRACTICE"
};
const updateSessionPayload = {
heartsLeft: 0,
startTime: Math.floor(Date.now() / 1000),
enableBonusPoints: false,
endTime: Math.floor(Date.now() / 1000) + 112,
failed: false,
maxInLessonStreak: 9,
shouldLearnThings: true
};
document.getElementById("_sd_toggle_btn").addEventListener("click", () => {
isVisible = !isVisible;
document.getElementById("_sd_container").classList.toggle("hidden", !isVisible);
document.getElementById("_sd_toggle_btn").innerHTML = isVisible ? "→" : "←";
});
document.getElementById("_sd_start_btn").addEventListener("click", () => {
document.getElementById("_sd_overlay").style.display = "flex";
isFarming = true;
farmXp(HEADERS, sessionPayload, updateSessionPayload);
});
document.getElementById("_sd_stop_btn").addEventListener("click", () => {
document.getElementById("_sd_overlay").style.display = "none";
isFarming = false;
const startBtn = document.getElementById("_sd_start_btn");
startBtn.disabled = true;
startBtn.innerText = "...";
setTimeout(() => {
startBtn.disabled = false;
startBtn.innerText = translations[currentLanguage].start;
}, 2000);
});
document.getElementById("_sd_language_switcher").addEventListener("click", () => {
currentLanguage = currentLanguage === "en" ? "vi" : "en";
updateLanguage();
});
document.getElementById("_sd_tab_farm_gems").addEventListener("click", () => {
window.open("https://discord.gg/ufBrcGemBH", "_blank");
});
document.getElementById("_sd_tab_upgrade").addEventListener("click", () => {
window.open("https://superduolingo.click", "_blank");
});
} catch (error) {
console.error("Error initializing SuperDuolingo:", error);
document.getElementById("_sd_welcome").innerText = "Error initializing SuperDuolingo. Please refresh the page.";
}
};
function updateLanguage() {
document.getElementById("_sd_title").innerText = translations[currentLanguage].title;
document.getElementById("_sd_language_switcher").innerText = translations[currentLanguage].switchLang;
const welcomeEl = document.getElementById("_sd_welcome");
if (!welcomeEl.innerHTML.includes("<strong>")) {
welcomeEl.innerText = translations[currentLanguage].welcome;
} else {
const username = welcomeEl.querySelector("strong").innerText;
welcomeEl.innerHTML = `${translations[currentLanguage].hello} <strong>${username}</strong>!`;
}
document.getElementById("_sd_tab_farm_xp").innerText = translations[currentLanguage].farmXp;
document.getElementById("_sd_tab_farm_gems").innerText = translations[currentLanguage].farmGems;
document.getElementById("_sd_tab_upgrade").innerText = translations[currentLanguage].upgrade;
document.getElementById("_sd_start_btn").innerText = translations[currentLanguage].start;
document.getElementById("_sd_modal_title").innerText = translations[currentLanguage].title;
document.getElementById("_sd_loading_message").innerText = translations[currentLanguage].loading;
document.getElementById("_sd_warning").innerText = translations[currentLanguage].warning;
document.getElementById("_sd_xp_label").innerText = `${translations[currentLanguage].xpGained}:`;
document.getElementById("_sd_stop_btn").innerText = translations[currentLanguage].stop;
}
initSuperDuolingo();
})();