doufire 前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

654 lines
20 KiB

console.log('抖音扩展背景脚本已加载');
chrome.runtime.onInstalled.addListener(() => {
console.log("抖音扩展已安装");
});
// 添加代理可用性检测函数
async function checkProxyAvailability(proxyConfig) {
return new Promise((resolve) => {
const timeoutDuration = 10000; // 增加超时时间到10秒
console.log(`正在测试代理 ${proxyConfig.host}:${proxyConfig.port} 的可用性...`);
// 使用 XMLHttpRequest 来测试代理
const xhr = new XMLHttpRequest();
xhr.timeout = timeoutDuration;
// 设置超时处理
const timeoutHandler = setTimeout(() => {
xhr.abort();
console.log(`代理 ${proxyConfig.host}:${proxyConfig.port} 测试超时`);
resolve(false);
}, timeoutDuration);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
clearTimeout(timeoutHandler);
if (xhr.status === 200) {
console.log(`代理 ${proxyConfig.host}:${proxyConfig.port} 测试成功`);
resolve(true);
} else {
console.log(`代理 ${proxyConfig.host}:${proxyConfig.port} 测试失败,状态码: ${xhr.status}`);
resolve(false);
}
}
};
xhr.onerror = function () {
clearTimeout(timeoutHandler);
console.log(`代理 ${proxyConfig.host}:${proxyConfig.port} 连接错误`);
resolve(false);
};
try {
// 使用 HTTPS 测试
xhr.open('GET', 'https://www.douyin.com/favicon.ico', true);
xhr.send();
} catch (error) {
clearTimeout(timeoutHandler);
console.error(`代理测试出错:`, error);
resolve(false);
}
});
}
// 添加一个全局变量来存储每个窗口的代理设置
const windowProxyMap = new Map();
// 修改代理设置函数
function setProxyForWindow(proxyConfig, windowId, callback) {
console.log(`设置窗口 ${windowId} 的代理:`, {
host: proxyConfig.host,
port: proxyConfig.port,
username: proxyConfig.username
});
// 存储当前窗口的代理设置
windowProxyMap.set(windowId, proxyConfig);
// 设置认证监听器
const authHandler = function (details) {
console.log("=========PROXY CONFIG===========",proxyConfig)
return {
authCredentials: {
username: "hwfq28m43",
password: "YW29ABi6"
}
};
};
// 移除之前的监听器(如果存在)
try {
chrome.webRequest.onAuthRequired.removeListener(authHandler);
} catch (e) { }
// 添加新的监听器
chrome.webRequest.onAuthRequired.addListener(
// authHandler,
function(details,callbackFn){
console.log("onAuthRequired!", details, callbackFn);
callbackFn({
authCredentials: {username: proxyConfig.username, password: proxyConfig.password}
});
},
{ urls: ["<all_urls>"] },
["asyncBlocking"]
);
// 设置代理配置
const config = {
value: {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: "http",
host: proxyConfig.host,
port: parseInt(proxyConfig.port)
},
httpsProxy:{
// 添加 HTTPS 代理规则
scheme: "http",
host: proxyConfig.host,
port: parseInt(proxyConfig.port),
username: proxyConfig.username,
password: proxyConfig.password
}
}
},
scope: "regular"
};
// 设置代理
chrome.proxy.settings.set(
config,
function () {
if (chrome.runtime.lastError) {
console.error('设置代理失败:', chrome.runtime.lastError);
callback(chrome.runtime.lastError);
return;
}
console.log(`窗口 ${windowId} 代理设置成功`);
// 刷新标签页
chrome.tabs.query({ windowId: windowId }, function (tabs) {
if (tabs.length === 0) {
callback(null, true);
return;
}
let refreshedCount = 0;
tabs.forEach(function (tab) {
chrome.tabs.reload(tab.id, { bypassCache: true }, function () {
refreshedCount++;
if (refreshedCount === tabs.length) {
callback(null, true);
}
});
});
});
}
);
}
// 消息监听器
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'checkIncognitoWindows') {
chrome.windows.getAll({ populate: true }, (windows) => {
console.log('获取到所有窗口数量:', windows.length);
const incognitoWindows = windows.filter(w => w.incognito);
console.log('找到无痕窗口数量:', incognitoWindows.length);
const windowDetails = incognitoWindows.map(w => ({
id: w.id,
type: w.type,
state: w.state,
tabCount: w.tabs ? w.tabs.length : 0,
firstTabUrl: w.tabs && w.tabs[0] ? w.tabs[0].url : 'no tabs'
}));
console.log('无痕窗口详情:', windowDetails);
sendResponse({
count: incognitoWindows.length,
windows: windowDetails,
allWindowsCount: windows.length,
timestamp: new Date().toISOString()
});
});
return true;
}
if (request.action === 'openIncognitoDouyin') {
chrome.windows.create({
incognito: true,
url: "https://www.douyin.com"
}, function (window) {
console.log('抖音无痕窗口已打开');
});
} else if (request.action === 'openLiveIncognito') {
chrome.windows.create({
incognito: true,
url: request.url
}, function (window) {
console.log('直播无痕窗口已打开');
});
}
if (request.action === 'login') {
console.log('收到登录请求');
const loginData = {
uname: request.username,
upass: request.password
};
fetch('https://douyin.xingtongworld.com/api/passport/login?t=crx', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(loginData)
})
.then(response => response.json())
.then(data => {
console.log('登录结果:', data);
if (data.status === 200) {
sendResponse({ status: 'success' });
chrome.storage.local.set({ loginStatus: true });
chrome.storage.local.set({ loginInfo: loginData });
chrome.storage.local.set({ loginTime: new Date().toLocaleString() });
chrome.storage.local.set({ loginToken: data.token });
chrome.cookies.set({
url: 'https://douyin.xingtongworld.com',
name: 'sessionid',
value: data.token,
domain: 'douyin.xingtongworld.com'
});
} else {
sendResponse({ status: 'error', message: '登录失败:' + (data.message || '未知错误') });
}
})
.catch(error => {
console.error('登录请求出错:', error);
sendResponse({ status: 'error', message: '登录请出错,请检查网络连接或稍后重试。' });
});
}
if (request.action === 'checkStatus') {
let status = '正常';
sendResponse({ status: status });
}
if (request.action === 'openLiveWithProxy') {
chrome.windows.create({
url: request.url,
incognito: true,
type: 'normal'
}, (window) => {
if (window) {
// 等待窗口创建完成后再设置代理
setTimeout(() => {
setProxyForWindow(
request.proxy,
window.id,
(error, success) => {
if (error) {
console.error('设置代理失败:', error);
sendResponse({ success: false, error: error.message });
} else {
console.log('代理已设置到新创建无痕窗口');
sendResponse({ success: true });
}
}
);
}, 1000);
} else {
console.error('建窗口失败');
sendResponse({ success: false, error: '创建窗口失败' });
}
});
return true;
}
if (request.action === 'setWindowProxy') {
chrome.windows.getAll({ populate: true }, (windows) => {
const incognitoWindows = windows.filter(w => w.incognito);
if (incognitoWindows.length > 0) {
const proxyList = request.proxyList;
console.log('可用代理列表:', proxyList);
if (proxyList.length === 0) {
sendResponse({
success: false,
error: '没有可用的代理'
});
return;
}
let completedCount = 0;
let errors = [];
let currentIndex = 0;
// 处理下一个窗口
function processNextWindow() {
if (currentIndex >= incognitoWindows.length) {
checkComplete();
return;
}
const window = incognitoWindows[currentIndex];
// 检查窗口是否已经有代理设置
const existingProxy = windowProxyMap.get(window.id);
if (existingProxy) {
console.log(`窗口 ${window.id} 已有代理设置,跳过:`, {
host: existingProxy.host,
port: existingProxy.port,
username: existingProxy.username
});
completedCount++;
currentIndex++;
processNextWindow();
return;
}
// 使用循环方式获取代理配置
const proxyIndex = currentIndex % proxyList.length;
const proxy = proxyList[proxyIndex];
if (!proxy || !proxy.host || !proxy.port) {
errors.push(`代理配置无效: ${JSON.stringify(proxy)}`);
completedCount++;
currentIndex++;
processNextWindow();
return;
}
console.log(`窗口 ${window.id} 使用第 ${proxyIndex + 1} 个代理 (总共 ${proxyList.length} 个)`);
// 为窗口设置代理
chrome.windows.update(window.id, { focused: true }, () => {
setTimeout(() => {
setProxyForWindow(
proxy,
window.id,
(error, success) => {
if (error) {
console.error(`窗口 ${window.id} 设置代理失败:`, error);
errors.push(`窗口 ${window.id} 设置代理失败: ${error.message}`);
} else {
console.log(`窗口 ${window.id} 使用代理:`, {
host: proxy.host,
port: proxy.port,
username: proxy.username,
password: proxy.password
});
}
completedCount++;
currentIndex++;
setTimeout(processNextWindow, 1000); // 等待1秒后处理下一个窗口
}
);
}, 1000);
});
}
// 开始处理第一个窗口
processNextWindow();
function checkComplete() {
if (completedCount === incognitoWindows.length) {
if (errors.length > 0) {
sendResponse({
success: false,
error: errors.join('\n')
});
} else {
sendResponse({
success: true,
message: `已为 ${incognitoWindows.length} 个无痕窗口设置代理`
});
}
}
}
} else {
sendResponse({ success: false, error: '未找到无痕窗口' });
}
});
return true;
}
// 清除代理信息
if (request.action === 'clearProxy') {
try {
// 清除代理设置
chrome.proxy.settings.clear(
{ scope: "regular" },
async function () {
if (chrome.runtime.lastError) {
console.error('清除代理设置失败:', chrome.runtime.lastError);
sendResponse({ success: false, error: chrome.runtime.lastError.message });
return;
}
console.log('代理设置已清除');
try {
// 获取所有窗口
const windows = await new Promise((resolve) => {
chrome.windows.getAll({
populate: true
}, resolve);
});
// 清除代理映射
windowProxyMap.clear();
console.log('代理映射已清除');
// 清除认证缓存
const removeCache = async () => {
try {
await chrome.browsingData.remove({
"since": 0
}, {
"cache": true,
"cookies": true,
"passwords": true,
"webSQL": true,
"serviceWorkers": true,
"indexedDB": true
});
console.log('认证缓存已清除');
} catch (error) {
console.error('清除认证缓存失败:', error);
}
};
await removeCache();
// 刷新所有无痕窗口的标签页
for (const window of windows) {
if (window.incognito) {
console.log(`刷新无痕窗口 ${window.id} 的标签页`);
for (const tab of window.tabs) {
try {
// 先导航到空白页面
await new Promise((resolve) => {
chrome.tabs.update(tab.id, { url: 'about:blank' }, resolve);
});
await new Promise(resolve => setTimeout(resolve, 500));
// 然后重新加载原始URL
await new Promise((resolve) => {
chrome.tabs.reload(tab.id, { bypassCache: true }, resolve);
});
// 添加短暂延迟,避免同时刷新太多标签页
await new Promise(resolve => setTimeout(resolve, 500));
} catch (error) {
console.error(`刷新标签页 ${tab.id} 失败:`, error);
}
}
}
}
sendResponse({
success: true,
message: '已清除所有代理设置、认证缓存并刷新标签页'
});
} catch (error) {
console.error('刷新标签页时出错:', error);
sendResponse({
success: false,
error: '清除代理成功但刷新标签页失败: ' + error.message
});
}
}
);
} catch (error) {
console.error('清除代理时出错:', error);
sendResponse({ success: false, error: error.message });
}
return true;
}
// 当前代理
if (request.action === 'getCurrentProxy') {
try {
const windowId = request.windowId;
const proxyConfig = windowProxyMap.get(windowId);
if (proxyConfig) {
sendResponse({
success: true,
proxy: {
host: proxyConfig.host,
port: proxyConfig.port,
username: proxyConfig.username
// 出于安全考虑,不返回密码
}
});
} else {
sendResponse({
success: true,
proxy: null
});
}
} catch (error) {
console.error('获取代理信息失败:', error);
sendResponse({
success: false,
error: error.message
});
}
return true;
}
chrome.webRequest.onCompleted.addListener(
function (details) {
console.log("请求完成:", details);
},
{ urls: ["<all_urls>"] }
);
});
// 新窗口监听
chrome.windows.onCreated.addListener((window) => {
console.log('新窗口创:', {
id: window.id,
incognito: window.incognito,
type: window.type,
state: window.state,
alwaysOnTop: window.alwaysOnTop,
focused: window.focused,
timestamp: new Date().toISOString()
});
});
// 新标签监听
chrome.tabs.onCreated.addListener((tab) => {
console.log('新标签创建:', {
id: tab.id,
windowId: tab.windowId,
url: tab.url
});
});
// 修改错误监听器,添加更多需要忽略的误类型
chrome.webRequest.onErrorOccurred.addListener(
function (details) {
// 扩展需要忽略的错误类型列表
const ignoredErrors = [
'net::ERR_ABORTED', // 请求中断
'net::ERR_NETWORK_CHANGED', // 网络变化
'net::ERR_CONNECTION_CLOSED', // 连接关闭
'net::ERR_CACHE_MISS', // 缓存未命中
'net::ERR_EMPTY_RESPONSE', // 空响应
'net::ERR_FAILED', // 一般性失败
'net::ERR_TIMED_OUT', // 超时
'net::ERR_TOO_MANY_RETRIES', // 重试次数过多
'net::ERR_TUNNEL_CONNECTION_FAILED' // 隧道连接失败
];
// 略的资源类型
const ignoredResourceTypes = [
'font', // 字体文件
'image', // 图片
'media', // 媒体文件
'stylesheet', // CSS文件
'other' // 其他资源
];
if (details.error &&
!ignoredErrors.includes(details.error) &&
!ignoredResourceTypes.includes(details.type)) {
// 只记录重要的错误
const errorInfo = {
错误类型: details.error,
URL: details.url,
时间: new Date(details.timeStamp).toLocaleString(),
标签页ID: details.tabId,
请求类型: details.type
};
// 如果是代理相关错误,添加更多信息
if (details.error.toLowerCase().includes('proxy') ||
details.error.toLowerCase().includes('connection_refused')) {
errorInfo.代理错误 = true;
errorInfo.IP地址 = details.ip || '未知';
console.error('代理相关错误:\n' +
Object.entries(errorInfo)
.map(([key, value]) => `${key}: ${value}`)
.join('\n')
);
} else if (details.error.toLowerCase().includes('cert')) {
// 证书相关错误
console.warn('证书相关错误:\n' +
Object.entries(errorInfo)
.map(([key, value]) => `${key}: ${value}`)
.join('\n')
);
} else {
// 其他重要错误
console.error('重要网络错误:\n' +
Object.entries(errorInfo)
.map(([key, value]) => `${key}: ${value}`)
.join('\n')
);
}
}
},
{ urls: ["<all_urls>"] }
);
chrome.windows.onRemoved.addListener((windowId) => {
console.log('窗口被关闭:', {
id: windowId,
timestamp: new Date().toISOString()
});
});
chrome.windows.onFocusChanged.addListener((windowId) => {
if (windowId !== chrome.windows.WINDOW_ID_NONE) {
console.log('窗口点改变:', windowId);
}
});
// 修改窗口焦点变化监听器
chrome.windows.onFocusChanged.addListener((windowId) => {
if (windowId !== chrome.windows.WINDOW_ID_NONE) {
const proxyConfig = windowProxyMap.get(windowId);
if (proxyConfig) {
console.log(`窗口 ${windowId} 获得焦点,恢复其代理设置:`, proxyConfig);
setProxyForWindow(proxyConfig, windowId, (error) => {
if (error) {
console.error('恢复代理设置失败:', error);
}
});
}
}
});
// 添加窗口关闭监听器
chrome.windows.onRemoved.addListener((windowId) => {
console.log(`窗口 ${windowId} 被关闭,移除其代理设置`);
windowProxyMap.delete(windowId);
});
// 添加证书错误处理
chrome.webRequest.onErrorOccurred.addListener(
function (details) {
if (details.error && details.error.includes('ERR_CERT')) {
console.log('忽略证书错误:', details.url);
return { cancel: false };
}
},
{
urls: ["<all_urls>"],
types: ["main_frame", "sub_frame", "stylesheet", "script", "image", "object", "xmlhttprequest", "other"]
}
);