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.
486 lines
14 KiB
486 lines
14 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) {
|
|
const maxRetries = 3;
|
|
let retryCount = 0;
|
|
|
|
function trySetProxy() {
|
|
console.log(`窗口 ${windowId} 设置代理尝试 ${retryCount + 1}/${maxRetries}:`, proxyConfig);
|
|
|
|
// 存储当前窗口的代理设置
|
|
windowProxyMap.set(windowId, proxyConfig);
|
|
|
|
// 设置新的代理
|
|
const config = {
|
|
value: {
|
|
mode: "fixed_servers",
|
|
rules: {
|
|
singleProxy: {
|
|
scheme: "http",
|
|
host: proxyConfig.host,
|
|
port: parseInt(proxyConfig.port)
|
|
},
|
|
bypassList: [
|
|
"localhost",
|
|
"127.0.0.1",
|
|
"<local>"
|
|
]
|
|
}
|
|
},
|
|
scope: "regular"
|
|
};
|
|
|
|
chrome.proxy.settings.set(
|
|
config,
|
|
function() {
|
|
if (chrome.runtime.lastError) {
|
|
console.error('设置代理失败:', chrome.runtime.lastError);
|
|
handleError(chrome.runtime.lastError);
|
|
return;
|
|
}
|
|
|
|
// 验证代理设置
|
|
chrome.proxy.settings.get(
|
|
{ incognito: false },
|
|
function(config) {
|
|
console.log(`窗口 ${windowId} 当前代理配置:`, config);
|
|
if (config.value.mode === "fixed_servers") {
|
|
// 只刷新当前窗口的标签页
|
|
chrome.tabs.query({ windowId: windowId }, function(tabs) {
|
|
let refreshedCount = 0;
|
|
if (tabs.length === 0) {
|
|
callback(null, true);
|
|
return;
|
|
}
|
|
|
|
tabs.forEach(function(tab) {
|
|
chrome.tabs.reload(tab.id, { bypassCache: true }, function() {
|
|
refreshedCount++;
|
|
if (refreshedCount === tabs.length) {
|
|
callback(null, true);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
} else {
|
|
handleError(new Error('代理设置验证失败'));
|
|
}
|
|
}
|
|
);
|
|
}
|
|
);
|
|
}
|
|
|
|
function handleError(error) {
|
|
if (retryCount < maxRetries - 1) {
|
|
retryCount++;
|
|
setTimeout(trySetProxy, 2000);
|
|
} else {
|
|
callback(error);
|
|
}
|
|
}
|
|
|
|
trySetProxy();
|
|
}
|
|
|
|
// 消息监听器
|
|
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 < incognitoWindows.length) {
|
|
sendResponse({
|
|
success: false,
|
|
error: `代理数量不足,需要 ${incognitoWindows.length} 个代理,但只有 ${proxyList.length} 个`
|
|
});
|
|
return;
|
|
}
|
|
|
|
let completedCount = 0;
|
|
let errors = [];
|
|
|
|
// 为每个窗口单独设置代理
|
|
incognitoWindows.forEach((window, index) => {
|
|
const proxy = proxyList[index];
|
|
const [host, port] = proxy.split(':');
|
|
|
|
if (!host || !port) {
|
|
errors.push(`代理格式错误: ${proxy}`);
|
|
completedCount++;
|
|
checkComplete();
|
|
return;
|
|
}
|
|
|
|
// 为每个窗口设置代理时先激活该窗口
|
|
chrome.windows.update(window.id, { focused: true }, () => {
|
|
setTimeout(() => {
|
|
setProxyForWindow(
|
|
{ host, port: parseInt(port) },
|
|
window.id,
|
|
(error, success) => {
|
|
if (error) {
|
|
errors.push(`窗口 ${window.id} 设置代理失败: ${error.message}`);
|
|
}
|
|
completedCount++;
|
|
checkComplete();
|
|
}
|
|
);
|
|
}, index * 3000); // 每个窗口间隔3秒
|
|
});
|
|
});
|
|
|
|
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') {
|
|
chrome.proxy.settings.clear(
|
|
{
|
|
scope: "regular"
|
|
},
|
|
() => {
|
|
if (chrome.runtime.lastError) {
|
|
console.error('清除代理失败:', chrome.runtime.lastError);
|
|
sendResponse({ success: false, error: chrome.runtime.lastError.message });
|
|
} else {
|
|
console.log('代理设置已完全清除');
|
|
sendResponse({ success: true });
|
|
}
|
|
}
|
|
);
|
|
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' // 超时
|
|
];
|
|
|
|
// 忽略的资源类型
|
|
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);
|
|
chrome.proxy.settings.set({
|
|
value: {
|
|
mode: "fixed_servers",
|
|
rules: {
|
|
singleProxy: {
|
|
scheme: "http",
|
|
host: proxyConfig.host,
|
|
port: parseInt(proxyConfig.port)
|
|
},
|
|
bypassList: ["localhost", "127.0.0.1", "<local>"]
|
|
}
|
|
},
|
|
scope: "regular"
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// 添加窗口关闭监听器
|
|
chrome.windows.onRemoved.addListener((windowId) => {
|
|
console.log(`窗口 ${windowId} 被关闭,移除其代理设置`);
|
|
windowProxyMap.delete(windowId);
|
|
});
|