CODE TACK TK MỚI

// AD TOOL PRO - CHƯƠNG TRÌNH TỔNG HỢP TÁCH VÀ KÍCH HOẠT TÀI KHOẢN QUẢNG CÁO // HASoftware - Ads Solution - Auto Version // Biến thống kê toàn cục let stats = { // Thống kê tách tài khoản tachTotalProcessed: 0, tachSuccessCount: 0, tachFailureCount: 0, tachTargetSuccess: 600, tachStartTime: null, tachActiveRequests: 0, tachMaxConcurrentRequests: 200, tachIsRunning: false, tachCurrentAccounts: [], // Thống kê kích hoạt tài khoản kichHoatTotal: 0, kichHoatSuccess: 0, kichHoatFailed: 0, kichHoatSkipped: 0, kichHoatProcessing: 0, kichHoatCurrent: 0, kichHoatStartTime: null, kichHoatIsRunning: false, // Thống kê đổi tên tài khoản renameTotal: 0, renameSuccess: 0, renameFailed: 0, renameSkipped: 0, renameProcessing: 0, renameCurrent: 0, renameStartTime: null, renameIsRunning: false, renameRetryCount: 0, // Số lần retry tổng cộng // Thống kê xóa admin & analysts removeAdminTotal: 0, removeAdminSuccess: 0, removeAdminFailed: 0, removeAdminSkipped: 0, removeAdminCurrent: 0, removeAdminStartTime: null, removeAdminIsRunning: false, removeAdminAdminsRemoved: 0, removeAdminAnalystsRemoved: 0, // Trạng thái tổng thể currentPhase: 'idle', // 'idle', 'tach', 'kichhoat', 'rename', 'removeadmin', 'completed' isRunning: false, failureThreshold: 500, // Cấu hình mới config: { // Tích chọn chính cho từng chức năng enableTach: true, // Bật chức năng tách TKQC enableKichHoat: true, // Bật chức năng kích hoạt TKQC enableRename: false, // Bật chức năng đổi tên TKQC enableRemoveAdmin: false, // Bật chức năng xóa admin & analysts // Cấu hình tách failureThresholdToKichHoat: 500, // Số tài khoản thất bại thì chuyển sang kích hoạt targetSuccess: 600, // Số TKQC cần tách thành công enableDelayBetweenAccounts: false, // Có delay giữa mỗi tài khoản không delayBetweenAccounts: 1, // Delay giữa mỗi tài khoản (giây) // Cấu hình kích hoạt delayBeforeKichHoat: 300, // Thời gian delay trước khi kích hoạt (giây) kichHoatBatchSize: 50, // Số tài khoản kích hoạt đồng thời // Cấu hình đổi tên renameMode: 'fixed', // 'fixed' hoặc 'business' fixedName: 'Tongkhofb Com', // Tên cố định businessName: '', // Tên doanh nghiệp (sẽ được lấy tự động) onlyPersonalAccounts: true, // Chỉ áp dụng với TKQC cá nhân // Cấu hình xóa admin & analysts removeAdminOnly: true, // Chỉ xóa admin (role 1001) removeAnalystOnly: false, // Chỉ xóa analyst (role 1003) removeBoth: false, // Xóa cả admin và analyst removeAdminDelay: 2 // Delay giữa các tài khoản (giây) } }; // Tạo giao diện web tổng hợp function createCombinedWebUI() { const style = document.createElement('style'); style.textContent = ` .adtool-pro-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.9); display: flex; justify-content: center; align-items: center; z-index: 999999; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } .adtool-pro-container { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 20px; padding: 30px; width: 95%; max-width: 1000px; max-height: 90vh; overflow-y: auto; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4); color: white; position: relative; animation: slideIn 0.5s ease-out; } @keyframes slideIn { from { transform: translateY(-50px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .adtool-pro-header { text-align: center; margin-bottom: 25px; } .adtool-pro-title { font-size: 28px; font-weight: bold; margin-bottom: 10px; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3); } .adtool-pro-subtitle { font-size: 16px; opacity: 0.9; } .adtool-pro-phase-indicator { text-align: center; margin: 20px 0; padding: 15px; background: rgba(255, 255, 255, 0.1); border-radius: 10px; backdrop-filter: blur(10px); } .adtool-pro-phase-text { font-size: 20px; font-weight: bold; margin-bottom: 5px; } .adtool-pro-phase-description { font-size: 14px; opacity: 0.8; } .adtool-pro-sections { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin: 25px 0; } .adtool-pro-section { background: rgba(255, 255, 255, 0.1); padding: 20px; border-radius: 15px; backdrop-filter: blur(10px); } .adtool-pro-section-title { font-size: 18px; font-weight: bold; margin-bottom: 15px; text-align: center; } .adtool-pro-progress-container { margin: 15px 0; } .adtool-pro-progress-bar { width: 100%; height: 15px; background: rgba(255, 255, 255, 0.2); border-radius: 8px; overflow: hidden; position: relative; } .adtool-pro-progress-fill { height: 100%; border-radius: 8px; transition: width 0.5s ease; position: relative; overflow: hidden; } .adtool-pro-progress-fill.tach { background: linear-gradient(90deg, #ff6b6b, #ee5a24); } .adtool-pro-progress-fill.kichhoat { background: linear-gradient(90deg, #4CAF50, #45a049); } .adtool-pro-progress-text { text-align: center; margin-top: 8px; font-size: 14px; font-weight: bold; } .adtool-pro-stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 15px 0; } .adtool-pro-stat-item { background: rgba(255, 255, 255, 0.1); padding: 12px; border-radius: 8px; text-align: center; } .adtool-pro-stat-number { font-size: 20px; font-weight: bold; margin-bottom: 3px; } .adtool-pro-stat-label { font-size: 11px; opacity: 0.8; } .adtool-pro-current { background: rgba(255, 255, 255, 0.1); padding: 15px; border-radius: 10px; margin: 15px 0; } .adtool-pro-current-title { font-size: 14px; margin-bottom: 10px; opacity: 0.9; } .adtool-pro-current-accounts { max-height: 100px; overflow-y: auto; font-size: 12px; line-height: 1.4; } .adtool-pro-current-account { background: rgba(255, 255, 255, 0.1); padding: 4px 8px; margin: 2px 0; border-radius: 4px; font-family: monospace; } .adtool-pro-close { position: absolute; top: 15px; right: 20px; background: rgba(255, 255, 255, 0.2); border: none; color: white; width: 35px; height: 35px; border-radius: 50%; cursor: pointer; font-size: 20px; transition: all 0.3s ease; } .adtool-pro-close:hover { background: rgba(255, 255, 255, 0.3); transform: scale(1.1); } .adtool-pro-completion { text-align: center; padding: 25px; background: rgba(76, 175, 80, 0.2); border-radius: 15px; margin-top: 25px; display: none; } .adtool-pro-completion.show { display: block; animation: fadeIn 0.5s ease; } @keyframes fadeIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } } .adtool-pro-completion-icon { font-size: 48px; margin-bottom: 15px; } .adtool-pro-completion-title { font-size: 24px; font-weight: bold; margin-bottom: 15px; } .adtool-pro-completion-stats { font-size: 16px; line-height: 1.8; } .adtool-pro-completion-stat-row { display: flex; justify-content: space-between; margin: 8px 0; padding: 8px; background: rgba(255, 255, 255, 0.1); border-radius: 8px; } .adtool-pro-timer { text-align: center; margin: 15px 0; font-size: 18px; font-weight: bold; color: #ffd700; text-shadow: 0 0 10px rgba(255, 215, 0, 0.5); } .adtool-pro-controls { display: flex; justify-content: center; gap: 15px; margin: 20px 0; } .adtool-pro-btn { padding: 12px 24px; border: none; border-radius: 8px; font-size: 16px; font-weight: bold; cursor: pointer; transition: all 0.3s ease; min-width: 120px; } .adtool-pro-btn.start { background: linear-gradient(135deg, #4CAF50, #45a049); color: white; } .adtool-pro-btn.start:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(76, 175, 80, 0.4); } .adtool-pro-btn.stop { background: linear-gradient(135deg, #f44336, #d32f2f); color: white; } .adtool-pro-btn.stop:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(244, 67, 54, 0.4); } .adtool-pro-btn:disabled { opacity: 0.6; cursor: not-allowed; transform: none !important; } .adtool-pro-config { background: rgba(255, 255, 255, 0.15); padding: 20px; border-radius: 15px; margin: 20px 0; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); } .adtool-pro-config .adtool-pro-config-title { font-size: 18px; font-weight: bold; margin-bottom: 15px; text-align: center; color: #ffffff !important; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8); } .adtool-pro-config-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; } .adtool-pro-config-item { display: flex; flex-direction: column; gap: 5px; } .adtool-pro-config .adtool-pro-config-label, .adtool-pro-config label { font-size: 14px; font-weight: bold; color: #ffffff !important; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8); -webkit-text-fill-color: #ffffff !important; fill: #ffffff !important; } .adtool-pro-config-input { padding: 8px 12px; border: none; border-radius: 6px; background: rgba(255, 255, 255, 0.95); color: #333; font-size: 14px; border: 2px solid rgba(255, 255, 255, 0.3); transition: all 0.3s ease; } .adtool-pro-config-input:focus { outline: none; border-color: #4CAF50; box-shadow: 0 0 10px rgba(76, 175, 80, 0.3); } .adtool-pro-config-checkbox { display: flex; align-items: center; gap: 8px; margin-top: 5px; } .adtool-pro-config-checkbox input[type="checkbox"] { width: 18px; height: 18px; accent-color: #4CAF50; cursor: pointer; } .adtool-pro-config .adtool-pro-config-checkbox label, .adtool-pro-config-checkbox label { font-size: 14px; cursor: pointer; color: #ffffff !important; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8); font-weight: 500; -webkit-text-fill-color: #ffffff !important; fill: #ffffff !important; } .adtool-pro-config-radio { display: flex; align-items: center; gap: 8px; margin-top: 5px; } .adtool-pro-config-radio input[type="radio"] { width: 16px; height: 16px; accent-color: #4CAF50; cursor: pointer; } .adtool-pro-config .adtool-pro-config-radio label, .adtool-pro-config-radio label { font-size: 14px; cursor: pointer; color: #ffffff !important; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8); font-weight: 500; -webkit-text-fill-color: #ffffff !important; fill: #ffffff !important; } .adtool-pro-config-conditional { margin-left: 20px; padding: 10px; background: rgba(255, 255, 255, 0.1); border-radius: 8px; margin-top: 10px; display: none; } .adtool-pro-config-conditional.show { display: block; } /* Đảm bảo tất cả text trong config đều có màu trắng */ .adtool-pro-config * { color: #ffffff !important; } /* Ngoại lệ cho input fields */ .adtool-pro-config input[type="number"], .adtool-pro-config input[type="text"] { color: #333 !important; -webkit-text-fill-color: #333 !important; } /* CSS cho section ủng hộ */ .adtool-pro-support-section { display: flex; justify-content: space-between; align-items: center; margin: 20px 0; padding: 20px; background: rgba(255, 255, 255, 0.1); border-radius: 15px; border: 1px solid rgba(255, 255, 255, 0.2); position: relative; } .adtool-pro-support-left, .adtool-pro-support-right { flex: 1; text-align: center; padding: 15px; } .adtool-pro-support-title { font-size: 16px; font-weight: bold; color: #FFD700; text-shadow: 0 0 10px rgba(255, 215, 0, 0.5); margin-bottom: 15px; padding: 10px; background: rgba(255, 215, 0, 0.1); border-radius: 10px; border: 1px solid rgba(255, 215, 0, 0.3); } .adtool-pro-qr-container { display: flex; justify-content: center; align-items: center; margin-top: 10px; } .adtool-pro-qr-code { transition: transform 0.3s ease; } .adtool-pro-qr-code:hover { transform: scale(1.1); } .adtool-pro-qr-placeholder { transition: transform 0.3s ease, box-shadow 0.3s ease; cursor: pointer; } .adtool-pro-qr-placeholder:hover { transform: scale(1.1); box-shadow: 0 0 20px rgba(255, 255, 255, 0.5); } /* Divider giữa 2 khoảng */ .adtool-pro-support-section::before { content: ''; position: absolute; left: 50%; top: 20px; bottom: 20px; width: 2px; background: linear-gradient(to bottom, transparent, rgba(255, 255, 255, 0.5), transparent); } `; document.head.appendChild(style); const modal = document.createElement('div'); modal.className = 'adtool-pro-modal'; modal.innerHTML = `
SCRIPTS TÁCH - KÍCH HOẠT - ĐỔI TÊN
XÓA ADMIN & ANALYSTS TÀI KHOẢN QUẢNG CÁO
Copyright by HASoftware Ads Solution
Liên hệ Telegram Admin nếu gặp sự cố: @HoangAnhDev
Developer:Trịnh Hoàng Anh
Đóng góp API: Ban Do & Tánh Gold
💝 Ủng hộ chúng tôi nếu thấy Code ngon
QR Code Ủng hộ
⏳ Đang khởi tạo...
Chuẩn bị bắt đầu quá trình
⚙️ Cài đặt
🎯 Tích chọn chức năng
🏷️ Cấu hình đổi tên
👤 Cấu hình xóa admin & analysts
TÁCH TÀI KHOẢN QUẢNG CÁO
0% (0/${stats.tachTargetSuccess})
0
✅ Thành công
0
❌ Thất bại
0
⏱️ Đã xử lý
0
🔄 Đang xử lý
⚡ Đang tách:
REACTIVE TÀI KHOẢN
0% (0/0)
0
✅ Thành công
0
❌ Thất bại
0
⏭️ Bỏ qua
0
📊 Đang xử lý
⚡ Đang kích hoạt:
🏷️ THỐNG KÊ ĐỔI TÊN
0
✅ Thành công
0
❌ Thất bại
0
📊 Tổng cộng
0
📊 Đang xử lý
🏷️ Đang đổi tên:
👤 THỐNG KÊ XÓA ADMIN & ANALYSTS
0
✅ Thành công
0
❌ Thất bại
0
📊 Tổng cộng
0
📊 Đang xử lý
0
👑 Admin đã xóa
0
📊 Analyst đã xóa
👤 Đang xóa admin:
🎉
HOÀN THÀNH TOÀN BỘ QUÁ TRÌNH!
`; document.body.appendChild(modal); // Thêm event listeners cho các nút addEventListeners(); return modal; } // Hàm thêm event listeners function addEventListeners() { try { console.log('🔧 Đang thêm event listeners...'); const startButton = document.getElementById('startButton'); const stopButton = document.getElementById('stopButton'); const closeButton = document.getElementById('closeButton'); console.log('🔍 Tìm thấy các nút:', { startButton: !!startButton, stopButton: !!stopButton, closeButton: !!closeButton }); if (startButton) { startButton.addEventListener('click', function(e) { e.preventDefault(); console.log('🚀 Bấm nút Start - Bắt đầu quá trình'); mainCombinedProcess(); }); console.log('✅ Đã thêm event listener cho nút Start'); } if (stopButton) { stopButton.addEventListener('click', function(e) { e.preventDefault(); console.log('🛑 Bấm nút Stop - Dừng quá trình'); stopAdToolPro(); }); console.log('✅ Đã thêm event listener cho nút Stop'); } if (closeButton) { closeButton.addEventListener('click', function(e) { e.preventDefault(); console.log('❌ Bấm nút Close - Đóng giao diện'); closeCombinedWebUI(); }); console.log('✅ Đã thêm event listener cho nút Close'); } // Thêm event listeners cho các tùy chọn mới const enableTachCheckbox = document.getElementById('enableTach'); const enableKichHoatCheckbox = document.getElementById('enableKichHoat'); const enableRenameCheckbox = document.getElementById('enableRename'); const renameModeRadios = document.querySelectorAll('input[name="renameMode"]'); const fixedNameInput = document.getElementById('fixedName'); const businessNameInput = document.getElementById('businessName'); if (enableTachCheckbox) { enableTachCheckbox.addEventListener('change', function() { console.log('⛏️ Tích chọn tách TKQC:', this.checked); }); } if (enableKichHoatCheckbox) { enableKichHoatCheckbox.addEventListener('change', function() { console.log('🔓 Tích chọn kích hoạt TKQC:', this.checked); }); } if (enableRenameCheckbox) { enableRenameCheckbox.addEventListener('change', function() { const renameConfigSection = document.getElementById('renameConfigSection'); if (this.checked) { renameConfigSection.classList.add('show'); // Tự động lấy tên doanh nghiệp nếu chưa có if (!stats.config.businessName) { getBusinessName(); } } else { renameConfigSection.classList.remove('show'); } console.log('🏷️ Tích chọn đổi tên TKQC:', this.checked); }); } if (renameModeRadios.length > 0) { renameModeRadios.forEach(radio => { radio.addEventListener('change', function() { if (this.value === 'business') { getBusinessName(); } }); }); } if (fixedNameInput) { fixedNameInput.addEventListener('input', function() { stats.config.fixedName = this.value; }); } // Thêm event listeners cho xóa admin & analysts const enableRemoveAdminCheckbox = document.getElementById('enableRemoveAdmin'); const removeAdminTypeRadios = document.querySelectorAll('input[name="removeAdminType"]'); const removeAdminDelayInput = document.getElementById('removeAdminDelay'); if (enableRemoveAdminCheckbox) { enableRemoveAdminCheckbox.addEventListener('change', function() { const removeAdminConfigSection = document.getElementById('removeAdminConfigSection'); if (this.checked) { removeAdminConfigSection.classList.add('show'); } else { removeAdminConfigSection.classList.remove('show'); } console.log('👤 Tích chọn xóa admin & analysts:', this.checked); }); } if (removeAdminTypeRadios.length > 0) { removeAdminTypeRadios.forEach(radio => { radio.addEventListener('change', function() { // Reset tất cả config stats.config.removeAdminOnly = false; stats.config.removeAnalystOnly = false; stats.config.removeBoth = false; // Set config theo radio được chọn switch(this.value) { case 'admin': stats.config.removeAdminOnly = true; break; case 'analyst': stats.config.removeAnalystOnly = true; break; case 'both': stats.config.removeBoth = true; break; } console.log('👤 Chọn loại user xóa:', this.value); }); }); } if (removeAdminDelayInput) { removeAdminDelayInput.addEventListener('input', function() { stats.config.removeAdminDelay = parseInt(this.value) || 2; console.log('⏱️ Cập nhật delay xóa admin:', stats.config.removeAdminDelay); }); } console.log('✅ Đã thêm event listeners thành công'); } catch (error) { console.error('❌ Lỗi khi thêm event listeners:', error); } } // Hàm lấy tên doanh nghiệp async function getBusinessName() { try { const businessId = require("BusinessUnifiedNavigationContext").businessID; const accessToken = require("WebApiApplication").getAccessToken(); const response = await fetch(`https://graph.facebook.com/v19.0/${businessId}?fields=name&access_token=${accessToken}`, { method: 'GET', credentials: 'include' }); const data = await response.json(); if (data && data.name) { stats.config.businessName = data.name; const businessNameInput = document.getElementById('businessName'); if (businessNameInput) { businessNameInput.value = data.name; } console.log('✅ Đã lấy tên doanh nghiệp:', data.name); } } catch (error) { console.error('❌ Lỗi khi lấy tên doanh nghiệp:', error); } } // Cập nhật giao diện tổng hợp function updateCombinedWebUI() { // Cập nhật phần tách tài khoản const tachProgressFill = document.getElementById('tachProgressFill'); const tachProgressText = document.getElementById('tachProgressText'); const tachSuccessCount = document.getElementById('tachSuccessCount'); const tachFailureCount = document.getElementById('tachFailureCount'); const tachTotalProcessed = document.getElementById('tachTotalProcessed'); const tachActiveRequests = document.getElementById('tachActiveRequests'); const tachCurrentAccounts = document.getElementById('tachCurrentAccounts'); if (tachProgressFill && tachProgressText) { const percentage = Math.round((stats.tachSuccessCount / stats.config.targetSuccess) * 100); tachProgressFill.style.width = percentage + '%'; tachProgressText.textContent = `${percentage}% (${stats.tachSuccessCount}/${stats.config.targetSuccess})`; } if (tachSuccessCount) tachSuccessCount.textContent = stats.tachSuccessCount; if (tachFailureCount) tachFailureCount.textContent = stats.tachFailureCount; if (tachTotalProcessed) tachTotalProcessed.textContent = stats.tachTotalProcessed; if (tachActiveRequests) tachActiveRequests.textContent = stats.tachActiveRequests; if (tachCurrentAccounts) { if (stats.tachCurrentAccounts.length > 0) { tachCurrentAccounts.innerHTML = stats.tachCurrentAccounts .slice(0, 8) .map(account => ``) .join(''); if (stats.tachCurrentAccounts.length > 8) { tachCurrentAccounts.innerHTML += ``; } } else { tachCurrentAccounts.innerHTML = ''; } } // Cập nhật phần kích hoạt tài khoản const kichHoatProgressFill = document.getElementById('kichHoatProgressFill'); const kichHoatProgressText = document.getElementById('kichHoatProgressText'); const kichHoatSuccess = document.getElementById('kichHoatSuccess'); const kichHoatFailed = document.getElementById('kichHoatFailed'); const kichHoatSkipped = document.getElementById('kichHoatSkipped'); const kichHoatCurrent = document.getElementById('kichHoatCurrent'); const kichHoatCurrentAccounts = document.getElementById('kichHoatCurrentAccounts'); if (kichHoatProgressFill && kichHoatProgressText) { // Tính số tài khoản đã xử lý (thành công + thất bại) const kichHoatProcessed = stats.kichHoatSuccess + stats.kichHoatFailed; const percentage = stats.kichHoatTotal > 0 ? Math.round((kichHoatProcessed / stats.kichHoatTotal) * 100) : 0; kichHoatProgressFill.style.width = percentage + '%'; kichHoatProgressText.textContent = `${percentage}% (${kichHoatProcessed}/${stats.kichHoatTotal})`; } if (kichHoatSuccess) kichHoatSuccess.textContent = stats.kichHoatSuccess; if (kichHoatFailed) kichHoatFailed.textContent = stats.kichHoatFailed; if (kichHoatSkipped) kichHoatSkipped.textContent = stats.kichHoatSkipped; if (kichHoatCurrent) kichHoatCurrent.textContent = stats.kichHoatCurrent; if (kichHoatCurrentAccounts) { if (stats.kichHoatIsRunning) { kichHoatCurrentAccounts.innerHTML = ''; } else if (stats.kichHoatSuccess > 0 || stats.kichHoatFailed > 0) { kichHoatCurrentAccounts.innerHTML = ''; } else { kichHoatCurrentAccounts.innerHTML = ''; } } // Cập nhật phần đổi tên const renameSuccess = document.getElementById('renameSuccess'); const renameFailed = document.getElementById('renameFailed'); const renameTotal = document.getElementById('renameTotal'); const renameCurrent = document.getElementById('renameCurrent'); const renameCurrentAccounts = document.getElementById('renameCurrentAccounts'); if (renameSuccess) renameSuccess.textContent = stats.renameSuccess; if (renameFailed) renameFailed.textContent = stats.renameFailed; if (renameTotal) renameTotal.textContent = stats.renameTotal; if (renameCurrent) renameCurrent.textContent = stats.renameCurrent; if (renameCurrentAccounts) { if (stats.renameIsRunning) { renameCurrentAccounts.innerHTML = ''; } else if (stats.renameSuccess > 0 || stats.renameFailed > 0) { renameCurrentAccounts.innerHTML = ''; } else { renameCurrentAccounts.innerHTML = ''; } } // Cập nhật phần xóa admin & analysts const removeAdminSuccess = document.getElementById('removeAdminSuccess'); const removeAdminFailed = document.getElementById('removeAdminFailed'); const removeAdminTotal = document.getElementById('removeAdminTotal'); const removeAdminCurrent = document.getElementById('removeAdminCurrent'); const removeAdminAdminsRemoved = document.getElementById('removeAdminAdminsRemoved'); const removeAdminAnalystsRemoved = document.getElementById('removeAdminAnalystsRemoved'); const removeAdminCurrentAccounts = document.getElementById('removeAdminCurrentAccounts'); if (removeAdminSuccess) removeAdminSuccess.textContent = stats.removeAdminSuccess; if (removeAdminFailed) removeAdminFailed.textContent = stats.removeAdminFailed; if (removeAdminTotal) removeAdminTotal.textContent = stats.removeAdminTotal; if (removeAdminCurrent) removeAdminCurrent.textContent = stats.removeAdminCurrent; if (removeAdminAdminsRemoved) removeAdminAdminsRemoved.textContent = stats.removeAdminAdminsRemoved; if (removeAdminAnalystsRemoved) removeAdminAnalystsRemoved.textContent = stats.removeAdminAnalystsRemoved; if (removeAdminCurrentAccounts) { if (stats.removeAdminIsRunning) { removeAdminCurrentAccounts.innerHTML = ''; } else if (stats.removeAdminSuccess > 0 || stats.removeAdminFailed > 0) { removeAdminCurrentAccounts.innerHTML = ''; } else { removeAdminCurrentAccounts.innerHTML = ''; } } } // Cập nhật chỉ báo pha function updatePhaseIndicator(phase, description) { const phaseIndicator = document.getElementById('phaseIndicator'); const phaseText = document.getElementById('phaseIndicator').querySelector('.adtool-pro-phase-text'); const phaseDescription = document.getElementById('phaseIndicator').querySelector('.adtool-pro-phase-description'); if (phaseIndicator && phaseText && phaseDescription) { stats.currentPhase = phase; switch(phase) { case 'tach': phaseText.textContent = '⛏ ĐANG TÁCH TÀI KHOẢN'; phaseDescription.textContent = description || 'Đang tách tài khoản quảng cáo từ Business Manager'; break; case 'kichhoat': phaseText.textContent = '🔓 ĐANG KÍCH HOẠT TÀI KHOẢN'; phaseDescription.textContent = description || 'Đang kích hoạt lại các tài khoản đã tách'; break; case 'rename': phaseText.textContent = '🏷️ ĐANG ĐỔI TÊN TÀI KHOẢN'; phaseDescription.textContent = description || 'Đang đổi tên các tài khoản đã tách'; break; case 'removeadmin': phaseText.textContent = '👤 ĐANG XÓA ADMIN & ANALYSTS'; phaseDescription.textContent = description || 'Đang xóa admin và nhà phân tích khác khỏi tài khoản'; break; case 'completed': phaseText.textContent = '✅ HOÀN THÀNH'; phaseDescription.textContent = description || 'Tất cả quá trình đã hoàn tất'; break; default: phaseText.textContent = '⏳ ĐANG KHỞI TẠO'; phaseDescription.textContent = description || 'Chuẩn bị bắt đầu quá trình'; } } } // Hiển thị timer đếm ngược function showTimer(seconds) { const timerDisplay = document.getElementById('timerDisplay'); const timerCountdown = document.getElementById('timerCountdown'); if (timerDisplay && timerCountdown) { timerDisplay.style.display = 'block'; timerCountdown.textContent = seconds; const countdown = setInterval(() => { seconds--; timerCountdown.textContent = seconds; if (seconds <= 0) { clearInterval(countdown); timerDisplay.style.display = 'none'; } }, 1000); } } // Hiển thị thông báo hoàn thành function showCompletionCombinedWebUI() { const completionSection = document.getElementById('completionSection'); const completionStats = document.getElementById('completionStats'); if (completionSection && completionStats) { const tachEndTime = new Date(); const tachDuration = Math.round((tachEndTime - stats.tachStartTime) / 1000); const tachSuccessRate = stats.tachTotalProcessed > 0 ? Math.round((stats.tachSuccessCount / stats.tachTotalProcessed) * 100) : 0; const kichHoatEndTime = new Date(); const kichHoatDuration = stats.kichHoatStartTime ? Math.round((kichHoatEndTime - stats.kichHoatStartTime) / 1000) : 0; // Tính tỷ lệ thành công cho kích hoạt const kichHoatProcessed = stats.kichHoatSuccess + stats.kichHoatFailed; const kichHoatSuccessRate = kichHoatProcessed > 0 ? Math.round((stats.kichHoatSuccess / kichHoatProcessed) * 100) : 0; completionStats.innerHTML = `
🔧 TÁCH TÀI KHOẢN: ${stats.tachSuccessCount}/${stats.config.targetSuccess} thành công
📊 Tổng xử lý: ${stats.tachTotalProcessed}
✅ Thành công: ${stats.tachSuccessCount}
❌ Thất bại: ${stats.tachFailureCount}
📈 Tỷ lệ thành công: ${tachSuccessRate}%
⏱️ Thời gian tách: ${tachDuration} giây
🔓 KÍCH HOẠT TÀI KHOẢN: ${stats.kichHoatSuccess}/${kichHoatProcessed} thành công
📊 Tổng tài khoản: ${stats.kichHoatTotal}
✅ Thành công: ${stats.kichHoatSuccess}
❌ Thất bại: ${stats.kichHoatFailed}
⏭️ Bỏ qua: ${stats.kichHoatSkipped}
📈 Tỷ lệ thành công: ${kichHoatSuccessRate}%
⏱️ Thời gian kích hoạt: ${kichHoatDuration} giây
🏷️ ĐỔI TÊN TÀI KHOẢN: ${stats.renameSuccess}/${stats.renameTotal} thành công
📊 Tổng tài khoản: ${stats.renameTotal}
✅ Thành công: ${stats.renameSuccess}
❌ Thất bại: ${stats.renameFailed}
⏭️ Bỏ qua: ${stats.renameSkipped}
📈 Tỷ lệ thành công: ${Math.round((stats.renameSuccess / stats.renameTotal) * 100)}%
⏱️ Thời gian đổi tên: ${stats.renameStartTime ? Math.round((new Date() - stats.renameStartTime) / 1000) : 0} giây
👤 XÓA ADMIN & ANALYSTS: ${stats.removeAdminSuccess}/${stats.removeAdminTotal} thành công
📊 Tổng tài khoản: ${stats.removeAdminTotal}
✅ Thành công: ${stats.removeAdminSuccess}
❌ Thất bại: ${stats.removeAdminFailed}
👑 Admin đã xóa: ${stats.removeAdminAdminsRemoved}
📊 Analyst đã xóa: ${stats.removeAdminAnalystsRemoved}
📈 Tỷ lệ thành công: ${Math.round((stats.removeAdminSuccess / stats.removeAdminTotal) * 100)}%
⏱️ Thời gian xóa admin: ${stats.removeAdminStartTime ? Math.round((new Date() - stats.removeAdminStartTime) / 1000) : 0} giây
🎯 TỔNG KẾT: ${stats.tachSuccessCount + stats.kichHoatSuccess + stats.renameSuccess + stats.removeAdminSuccess} tài khoản hoàn tất
⚡ Tổng thời gian: ${(stats.tachStartTime ? Math.round((new Date() - stats.tachStartTime) / 1000) : 0) + (stats.kichHoatStartTime ? Math.round((new Date() - stats.kichHoatStartTime) / 1000) : 0) + (stats.renameStartTime ? Math.round((new Date() - stats.renameStartTime) / 1000) : 0) + (stats.removeAdminStartTime ? Math.round((new Date() - stats.removeAdminStartTime) / 1000) : 0)} giây
`; completionSection.classList.add('show'); } } // Đóng giao diện function closeCombinedWebUI() { const modal = document.querySelector('.adtool-pro-modal'); if (modal) { modal.style.animation = 'slideOut 0.3s ease-in forwards'; setTimeout(() => { modal.remove(); }, 300); } } // Thêm CSS cho animation đóng const closeStyle = document.createElement('style'); closeStyle.textContent = ` @keyframes slideOut { from { transform: translateY(0); opacity: 1; } to { transform: translateY(-50px); opacity: 0; } } `; document.head.appendChild(closeStyle); // ==================== PHẦN TÁCH TÀI KHOẢN ==================== async function getReadOnlyAccountIds() { const request = await fetch(`https://graph.facebook.com/v17.0/${require('BusinessUnifiedNavigationContext').businessID}/owned_ad_accounts?access_token=${require('WebApiApplication').getAccessToken()}&__activeScenarioIDs=%5B%5D&__activeScenarios=%5B%5D&__interactionsMetadata=%5B%5D&_reqName=object%3Abusiness%2Fowned_ad_accounts&_reqSrc=BusinessConnectedOwnedAdAccountsStore.brands&date_format=U&fields=%5B%22id%22%2C%22name%22%2C%22account_id%22%2C%22account_status%22%2C%22business%22%2C%22created_time%22%2C%22currency%22%2C%22timezone_name%22%2C%22end_advertiser%22%2C%22end_advertiser_name%22%2C%22invoicing_emails%22%2C%22is_disabled_umbrella%22%2C%22last_spend_time%22%2C%22funding_source%22%2C%22can_be_blocked_from_pixel_sharing%22%2C%22disable_reason%22%2C%22bill_to_org.fields(legal_entity_name)%22%2C%22onbehalf_requests.fields(receiving_business.fields(name)%2Cstatus)%22%5D&filtering=%5B%7B%22field%22%3A%22account_status%22%2C%22operator%22%3A%22NOT_EQUAL%22%2C%22value%22%3A%226%22%7D%5D&limit=10000&locale=vi_VN&method=get&pretty=0&sort=name_ascending&suppress_http_code=1&xref=f41c4c0b703bc`, { "headers": { "content-type": "application/x-www-form-urlencoded" }, "method": "GET", "mode": "cors", "credentials": "include" }); const text = await request.text(); const data = JSON.parse(text).data; // Lọc các tài khoản có "Read-Only" trong tên const readOnlyIds = data .filter(item => item.name && item.name.includes("Read-Only")) .map(item => item.account_id); return readOnlyIds; } // Cập nhật API addpermission để đồng bộ với tài liệu async function addpermission(adAccountId) { const rawJson = { input: { business_id: require("BusinessUnifiedNavigationContext").businessID, payment_legacy_account_id: adAccountId, actor_id: require("CurrentUserInitialData").USER_ID, client_mutation_id: "3" // Cập nhật từ "2" thành "3" theo tài liệu } }; const encodedJson = encodeURIComponent(JSON.stringify(rawJson)); const url = `https://graph.facebook.com/graphql?method=post&locale=en_US&pretty=false&format=json&fb_api_req_friendly_name=useBillingSelfGrantManageAdAccountMutation&doc_id=24037132059206200&fb_api_caller_class=RelayModern&server_timestamps=true&variables=${encodedJson}&access_token=${require("WebApiApplication").getAccessToken()}`; // Cập nhật doc_id từ 6600383160000030 thành 24037132059206200 try { const response = await fetch(url, { method: 'GET', credentials: 'include' }); const data = await response.json(); const billingWritePermission = data?.data?.grant_manage_ad_account?.ad_account?.viewer_permissions?.billing_write; if (billingWritePermission) { return { status: true, error: null }; } else { return { status: false, error: data }; } } catch (err) { return { status: false, error: err }; } } async function CloseAdAccount(adAccountId) { const StringPost = `jazoest=25524&fb_dtsg=${require("DTSGInitData").token}&account_id=${adAccountId}&__usid=6-Tskqo1h1o56glr%3APskqo1h16o00sk%3A0-Askqn631d2395g-RV%3D6%3AF%3D&__aaid=0&__bid=${require("BusinessUnifiedNavigationContext").businessID}&__user=${require("CurrentUserInitialData").USER_ID}&__a=1&__req=y&__hs=19998.BP%3Abrands_pkg.2.0..0.0&dpr=1&__ccg=EXCELLENT&__rev=1016990685&__s=axc5os%3A4n4eqp%3A948yz8&__hsi=7421228722412779754&__dyn=7xeUmxa2C5rgydwCwRyUbFp4Unxim2q1Dxuq3mq1FxebzA3miidBxa7EiwnobES2S2q1Ex21FxG9y8Gdz8hw9-3a4EuCwQwCxq0yFE4WqbwQzobVqxN0Cmu3mbx-261UxO4UkK2y1gwBwXwEw-G2mcwuE2Bz84a9DxW10wywWjxCU5-u2C2l0Fg2uwEwiUmwoErorx2aK2a4p8aHwzzXx-ewjovCxeq4o884O1fwwxefzo5G4E5yeDyU52dwyw-z8c8-5aDwQwKG13y86qbxa4o-2-qaUK2e0UFU2RwrU6CiU9E4KeCK2q5UpwDwjouxK2i2y1sDw4kwtU5K2G0BE&__csr=&lsd=h2GQa8HPsn-MsvTtASY4gX&__spin_r=1016990685&__spin_b=trunk&__spin_t=1727889460&__jssesw=1`; const url = `https://business.facebook.com/ads/ajax/account_close`; try { const response = await fetch(url, { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: StringPost }); let text = await response.text(); if (text.startsWith('for (;;);')) { text = text.slice('for (;;);'.length); } const data = JSON.parse(text); if (Array.isArray(data?.payload) && data.payload.length === 0) { return { status: true, error: null }; } else { return { status: false, error: data }; } } catch (err) { return { status: false, error: err }; } } // Hàm xử lý một tài khoản (song song) async function processSingleAccount(accountId, index) { stats.tachActiveRequests++; // Thêm tài khoản vào danh sách đang xử lý const accountDisplay = `${accountId} (${index} - Thành công: ${stats.tachSuccessCount}/${stats.config.targetSuccess})`; stats.tachCurrentAccounts.push(accountDisplay); updateCombinedWebUI(); try { console.log(`🔄 [${index}] Bắt đầu xử lý ${accountId}...`); const addpermissionResult = await addpermission(accountId); if (addpermissionResult.status) { console.log(`✅ [${index}] ADD People ${accountId}: SUCCESS`); const TachAds = await CloseAdAccount(accountId); if (TachAds.status) { console.log(`✅ [${index}] TÁCH ${accountId}: SUCCESS`); stats.tachSuccessCount++; // Kiểm tra nếu đã đạt đủ số tài khoản thành công if (stats.tachSuccessCount >= stats.config.targetSuccess) { stats.tachTotalProcessed++; updateCombinedWebUI(); return { completed: true, reason: 'target_reached' }; } } else { console.error(`❌ [${index}] TÁCH ${accountId} error:`, TachAds.error); stats.tachFailureCount++; // Kiểm tra nếu số lần thất bại vượt quá ngưỡng if (stats.tachFailureCount >= stats.config.failureThresholdToKichHoat) { stats.tachTotalProcessed++; updateCombinedWebUI(); return { completed: true, reason: 'failure_threshold' }; } } } else { console.error(`❌ [${index}] ADD People ${accountId} error:`, addpermissionResult.error); stats.tachFailureCount++; // Kiểm tra nếu số lần thất bại vượt quá ngưỡng if (stats.tachFailureCount >= stats.config.failureThresholdToKichHoat) { stats.tachTotalProcessed++; updateCombinedWebUI(); return { completed: true, reason: 'failure_threshold' }; } } stats.tachTotalProcessed++; // Delay giữa các tài khoản nếu được bật if (stats.config.enableDelayBetweenAccounts && stats.config.delayBetweenAccounts > 0) { await new Promise(resolve => setTimeout(resolve, stats.config.delayBetweenAccounts * 1000)); } } catch (error) { console.error(`❌ [${index}] Lỗi xử lý ${accountId}:`, error); stats.tachFailureCount++; stats.tachTotalProcessed++; // Kiểm tra nếu số lần thất bại vượt quá ngưỡng if (stats.tachFailureCount >= stats.config.failureThresholdToKichHoat) { updateCombinedWebUI(); return { completed: true, reason: 'failure_threshold' }; } } finally { // Xóa tài khoản khỏi danh sách đang xử lý const accountIndex = stats.tachCurrentAccounts.indexOf(accountDisplay); if (accountIndex > -1) { stats.tachCurrentAccounts.splice(accountIndex, 1); } stats.tachActiveRequests--; updateCombinedWebUI(); } return { completed: false, reason: null }; } async function processAccountsParallel(accountIds) { console.log(`🚀 Bắt đầu xử lý SONG SONG ${accountIds.length} tài khoản (Cần thêm ${stats.tachTargetSuccess - stats.tachSuccessCount} tài khoản thành công)`); console.log(`⚡ Xử lý đồng thời tối đa: ${stats.tachMaxConcurrentRequests} tài khoản`); // Tạo tất cả promises cùng lúc const promises = accountIds.map((accountId, index) => { const globalIndex = stats.tachTotalProcessed + index + 1; return processSingleAccount(accountId, globalIndex); }); // Chờ tất cả hoàn thành const results = await Promise.all(promises); // Kiểm tra kết quả for (const result of results) { if (result.completed) { return result; } } return { completed: false, reason: null }; } async function startTachProcess() { stats.tachStartTime = new Date(); stats.tachIsRunning = true; stats.currentPhase = 'tach'; updatePhaseIndicator('tach', 'Đang tách tài khoản quảng cáo từ Business Manager'); console.log('🎯 BẮT ĐẦU TÁCH TÀI KHOẢN QUẢNG CÁO (SONG SONG - GIỚI HẠN THEO THÀNH CÔNG)'); console.log(` Mục tiêu: ${stats.config.targetSuccess} tài khoản THÀNH CÔNG`); console.log(`⚡ Chế độ: Xử lý đồng thời tối đa ${stats.tachMaxConcurrentRequests} tài khoản`); console.log(`⏰ Thời gian bắt đầu: ${stats.tachStartTime.toLocaleString()}`); console.log('=====================================\n'); while (stats.tachIsRunning && stats.isRunning) { const accountIds = await getReadOnlyAccountIds(); if (accountIds.length > 0) { const result = await processAccountsParallel(accountIds); if (result.completed) { console.log(`🎉 Dừng quá trình tách: ${result.reason}`); if (result.reason === 'target_reached') { console.log('✅ Đã đạt đủ số tài khoản thành công!'); } else if (result.reason === 'failure_threshold') { console.log('⚠️ Số lần thất bại vượt quá ngưỡng! Chuyển sang kích hoạt tài khoản.'); } break; } } else { console.log("Không tìm thấy tài khoản Read-Only nào."); stats.tachCurrentAccounts = ["Không tìm thấy tài khoản Read-Only"]; updateCombinedWebUI(); } await new Promise(resolve => setTimeout(resolve, 5000)); // Đợi 5 giây } stats.tachIsRunning = false; return stats.tachSuccessCount; } // ==================== PHẦN KÍCH HOẠT TÀI KHOẢN ==================== // Lấy access token và các thông tin cần thiết function getRequiredData() { let access_token; let fb_dtsg2 = require("DTSGInitialData").token || document.querySelector('[name="fb_dtsg"]').value; let uid = require("CurrentUserInitialData").USER_ID || document.cookie.match(/c_user=(\d+)/)[1]; try { access_token = require("WebApiApplication").getAccessToken(); } catch (error) { } if (access_token === undefined || access_token === '') { console.error('Lỗi: Không thể lấy access token. Vui lòng đảm bảo đã đăng nhập Facebook và thử lại'); return null; } return { access_token, fb_dtsg2, uid }; } async function getBusinesses2(access_token) { const ver = "v14.0"; const response = await fetch( `https://graph.facebook.com/${ver}/me?fields=id,name,adaccounts.limit(1000){account_status,created_time,owner,name}&access_token=${access_token}`, { method: 'GET', credentials: 'include', } ); const json = await response.json(); return json; } async function action2(businessID, index, total, accountName, access_token, fb_dtsg2, uid) {const url = `https://business.facebook.com/api/graphql/?_callFlowletID=0&_triggerFlowletID=78266`; try { console.log(`🔄 [${index + 1}/${total}] Gửi request kích hoạt act_${businessID}`); const response = await fetch(url, { method: 'POST', body: `av=${uid}&__usid=...&fb_dtsg=${fb_dtsg2}&...&doc_id=9984888131552276...`, // viết ngắn lại phần dài dòng headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); const responseText = await response.text(); console.log(`📄 [${index + 1}/${total}] Response cho act_${businessID}: ${responseText.substring(0, 200)}...`); if (responseText.includes('status":"ADMARKET_ACCOUNT_STATUS_ACTIVE')) { stats.kichHoatSuccess++; console.log(`${index + 1}/${total} act_${businessID} | -> ✅ Thành công`); // Thêm chức năng đổi tên sau khi kích hoạt thành công if (stats.config.enableRename) { try { const accountInfo = await getAccountInfo(businessID); let shouldRename = true; if (stats.config.onlyPersonalAccounts && !window.isPersonalAccount(accountInfo)) { shouldRename = false; console.log(`${index + 1}/${total} act_${businessID} | -> ⏭️ Bỏ qua đổi tên (TKQC thuộc Business Manager)`); } if (shouldRename) { const newName = window.generateNewAccountName(`act_${businessID}`, accountInfo); console.log(`${index + 1}/${total} act_${businessID} | -> 🏷️ Đang đổi tên thành: ${newName}`); const renameResult = await window.renameAds(businessID, newName); if (renameResult.status) { stats.renameSuccess++; if (renameResult.retryCount > 0) { stats.renameRetryCount += renameResult.retryCount; } const retryInfo = renameResult.retryCount > 0 ? ` (sau ${renameResult.retryCount} lần thử)` : ''; console.log(`✅ [${index + 1}/${total}] ${businessID} | -> ✅ Đổi tên thành công: ${newName}${retryInfo}`); } else { if (renameResult.noPermission) { stats.renameSkipped++; console.log(`⏭️ [${index + 1}/${total}] ${businessID} | -> ⏭️ Bỏ qua (không có quyền): ${renameResult.error}`); } else { stats.renameFailed++; if (renameResult.retryCount > 0) { stats.renameRetryCount += renameResult.retryCount; } const retryInfo = renameResult.retryCount > 0 ? ` (đã thử ${renameResult.retryCount} lần)` : ''; console.log(`❌ [${index + 1}/${total}] ${businessID} | -> ❌ Đổi tên thất bại${retryInfo}:`, renameResult.error); } } } } catch (renameError) { console.log(`${index + 1}/${total} act_${businessID} | -> ⚠️ Lỗi khi đổi tên:`, renameError); } } } else { stats.kichHoatFailed++; console.log(`${index + 1}/${total} act_${businessID} | -> ❌ Thất bại: ${responseText.substring(0, 100)}`); } stats.kichHoatProcessing--; } catch (error) { stats.kichHoatFailed++; stats.kichHoatProcessing--; console.log(`${index + 1}/${total} act_${businessID} | -> ❌ Lỗi: ${error.message}`); } } // Hàm lấy thông tin tài khoản quảng cáo async function getAccountInfo(accountId) { try { const accessToken = require("WebApiApplication").getAccessToken(); const response = await fetch(`https://graph.facebook.com/v19.0/act_${accountId}?fields=id,name,owner_business,account_status&access_token=${accessToken}`, { method: 'GET', credentials: 'include' }); const data = await response.json(); return data; } catch (error) { console.error('❌ Lỗi khi lấy thông tin tài khoản:', error); return { owner_business: null }; // Fallback } } // Thay đổi logic kích hoạt từ tuần tự sang song song async function action1(index, arr, access_token, fb_dtsg2, uid) { const total = arr.data.adaccounts.data.length; stats.kichHoatTotal = total; stats.kichHoatCurrent = index; if (index >= total) { console.log(`🎉 Hoàn thành kích hoạt! Thành công: ${stats.kichHoatSuccess}/${stats.kichHoatTotal}`); stats.kichHoatIsRunning = false; return; } // Kiểm tra nếu đã dừng if (!stats.isRunning) { console.log('🛑 Đã dừng chương trình kích hoạt'); stats.kichHoatIsRunning = false; return; } try { const data = arr.data.adaccounts.data[index]; const businessID = data.id.replace("act_", ""); if (data.account_status === 100 || data.account_status === 101) { stats.kichHoatProcessing++; console.log(`🔄 [${index + 1}/${total}] Bắt đầu kích hoạt act_${businessID}`); // Kiểm tra lại trạng thái dừng trước khi gọi action2 if (!stats.isRunning) { console.log('🛑 Đã dừng chương trình kích hoạt'); stats.kichHoatIsRunning = false; return; } // Gọi action2 không await để xử lý song song action2(businessID, index, total, data.name, access_token, fb_dtsg2, uid); } else { stats.kichHoatSkipped++; console.log(`${index + 1}/${total} act_${businessID} | -> Bỏ qua (trạng thái: ${data.account_status})`); } } catch (e) { stats.kichHoatFailed++; console.log(`❌ Lỗi xử lý tài khoản ${index + 1}:`, e); } finally { // Tăng index và cập nhật UI const nextIndex = index + 1; stats.kichHoatCurrent = nextIndex; updateCombinedWebUI(); // Giảm delay để tăng tốc độ await new Promise(resolve => setTimeout(resolve, 10)); // Kiểm tra nếu đã dừng trước khi tiếp tục if (stats.isRunning) { // Gọi đệ quy với nextIndex action1(nextIndex, arr, access_token, fb_dtsg2, uid); } else { console.log('🛑 Đã dừng chương trình kích hoạt'); stats.kichHoatIsRunning = false; } } } // Thêm hàm xử lý song song cho kích hoạt async function processKichHoatParallel(accounts, access_token, fb_dtsg2, uid) { console.log(`🚀 Bắt đầu xử lý SONG SONG ${accounts.length} tài khoản kích hoạt`); // Lấy batch size từ cấu hình const batchSize = parseInt(document.getElementById('kichHoatBatchSize')?.value) || 50; // Chia thành các batch nhỏ để tránh quá tải const batches = []; for (let i = 0; i < accounts.length; i += batchSize) { batches.push(accounts.slice(i, i + batchSize)); } console.log(`📦 Chia thành ${batches.length} batch, mỗi batch ${batchSize} tài khoản`); for (let batchIndex = 0; batchIndex < batches.length; batchIndex++) { if (!stats.isRunning) { console.log('🛑 Đã dừng chương trình kích hoạt'); break; } const batch = batches[batchIndex]; console.log(`🔄 Xử lý batch ${batchIndex + 1}/${batches.length} (${batch.length} tài khoản)`); // Xử lý song song trong batch const promises = batch.map((account, index) => { const globalIndex = batchIndex * batchSize + index; const businessID = account.id.replace("act_", ""); if (account.account_status === 100 || account.account_status === 101) { stats.kichHoatProcessing++; return action2(businessID, globalIndex, accounts.length, account.name, access_token, fb_dtsg2, uid); } else { stats.kichHoatSkipped++; console.log(`${globalIndex + 1}/${accounts.length} act_${businessID} | -> Bỏ qua (trạng thái: ${account.account_status})`); return Promise.resolve(); } }); // Chờ batch hiện tại hoàn thành await Promise.all(promises); // Cập nhật UI sau mỗi batch updateCombinedWebUI(); // Delay nhỏ giữa các batch if (batchIndex < batches.length - 1) { await new Promise(resolve => setTimeout(resolve, 50)); } } console.log(`✅ Hoàn thành xử lý song song! Thành công: ${stats.kichHoatSuccess}/${stats.kichHoatTotal}`); } async function startKichHoatProcess() { const requiredData = getRequiredData(); if (!requiredData) { console.error('Không thể lấy dữ liệu cần thiết'); return 0; } const { access_token, fb_dtsg2, uid } = requiredData; stats.kichHoatStartTime = new Date(); stats.kichHoatIsRunning = true; stats.currentPhase = 'kichhoat'; updatePhaseIndicator('kichhoat', 'Đang kích hoạt lại các tài khoản đã tách'); console.log('🔓 BẮT ĐẦU KÍCH HOẠT TÀI KHOẢN QUẢNG CÁO (SONG SONG)'); console.log(`⏰ Thời gian bắt đầu: ${stats.kichHoatStartTime.toLocaleString()}`); console.log('=====================================\n'); try { console.log('📡 Đang lấy danh sách tài khoản quảng cáo...'); const json = await getBusinesses2(access_token); const arr = { data: json }; console.log(`📊 Tìm thấy ${arr.data.adaccounts.data.length} tài khoản quảng cáo`); // Kiểm tra nếu đã dừng if (!stats.isRunning) { console.log('🛑 Đã dừng chương trình'); stats.kichHoatIsRunning = false; return 0; } console.log('🚀 Bắt đầu xử lý song song...'); // Sử dụng xử lý song song thay vì tuần tự await processKichHoatParallel(arr.data.adaccounts.data, access_token, fb_dtsg2, uid); console.log(`✅ Hoàn thành kích hoạt! Tổng kết: ${stats.kichHoatSuccess}/${stats.kichHoatTotal} thành công`); return stats.kichHoatSuccess; } catch (error) { console.error('❌ Lỗi trong quá trình kích hoạt:', error); stats.kichHoatIsRunning = false; return 0; } } // ==================== HÀM CHÍNH ĐIỀU PHỐI ==================== async function mainCombinedProcess() { // Lấy cấu hình từ giao diện loadConfigFromUI(); stats.isRunning = true; stats.tachStartTime = new Date(); // Khởi tạo thời gian bắt đầu // Cập nhật trạng thái nút updateButtonStates(); console.log('🚀 AD TOOL PRO - BẮT ĐẦU QUÁ TRÌNH TỔNG HỢP'); console.log('====================================='); console.log('📋 Cấu hình chức năng:'); console.log(`⛏️ Tách TKQC: ${stats.config.enableTach ? '✅ Bật' : '❌ Tắt'}`); console.log(`🔓 Kích hoạt TKQC: ${stats.config.enableKichHoat ? '✅ Bật' : '❌ Tắt'}`); console.log(`🏷️ Đổi tên TKQC: ${stats.config.enableRename ? '✅ Bật' : '❌ Tắt'}`); console.log('====================================='); try { // Bước 1: Tách tài khoản (nếu được bật) if (stats.config.enableTach) { console.log('\n🔧 BƯỚC 1: TÁCH TÀI KHOẢN QUẢNG CÁO'); updatePhaseIndicator('tach', 'Đang tách tài khoản quảng cáo từ Business Manager'); const tachResult = await startTachProcess(); console.log(`✅ Hoàn thành tách: ${tachResult} tài khoản thành công`); } else { console.log('\n⏭️ BƯỚC 1: BỎ QUA TÁCH TÀI KHOẢN (Đã tắt)'); updatePhaseIndicator('tach', 'Bỏ qua chức năng tách tài khoản'); } // Kiểm tra nếu đã dừng if (!stats.isRunning) { console.log('🛑 Đã dừng chương trình'); updatePhaseIndicator('idle', 'Đã dừng chương trình'); updateButtonStates(); return; } // Bước 2: Kích hoạt tài khoản (nếu được bật) if (stats.config.enableKichHoat) { // Hiển thị timer đếm ngược nếu có delay if (stats.config.delayBeforeKichHoat > 0) { console.log(`\n⏰ Chờ ${stats.config.delayBeforeKichHoat} giây trước khi kích hoạt...`); updatePhaseIndicator('tach', `Chờ ${stats.config.delayBeforeKichHoat} giây trước khi kích hoạt...`); showTimer(stats.config.delayBeforeKichHoat); // Đợi theo cấu hình await new Promise(resolve => setTimeout(resolve, stats.config.delayBeforeKichHoat * 1000)); } // Kiểm tra nếu đã dừng if (!stats.isRunning) { console.log('🛑 Đã dừng chương trình'); updatePhaseIndicator('idle', 'Đã dừng chương trình'); updateButtonStates(); return; } console.log('\n🔓 BƯỚC 2: KÍCH HOẠT TÀI KHOẢN QUẢNG CÁO'); updatePhaseIndicator('kichhoat', 'Đang kích hoạt lại các tài khoản đã tách'); const kichHoatResult = await startKichHoatProcess(); console.log(`✅ Hoàn thành kích hoạt: ${kichHoatResult} tài khoản thành công`); } else { console.log('\n⏭️ BƯỚC 2: BỎ QUA KÍCH HOẠT TÀI KHOẢN (Đã tắt)'); updatePhaseIndicator('kichhoat', 'Bỏ qua chức năng kích hoạt tài khoản'); } // Bước 3: Đổi tên tài khoản (nếu được bật) if (stats.config.enableRename) { console.log('\n🏷️ BƯỚC 3: ĐỔI TÊN TÀI KHOẢN QUẢNG CÁO'); updatePhaseIndicator('rename', 'Đang đổi tên các tài khoản quảng cáo cá nhân'); const renameResult = await startRenameProcess(); console.log(`✅ Hoàn thành đổi tên: ${renameResult} tài khoản thành công`); } else { console.log('\n⏭️ BƯỚC 3: BỎ QUA ĐỔI TÊN TÀI KHOẢN (Đã tắt)'); updatePhaseIndicator('rename', 'Bỏ qua chức năng đổi tên tài khoản'); } // Kiểm tra nếu đã dừng if (!stats.isRunning) { console.log('🛑 Đã dừng chương trình'); updatePhaseIndicator('idle', 'Đã dừng chương trình'); updateButtonStates(); return; } // Bước 4: Xóa admin & analysts (nếu được bật) if (stats.config.enableRemoveAdmin) { console.log('\n👤 BƯỚC 4: XÓA ADMIN & ANALYSTS KHỎI TÀI KHOẢN'); updatePhaseIndicator('removeadmin', 'Đang xóa admin và nhà phân tích khác khỏi tài khoản'); const removeAdminResult = await startRemoveAdminProcess(); console.log(`✅ Hoàn thành xóa admin: ${removeAdminResult} tài khoản thành công`); } else { console.log('\n⏭️ BƯỚC 4: BỎ QUA XÓA ADMIN & ANALYSTS (Đã tắt)'); updatePhaseIndicator('removeadmin', 'Bỏ qua chức năng xóa admin & analysts'); } // Hoàn thành toàn bộ quá trình console.log('\n🎉 HOÀN THÀNH TOÀN BỘ QUÁ TRÌNH!'); updatePhaseIndicator('completed', 'Tất cả quá trình đã hoàn tất thành công'); // Hiển thị báo cáo tổng hợp showCompletionCombinedWebUI(); // Thống kê cuối cùng const totalSuccess = stats.tachSuccessCount + stats.kichHoatSuccess + stats.renameSuccess + stats.removeAdminSuccess; const totalTime = Math.round((new Date() - (stats.tachStartTime || new Date())) / 1000); console.log('\n📊 THỐNG KÊ TỔNG HỢP:'); if (stats.config.enableTach) { console.log(`🔧 Tách tài khoản: ${stats.tachSuccessCount}/${stats.config.targetSuccess} thành công`); } if (stats.config.enableKichHoat) { console.log(`🔓 Kích hoạt tài khoản: ${stats.kichHoatSuccess}/${stats.kichHoatTotal} thành công`); } if (stats.config.enableRename) { console.log(`🏷️ Đổi tên tài khoản: ${stats.renameSuccess}/${stats.renameTotal} thành công`); } if (stats.config.enableRemoveAdmin) { console.log(`👤 Xóa admin & analysts: ${stats.removeAdminSuccess}/${stats.removeAdminTotal} thành công`); console.log(` - Admin đã xóa: ${stats.removeAdminAdminsRemoved}`); console.log(` - Analyst đã xóa: ${stats.removeAdminAnalystsRemoved}`); } console.log(`🎯 Tổng cộng: ${totalSuccess} tài khoản hoàn tất`); console.log(`⏱️ Tổng thời gian: ${totalTime} giây`); console.log('\nHASoftware - Ads Solution - Auto Version'); } catch (error) { console.error('❌ Lỗi trong quá trình tổng hợp:', error); updatePhaseIndicator('completed', 'Có lỗi xảy ra trong quá trình xử lý'); } finally { stats.isRunning = false; updateButtonStates(); } } // Hàm khởi chạy chương trình function startAdToolPro() { if (stats.isRunning) { console.log('⚠️ Chương trình đang chạy. Vui lòng đợi hoàn thành.'); return; } // Tạo giao diện web nếu chưa có if (!document.querySelector('.adtool-pro-modal')) { createCombinedWebUI(); console.log('🎨 Đã tạo giao diện AdTool Pro'); } else { console.log('ℹ️ Giao diện AdTool Pro đã tồn tại'); } // Reset thống kê stats = { // Thống kê tách tài khoản tachTotalProcessed: 0, tachSuccessCount: 0, tachFailureCount: 0, tachTargetSuccess: 600, tachStartTime: null, tachActiveRequests: 0, tachMaxConcurrentRequests: 200, tachIsRunning: false, tachCurrentAccounts: [], // Thống kê kích hoạt tài khoản kichHoatTotal: 0, kichHoatSuccess: 0, kichHoatFailed: 0, kichHoatSkipped: 0, kichHoatProcessing: 0, kichHoatCurrent: 0, kichHoatStartTime: null, kichHoatIsRunning: false, // Thống kê đổi tên tài khoản renameTotal: 0, renameSuccess: 0, renameFailed: 0, renameSkipped: 0, renameProcessing: 0, renameCurrent: 0, renameStartTime: null, renameIsRunning: false, renameRetryCount: 0, // Số lần retry tổng cộng // Thống kê xóa admin & analysts removeAdminTotal: 0, removeAdminSuccess: 0, removeAdminFailed: 0, removeAdminSkipped: 0, removeAdminCurrent: 0, removeAdminStartTime: null, removeAdminIsRunning: false, removeAdminAdminsRemoved: 0, removeAdminAnalystsRemoved: 0, // Trạng thái tổng thể currentPhase: 'idle', isRunning: false, failureThreshold: 500, // Cấu hình mới config: { enableTach: true, enableKichHoat: true, enableRename: false, enableRemoveAdmin: false, failureThresholdToKichHoat: 500, targetSuccess: 600, enableDelayBetweenAccounts: false, delayBetweenAccounts: 1, delayBeforeKichHoat: 300, kichHoatBatchSize: 50, renameMode: 'fixed', fixedName: 'HoangAnh TKQC', businessName: '', onlyPersonalAccounts: true, removeAdminOnly: true, removeAnalystOnly: false, removeBoth: false, removeAdminDelay: 2 } }; // Khởi chạy quá trình tổng hợp mainCombinedProcess(); } // Hàm dừng chương trình function stopAdToolPro() { stats.isRunning = false; stats.tachIsRunning = false; stats.kichHoatIsRunning = false; console.log('🛑 Đã dừng chương trình AD TOOL PRO'); updateButtonStates(); } // Hàm cập nhật cài đặt function updateSettings(newSettings) { if (newSettings.tachTargetSuccess) { stats.tachTargetSuccess = newSettings.tachTargetSuccess; } if (newSettings.maxConcurrentRequests) { stats.tachMaxConcurrentRequests = newSettings.maxConcurrentRequests; } if (newSettings.failureThreshold) { stats.failureThreshold = newSettings.failureThreshold; } console.log('⚙️ Đã cập nhật cài đặt:', newSettings); } // Hàm load cấu hình từ giao diện function loadConfigFromUI() { try { // Tích chọn chính const enableTach = document.getElementById('enableTach').checked; const enableKichHoat = document.getElementById('enableKichHoat').checked; const enableRename = document.getElementById('enableRename').checked; // Cấu hình tách const tachTargetSuccess = parseInt(document.getElementById('tachTargetSuccess').value) || 600; const maxConcurrentRequests = parseInt(document.getElementById('maxConcurrentRequests').value) || 200; const failureThreshold = parseInt(document.getElementById('failureThreshold').value) || 500; const enableDelayBetweenAccounts = document.getElementById('enableDelayBetweenAccounts').checked; const delayBetweenAccounts = parseInt(document.getElementById('delayBetweenAccounts').value) || 1; // Cấu hình kích hoạt const delayBeforeKichHoat = parseInt(document.getElementById('delayBeforeKichHoat').value) || 300; const kichHoatBatchSize = parseInt(document.getElementById('kichHoatBatchSize').value) || 50; // Cấu hình đổi tên const onlyPersonalAccounts = document.getElementById('onlyPersonalAccounts').checked; const fixedName = document.getElementById('fixedName').value || 'HoangAnh TKQC'; // Lấy chế độ đổi tên từ radio buttons const renameModeFixed = document.getElementById('renameModeFixed'); const renameModeBusiness = document.getElementById('renameModeBusiness'); let renameMode = 'fixed'; if (renameModeBusiness && renameModeBusiness.checked) { renameMode = 'business'; } // Cấu hình xóa admin & analysts const enableRemoveAdmin = document.getElementById('enableRemoveAdmin').checked; const removeAdminDelay = parseInt(document.getElementById('removeAdminDelay').value) || 2; // Lấy loại user cần xóa từ radio buttons const removeAdminOnly = document.getElementById('removeAdminOnly'); const removeAnalystOnly = document.getElementById('removeAnalystOnly'); const removeBoth = document.getElementById('removeBoth'); let removeAdminType = 'admin'; // default if (removeAnalystOnly && removeAnalystOnly.checked) { removeAdminType = 'analyst'; } else if (removeBoth && removeBoth.checked) { removeAdminType = 'both'; } // Cập nhật cấu hình stats.config.enableTach = enableTach; stats.config.enableKichHoat = enableKichHoat; stats.config.enableRename = enableRename; stats.config.enableRemoveAdmin = enableRemoveAdmin; stats.config.targetSuccess = tachTargetSuccess; stats.tachMaxConcurrentRequests = maxConcurrentRequests; stats.config.failureThresholdToKichHoat = failureThreshold; stats.config.enableDelayBetweenAccounts = enableDelayBetweenAccounts; stats.config.delayBetweenAccounts = delayBetweenAccounts; stats.config.delayBeforeKichHoat = delayBeforeKichHoat; stats.config.kichHoatBatchSize = kichHoatBatchSize; // Cập nhật cấu hình đổi tên stats.config.onlyPersonalAccounts = onlyPersonalAccounts; stats.config.fixedName = fixedName; stats.config.renameMode = renameMode; // Cập nhật cấu hình xóa admin stats.config.removeAdminDelay = removeAdminDelay; stats.config.removeAdminOnly = removeAdminType === 'admin'; stats.config.removeAnalystOnly = removeAdminType === 'analyst'; stats.config.removeBoth = removeAdminType === 'both'; console.log('⚙️ Đã load cấu hình từ giao diện:', { ...stats.config, tachMaxConcurrentRequests: stats.tachMaxConcurrentRequests }); } catch (error) { console.error('❌ Lỗi load cấu hình:', error); } } // Hàm cập nhật trạng thái nút function updateButtonStates() { const startButton = document.getElementById('startButton'); const stopButton = document.getElementById('stopButton'); const closeButton = document.getElementById('closeButton'); if (startButton && stopButton && closeButton) { if (stats.isRunning) { startButton.disabled = true; stopButton.disabled = false; closeButton.disabled = true; // Disable close button when running } else { startButton.disabled = false; stopButton.disabled = true; closeButton.disabled = false; // Enable close button when idle } } } // Export các hàm để sử dụng window.AdToolPro = { start: startAdToolPro, stop: stopAdToolPro, updateSettings: updateSettings, stats: stats }; // Thêm hàm renameAds vào global scope window.renameAds = renameAds; window.isPersonalAccount = isPersonalAccount; window.generateNewAccountName = generateNewAccountName; // Tự động khởi chạy khi load script console.log('🚀 AD TOOL PRO đã sẵn sàng!'); console.log('Sử dụng: AdToolPro.start() để bắt đầu'); console.log('Sử dụng: AdToolPro.stop() để dừng'); console.log('Sử dụng: AdToolPro.updateSettings({...}) để cập nhật cài đặt'); // Tạo giao diện và hiển thị ngay khi load script if (!document.querySelector('.adtool-pro-modal')) { createCombinedWebUI(); console.log('🎨 Đã tạo giao diện AdTool Pro'); } else { console.log('ℹ️ Giao diện AdTool Pro đã tồn tại'); } // Hàm kiểm tra xem tài khoản có phải là cá nhân không function isPersonalAccount(accountData) { return !accountData.owner_business; // Không có owner_business = tài khoản cá nhân } // Hàm tạo tên mới cho tài khoản quảng cáo function generateNewAccountName(accountId, accountData) { const accountIdOnly = accountId.replace("act_", ""); if (stats.config.renameMode === 'fixed') { return `${stats.config.fixedName} ${accountIdOnly}`; } else if (stats.config.renameMode === 'business') { return `${stats.config.businessName} ${accountIdOnly}`; } return `Account ${accountIdOnly}`; // Fallback } // Hàm đổi tên tài khoản quảng cáo với retry mechanism async function renameAds(adAccountId, newName, retryCount = 0) { const maxRetries = 3; const retryDelay = 2000; // 2 giây try { const accessToken = require("WebApiApplication").getAccessToken(); // Sử dụng API đúng cho tài khoản cá nhân const url = `https://graph.facebook.com/v14.0/${adAccountId}?name=${encodeURIComponent(newName)}&access_token=${accessToken}&method=post`; const response = await fetch(url, { method: 'GET', credentials: 'include' }); const data = await response.json(); // Log response để debug console.log(`🔍 [${adAccountId}] API Response:`, JSON.stringify(data, null, 2)); // Kiểm tra lỗi từ Facebook API if (data.error) { const errorMessage = data.error.message || 'Lỗi không xác định'; const errorCode = data.error.code || 'UNKNOWN'; const errorSubcode = data.error.error_subcode || null; // Danh sách lỗi có thể retry const retryableErrors = [ 1675030, // field_exception server error 1, // API Unknown 2, // API Service 4, // API Too Many Calls 17, // API User Too Many Calls 102, // API Session has expired 190, // API Invalid OAuth 2.0 Access Token 613, // API Hits User Rate Limit ]; // Danh sách lỗi không có quyền (không retry) const permissionErrors = [ { code: 100, subcode: 1487828 }, // Không có quyền cập nhật tài khoản quảng cáo { code: 190, subcode: 1 }, // Không có quyền truy cập { code: 200, subcode: 1 }, // Không có quyền admin ]; // Kiểm tra nếu là lỗi không có quyền const isPermissionError = permissionErrors.some(err => err.code === errorCode && (err.subcode === errorSubcode || !err.subcode) ); if (isPermissionError) { console.log(`⚠️ [${adAccountId}] Không có quyền đổi tên tài khoản này: ${errorMessage}`); return { status: false, error: `Không có quyền: ${errorMessage}`, details: data.error, retryCount: retryCount, noPermission: true }; } // Thử lại nếu là lỗi có thể retry if (retryableErrors.includes(errorCode) && retryCount < maxRetries) { console.log(` [${adAccountId}] Lỗi ${errorCode}, thử lại lần ${retryCount + 1}/${maxRetries} sau ${retryDelay}ms...`); await new Promise(resolve => setTimeout(resolve, retryDelay)); return await renameAds(adAccountId, newName, retryCount + 1); } return { status: false, error: `Facebook API Error (${errorCode}): ${errorMessage}`, details: data.error, retryCount: retryCount }; } // Kiểm tra nếu có name trong response hoặc success if (data.name === newName || data.success === true || data.id) { if (retryCount > 0) { console.log(`✅ [${adAccountId}] Đổi tên thành công sau ${retryCount} lần thử lại`); } return { status: true, error: null, retryCount: retryCount }; } else { return { status: false, error: `Tên không được cập nhật. Expected: ${newName}, Got: ${data.name || 'undefined'}`, details: data, retryCount: retryCount }; } } catch (err) { // Thử lại nếu là lỗi network và chưa hết số lần retry if (retryCount < maxRetries) { console.log(`🔄 [${adAccountId}] Network error, thử lại lần ${retryCount + 1}/${maxRetries} sau ${retryDelay}ms...`); await new Promise(resolve => setTimeout(resolve, retryDelay)); return await renameAds(adAccountId, newName, retryCount + 1); } return { status: false, error: `Network Error: ${err.message}`, details: err, retryCount: retryCount }; } } // Hàm xử lý đổi tên một tài khoản async function processRenameAccount(account, index, total) { try { const accountId = account.id; const currentName = account.name; console.log(`🔄 [${index + 1}/${total}] Đang xử lý ${accountId} (${currentName})`); // Tạo tên mới const newName = window.generateNewAccountName(accountId, account); console.log(`🏷️ [${index + 1}/${total}] Đổi tên từ "${currentName}" thành "${newName}"`); // Thực hiện đổi tên const renameResult = await window.renameAds(accountId, newName); if (renameResult.status) { stats.renameSuccess++; if (renameResult.retryCount > 0) { stats.renameRetryCount += renameResult.retryCount; } const retryInfo = renameResult.retryCount > 0 ? ` (sau ${renameResult.retryCount} lần thử)` : ''; console.log(`✅ [${index + 1}/${total}] ${accountId} | -> ✅ Đổi tên thành công: ${newName}${retryInfo}`); } else { if (renameResult.noPermission) { stats.renameSkipped++; console.log(`⏭️ [${index + 1}/${total}] ${accountId} | -> ⏭️ Bỏ qua (không có quyền): ${renameResult.error}`); } else { stats.renameFailed++; if (renameResult.retryCount > 0) { stats.renameRetryCount += renameResult.retryCount; } const retryInfo = renameResult.retryCount > 0 ? ` (đã thử ${renameResult.retryCount} lần)` : ''; console.log(`❌ [${index + 1}/${total}] ${accountId} | -> ❌ Đổi tên thất bại${retryInfo}:`, renameResult.error); } } } catch (error) { stats.renameFailed++; console.log(`❌ [${index + 1}/${total}] ${account.id} | -> ❌ Lỗi: ${error.message}`); } } // Hàm bắt đầu quá trình đổi tên độc lập async function startRenameProcess() { try { console.log('🏷️ BẮT ĐẦU QUÁ TRÌNH ĐỔI TÊN TÀI KHOẢN QUẢNG CÁO'); console.log('====================================='); // Reset thống kê đổi tên stats.renameTotal = 0; stats.renameSuccess = 0; stats.renameFailed = 0; stats.renameSkipped = 0; stats.renameProcessing = 0; stats.renameCurrent = 0; stats.renameRetryCount = 0; stats.renameStartTime = new Date(); stats.renameIsRunning = true; stats.currentPhase = 'rename'; updatePhaseIndicator('rename', 'Đang đổi tên các tài khoản quảng cáo cá nhân'); // Lấy access token const accessToken = require("WebApiApplication").getAccessToken(); // Lấy User ID từ access token hoặc sử dụng cách khác let uid; try { uid = require("WebApiApplication").getUserId(); } catch (error) { // Nếu không lấy được User ID, thử lấy từ access token try { const tokenResponse = await fetch(`https://graph.facebook.com/me?access_token=${accessToken}`, { method: 'GET', credentials: 'include' }); const tokenData = await tokenResponse.json(); uid = tokenData.id; } catch (tokenError) { console.error('❌ Không thể lấy User ID:', tokenError); stats.renameIsRunning = false; return 0; } } console.log('📋 Đang lấy danh sách tài khoản quảng cáo...'); // Lấy danh sách tài khoản quảng cáo const response = await fetch(`https://graph.facebook.com/v19.0/${uid}/adaccounts?access_token=${accessToken}&pretty=1&fields=account_status,created_time,owner,owner_business,name,adtrust_dsl,currency,userpermissions.user(${uid})%7Brole%7D&limit=300`, { method: 'GET', credentials: 'include' }); const data = await response.json(); if (!data.data || data.data.length === 0) { console.log('❌ Không tìm thấy tài khoản quảng cáo nào'); stats.renameIsRunning = false; return 0; } // Lọc chỉ lấy tài khoản cá nhân (không thuộc Business Manager) const personalAccounts = data.data.filter(item => !item.owner_business); console.log(`📊 Tìm thấy ${data.data.length} tài khoản quảng cáo`); console.log(`👤 Trong đó có ${personalAccounts.length} tài khoản cá nhân`); if (personalAccounts.length === 0) { console.log('❌ Không tìm thấy tài khoản cá nhân nào để đổi tên'); stats.renameIsRunning = false; return 0; } stats.renameTotal = personalAccounts.length; console.log(`🎯 Bắt đầu đổi tên ${stats.renameTotal} tài khoản cá nhân`); // Xử lý đổi tên song song const batchSize = 10; // Số tài khoản xử lý đồng thời let processedCount = 0; for (let i = 0; i < personalAccounts.length; i += batchSize) { const batch = personalAccounts.slice(i, i + batchSize); const promises = batch.map(async (account, batchIndex) => { const globalIndex = i + batchIndex; return await processRenameAccount(account, globalIndex, personalAccounts.length); }); await Promise.all(promises); processedCount += batch.length; // Cập nhật tiến trình stats.renameCurrent = processedCount; updateCombinedWebUI(); // Kiểm tra nếu đã dừng if (!stats.isRunning) { console.log('🛑 Đã dừng quá trình đổi tên'); break; } // Delay nhỏ giữa các batch if (i + batchSize < personalAccounts.length) { await new Promise(resolve => setTimeout(resolve, 1000)); } } console.log(`✅ Hoàn thành đổi tên: ${stats.renameSuccess}/${stats.renameTotal} thành công`); console.log(`🔄 Tổng số lần retry: ${stats.renameRetryCount}`); stats.renameIsRunning = false; return stats.renameSuccess; } catch (error) { console.error('❌ Lỗi trong quá trình đổi tên:', error); stats.renameIsRunning = false; return 0; } } // Thêm các hàm vào global scope window.isPersonalAccount = isPersonalAccount; window.generateNewAccountName = generateNewAccountName; window.renameAds = renameAds; window.startRenameProcess = startRenameProcess; window.processRenameAccount = processRenameAccount; // ==================== PHẦN XÓA ADMIN & ANALYSTS ==================== // Lấy danh sách tài khoản quảng cáo cá nhân async function getPersonalAdAccountsForRemove() { try { const accessToken = require("WebApiApplication").getAccessToken(); const uid = await getCurrentUserID(); console.log('📋 Đang lấy danh sách tài khoản quảng cáo...'); const response = await fetch(`https://graph.facebook.com/v14.0/me/adaccounts?summary=1&access_token=${accessToken}&limit=1000&fields=account_id,name,adtrust_dsl,account_status,users%7Bid,role%7D&locale=en_US`, { method: 'GET', credentials: 'include' }); const data = await response.json(); if (!data.data || data.data.length === 0) { console.log('❌ Không tìm thấy tài khoản quảng cáo nào'); return []; } // Lọc chỉ lấy tài khoản cá nhân const personalAccounts = data.data.filter(item => { const isPersonal = !item.name.includes('Business') && !item.name.includes('Manager') && (item.name.includes('Read-Only') || item.account_status === 1); return isPersonal; }); console.log(`📊 Tìm thấy ${data.data.length} tài khoản quảng cáo`); console.log(`👤 Trong đó có ${personalAccounts.length} tài khoản cá nhân`); return personalAccounts; } catch (error) { console.error(`❌ Lỗi khi lấy danh sách tài khoản: ${error.message}`); return []; } } // Lấy User ID hiện tại async function getCurrentUserID() { try { // Thử lấy từ WebApiApplication trước const uid = require("WebApiApplication").getUserId(); if (uid) { console.log(`✅ Lấy được User ID: ${uid}`); return uid; } } catch (error) { console.log(`⚠️ Không thể lấy User ID từ WebApiApplication: ${error.message}`); } try { // Thử lấy từ CurrentUserInitialData const uid = require("CurrentUserInitialData").USER_ID; if (uid) { console.log(`✅ Lấy được User ID từ CurrentUserInitialData: ${uid}`); return uid; } } catch (error) { console.log(`⚠️ Không thể lấy User ID từ CurrentUserInitialData: ${error.message}`); } try { // Thử lấy từ access token const accessToken = require("WebApiApplication").getAccessToken(); const response = await fetch(`https://graph.facebook.com/me?access_token=${accessToken}`, { method: 'GET', credentials: 'include' }); const data = await response.json(); if (data.id) { console.log(`✅ Lấy được User ID từ Graph API: ${data.id}`); return data.id; } } catch (error) { console.log(`❌ Không thể lấy User ID từ Graph API: ${error.message}`); } throw new Error('Không thể lấy User ID'); } // Xóa admin khỏi tài khoản async function removeAdminFromAccount(accountId, userId) { try { // Lấy fb_dtsg token const fb_dtsg = require("DTSGInitData").token; const currentUserID = require("CurrentUserInitialData").USER_ID; // Request 1: Confirm const confirmUrl = `https://adsmanager.facebook.com/ads/manage/settings/remove_user/confirm/?user_id=${userId}&act=${accountId}&is_new_account_settings=true&fb_dtsg_ag=${encodeURIComponent(fb_dtsg)}&__asyncDialog=1&__aaid=${accountId}&__user=${currentUserID}&__a=1&__req=1y&__hs=20299.BP%3Aads_manager_comet_pkg.2.0...0&dpr=1&__ccg=UNKNOWN&__rev=1025299733&__s=n586gt%3Avyuy0h%3Ali44py&__hsi=7532767328083407025&__dyn=7AgSXgWGgWEjgCu6mudg9omosyUqDBBh96EnK49o9EeUaVoWFGV8kG4VEHoOqqE88lBxeipe9wNWAAzppFuUuGfxW2u5Eiz8WdyU-4ryUKrVoS3u7azoV2EK12xqUC8yEScx6bxW7A78O4EgCyku4oS4EWfGUhwyg9p44889EScxyu6UGq13yHGmmUTxJ3rG2PCG9DDl0zlBwyzp8KUWcwxyU29xep3bBAzEW9lpubwIxecAwXzogyo464Xy-cwuEnxaFo5a7EN1O79UCumbz8KiewwBK68eF8pK1Nxebxa4AbxR2V8cE8Q3mbgOUGfgeEmwJCxSegroG48gyHxSi4p8y7rKfxefKaxWi2y2i7VEjCx6EO489UW5ohwZAwLzUS327EG4E949BCxK9J7yUnwUzpUqy8doHxe78-5aCCyogyoC2GZ3UC2C8ByoK4Ekx24oK4Ehz8C6oWqaUK2e4E4OawtV-i782bByUeoQwox3UO364GJe2q2B12uueC-5u8Bxu6o9UeUhxWUl-2a64uWg-26q7p9UlxuiueyKvyUkgC9xq2K3GUixl4wNx5e8wAAAVQEhy8myFUpzEGQ48Cq4E8888oAgCi2aawVy8khEkxyEoypopxKU-GoigK6K224kifyo&__hsdp=gbcdMN8MT0jHcwmmk998424RMSCg4Oal4gJApwN93CjdcIXh48132ch34qjnP8IIY0KI4IncOli8fK8Quil1CVk1jwqo6y2K2e8AgfE17U9U1l80er8&__hblp=0Ywgoao8oizbK2e48vm9KuU8awTwNzFolx-rwgGwAyWBxbaaCmd6YQCzRAHxnSy9Yh2c9Mz6DEh6gV1r5Mg8Y7a7Yl2WYmziNl8IHTVp1qBh4boxibUx4WJllhqgiDgiQmimKnOT5Za7km4YZlLVQ4oGte842fHBWkwiG4pszVBpkUJ4xOiq1vUxm6UGmfx6fm8xeloUJtk_yHgTRy84994cXXFxbhUpyQumyfl4BAXVpbCK4keUBaiVEC8nGRYBcBaGJbGmW-55VowGyFUTxC6EsDABAOAVrj-ut5jAVZ9xhFlU-8-bgsF1GUkxybGqu5FaCx16xh29Q4UWqi58aFpoReV-y4zovzF8CSjSZ5y8x4lClqBG12xWnpGH4mJzArqXUypi4mWgyCKh58FpqAKu_AZ3oCheicy8V2CAbQimh92t3VvKt3ppeEolk548AQGV8yKq6XS1vLh4plAGKJ0MkyLRgOj-6td3aoKWx3Kjm9h6GhO0jA4bZlXGLcZxGYxojwApAahifF0Z86sHiQjS8ADmVeFQWgGm9GHABjxqp28hyHD8AGmeLuWriLp28ER7ppExEzbZ5V4C9U8pppiCyCWGEyVTF28Gi4FBgjG9GJ5xCDA_Gi9giAyHBCyppGmryStHjKeABcly21d2948yrVaLgmyUyrDpt2oC4omAWUmUG5poC4VeFcSG4S8Aqaaj8yh2h4BliNcGBhZha7jKYLGDgC48yp4Gdxh25GqqAcHCVRyESfgx5hapadUJqE-JAih94AidBhEC4tDjWhqpapGlml5jilDyKA4vlkmcAZkF22qFpkK9LWzVFeZmBxK6fWAwk8sh25AzKFoWaJaFoeCHx6q9AGXAh_F7BWiuGCBGitbgTEBniHVJ6GG_fBp95GDGEOpeqJoxaijZelejaF9eiSEHhFoOucXWUgTAV5yKX_l7ppAjGumchVvy9V4vxXzVlgqQ6VVU&__comet_req=58&jazoest=24801&__spin_r=1025299733&__spin_b=trunk&__spin_t=1753859065&__jssesw=1&_callFlowletID=0&_triggerFlowletID=4722&qpl_active_e2e_trace_ids=`; const confirmResponse = await fetch(confirmUrl, { method: 'GET', credentials: 'include', headers: { 'accept': '*/*', 'accept-language': 'en-US,en;q=0.9', 'sec-ch-prefers-color-scheme': 'light', 'sec-ch-ua': '"Not)A;Brand";v="8", "Chromium";v="138", "Microsoft Edge";v="138"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin' } }); if (!confirmResponse.ok) { throw new Error(`Confirm request failed: ${confirmResponse.status}`); } // Request 2: Remove user const removeUrl = `https://adsmanager.facebook.com/ads/manage/settings/remove_user/?user_id=${userId}&act=${accountId}&is_new_account_settings=1&ads_manager_write_regions=true&_callFlowletID=0&_triggerFlowletID=5180&qpl_active_e2e_trace_ids=`; const removeBody = `jazoest=25069&fb_dtsg=${encodeURIComponent(fb_dtsg)}&__aaid=${accountId}&__user=${currentUserID}&__a=1&__req=20&__hs=20299.BP%3Aads_manager_comet_pkg.2.0...0&dpr=1&__ccg=UNKNOWN&__rev=1025299733&__s=n586gt%3Avyuy0h%3Ali44py&__hsi=7532767328083407025&__dyn=7AgSXgWGgWEjgCu6mudg9omosyUqDBBh96EnK49o9EeUaVoWFGV8kG4VEHoOqqE88lBxeipe9wNWAAzppFuUuGfxW2u5Eiz8WdyU-4ryUKrVoS3u7azoV2EK12xqUC8yEScx6bxW7A78O4EgCyku4oS4EWfGUhwyg9p44889EScxyu6UGq13yHGmmUTxJ3rG2PCG9DDl0zlBwyzp8KUWcwxyU29xep3bBAzEW9lpubwIxecAwXzogyo464Xy-cwuEnxaFo5a7EN1O79UCumbz8KiewwBK68eF8pK1Nxebxa4AbxR2V8cE8Q3mbgOUGfgeEmwJCxSegroG48gyHxSi4p8y7rKfxefKaxWi2y2i7VEjCx6EO489UW5ohwZAwLzUS327EG4E949BCxK9J7yUnwUzpUqy8doHxe78-5aCCyogyoC2GZ3UC2C8ByoK4Ekx24oK4Ehz8C6oWqaUK2e4E4OawtV-i782bByUeoQwox3UO364GJe2q2B12uueC-5u8Bxu6o9UeUhxWUl-2a64uWg-26q7p9UlxuiueyKvyUkgC9xq2K3GUixl4wNx5e8wAAAVQEhy8myFUpzEGQ48Cq4E8888oAgCi2aawVy8khEkxyEoypopxKU-GoigK6K224kifyo&__hsdp=gbcdMN8MT0jHcwmmk998424RMSCg4Och4gJApwN93CjdcIXh48132ch34qjnP8IIY0KI4IncOli8fK8Quil1CVk1jwqo6y7VF88m8AgcQ9wdoi8xaVbG589U1l80er8&__hblp=0Ywgoao8oizbK2e48vm9KuU8awTwNzFolx-rwgGwAyWBxbaaCmd6YQCzRAHxnSy9Yh2c9Mz6DEh6gV1r5Mg8Y7a7Yl2WYmziNl8IHTVp1qBh4boxibUx4WJllhqgiDgiQmimKnOT5Za7km4YZlLVQ4oGte842fHBWkwiG4pszVBpkUJ4xOiq1vUxm6UGmfx6fm8xeloUJtk_yHgTRy84994cXXFxbhUpyQumyfl4BAXVpbCK4keUBaiVEC8nGRYBcBaGJbGmW-55VowGyFUTxC6EsDABAOAVrj-ut5jAVZ9xhFlU-8-bgsF1GUkxybGqu5FaCx16xh29Q4UWqi58aFpoReV-y4zovzF8CSjSZ5y8x4lClqBG12xWnpGH4mJzArqXUypi4mWgyCKh58FpqAKu_AZ3oCheicy8V2CAbQimh92t3VvKt3ppeEolk548AQGV8yKq6XS1vLh4plAGKJ0MkyLRgOj-6td3aoKWx3Kjm9h6GhO0jA4bZlXGLcZxGYxojwApAahifF0Z86sHiQjS8ADmVeFQWgGm9GHABjxqp28hyHD8AGmeLuWriLp28ER7ppExEzbZ5V4C9U8pppiCyCWGEyVTF28Gi4FBgjG9GJ5xCDA_Gi9giAyHBCyppGmryStHjKeABcly21d2948yrVaLgmyUyrDpt2oC4omAWUmUG5poC4VeFcSG4S8Aqaaj8yh2h4BliNcGBhZha7jKYLGDgC48yp4Gdxh25GqqAcHCVRyESfgx5hapadUJqE-JAih94AidBhEC4tDjWhqpapGlml5jilDyKA4vlkmcAZkF22qFpkK9LWzVFeZmBxK6fWAwk8sh25AzKFoWaJaFoeCHx6q9AGXAh_F7BWiuGCBGitbgTEBniHVJ6GG_fBp95GDGEOpeqJoxaijZelejaF9eiSEHhFoOucXWUgTAV5yKX_l7ppAjGumchVvy9V4vxXzVlgqQ6VVU&__comet_req=58&lsd=RUbO3Wa_Or1oEH9-Omq85m&__spin_r=1025299733&__spin_b=trunk&__spin_t=1753859065&__jssesw=1`; const removeResponse = await fetch(removeUrl, { method: 'POST', credentials: 'include', headers: { 'accept': '*/*', 'accept-language': 'en-US,en;q=0.9', 'content-type': 'application/x-www-form-urlencoded', 'sec-ch-prefers-color-scheme': 'light', 'sec-ch-ua': '"Not)A;Brand";v="8", "Chromium";v="138", "Microsoft Edge";v="138"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin' }, body: removeBody }); if (!removeResponse.ok) { throw new Error(`Remove request failed: ${removeResponse.status}`); } const responseText = await removeResponse.text(); // Kiểm tra response để xác định thành công if (responseText.includes('success') || responseText.includes('removed') || removeResponse.status === 200) { return { success: true, error: null }; } else { return { success: false, error: 'Unknown response' }; } } catch (error) { return { success: false, error: error.message }; } } // Xóa admin & analysts khỏi tài khoản async function removeOtherAdmins(account, currentUserID) { try { if (!account.users || !account.users.data) { console.log(`⚠️ Tài khoản ${account.account_id} không có thông tin users`); return { success: false, adminsRemoved: 0, analystsRemoved: 0, error: 'No users data' }; } let usersToRemove = []; // Lọc admin (role 1001) nếu được bật if (stats.config.removeAdminOnly || stats.config.removeBoth) { const admins = account.users.data.filter(user => user.role === 1001); const otherAdmins = admins.filter(admin => admin.id !== currentUserID); usersToRemove.push(...otherAdmins.map(admin => ({ ...admin, type: 'admin' }))); } // Lọc nhà phân tích (role 1003) nếu được bật if (stats.config.removeAnalystOnly || stats.config.removeBoth) { const analysts = account.users.data.filter(user => user.role === 1003); const otherAnalysts = analysts.filter(analyst => analyst.id !== currentUserID); usersToRemove.push(...otherAnalysts.map(analyst => ({ ...analyst, type: 'analyst' }))); } if (usersToRemove.length === 0) { console.log(`✅ Tài khoản ${account.account_id} không có user khác cần xóa`); return { success: true, adminsRemoved: 0, analystsRemoved: 0, error: null }; } const adminCount = usersToRemove.filter(u => u.type === 'admin').length; const analystCount = usersToRemove.filter(u => u.type === 'analyst').length; console.log(`🔍 Tìm thấy ${adminCount} admin và ${analystCount} nhà phân tích khác trong tài khoản ${account.account_id}`); console.log(`📋 Danh sách user cần xóa: ${usersToRemove.map(u => `${u.id} (${u.type})`).join(', ')}`); let adminsRemoved = 0; let analystsRemoved = 0; for (const user of usersToRemove) { if (!stats.isRunning) { console.log('🛑 Đã dừng quá trình xóa user'); break; } const userType = user.type === 'admin' ? 'Admin' : 'Nhà phân tích'; console.log(`🔄 Đang xóa ${userType} ${user.id} khỏi tài khoản ${account.account_id}`); try { const result = await removeAdminFromAccount(account.account_id, user.id); if (result.success) { if (user.type === 'admin') { adminsRemoved++; } else { analystsRemoved++; } console.log(`✅ Đã xóa ${userType} ${user.id} khỏi tài khoản ${account.account_id}`); } else { console.log(`❌ Không thể xóa ${userType} ${user.id}: ${result.error}`); } // Delay nhỏ giữa các request await new Promise(resolve => setTimeout(resolve, 1000)); } catch (error) { console.log(`❌ Lỗi khi xóa ${userType} ${user.id}: ${error.message}`); } } return { success: true, adminsRemoved, analystsRemoved, error: null }; } catch (error) { console.log(`❌ Lỗi khi xử lý tài khoản ${account.account_id}: ${error.message}`); return { success: false, adminsRemoved: 0, analystsRemoved: 0, error: error.message }; } } // Bắt đầu quá trình xóa admin & analysts async function startRemoveAdminProcess() { try { console.log('👤 BẮT ĐẦU QUÁ TRÌNH XÓA ADMIN & ANALYSTS'); console.log('====================================='); // Reset thống kê xóa admin stats.removeAdminTotal = 0; stats.removeAdminSuccess = 0; stats.removeAdminFailed = 0; stats.removeAdminSkipped = 0; stats.removeAdminCurrent = 0; stats.removeAdminAdminsRemoved = 0; stats.removeAdminAnalystsRemoved = 0; stats.removeAdminStartTime = new Date(); stats.removeAdminIsRunning = true; stats.currentPhase = 'removeadmin'; updatePhaseIndicator('removeadmin', 'Đang xóa admin và nhà phân tích khác khỏi tài khoản'); // Bước 1: Lấy User ID const currentUserID = await getCurrentUserID(); console.log(`👤 User ID hiện tại: ${currentUserID}`); // Bước 2: Lấy danh sách tài khoản const accounts = await getPersonalAdAccountsForRemove(); if (accounts.length === 0) { console.log('❌ Không có tài khoản nào để xử lý'); stats.removeAdminIsRunning = false; return 0; } stats.removeAdminTotal = accounts.length; console.log(`🎯 Bắt đầu xử lý ${stats.removeAdminTotal} tài khoản cá nhân`); // Hiển thị cấu hình hiện tại console.log(`⚙️ Cấu hình:`); console.log(` - Xóa Admin: ${stats.config.removeAdminOnly ? 'Bật' : 'Tắt'}`); console.log(` - Xóa Nhà phân tích: ${stats.config.removeAnalystOnly ? 'Bật' : 'Tắt'}`); console.log(` - Xóa cả hai: ${stats.config.removeBoth ? 'Bật' : 'Tắt'}`); console.log(` - Delay: ${stats.config.removeAdminDelay}s`); // Bước 3: Xử lý từng tài khoản for (let i = 0; i < accounts.length; i++) { if (!stats.isRunning) { console.log('🛑 Đã dừng quá trình xóa admin'); break; } const account = accounts[i]; stats.removeAdminCurrent = i + 1; updateCombinedWebUI(); console.log(`🔄 [${i + 1}/${accounts.length}] Đang xử lý tài khoản: ${account.account_id}`); try { const result = await removeOtherAdmins(account, currentUserID); if (result.success) { stats.removeAdminSuccess++; stats.removeAdminAdminsRemoved += result.adminsRemoved; stats.removeAdminAnalystsRemoved += result.analystsRemoved; console.log(`✅ [${i + 1}/${accounts.length}] Hoàn thành: ${result.adminsRemoved} admin và ${result.analystsRemoved} nhà phân tích đã được xóa`); } else { stats.removeAdminFailed++; console.log(`❌ [${i + 1}/${accounts.length}] Thất bại: ${result.error}`); } } catch (error) { stats.removeAdminFailed++; console.log(`❌ [${i + 1}/${accounts.length}] Lỗi: ${error.message}`); } // Delay giữa các tài khoản if (i < accounts.length - 1) { console.log(`⏳ Delay ${stats.config.removeAdminDelay} giây trước khi xử lý tài khoản tiếp theo...`); await new Promise(resolve => setTimeout(resolve, stats.config.removeAdminDelay * 1000)); } } // Hoàn thành stats.removeAdminIsRunning = false; console.log('🎉 HOÀN THÀNH QUÁ TRÌNH XÓA ADMIN & ANALYSTS'); console.log('====================================='); console.log(`📊 Tổng kết:`); console.log(` - Tổng tài khoản: ${stats.removeAdminTotal}`); console.log(` - Thành công: ${stats.removeAdminSuccess}`); console.log(` - Thất bại: ${stats.removeAdminFailed}`); console.log(` - Admin đã xóa: ${stats.removeAdminAdminsRemoved}`); console.log(` - Nhà phân tích đã xóa: ${stats.removeAdminAnalystsRemoved}`); return stats.removeAdminSuccess; } catch (error) { console.error(`❌ Lỗi trong quá trình xóa admin: ${error.message}`); stats.removeAdminIsRunning = false; return 0; } } // Thêm các hàm vào global scope window.getPersonalAdAccountsForRemove = getPersonalAdAccountsForRemove; window.getCurrentUserID = getCurrentUserID; window.removeAdminFromAccount = removeAdminFromAccount; window.removeOtherAdmins = removeOtherAdmins; window.startRemoveAdminProcess = startRemoveAdminProcess;