// ==UserScript== // @name DUOAUTO_KEEPSTREAK // @match https://*.duolingo.com/* // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @version 1.01BETA // @author HACKER_DUOLINGO_666 // @icon https://www.google.com/s2/favicons?sz=64&domain=duolingo.com // @description IT AUTO KEEP STREAK AUTOMATICALLY AND VERY TO USE // @namespace https://greasyfork.org/users/1430241 // @downloadURL none // ==/UserScript== const getToken = () => document.cookie.split(';').map(c => c.trim()).find(c => c.startsWith('jwt_token='))?.split('=')[1] || null; const decodeJWT = token => JSON.parse(decodeURIComponent(atob(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')).split('').map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join(''))); const getHeaders = token => ({ "Content-Type": "application/json", "Authorization": `Bearer ${token}`, "User-Agent": navigator.userAgent }); const fetchUserData = async userId => (await fetch(`https://www.duolingo.com/2017-06-30/users/${userId}?fields=fromLanguage,learningLanguage,streakData`, { headers })).json(); const hasStreak = data => data?.streakData?.currentStreak?.endDate === new Date().toISOString().split('T')[0]; const startSession = async (fromLang, learningLang) => { const payload = { fromLanguage: fromLang, learningLanguage: learningLang, type: "GLOBAL_PRACTICE", isV2: true }; return (await fetch("https://www.duolingo.com/2017-06-30/sessions", { method: 'POST', headers, body: JSON.stringify(payload) })).json(); }; const completeSession = async session => { const payload = { ...session, heartsLeft: 0, startTime: Date.now() / 1000, endTime: Date.now() / 1000 + 112, failed: false }; return (await fetch(`https://www.duolingo.com/2017-06-30/sessions/${session.id}`, { method: 'PUT', headers, body: JSON.stringify(payload) })).json(); }; const streakKeeper = async () => { try { const token = getToken(); if (!token) return alert("Not logged in"); const userId = decodeJWT(token).sub; headers = getHeaders(token); const userData = await fetchUserData(userId); if (hasStreak(userData)) return alert("You already have a streak today. Enjoy! :)"); const session = await startSession(userData.fromLanguage, userData.learningLanguage); await completeSession(session); alert("Streak claimed successfully! Come back tomorrow to claim again."); } catch (error) { console.error(error); alert("An error occurred, please try again later."); } }; // UI Creation const createUI = () => { const container = document.createElement('div'); container.style = ` position: fixed; top: 10px; right: 10px; background: rgba(255, 255, 255, 0.1); border-radius: 10px; padding: 10px; backdrop-filter: blur(5px); box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); transition: right 0.3s ease; `; // Claim Streak Button const claimButton = document.createElement('button'); claimButton.style = ` background: #28a745; color: #fff; border: none; border-radius: 5px; padding: 8px 15px; cursor: pointer; font-size: 14px; display: block; width: 100%; `; claimButton.innerText = 'Claim Streak'; claimButton.onclick = async () => { claimButton.disabled = true; claimButton.style.background = 'gray'; claimButton.innerText = 'Processing...'; await streakKeeper(); claimButton.disabled = false; claimButton.style.background = '#28a745'; claimButton.innerText = 'Claim Streak'; }; container.appendChild(claimButton); document.body.appendChild(container); }; // Run UI createUI();