document.addEventListener('DOMContentLoaded', function() { console.log('DOM 已加载完成'); // 获取所有需要的元素 const elements = { usernameInput: document.getElementById('username'), passwordInput: document.getElementById('password'), liveIdInput: document.getElementById('liveId'), openIncognitoButton: document.getElementById('openIncognito'), openLiveButton: document.getElementById('openLive'), loginButton: document.getElementById('login'), userinfoElement: document.getElementById('userinfo'), checkOnlineStatusButton: document.getElementById('checkOnlineStatus'), liveRoomIdInput: document.getElementById('liveRoomId'), openLiveRoomButton: document.getElementById('openLiveRoom'), checkViewersButton: document.getElementById('checkViewers'), liveRoomCountElement: document.getElementById('liveRoomCount'), batchOpenIncognitoBtn: document.getElementById('batchOpenIncognito'), incognitoCountInput: document.getElementById('incognitoCount'), getCurrentRoomIdButton: document.getElementById('getCurrentRoomId'), currentRoomIdElement: document.getElementById('currentRoomId'), taskListTextarea: document.getElementById('taskList'), saveTasksButton: document.getElementById('saveTasks'), executeTasksButton: document.getElementById('executeTasks'), taskStatusElement: document.getElementById('taskStatus'), checkDuplicateRoomsButton: document.getElementById('checkDuplicateRooms'), duplicateRoomsStatusElement: document.getElementById('duplicateRoomsStatus'), proxyListTextarea: document.getElementById('proxyList'), saveProxiesButton: document.getElementById('saveProxies'), updateProxiesButton: document.getElementById('updateProxies'), proxyStatusElement: document.getElementById('proxyStatus'), clearProxyButton: document.getElementById('clearProxy'), checkIncognito: document.getElementById('checkIncognito'), checkCurrentProxy: document.getElementById('checkCurrentProxy'), currentProxyStatus: document.getElementById('currentProxyStatus') }; // 检查登录状态 chrome.storage.local.get(['loginStatus', 'loginInfo'], function(data) { if (data.loginStatus && elements.userinfoElement) { elements.userinfoElement.textContent = '已登录:' + data.loginInfo.uname; } }); // 批量打开无痕窗口 if (elements.batchOpenIncognitoBtn && elements.incognitoCountInput) { elements.batchOpenIncognitoBtn.addEventListener('click', async () => { const count = parseInt(elements.incognitoCountInput.value) || 1; const actualCount = Math.min(Math.max(count, 1), 10); for (let i = 0; i < actualCount; i++) { await chrome.runtime.sendMessage({ action: 'openIncognitoDouyin', username: elements.usernameInput ? elements.usernameInput.value : '', password: elements.passwordInput ? elements.passwordInput.value : '' }); await new Promise(resolve => setTimeout(resolve, 500)); } }); } // 打开单个无痕窗口 if (elements.openIncognitoButton) { elements.openIncognitoButton.addEventListener('click', function() { console.log('打开无痕窗口按钮被点击'); chrome.runtime.sendMessage({ action: 'openIncognitoDouyin', username: elements.usernameInput ? elements.usernameInput.value : '', password: elements.passwordInput ? elements.passwordInput.value : '' }); }); } // 打开直播间 if (elements.openLiveButton && elements.liveIdInput) { elements.openLiveButton.addEventListener('click', () => { console.log('打开直播间按钮被点击'); const liveId = elements.liveIdInput.value.trim(); if (liveId) { const liveUrl = `https://live.douyin.com/${liveId}`; chrome.runtime.sendMessage({ action: 'openLiveIncognito', url: liveUrl }); } else { alert('请输入直播ID'); } }); } // 打开指定直播间 if (elements.openLiveRoomButton && elements.liveRoomIdInput) { elements.openLiveRoomButton.addEventListener('click', function() { console.log('打开指定直播间按钮被点击'); const liveRoomId = elements.liveRoomIdInput.value.trim(); if (liveRoomId) { const liveRoomUrl = `https://live.douyin.com/${liveRoomId}`; chrome.tabs.create({ url: liveRoomUrl }); } else { alert('请输入直播间ID'); } }); } // 查看观众数量 if (elements.checkViewersButton) { elements.checkViewersButton.addEventListener('click', async function() { console.log('查看观众数量按钮被点击'); try { const count = await getLiveRoomCount(); if (elements.liveRoomCountElement) { elements.liveRoomCountElement.textContent = count ? `观众数量: ${count}` : '无法获取观众数量'; } } catch (error) { console.error('获取观众数量失败:', error); alert('获取观众数量失败'); } }); } // 登录功能 if (elements.loginButton && elements.usernameInput && elements.passwordInput) { elements.loginButton.addEventListener('click', function() { const username = elements.usernameInput.value.trim(); const password = elements.passwordInput.value.trim(); if (!username || !password) { alert('请输入账号和密码!'); return; } chrome.runtime.sendMessage({ action: 'login', username, password }); }); } // 检查在线状态 if (elements.checkOnlineStatusButton) { elements.checkOnlineStatusButton.addEventListener('click', function() { injectContentScriptAndSendMessage('checkOnlineStatus'); }); } // 获取当前直播间ID if (elements.getCurrentRoomIdButton) { elements.getCurrentRoomIdButton.addEventListener('click', async function() { console.log('获取当前直播间ID按钮被点击'); try { const tabs = await chrome.tabs.query({active: true, currentWindow: true}); if (!tabs[0]) { throw new Error('未找到活动标签页'); } const response = await chrome.tabs.sendMessage(tabs[0].id, { action: 'getCurrentRoomId' }); if (response && response.roomId) { elements.currentRoomIdElement.textContent = `当前直播间ID: ${response.roomId}`; // 可选:自动填充到输入框 if (elements.liveRoomIdInput) { elements.liveRoomIdInput.value = response.roomId; } } else { elements.currentRoomIdElement.textContent = '未能获取直播间ID'; } } catch (error) { console.error('获取直播间ID失败:', error); alert('获取直播间ID失败,请确保您在抖音直播页'); } }); } // 加载保存的任务 chrome.storage.local.get(['tasks'], function(data) { if (data.tasks && elements.taskListTextarea) { elements.taskListTextarea.value = data.tasks.join('\n'); } }); // 保存任务按钮 if (elements.saveTasksButton && elements.taskListTextarea) { elements.saveTasksButton.addEventListener('click', function() { const tasks = elements.taskListTextarea.value .split('\n') .map(task => task.trim()) .filter(task => task.length > 0) .map(task => { // 验证务格式 const parts = task.split('-'); if (parts.length !== 2) { throw new Error(`任务格式错误: ${task}\n正确格式: 直播间ID-代理IP:端口`); } const [roomId, proxy] = parts; if (!roomId || !proxy || !proxy.includes(':')) { throw new Error(`任务格式错误: ${task}\n正确格式: 直播间ID-代理IP:端口`); } return task; }); chrome.storage.local.set({ tasks: tasks }, function() { if (elements.taskStatusElement) { elements.taskStatusElement.textContent = `已存 ${tasks.length} 个任务`; setTimeout(() => { elements.taskStatusElement.textContent = ''; }, 2000); } }); }); } // 执行任务按钮 if (elements.executeTasksButton) { elements.executeTasksButton.addEventListener('click', async function() { try { const data = await chrome.storage.local.get(['tasks']); const tasks = data.tasks || []; if (tasks.length === 0) { alert('没有可执行的任务'); return; } if (elements.taskStatusElement) { elements.taskStatusElement.textContent = '开始执行任务...'; } for (let i = 0; i < tasks.length; i++) { const task = tasks[i]; if (elements.taskStatusElement) { elements.taskStatusElement.textContent = `正在执行任务 ${i + 1}/${tasks.length}`; } // 这里执行具体任务 await executeTask(task); // 任务之间添加延迟 await new Promise(resolve => setTimeout(resolve, 1000)); } if (elements.taskStatusElement) { elements.taskStatusElement.textContent = '所有任务执行完成'; setTimeout(() => { elements.taskStatusElement.textContent = ''; }, 2000); } } catch (error) { console.error('执行任务时出错:', error); if (elements.taskStatusElement) { elements.taskStatusElement.textContent = '执行任务时出错: ' + error.message; } } }); } // 修改检查重复直播间功能 if (elements.checkDuplicateRoomsButton) { elements.checkDuplicateRoomsButton.addEventListener('click', async function() { console.log('检查重复直播间按钮被点击'); try { // 首先获取当前窗口 const currentWindow = await chrome.windows.getCurrent({ populate: true // 取窗中的所有标签页 }); // 只检��当前窗口中的标签页 const liveRooms = new Map(); // 存储直播间ID和第一次出现的标签页信息 const duplicates = new Map(); // 存储重复的直播间信息 // 遍历当前窗口的所有标签页 for (const tab of currentWindow.tabs) { const match = tab.url.match(/live\.douyin\.com\/([^/?]+)/); if (match) { const roomId = match[1]; if (liveRooms.has(roomId)) { // 发现重复,记录重复的标签页信息 if (!duplicates.has(roomId)) { // 第一次发现重复,将原始标签页信息也加入到重复列表 duplicates.set(roomId, { original: liveRooms.get(roomId), duplicates: [] }); } duplicates.get(roomId).duplicates.push({ tabId: tab.id, url: tab.url }); } else { // 记录第一次出现的标签页信息 liveRooms.set(roomId, { tabId: tab.id, url: tab.url }); } } } // 显示结果并处理重复 if (elements.duplicateRoomsStatusElement) { if (duplicates.size > 0) { let message = '当前窗口发现并处理重复的直播间:\n'; // 处理每个重复的直播间 for (const [roomId, info] of duplicates) { message += `房间ID ${roomId}:\n`; message += `- 保留标签页 ${info.original.tabId}\n`; // 关闭重复的标签页 for (const dupTab of info.duplicates) { message += `- 关闭标签页 ${dupTab.tabId}\n`; try { await chrome.tabs.remove(dupTab.tabId); } catch (error) { console.error(`关闭标签页 ${dupTab.tabId} 失败:`, error); } } // 切换到留的标签页 try { await chrome.tabs.update(info.original.tabId, { active: true }); } catch (error) { console.error(`切换到标签页 ${info.original.tabId} 失败:`, error); } } elements.duplicateRoomsStatusElement.textContent = message; } else { elements.duplicateRoomsStatusElement.textContent = '当前窗口未发现重复的直播间'; } // 5秒后清除状态信息 setTimeout(() => { elements.duplicateRoomsStatusElement.textContent = ''; }, 5000); } } catch (error) { console.error('检查重复直播间时出错:', error); if (elements.duplicateRoomsStatusElement) { elements.duplicateRoomsStatusElement.textContent = '检查失败: ' + error.message; } } }); } // 加载保存的代理列表 chrome.storage.local.get(['proxyList'], function(data) { if (data.proxyList && elements.proxyListTextarea) { elements.proxyListTextarea.value = data.proxyList.join('\n'); } }); // 保存代理按钮 if (elements.saveProxiesButton && elements.proxyListTextarea) { elements.saveProxiesButton.addEventListener('click', function() { try { const proxies = elements.proxyListTextarea.value .split('\n') .map(proxy => proxy.trim()) .filter(proxy => proxy.length > 0) .map(proxy => { // 验证代理格式 if (!validateProxy(proxy)) { throw new Error(`代理格式错误: ${proxy}\n正确格式: IP:端口`); } return proxy; }); chrome.storage.local.set({ proxyList: proxies }, function() { if (elements.proxyStatusElement) { elements.proxyStatusElement.textContent = `已保存 ${proxies.length} 个代理`; setTimeout(() => { elements.proxyStatusElement.textContent = ''; }, 2000); } }); } catch (error) { console.error('保存代理时出错:', error); if (elements.proxyStatusElement) { elements.proxyStatusElement.textContent = error.message; } } }); } // 修改更新代理按钮的处理逻辑 if (elements.updateProxiesButton && elements.proxyListTextarea) { elements.updateProxiesButton.addEventListener('click', async function() { try { // 获取代理列表 const proxyList = elements.proxyListTextarea.value .split('\n') .map(proxy => proxy.trim()) .filter(proxy => proxy.length > 0 && validateProxy(proxy)) .map(proxy => parseProxy(proxy)); // 解析代理字符串 if (proxyList.length === 0) { throw new Error('没有可用的代理'); } // 发送消息给background script,包含完整的代理列表 const response = await chrome.runtime.sendMessage({ action: 'setWindowProxy', proxyList: proxyList }); if (response.success) { if (elements.proxyStatusElement) { elements.proxyStatusElement.textContent = response.message; setTimeout(() => { elements.proxyStatusElement.textContent = ''; }, 3000); } } else { throw new Error(response.error || '更新代理失败'); } } catch (error) { console.error('更新代理时出错:', error); if (elements.proxyStatusElement) { elements.proxyStatusElement.textContent = error.message; setTimeout(() => { elements.proxyStatusElement.textContent = ''; }, 3000); } } }); } // 添加清除代理按钮功能 if (elements.clearProxyButton) { elements.clearProxyButton.addEventListener('click', async function() { try { // 发送消息给background script清除代理 await chrome.runtime.sendMessage({ action: 'clearProxy' }); // 获取所有无痕窗口 const windows = await chrome.windows.getAll({ windowTypes: ['normal'], populate: true }); // 刷新所有无痕窗口的标签页 for (const window of windows) { if (window.incognito) { for (const tab of window.tabs) { await chrome.tabs.reload(tab.id, { bypassCache: true }); // 添加短暂延迟,避免同时刷新太多标签页 await new Promise(resolve => setTimeout(resolve, 200)); } } } if (elements.proxyStatusElement) { elements.proxyStatusElement.textContent = '已清除所有代理设置'; setTimeout(() => { elements.proxyStatusElement.textContent = ''; }, 3000); } } catch (error) { console.error('清除代理时出错:', error); if (elements.proxyStatusElement) { elements.proxyStatusElement.textContent = '清除代理失败: ' + error.message; setTimeout(() => { elements.proxyStatusElement.textContent = ''; }, 3000); } } }); } // 检查无痕窗口数量 if (elements.checkIncognito) { elements.checkIncognito.addEventListener('click', function() { chrome.runtime.sendMessage({ action: 'checkIncognitoWindows' }, function(response) { const statusDiv = document.getElementById('incognitoStatus'); if (response.count === 0) { statusDiv.textContent = '当前没有无痕窗口'; } else { statusDiv.textContent = `当前有 ${response.count} 个无痕窗口`; // 可选:显示详细信息 const details = response.windows.map(w => `窗口ID: ${w.id}, 类型: ${w.type}, 标签数: ${w.tabCount}` ).join('\n'); console.log('无痕窗口详情:', details); } }); }); } // 添加查看当前代理的功能 if (elements.checkCurrentProxy) { elements.checkCurrentProxy.addEventListener('click', async function() { try { // 获取当前窗口 const currentWindow = await chrome.windows.getCurrent(); // 获取代理信息 const proxyInfo = await chrome.runtime.sendMessage({ action: 'getCurrentProxy', windowId: currentWindow.id }); // 显示代理信息 if (elements.currentProxyStatus) { if (proxyInfo.success) { if (proxyInfo.proxy) { const proxyText = `当前窗口ID: ${currentWindow.id}\n` + `代理服务器: ${proxyInfo.proxy.host}:${proxyInfo.proxy.port}\n` + `用户名: ${proxyInfo.proxy.username}`; elements.currentProxyStatus.textContent = proxyText; } else { elements.currentProxyStatus.textContent = '当前窗口未设置代理'; } } else { elements.currentProxyStatus.textContent = proxyInfo.error || '获取代理信息失败'; } // 3秒后清除状态信息 setTimeout(() => { elements.currentProxyStatus.textContent = ''; }, 3000); } } catch (error) { console.error('查看代理信息失败:', error); if (elements.currentProxyStatus) { elements.currentProxyStatus.textContent = '查看代理信息失败: ' + error.message; } } }); } }); // 辅助函数:获取直播间人数 async function getLiveRoomCount() { try { const tabs = await chrome.tabs.query({active: true, currentWindow: true}); if (!tabs[0]) return null; const response = await chrome.tabs.sendMessage(tabs[0].id, {action: "getLiveRoomCount"}); return response.count; } catch (error) { console.error("获取直播间人数失败:", error); return null; } } // 辅助函数:注入内容脚本并发送消息 function injectContentScriptAndSendMessage(action) { chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { if (!tabs[0]) { alert('无法获取当前标签页'); return; } chrome.scripting.executeScript({ target: {tabId: tabs[0].id}, files: ['content.js'] }, function() { if (chrome.runtime.lastError) { console.error('注入脚本失败:', chrome.runtime.lastError); return; } chrome.tabs.sendMessage(tabs[0].id, {action: action}, function(response) { if (chrome.runtime.lastError) { console.error('发送消息失败:', chrome.runtime.lastError); return; } console.log('收到响应:', response); }); }); }); } // 监听登录结果 chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { if (request.action === 'loginResult') { const userinfoElement = document.getElementById('userinfo'); if (request.status === 'success' && userinfoElement) { userinfoElement.textContent = '已登录:' + request.uname; } else { alert('登录失败:' + (request.message || '未知错误')); } } }); // 修改执行任务的函数 async function executeTask(task) { try { // 解析任务字符串 const [roomId, proxyString] = task.split('-'); const [proxyHost, proxyPort] = proxyString.split(':'); // 验证数据 if (!roomId || !proxyHost || !proxyPort) { throw new Error(`任务格式错误: ${task}`); } // 构建直播间URL const liveUrl = `https://live.douyin.com/${roomId}`; // 发送消息给background script,包含代理信息 await chrome.runtime.sendMessage({ action: 'openLiveWithProxy', url: liveUrl, proxy: { host: proxyHost, port: proxyPort } }); console.log(`已执行任务: 打开直播间 ${roomId}, 使用代理 ${proxyHost}:${proxyPort}`); } catch (error) { console.error(`执行任务 "${task}" 时出错:`, error); throw error; } } // 添加任务格式验证函数 function validateTask(task) { const parts = task.split('-'); if (parts.length !== 2) return false; const [roomId, proxy] = parts; if (!roomId || !proxy) return false; const [host, port] = proxy.split(':'); if (!host || !port) return false; // 简单的IP格式验证 const isValidIp = host.split('.').length === 4 && host.split('.').every(num => { const n = parseInt(num); return !isNaN(n) && n >= 0 && n <= 255; }); // 简单的端口验证 const isValidPort = !isNaN(parseInt(port)) && parseInt(port) > 0 && parseInt(port) <= 65535; return isValidIp && isValidPort; } // 修改代理验证函数 function validateProxy(proxy) { try { // 移除 http:// 前缀(如果存在) if (proxy.startsWith('http://')) { proxy = proxy.substring(7); } let host, port; if (proxy.includes('@')) { // 带认证信息的格式 const [auth, address] = proxy.split('@'); // 验证认证信息 const [username, password] = auth.split(':'); if (!username || !password) return false; [host, port] = address.split(':'); } else { // 简单格式 [host, port] = proxy.split(':'); } if (!host || !port) return false; // 验证IP格式 const isValidIp = host.split('.').length === 4 && host.split('.').every(num => { const n = parseInt(num); return !isNaN(n) && n >= 0 && n <= 255; }); // 验证端口 const isValidPort = !isNaN(parseInt(port)) && parseInt(port) > 0 && parseInt(port) <= 65535; return isValidIp && isValidPort; } catch (error) { console.error('代理格式验证失败:', error); return false; } } // 修改代理解析函数 function parseProxy(proxyString) { try { // 处理完整的代理URL格式 if (proxyString.startsWith('http://')) { // 移除 'http://' 前缀 proxyString = proxyString.substring(7); } let username = "", password = "", host = "", port = ""; if (proxyString.includes('@')) { // 带认证信息的格式 username:password@host:port const [auth, address] = proxyString.split('@'); [username, password] = auth.split(':'); [host, port] = address.split(':'); } else { // 简单格式 host:port [host, port] = proxyString.split(':'); } if (!host || !port) { throw new Error(`代理格式错误: ${proxyString}`); } return { username, password, host, port: parseInt(port) }; } catch (error) { console.error('解析代理字符串失败:', error); throw new Error(`代理格式错误: ${proxyString}\n正确格式: http://username:password@host:port`); } }