您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
cả cái gia tài của bố meow đó =((( đăng kiếm mem discord;))
// ==UserScript== // @name Duolingo Auto-Super-Generate // @namespace http://tampermonkey.net/ // @version https://discord.gg/ufBrcGemBH // @description cả cái gia tài của bố meow đó =((( đăng kiếm mem discord;)) // @author Bố Meow // @match *://*.duolingo.com/* // @license MIT // @icon https://d35aaqx5ub95lt.cloudfront.net/vendor/a0ee30fa22ca3d00e9e5db913b1965b5.svg // @grant none // ==/UserScript== (function() { 'use strict'; const CONFIG = { defaultPassword: 'DuolingoAuto2025', emailDomains: ['@tempmail.org', '@10minutemail.com', '@guerrillamail.com'], exportShortcut: 'Alt+E', exportMultipleShortcut: 'Alt+M', discordLink: 'https://discord.gg/ufBrcGemBH', storageKeys: { accounts: 'duolingoAccountsList', currentIndex: 'duolingoCurrentAccountIndex', registeredAccounts: 'duolingoRegisteredAccounts', selectedCourse: 'selectedCourse', windowPosition: 'duoWindowPos', windowMinimized: 'duoWindowMin' } }; const util = { generateRandomEmail: () => { const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; const domains = CONFIG.emailDomains; const randomString = Array(8).fill().map(() => chars[Math.floor(Math.random() * chars.length)]).join(''); const randomDomain = domains[Math.floor(Math.random() * domains.length)]; return randomString + randomDomain; }, getJwtToken: () => { const match = document.cookie.match(new RegExp('(^| )jwt_token=([^;]+)')); return match ? match[0].slice(11) : null; }, downloadAsFile: (content, filename) => { const blob = new Blob([content], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 100); }, createElement: (tag, attributes = {}, styles = {}, eventListeners = {}) => { const element = document.createElement(tag); Object.entries(attributes).forEach(([key, value]) => element[key] = value); Object.entries(styles).forEach(([key, value]) => element.style[key] = value); Object.entries(eventListeners).forEach(([event, handler]) => element.addEventListener(event, handler)); return element; }, setValue: (selector, value) => { const element = document.querySelector(selector); if (!element) return false; const valueSetter = Object.getOwnPropertyDescriptor(element, 'value')?.set; const prototype = Object.getPrototypeOf(element); const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value')?.set; if (valueSetter && prototypeValueSetter) { (valueSetter !== prototypeValueSetter ? prototypeValueSetter : valueSetter).call(element, value); } else { element.value = value; } ['input', 'change', 'blur'].forEach(eventType => element.dispatchEvent(new Event(eventType, { bubbles: true })) ); const keyupEvent = new Event('keyup', { bubbles: true }); Object.defineProperty(keyupEvent, 'keyCode', { get: () => 13 }); element.dispatchEvent(keyupEvent); return true; }, clickElement: selector => { const element = document.querySelector(selector); if (element) element.click(); return !!element; }, storeAccount: (email, password, token) => { const accounts = JSON.parse(localStorage.getItem(CONFIG.storageKeys.registeredAccounts) || '[]'); const newAccount = { id: (accounts.length + 1).toString(), username: email, password: password, token: token, createdAt: new Date().toISOString() }; accounts.push(newAccount); localStorage.setItem(CONFIG.storageKeys.registeredAccounts, JSON.stringify(accounts)); return newAccount; }, delay: ms => new Promise(resolve => setTimeout(resolve, ms)), formatDate: (date) => { if (!date) return ''; const options = { year: 'numeric', month: 'numeric', day: 'numeric', hour: '2-digit', minute: '2-digit' }; return date.toLocaleDateString('en-US', options); }, saveWindowState: (x, y, minimized) => { localStorage.setItem(CONFIG.storageKeys.windowPosition, JSON.stringify({x, y})); localStorage.setItem(CONFIG.storageKeys.windowMinimized, minimized); }, loadWindowState: () => { const pos = JSON.parse(localStorage.getItem(CONFIG.storageKeys.windowPosition) || '{"x":20,"y":20}'); const minimized = localStorage.getItem(CONFIG.storageKeys.windowMinimized) === 'true'; return {pos, minimized}; }, updateAccountCount: () => { const accountCountElement = document.querySelector('#accountCount'); if (accountCountElement) { const registeredAccounts = JSON.parse(localStorage.getItem(CONFIG.storageKeys.registeredAccounts) || '[]'); accountCountElement.textContent = `${registeredAccounts.length} accounts`; } } }; const ui = { isDragging: false, dragOffset: {x: 0, y: 0}, createWindow: () => { const {pos, minimized} = util.loadWindowState(); const discordCheck = () => { if (!CONFIG.discordLink) throw new Error('Discord integration required'); return true; }; discordCheck(); const windowContainer = util.createElement('div', {id: 'duoAutoWindow'}, { position: 'fixed', left: pos.x + 'px', top: pos.y + 'px', width: '380px', minHeight: minimized ? '40px' : '480px', backgroundColor: '#202020', border: '1px solid #404040', borderRadius: '12px', boxShadow: '0 8px 32px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.05)', zIndex: '999999', fontFamily: 'Segoe UI, system-ui, sans-serif', overflow: 'hidden', backdropFilter: 'blur(20px)', transition: 'all 0.2s cubic-bezier(0.4, 0, 0.2, 1)' }); const titleBar = util.createElement('div', {}, { height: '40px', backgroundColor: '#2d2d2d', borderBottom: '1px solid #404040', display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 16px', cursor: 'move', userSelect: 'none' }); const titleText = util.createElement('div', { innerHTML: '<span style="color: #00d4ff; font-weight: 600;">Duolingo</span> <span style="color: #ffffff;">Auto Tools</span>' }, { fontSize: '14px', fontWeight: '500' }); const windowControls = util.createElement('div', {}, { display: 'flex', gap: '12px' }); const minimizeBtn = util.createElement('div', {innerHTML: '⎯'}, { width: '20px', height: '20px', borderRadius: '4px', backgroundColor: '#404040', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', fontSize: '12px', color: '#ffffff', transition: 'all 0.15s ease' }); const closeBtn = util.createElement('div', {innerHTML: '✕'}, { width: '20px', height: '20px', borderRadius: '4px', backgroundColor: '#e74c3c', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', fontSize: '10px', color: '#ffffff', transition: 'all 0.15s ease' }); const content = util.createElement('div', {id: 'windowContent'}, { padding: '20px', height: 'calc(100% - 40px)', display: minimized ? 'none' : 'block' }); const discordBanner = util.createElement('div', { innerHTML: `<div style="display: flex; align-items: center; gap: 12px;"> <div style="width: 32px; height: 32px; background: linear-gradient(135deg, #5865f2, #7289da); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 18px;">D</div> <div> <div style="color: #ffffff; font-weight: 600; font-size: 14px;">Join Discord Server</div> <div style="color: #b0b0b0; font-size: 12px;">Get support & updates</div> </div> </div>` }, { background: 'linear-gradient(135deg, #5865f2 0%, #7289da 100%)', padding: '16px', borderRadius: '8px', marginBottom: '20px', cursor: 'pointer', transition: 'all 0.2s ease', border: '1px solid rgba(255,255,255,0.1)' }, { click: () => window.open(CONFIG.discordLink, '_blank'), mouseenter: e => { e.target.style.transform = 'translateY(-2px)'; e.target.style.boxShadow = '0 8px 25px rgba(88, 101, 242, 0.3)'; }, mouseleave: e => { e.target.style.transform = 'translateY(0)'; e.target.style.boxShadow = 'none'; } }); const buttonGrid = util.createElement('div', {}, { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px', marginBottom: '16px' }); const buttons = [ {text: 'Register', handler: actions.startAutoRegister, color: '#00d4ff'}, {text: 'Logout', handler: actions.logOut, color: '#ff6b6b'}, {text: 'Auto Login', handler: actions.handleLoginAuto, color: '#51cf66'}, {text: 'Get Plus', handler: actions.startPlusOfferProcess, color: '#ffd43b'}, {text: 'Get Link', handler: actions.getLink, color: '#9c88ff'}, {text: 'Auto Kick', handler: actions.autoKick, color: '#ff8787'} ]; buttons.forEach(btn => { const button = ui.createButton(btn.text, btn.handler, btn.color); buttonGrid.appendChild(button); }); const fullWidthButtons = [ {text: 'Complete Course Setup', handler: actions.startAdditionalSteps, color: '#20c997'}, {text: 'Export Accounts', handler: () => actions.exportAccounts(), color: '#6c5ce7'} ]; content.appendChild(discordBanner); content.appendChild(buttonGrid); fullWidthButtons.forEach(btn => { const button = ui.createButton(btn.text, btn.handler, btn.color); button.style.width = '100%'; button.style.marginBottom = '12px'; content.appendChild(button); }); // Tạo statusBar với account count const registeredAccounts = JSON.parse(localStorage.getItem(CONFIG.storageKeys.registeredAccounts) || '[]'); const statusBar = util.createElement('div', { innerHTML: `<div style="display: flex; justify-content: space-between; align-items: center;"> <span style="color: #b0b0b0; font-size: 11px;">Alt+E: Export current | Alt+M: Export all</span> <span id="accountCount" style="color: #00d4ff; font-size: 11px; font-weight: 600;">${registeredAccounts.length} accounts</span> </div>` }, { padding: '12px 16px', backgroundColor: '#1a1a1a', borderTop: '1px solid #404040', fontSize: '11px' }); titleBar.appendChild(titleText); windowControls.appendChild(minimizeBtn); windowControls.appendChild(closeBtn); titleBar.appendChild(windowControls); windowContainer.appendChild(titleBar); windowContainer.appendChild(content); content.appendChild(statusBar); minimizeBtn.addEventListener('click', () => { const isMinimized = content.style.display === 'none'; content.style.display = isMinimized ? 'block' : 'none'; windowContainer.style.minHeight = isMinimized ? '480px' : '40px'; util.saveWindowState( parseInt(windowContainer.style.left), parseInt(windowContainer.style.top), !isMinimized ); }); minimizeBtn.addEventListener('mouseenter', e => { e.target.style.backgroundColor = '#595959'; }); minimizeBtn.addEventListener('mouseleave', e => { e.target.style.backgroundColor = '#404040'; }); closeBtn.addEventListener('click', () => { windowContainer.remove(); }); closeBtn.addEventListener('mouseenter', e => { e.target.style.backgroundColor = '#c0392b'; }); closeBtn.addEventListener('mouseleave', e => { e.target.style.backgroundColor = '#e74c3c'; }); titleBar.addEventListener('mousedown', e => { ui.isDragging = true; ui.dragOffset.x = e.clientX - windowContainer.offsetLeft; ui.dragOffset.y = e.clientY - windowContainer.offsetTop; document.addEventListener('mousemove', ui.handleDrag); document.addEventListener('mouseup', ui.stopDrag); }); return windowContainer; }, createButton: (text, handler, color = '#00d4ff') => { return util.createElement('button', {innerHTML: text}, { backgroundColor: color, color: '#ffffff', border: 'none', padding: '10px 16px', borderRadius: '6px', cursor: 'pointer', fontSize: '13px', fontWeight: '600', transition: 'all 0.15s ease', fontFamily: 'Segoe UI, system-ui, sans-serif' }, { click: handler, mouseenter: e => { e.target.style.transform = 'translateY(-1px)'; e.target.style.filter = 'brightness(1.1)'; }, mouseleave: e => { e.target.style.transform = 'translateY(0)'; e.target.style.filter = 'brightness(1)'; } }); }, handleDrag: (e) => { if (!ui.isDragging) return; const windowContainer = document.getElementById('duoAutoWindow'); const newX = Math.max(0, Math.min(window.innerWidth - windowContainer.offsetWidth, e.clientX - ui.dragOffset.x)); const newY = Math.max(0, Math.min(window.innerHeight - windowContainer.offsetHeight, e.clientY - ui.dragOffset.y)); windowContainer.style.left = newX + 'px'; windowContainer.style.top = newY + 'px'; }, stopDrag: () => { if (ui.isDragging) { ui.isDragging = false; const windowContainer = document.getElementById('duoAutoWindow'); util.saveWindowState( parseInt(windowContainer.style.left), parseInt(windowContainer.style.top), document.getElementById('windowContent').style.display === 'none' ); document.removeEventListener('mousemove', ui.handleDrag); document.removeEventListener('mouseup', ui.stopDrag); } }, createNotification: () => { const notification = util.createElement('div', { innerHTML: 'Kurumi ơi né ra giùm em nha' }, { position: 'fixed', top: '20px', left: '50%', transform: 'translateX(-50%)', backgroundColor: '#2d2d2d', color: '#ffffff', padding: '12px 24px', borderRadius: '8px', fontSize: '14px', fontWeight: '500', zIndex: '1000000', border: '1px solid #404040', boxShadow: '0 4px 20px rgba(0,0,0,0.3)', fontFamily: 'Segoe UI, system-ui, sans-serif', animation: 'slideDown 0.3s ease-out' }); const style = document.createElement('style'); style.textContent = ` @keyframes slideDown { from { transform: translateX(-50%) translateY(-20px); opacity: 0; } to { transform: translateX(-50%) translateY(0); opacity: 1; } } `; document.head.appendChild(style); document.body.appendChild(notification); setTimeout(() => { notification.style.animation = 'slideUp 0.3s ease-in forwards'; style.textContent += ` @keyframes slideUp { from { transform: translateX(-50%) translateY(0); opacity: 1; } to { transform: translateX(-50%) translateY(-20px); opacity: 0; } } `; setTimeout(() => notification.remove(), 300); }, 3000); } }; const actions = { startAutoRegister: async () => { const haveAccountButton = document.querySelector('button[data-test="have-account"]'); if (haveAccountButton) { haveAccountButton.click(); await util.delay(500); } util.clickElement('button[data-test="sign-up-button"]'); await util.delay(800); const email = util.generateRandomEmail(); const password = CONFIG.defaultPassword; util.setValue('input[data-test="age-input"]', '25'); await util.delay(300); util.clickElement('button[data-test="continue-button"]'); await util.delay(800); util.setValue('input[data-test="full-name-input"]', 'Auto User'); util.setValue('input[data-test="email-input"]', email); util.setValue('input[data-test="password-input"]', password); await util.delay(500); util.clickElement('button[data-test="register-button"]'); localStorage.setItem('user_email', email); localStorage.setItem('user_password', password); setTimeout(() => { const token = util.getJwtToken(); if (token) { util.storeAccount(email, password, token); util.updateAccountCount(); // Sử dụng hàm helper mới console.log('Account registered:', email); } }, 2000); }, logOut: async () => { console.log('Logging out...'); try { const response = await fetch('/logout', { method: 'POST', credentials: 'same-origin', headers: {'Content-Type': 'application/json'} }); if (response.ok) { console.log('Logout successful'); const accountsListStr = localStorage.getItem(CONFIG.storageKeys.accounts); if (accountsListStr) { const accountsFromStorage = JSON.parse(accountsListStr); let currentIndex = parseInt(localStorage.getItem(CONFIG.storageKeys.currentIndex) || '0'); currentIndex++; if (currentIndex < accountsFromStorage.length) { localStorage.setItem(CONFIG.storageKeys.currentIndex, currentIndex); actions.loginWithAccount(accountsFromStorage[currentIndex]); } else { [CONFIG.storageKeys.accounts, CONFIG.storageKeys.currentIndex, 'user_email', 'user_password'] .forEach(key => localStorage.removeItem(key)); window.location.reload(); } } else { ['user_email', 'user_password'].forEach(key => localStorage.removeItem(key)); window.location.reload(); } } else { throw new Error('Logout failed'); } } catch (error) { console.error('Logout error:', error); window.location.reload(); } }, autoKick: () => { if (window.location.href !== 'https://www.duolingo.com/settings/super') { window.location.href = 'https://www.duolingo.com/settings/super'; return; } setTimeout(() => { const editButton = document.querySelector('button[data-test="edit-family"]'); if (editButton) { editButton.click(); setTimeout(() => { const checkboxes = document.querySelectorAll('input[type="checkbox"][data-test="select-member-checkbox"]'); checkboxes.forEach(checkbox => checkbox.click()); setTimeout(() => { const removeButton = document.querySelector('button[data-test="remove-member"]'); if (removeButton) { removeButton.click(); actions.logOut(); } }, 300); }, 300); } }, 1000); }, getLink: () => { if (window.location.href !== 'https://www.duolingo.com/settings/super') { window.location.href = 'https://www.duolingo.com/settings/super'; return; } setTimeout(() => { const addMemberButton = document.querySelector('li[role="button"][tabindex="0"]'); if (addMemberButton && addMemberButton.textContent.includes('Add')) { addMemberButton.click(); const checkCopyButton = setInterval(() => { const copyButton = document.querySelector('button[aria-label*="Copy"], button:contains("Copy")'); if (copyButton) { clearInterval(checkCopyButton); copyButton.click(); console.log('Link copied'); setTimeout(() => { const closeButton = document.querySelector('button[data-test*="close"]'); if (closeButton) { closeButton.click(); actions.logOut(); } }, 500); } }, 100); } }, 500); }, startAdditionalSteps: () => { const courseButtons = document.querySelectorAll('div[data-test*="course-"]'); if (courseButtons.length > 0) { courseButtons[0].click(); localStorage.setItem(CONFIG.storageKeys.selectedCourse, 'Selected'); } setTimeout(() => { util.clickElement('button[data-test="funboarding-continue-button"]'); }, 500); setTimeout(() => { window.location.href = 'https://www.duolingo.com/settings/super'; }, 3000); }, startPlusOfferProcess: () => { if (window.location.href !== 'https://www.duolingo.com/settings/super') { window.location.href = 'https://www.duolingo.com/settings/super'; return; } const steps = [ { selector: 'button[data-test="plus-offer-button"]', delay: 500 }, { selector: 'button[data-test="plus-continue"]', delay: 300 }, { selector: 'button[data-test="plus-continue"]', delay: 300 }, { selector: 'button[data-test="plus-continue"]', delay: 300 } ]; const executeSteps = (index = 0) => { if (index >= steps.length) return; const step = steps[index]; setTimeout(() => { const element = document.querySelector(step.selector); if (element) { element.click(); executeSteps(index + 1); } }, step.delay); }; executeSteps(); }, handleLoginAuto: () => { const fileInput = util.createElement('input', { type: 'file', accept: '.txt', style: { display: 'none' }, onchange: function(e) { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { const content = e.target.result; const accounts = content.split('\n') .filter(line => line.trim() !== '') .map(line => { const parts = line.split(':'); return parts.length >= 4 ? { id: parts[0], username: parts[1], password: parts[2], token: parts[3].trim() } : null; }) .filter(account => account !== null); if (accounts.length > 0) { localStorage.setItem(CONFIG.storageKeys.accounts, JSON.stringify(accounts)); localStorage.setItem(CONFIG.storageKeys.currentIndex, '0'); actions.loginWithAccount(accounts[0]); } else { alert('No valid accounts found'); } }; reader.readAsText(file); document.body.removeChild(fileInput); } }); document.body.appendChild(fileInput); fileInput.click(); }, loginWithAccount: (account) => { if (!account || !account.token) { console.error('Invalid account data'); return; } console.log(`Logging in with account: ${account.id}`); document.cookie = `jwt_token=${account.token}; path=/`; window.location.reload(); }, exportAccounts: (all = false) => { const accounts = JSON.parse(localStorage.getItem(CONFIG.storageKeys.registeredAccounts) || '[]'); if (accounts.length === 0) { alert('No accounts to export'); return; } const currentToken = util.getJwtToken(); if (currentToken && !all) { const currentEmail = localStorage.getItem('user_email'); const currentPassword = localStorage.getItem('user_password'); if (currentEmail && currentPassword) { const accountData = `1:${currentEmail}:${currentPassword}:${currentToken}`; util.downloadAsFile(accountData, 'duolingo_account.txt'); } else { alert('Current account details not found'); } } else { const accountsData = accounts.map((acc, idx) => `${idx + 1}:${acc.username}:${acc.password}:${acc.token}` ).join('\n'); util.downloadAsFile(accountsData, 'duolingo_accounts.txt'); console.log(`${accounts.length} accounts exported`); } } }; const init = () => { document.addEventListener('keydown', e => { if (e.altKey && e.key === 'e') { actions.exportAccounts(false); } else if (e.altKey && e.key === 'm') { actions.exportAccounts(true); } }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { setTimeout(() => { document.body.appendChild(ui.createWindow()); ui.createNotification(); }, 1000); }); } else { setTimeout(() => { document.body.appendChild(ui.createWindow()); ui.createNotification(); }, 1000); } const accountsListStr = localStorage.getItem(CONFIG.storageKeys.accounts); if (accountsListStr) { const currentIndex = parseInt(localStorage.getItem(CONFIG.storageKeys.currentIndex) || '0'); console.log(`Loaded ${JSON.parse(accountsListStr).length} accounts, index: ${currentIndex}`); } }; init(); })();