Files

423 lines
12 KiB
JavaScript

// General Auto - Injected Script
(function() {
'use strict';
console.log('General Auto Injected script 已加载');
// 存储原始方法
const originalXHR = window.XMLHttpRequest;
const originalFetch = window.fetch;
const originalOpen = window.open;
// 请求拦截器配置
window.GeneralAutoConfig = {
interceptXHR: true,
interceptFetch: true,
logRequests: true,
requestCallbacks: [],
responseCallbacks: []
};
// 拦截 XMLHttpRequest
window.XMLHttpRequest = function() {
const xhr = new originalXHR();
const config = window.GeneralAutoConfig;
if (!config.interceptXHR) return xhr;
const originalOpen = xhr.open;
const originalSend = xhr.send;
const originalSetRequestHeader = xhr.setRequestHeader;
let requestData = {
method: '',
url: '',
headers: {},
body: null,
timestamp: Date.now()
};
xhr.open = function(method, url) {
requestData.method = method;
requestData.url = url;
return originalOpen.apply(this, arguments);
};
xhr.setRequestHeader = function(name, value) {
requestData.headers[name] = value;
return originalSetRequestHeader.apply(this, arguments);
};
xhr.send = function(body) {
requestData.body = body;
// 请求前回调
config.requestCallbacks.forEach(callback => {
try {
callback(requestData);
} catch (e) {
console.error('Request callback error:', e);
}
});
// 监听响应
this.addEventListener('load', function() {
const responseData = {
...requestData,
status: this.status,
statusText: this.statusText,
responseHeaders: this.getAllResponseHeaders(),
response: this.response,
responseText: this.responseText,
responseType: this.responseType,
responseURL: this.responseURL
};
// 响应后回调
config.responseCallbacks.forEach(callback => {
try {
callback(responseData);
} catch (e) {
console.error('Response callback error:', e);
}
});
// 发送到 background
if (config.logRequests) {
window.postMessage({
type: 'FROM_PAGE',
action: 'logRequest',
data: {
type: 'xhr',
method: responseData.method,
url: responseData.url,
status: responseData.status,
requestHeaders: responseData.headers,
requestBody: responseData.body,
responseHeaders: responseData.responseHeaders,
response: responseData.responseText
}
}, '*');
}
});
this.addEventListener('error', function() {
console.error('XHR Error:', requestData.url);
});
return originalSend.apply(this, arguments);
};
return xhr;
};
// 拦截 Fetch
window.fetch = function() {
const config = window.GeneralAutoConfig;
if (!config.interceptFetch) {
return originalFetch.apply(this, arguments);
}
const url = arguments[0];
const options = arguments[1] || {};
const requestData = {
method: options.method || 'GET',
url: typeof url === 'string' ? url : url.url,
headers: options.headers || {},
body: options.body,
timestamp: Date.now()
};
// 请求前回调
config.requestCallbacks.forEach(callback => {
try {
callback(requestData);
} catch (e) {
console.error('Request callback error:', e);
}
});
return originalFetch.apply(this, arguments).then(response => {
const clonedResponse = response.clone();
clonedResponse.text().then(body => {
const responseData = {
...requestData,
status: response.status,
statusText: response.statusText,
headers: Object.fromEntries(response.headers.entries()),
response: body,
responseURL: response.url
};
// 响应后回调
config.responseCallbacks.forEach(callback => {
try {
callback(responseData);
} catch (e) {
console.error('Response callback error:', e);
}
});
// 发送到 background
if (config.logRequests) {
window.postMessage({
type: 'FROM_PAGE',
action: 'logRequest',
data: {
type: 'fetch',
method: responseData.method,
url: responseData.url,
status: responseData.status,
requestHeaders: responseData.headers,
requestBody: responseData.body,
responseHeaders: responseData.headers,
response: body
}
}, '*');
}
});
return response;
});
};
// 提供全局自动化工具 API
window.AutomationUtils = {
// 模拟人类输入
humanInput: function(element, text, minDelay = 50, maxDelay = 150) {
return new Promise((resolve) => {
element.focus();
let index = 0;
const type = () => {
if (index < text.length) {
const char = text[index];
// 触发键盘事件
const keydownEvent = new KeyboardEvent('keydown', {
key: char,
code: `Key${char.toUpperCase()}`,
bubbles: true,
cancelable: true
});
const keypressEvent = new KeyboardEvent('keypress', {
key: char,
code: `Key${char.toUpperCase()}`,
bubbles: true,
cancelable: true
});
const keyupEvent = new KeyboardEvent('keyup', {
key: char,
code: `Key${char.toUpperCase()}`,
bubbles: true,
cancelable: true
});
element.dispatchEvent(keydownEvent);
element.dispatchEvent(keypressEvent);
element.value += char;
element.dispatchEvent(new Event('input', { bubbles: true }));
element.dispatchEvent(keyupEvent);
index++;
const delay = minDelay + Math.random() * (maxDelay - minDelay);
setTimeout(type, delay);
} else {
element.dispatchEvent(new Event('change', { bubbles: true }));
element.blur();
resolve();
}
};
setTimeout(type, 100);
});
},
// 模拟人类点击
humanClick: function(element, options = {}) {
return new Promise((resolve) => {
const rect = element.getBoundingClientRect();
const x = rect.left + (options.offsetX || rect.width * (0.3 + Math.random() * 0.4));
const y = rect.top + (options.offsetY || rect.height * (0.3 + Math.random() * 0.4));
// 滚动到元素
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
setTimeout(() => {
// 鼠标移动
const mousemoveEvent = new MouseEvent('mousemove', {
view: window,
bubbles: true,
cancelable: true,
clientX: x,
clientY: y
});
element.dispatchEvent(mousemoveEvent);
setTimeout(() => {
// 鼠标按下
const mousedownEvent = new MouseEvent('mousedown', {
view: window,
bubbles: true,
cancelable: true,
clientX: x,
clientY: y,
button: 0
});
element.dispatchEvent(mousedownEvent);
setTimeout(() => {
// 鼠标抬起
const mouseupEvent = new MouseEvent('mouseup', {
view: window,
bubbles: true,
cancelable: true,
clientX: x,
clientY: y,
button: 0
});
element.dispatchEvent(mouseupEvent);
// 点击
const clickEvent = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
clientX: x,
clientY: y,
button: 0
});
element.dispatchEvent(clickEvent);
resolve();
}, 50 + Math.random() * 50);
}, 50 + Math.random() * 50);
}, 200 + Math.random() * 300);
});
},
// 等待元素出现
waitForElement: function(selector, timeout = 10000, checkVisible = true) {
return new Promise((resolve, reject) => {
const check = () => {
const element = document.querySelector(selector);
if (element) {
if (!checkVisible) {
resolve(element);
return true;
}
const rect = element.getBoundingClientRect();
const isVisible = rect.width > 0 && rect.height > 0 &&
window.getComputedStyle(element).visibility !== 'hidden' &&
window.getComputedStyle(element).display !== 'none';
if (isVisible) {
resolve(element);
return true;
}
}
return false;
};
if (check()) return;
const observer = new MutationObserver(() => {
if (check()) {
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['style', 'class']
});
setTimeout(() => {
observer.disconnect();
reject(new Error(`等待元素超时: ${selector}`));
}, timeout);
});
},
// 等待元素消失
waitForElementRemoved: function(selector, timeout = 10000) {
return new Promise((resolve, reject) => {
const check = () => {
const element = document.querySelector(selector);
if (!element) {
resolve();
return true;
}
const rect = element.getBoundingClientRect();
const isHidden = rect.width === 0 || rect.height === 0 ||
window.getComputedStyle(element).visibility === 'hidden' ||
window.getComputedStyle(element).display === 'none';
if (isHidden) {
resolve();
return true;
}
return false;
};
if (check()) return;
const observer = new MutationObserver(() => {
if (check()) {
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['style', 'class']
});
setTimeout(() => {
observer.disconnect();
reject(new Error(`等待元素消失超时: ${selector}`));
}, timeout);
});
},
// 随机延迟
randomDelay: function(min = 100, max = 500) {
return new Promise(resolve => {
setTimeout(resolve, min + Math.random() * (max - min));
});
},
// 获取所有元素
getElements: function(selector) {
return Array.from(document.querySelectorAll(selector));
},
// 监听请求
onRequest: function(callback) {
window.GeneralAutoConfig.requestCallbacks.push(callback);
},
// 监听响应
onResponse: function(callback) {
window.GeneralAutoConfig.responseCallbacks.push(callback);
},
// 清除所有回调
clearCallbacks: function() {
window.GeneralAutoConfig.requestCallbacks = [];
window.GeneralAutoConfig.responseCallbacks = [];
}
};
// 简写
window.AU = window.AutomationUtils;
console.log('AutomationUtils API 已就绪');
})();