mirror of
https://github.com/NaiboWang/EasySpider.git
synced 2025-04-19 18:59:52 +08:00
568 lines
25 KiB
JavaScript
568 lines
25 KiB
JavaScript
// Modules to control application life and create native browser window
|
||
const {app, BrowserWindow, dialog, ipcMain, screen, session} = require('electron');
|
||
app.commandLine.appendSwitch("--disable-http-cache");
|
||
const {Builder, By, Key, until} = require("selenium-webdriver");
|
||
const chrome = require('selenium-webdriver/chrome');
|
||
const {ServiceBuilder} = require('selenium-webdriver/chrome');
|
||
const {rootCertificates} = require('tls');
|
||
const {exit} = require('process');
|
||
const path = require('path');
|
||
const fs = require('fs');
|
||
const {exec, spawn} = require('child_process');
|
||
const iconPath = path.join(__dirname, 'favicon.ico');
|
||
const task_server = require(path.join(__dirname, 'server.js'));
|
||
const util = require('util');
|
||
|
||
let config = fs.readFileSync(path.join(task_server.getDir(), `config.json`), 'utf8');
|
||
config = JSON.parse(config);
|
||
|
||
if(config.debug){
|
||
let logPath = 'info.log'
|
||
let logFile = fs.createWriteStream(logPath, { flags: 'a' })
|
||
console.log = function() {
|
||
logFile.write(util.format.apply(null, arguments) + '\n')
|
||
process.stdout.write(util.format.apply(null, arguments) + '\n')
|
||
}
|
||
console.error = function() {
|
||
logFile.write(util.format.apply(null, arguments) + '\n')
|
||
process.stderr.write(util.format.apply(null, arguments) + '\n')
|
||
}
|
||
}
|
||
let allWindowSockets = [];
|
||
let allWindowScoketNames = [];
|
||
task_server.start(config.webserver_port); //start local server
|
||
let server_address = `${config.webserver_address}:${config.webserver_port}`;
|
||
const websocket_port = 8084; //目前只支持8084端口,写死,因为扩展里面写死了
|
||
console.log("server_address: " + server_address);
|
||
let driverPath = "";
|
||
let chromeBinaryPath = "";
|
||
let execute_path = "";
|
||
console.log(process.arch);
|
||
|
||
exec(`wmic os get Caption`, function(error, stdout, stderr) {
|
||
if (error) {
|
||
console.error(`执行的错误: ${error}`);
|
||
return;
|
||
}
|
||
|
||
if (stdout.includes('Windows 7')) {
|
||
console.log('Windows 7');
|
||
let sys_arch = config.sys_arch;
|
||
if (sys_arch === 'x64') {
|
||
dialog.showMessageBoxSync({
|
||
type: 'error',
|
||
title: 'Error',
|
||
message: 'Windows 7系统请下载使用x32版本的软件,不论Win 7系统为x64还是x32版本。\nFor Windows 7, please download and use the x32 version of the software, regardless of whether the Win 7 system is x64 or x32 version.',
|
||
});
|
||
}
|
||
} else {
|
||
console.log('Not Windows 7');
|
||
}
|
||
});
|
||
|
||
if (process.platform === 'win32' && process.arch === 'ia32') {
|
||
driverPath = path.join(__dirname, "chrome_win32/chromedriver_win32.exe");
|
||
chromeBinaryPath = path.join(__dirname, "chrome_win32/chrome.exe");
|
||
execute_path = path.join(__dirname, "chrome_win32/execute.bat");
|
||
} else if (process.platform === 'win32' && process.arch === 'x64') {
|
||
driverPath = path.join(__dirname, "chrome_win64/chromedriver_win64.exe");
|
||
chromeBinaryPath = path.join(__dirname, "chrome_win64/chrome.exe");
|
||
execute_path = path.join(__dirname, "chrome_win64/execute.bat");
|
||
} else if (process.platform === 'darwin') {
|
||
driverPath = path.join(__dirname, "chromedriver_mac64");
|
||
chromeBinaryPath = path.join(__dirname, "chrome_mac64.app/Contents/MacOS/Google Chrome");
|
||
execute_path = path.join(__dirname, "");
|
||
} else if (process.platform === 'linux') {
|
||
driverPath = path.join(__dirname, "chrome_linux64/chromedriver_linux64");
|
||
chromeBinaryPath = path.join(__dirname, "chrome_linux64/chrome");
|
||
execute_path = path.join(__dirname, "chrome_linux64/execute.sh");
|
||
}
|
||
console.log(driverPath, chromeBinaryPath, execute_path);
|
||
let language = "en";
|
||
let driver = null;
|
||
let mainWindow = null;
|
||
let flowchart_window = null;
|
||
let current_handle = null;
|
||
let old_handles = [];
|
||
let handle_pairs = {};
|
||
let socket_window = null;
|
||
let socket_start = null;
|
||
let socket_flowchart = null;
|
||
let invoke_window = null;
|
||
|
||
// var ffi = require('ffi-napi');
|
||
// var libm = ffi.Library('libm', {
|
||
// 'ceil': [ 'double', [ 'double' ] ]
|
||
// });
|
||
// libm.ceil(1.5); // 2
|
||
// const {user32FindWindowEx,
|
||
// winspoolGetDefaultPrinter,} = require('win32-api/fun');
|
||
// async function testt(){
|
||
// // 获取当前电脑当前用户默认打印机名
|
||
// const printerName = await winspoolGetDefaultPrinter()
|
||
// console.log(printerName);
|
||
// }
|
||
|
||
// testt();
|
||
|
||
function createWindow() {
|
||
// Create the browser window.
|
||
mainWindow = new BrowserWindow({
|
||
width: 550,
|
||
height: 750,
|
||
webPreferences: {
|
||
preload: path.join(__dirname, 'src/js/preload.js')
|
||
},
|
||
icon: iconPath,
|
||
// frame: false, //取消window自带的关闭最小化等
|
||
resizable: false //禁止改变主窗口尺寸
|
||
})
|
||
|
||
// and load the index.html of the app.
|
||
// mainWindow.loadFile('src/index.html');
|
||
mainWindow.loadURL(server_address + '/index.html?user_data_folder=' + config.user_data_folder+"©right=" + config.copyright, { extraHeaders: 'pragma: no-cache\n' });
|
||
// 隐藏菜单栏
|
||
const {Menu} = require('electron');
|
||
Menu.setApplicationMenu(null);
|
||
mainWindow.on('close', function (e) {
|
||
if (process.platform !== 'darwin') {
|
||
app.quit();
|
||
}
|
||
});
|
||
// mainWindow.webContents.openDevTools();
|
||
// Open the DevTools.
|
||
// mainWindow.webContents.openDevTools()
|
||
}
|
||
|
||
|
||
async function beginInvoke(msg, ws) {
|
||
if (msg.type == 1) {
|
||
if (msg.message.id != -1) {
|
||
let url = "";
|
||
if (language == "zh") {
|
||
url = server_address + `/taskGrid/FlowChart_CN.html?id=${msg.message.id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address;
|
||
} else if (language == "en") {
|
||
url = server_address + `/taskGrid/FlowChart.html?id=${msg.message.id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address;
|
||
}
|
||
console.log(url);
|
||
flowchart_window.loadURL(url, { extraHeaders: 'pragma: no-cache\n' });
|
||
}
|
||
mainWindow.hide();
|
||
// Prints the currently focused window bounds.
|
||
// This method has to be called on macOS before changing the window's bounds, otherwise it will throw an error.
|
||
// It will prompt an accessibility permission request dialog, if needed.
|
||
if(process.platform != "linux" && process.platform != "darwin"){
|
||
const {windowManager} = require("node-window-manager");
|
||
const window = windowManager.getActiveWindow();
|
||
console.log(window);
|
||
windowManager.requestAccessibility();
|
||
// Sets the active window's bounds.
|
||
let size = screen.getPrimaryDisplay().workAreaSize
|
||
let width = parseInt(size.width)
|
||
let height = parseInt(size.height * 0.6)
|
||
window.setBounds({x: 0, y: size.height * 0.4, height: height, width: width});
|
||
}
|
||
|
||
flowchart_window.show();
|
||
// flowchart_window.openDevTools();
|
||
} else if (msg.type == 2) {
|
||
// 键盘输入事件
|
||
// const robot = require("@jitsi/robotjs");
|
||
let keyInfo = msg.message.keyboardStr;
|
||
let handles = await driver.getAllWindowHandles();
|
||
console.log("handles", handles);
|
||
let exit = false;
|
||
let content_handle = handle_pairs[msg.message.id];
|
||
console.log(msg.message.id, content_handle);
|
||
let order = [...handles.filter(handle => handle != current_handle && handle != content_handle), current_handle, content_handle]; //搜索顺序
|
||
let len = order.length;
|
||
while (true) {
|
||
// console.log("handles");
|
||
try{
|
||
let iframe = msg.message.iframe;
|
||
let enter = false;
|
||
if (/<enter>/i.test(keyInfo)) {
|
||
keyInfo = keyInfo.replace(/<enter>/gi, '');
|
||
enter = true;
|
||
}
|
||
let h = order[len - 1];
|
||
console.log("current_handle", current_handle);
|
||
if(h != null && handles.includes(h)){
|
||
await driver.switchTo().window(h);
|
||
current_handle = h;
|
||
console.log("switch to handle: ", h);
|
||
}
|
||
// await driver.executeScript("window.stop();");
|
||
// console.log("executeScript");
|
||
if(!iframe){
|
||
let element = await driver.findElement(By.xpath(msg.message.xpath));
|
||
console.log("Find Element at handle: ", current_handle);
|
||
// 使用正则表达式匹配 '<enter>',不论大小写
|
||
await element.sendKeys(Key.HOME, Key.chord(Key.SHIFT, Key.END), keyInfo);
|
||
if(enter){
|
||
await element.sendKeys(Key.ENTER);
|
||
}
|
||
console.log("send key");
|
||
break;
|
||
} else {
|
||
let iframes = await driver.findElements(By.tagName('iframe'));
|
||
// 遍历所有的 iframe 并点击里面的元素
|
||
for(let i = 0; i < iframes.length; i++) {
|
||
let iframe = iframes[i];
|
||
// 切换到 iframe
|
||
await driver.switchTo().frame(iframe);
|
||
// 在 iframe 中查找并点击元素
|
||
let element;
|
||
try {
|
||
element = await driver.findElement(By.xpath(msg.message.xpath));
|
||
} catch (error) {
|
||
console.log('No such element found in the iframe');
|
||
}
|
||
if (element) {
|
||
await element.sendKeys(Key.HOME, Key.chord(Key.SHIFT, Key.END), keyInfo);
|
||
if(enter){
|
||
await element.sendKeys(Key.ENTER);
|
||
}
|
||
}
|
||
// 完成操作后切回主文档
|
||
await driver.switchTo().defaultContent();
|
||
}
|
||
break;
|
||
}
|
||
|
||
} catch (error) {
|
||
console.log("len", len);
|
||
len = len - 1;
|
||
if (len == 0) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
} else if (msg.type == 3) {
|
||
try {
|
||
if (msg.from == 0) {
|
||
socket_flowchart.send(msg.message.pipe); //直接把消息转接
|
||
let message = JSON.parse(msg.message.pipe);
|
||
let type = message.type;
|
||
console.log("FROM Browser: ", message);
|
||
console.log("Iframe:", message.iframe);
|
||
if(type.indexOf("Click")>=0){
|
||
// 鼠标点击事件
|
||
let iframe = message.iframe;
|
||
let handles = await driver.getAllWindowHandles();
|
||
console.log("handles", handles);
|
||
let exit = false;
|
||
let content_handle = handle_pairs[message.id];
|
||
console.log(message.id, content_handle);
|
||
let order = [...handles.filter(handle => handle != current_handle && handle != content_handle), current_handle, content_handle]; //搜索顺序
|
||
let len = order.length;
|
||
while(true) {
|
||
try{
|
||
let h = order[len - 1];
|
||
console.log("current_handle", current_handle);
|
||
if(h != null && handles.includes(h)){
|
||
await driver.switchTo().window(h); //执行失败会抛出异常
|
||
current_handle = h;
|
||
console.log("switch to handle: ", h);
|
||
}
|
||
//下面是找到窗口的情况下
|
||
if(!iframe){
|
||
let element = await driver.findElement(By.xpath(message.xpath));
|
||
await element.click();
|
||
break;
|
||
} else {
|
||
let iframes = await driver.findElements(By.tagName('iframe'));
|
||
// 遍历所有的 iframe 并点击里面的元素
|
||
for(let i = 0; i < iframes.length; i++) {
|
||
let iframe = iframes[i];
|
||
// 切换到 iframe
|
||
await driver.switchTo().frame(iframe);
|
||
// 在 iframe 中查找并点击元素
|
||
let element;
|
||
try {
|
||
element = await driver.findElement(By.xpath(message.xpath));
|
||
} catch (error) {
|
||
console.log('No such element found in the iframe');
|
||
}
|
||
if (element) {
|
||
await element.click();
|
||
}
|
||
// 完成操作后切回主文档
|
||
await driver.switchTo().defaultContent();
|
||
}
|
||
break;
|
||
}
|
||
} catch (error) {
|
||
console.log("len", len); //如果没有找到元素,就切换到下一个窗口
|
||
len = len - 1;
|
||
if (len == 0) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
socket_window.send(msg.message.pipe);
|
||
for(let i in allWindowSockets){
|
||
try{
|
||
allWindowSockets[i].send(msg.message.pipe);
|
||
} catch {
|
||
console.log("Cannot send to socket with id: ", allWindowScoketNames[i]);
|
||
}
|
||
}
|
||
console.log("FROM Flowchart: ", JSON.parse(msg.message.pipe));
|
||
}
|
||
} catch (e) {
|
||
console.log(e);
|
||
}
|
||
} else if (msg.type == 5) {
|
||
let child = require('child_process').execFile;
|
||
// 参数顺序: 1. task id 2. server address 3. saved_file_name 4. "remote" or "local" 5. user_data_folder
|
||
// var parameters = [msg.message.id, server_address];
|
||
let parameters = [];
|
||
console.log(msg.message)
|
||
if (msg.message.user_data_folder == null || msg.message.user_data_folder == undefined || msg.message.user_data_folder == "") {
|
||
parameters = ["--id", "[" + msg.message.id + "]", "--server_address", server_address, "--user_data", 0];
|
||
} else {
|
||
let user_data_folder_path = path.join(task_server.getDir(), msg.message.user_data_folder);
|
||
parameters = ["--id", "[" + msg.message.id + "]", "--server_address", server_address, "--user_data", 1];
|
||
config.user_data_folder = msg.message.user_data_folder;
|
||
config.absolute_user_data_folder = user_data_folder_path;
|
||
fs.writeFileSync(path.join(task_server.getDir(), "config.json"), JSON.stringify(config));
|
||
}
|
||
if(msg.message.mysql_config_path != "-1"){
|
||
config.mysql_config_path = msg.message.mysql_config_path;
|
||
}
|
||
fs.writeFileSync(path.join(task_server.getDir(), "config.json"), JSON.stringify(config));
|
||
// child('Chrome/easyspider_executestage.exe', parameters, function(err,stdout, stderr) {
|
||
// console.log(stdout);
|
||
// });
|
||
|
||
let spawn = require("child_process").spawn;
|
||
if (process.platform != "darwin" && msg.message.execute_type == 1 && msg.message.id != -1) {
|
||
let child_process = spawn(execute_path, parameters);
|
||
child_process.stdout.on('data', function (data) {
|
||
console.log(data.toString());
|
||
});
|
||
}
|
||
ws.send(JSON.stringify({"config_folder": task_server.getDir() + "/", "easyspider_location": task_server.getEasySpiderLocation()}));
|
||
} else if (msg.type == 6) {
|
||
try{
|
||
flowchart_window.openDevTools();
|
||
} catch {
|
||
console.log("open devtools error");
|
||
}
|
||
try{
|
||
invoke_window.openDevTools();
|
||
} catch {
|
||
console.log("open devtools error");
|
||
}
|
||
} else if (msg.type == 7) {
|
||
// 获得当前页面Cookies
|
||
try{
|
||
let cookies = await driver.manage().getCookies();
|
||
console.log("Cookies: ", cookies);
|
||
let cookiesText = cookies.map(cookie => `${cookie.name}=${cookie.value}`).join('\n');
|
||
socket_flowchart.send(JSON.stringify({"type": "GetCookies", "message": cookiesText}));
|
||
} catch {
|
||
console.log("Cannot get Cookies");
|
||
}
|
||
}
|
||
}
|
||
|
||
const WebSocket = require('ws');
|
||
const {all} = require("express/lib/application");
|
||
let wss = new WebSocket.Server({port: websocket_port});
|
||
wss.on('connection', function (ws) {
|
||
ws.on('message', async function (message, isBinary) {
|
||
let msg = JSON.parse(message.toString());
|
||
console.log("\n\nGET A MESSAGE: ", msg);
|
||
// console.log(msg, msg.type, msg.message);
|
||
if (msg.type == 0) {
|
||
if (msg.message.id == 0) {
|
||
socket_window = ws;
|
||
console.log("set socket_window")
|
||
} else if (msg.message.id == 1) {
|
||
socket_start = ws;
|
||
console.log("set socket_start")
|
||
} else if (msg.message.id == 2) {
|
||
socket_flowchart = ws;
|
||
console.log("set socket_flowchart");
|
||
} else { //其他的ID是用来标识不同的浏览器标签页的
|
||
await new Promise(resolve => setTimeout(resolve, 2300));
|
||
let handles = await driver.getAllWindowHandles();
|
||
if(arrayDifference(handles, old_handles).length > 0){
|
||
old_handles = handles;
|
||
current_handle = handles[handles.length - 1];
|
||
console.log("New tab opened, change current_handle to: ", current_handle);
|
||
}
|
||
handle_pairs[msg.message.id] = current_handle;
|
||
console.log("Set handle_pair for id: ", msg.message.id, " to ", current_handle, ", title is: ", msg.message.title);
|
||
socket_flowchart.send(JSON.stringify({"type": "title", "data": {"title":msg.message.title}}));
|
||
allWindowSockets.push(ws);
|
||
allWindowScoketNames.push(msg.message.id);
|
||
// console.log("handle_pairs: ", handle_pairs);
|
||
}
|
||
} else if (msg.type == 10) {
|
||
let leave_handle = handle_pairs[msg.message.id];
|
||
if (leave_handle!=null && leave_handle!=undefined && leave_handle!="")
|
||
{
|
||
await driver.switchTo().window(leave_handle);
|
||
console.log("Switch to handle: ", leave_handle);
|
||
current_handle = leave_handle;
|
||
}
|
||
}
|
||
else {
|
||
await beginInvoke(msg, ws);
|
||
}
|
||
});
|
||
});
|
||
|
||
console.log(process.platform);
|
||
|
||
async function runBrowser(lang = "en", user_data_folder = '', mobile = false) {
|
||
const serviceBuilder = new ServiceBuilder(driverPath);
|
||
let options = new chrome.Options();
|
||
options.addArguments('--disable-blink-features=AutomationControlled');
|
||
language = lang;
|
||
if (lang == "en") {
|
||
options.addExtensions(path.join(__dirname, "EasySpider_en.crx"));
|
||
} else if (lang == "zh") {
|
||
options.addExtensions(path.join(__dirname, "EasySpider_zh.crx"));
|
||
}
|
||
options.addExtensions(path.join(__dirname, "XPathHelper.crx"));
|
||
options.setChromeBinaryPath(chromeBinaryPath);
|
||
if (user_data_folder != "") {
|
||
let dir = path.join(task_server.getDir(), user_data_folder);
|
||
console.log(dir);
|
||
options.addArguments("--user-data-dir=" + dir);
|
||
config.user_data_folder = user_data_folder;
|
||
fs.writeFileSync(path.join(task_server.getDir(), "config.json"), JSON.stringify(config));
|
||
}
|
||
if (mobile) {
|
||
const mobileEmulation = {
|
||
deviceName: 'iPhone XR'
|
||
};
|
||
options.addArguments(`--user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 13_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"`);
|
||
options.setMobileEmulation(mobileEmulation);
|
||
}
|
||
driver = new Builder()
|
||
.forBrowser('chrome')
|
||
.setChromeOptions(options)
|
||
.setChromeService(serviceBuilder)
|
||
.build();
|
||
await driver.manage().setTimeouts({implicit: 10000, pageLoad: 10000, script: 10000});
|
||
await driver.executeScript("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})");
|
||
// await driver.executeScript("localStorage.clear();"); //重置参数数量
|
||
const cdpConnection = await driver.createCDPConnection("page");
|
||
let stealth_path = path.join(__dirname, "stealth.min.js");
|
||
let stealth = fs.readFileSync(stealth_path, 'utf8');
|
||
await cdpConnection.execute('Page.addScriptToEvaluateOnNewDocument', {
|
||
source: stealth,
|
||
});
|
||
try {
|
||
if(mobile){
|
||
await driver.get(server_address + "/taskGrid/taskList.html?wsport=" + websocket_port + "&backEndAddressServiceWrapper=" + server_address + "&mobile=1&lang=" + lang);
|
||
} else {
|
||
await driver.get(server_address + "/taskGrid/taskList.html?wsport=" + websocket_port + "&backEndAddressServiceWrapper=" + server_address + "&lang=" + lang);
|
||
}
|
||
|
||
old_handles = await driver.getAllWindowHandles();
|
||
current_handle = old_handles[old_handles.length - 1];
|
||
} finally {
|
||
// await driver.quit(); // 退出浏览器
|
||
}
|
||
}
|
||
|
||
function handleOpenBrowser(event, lang = "en", user_data_folder = "", mobile = false) {
|
||
const webContents = event.sender;
|
||
const win = BrowserWindow.fromWebContents(webContents);
|
||
runBrowser(lang, user_data_folder, mobile);
|
||
let size = screen.getPrimaryDisplay().workAreaSize;
|
||
let width = parseInt(size.width);
|
||
let height = parseInt(size.height * 0.6);
|
||
flowchart_window = new BrowserWindow({
|
||
x: 0,
|
||
y: 0,
|
||
width: width,
|
||
height: height,
|
||
icon: iconPath,
|
||
});
|
||
let url = "";
|
||
let id = -1;
|
||
if (lang == "en") {
|
||
url = server_address + `/taskGrid/FlowChart.html?id=${id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address + "&mobile=" + mobile.toString();
|
||
} else if (lang == "zh") {
|
||
url = server_address + `/taskGrid/FlowChart_CN.html?id=${id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address+ "&mobile=" + mobile.toString();
|
||
}
|
||
// and load the index.html of the app.
|
||
flowchart_window.loadURL(url, { extraHeaders: 'pragma: no-cache\n' });
|
||
if(process.platform != "darwin"){
|
||
flowchart_window.hide();
|
||
}
|
||
flowchart_window.on('close', function (event) {
|
||
mainWindow.show();
|
||
driver.quit();
|
||
});
|
||
}
|
||
|
||
function handleOpenInvoke(event, lang = "en") {
|
||
invoke_window = new BrowserWindow({icon: iconPath});
|
||
let url = "";
|
||
language = lang;
|
||
if (lang == "en") {
|
||
url = server_address + `/taskGrid/taskList.html?type=1&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address;
|
||
} else if (lang == "zh") {
|
||
url = server_address + `/taskGrid/taskList.html?type=1&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address + "&lang=zh";
|
||
}
|
||
// and load the index.html of the app.
|
||
invoke_window.loadURL(url, { extraHeaders: 'pragma: no-cache\n' });
|
||
invoke_window.maximize();
|
||
mainWindow.hide();
|
||
invoke_window.on('close', function (event) {
|
||
mainWindow.show();
|
||
});
|
||
}
|
||
|
||
// This method will be called when Electron has finished
|
||
// initialization and is ready to create browser windows.
|
||
// Some APIs can only be used after this event occurs.
|
||
app.whenReady().then(() => {
|
||
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
||
details.requestHeaders['Accept-Language'] = 'zh'
|
||
callback({ cancel: false, requestHeaders: details.requestHeaders })
|
||
})
|
||
ipcMain.on('start-design', handleOpenBrowser);
|
||
ipcMain.on('start-invoke', handleOpenInvoke);
|
||
ipcMain.on('accept-agreement', function (event, arg) {
|
||
config.copyright = 1;
|
||
fs.writeFileSync(path.join(task_server.getDir(), "config.json"), JSON.stringify(config));
|
||
});
|
||
createWindow();
|
||
|
||
app.on('activate', function () {
|
||
// On macOS it's common to re-create a window in the app when the
|
||
// dock icon is clicked and there are no other windows open.
|
||
if (BrowserWindow.getAllWindows().length === 0) {
|
||
createWindow();
|
||
}
|
||
})
|
||
})
|
||
|
||
// Quit when all windows are closed, except on macOS. There, it's common
|
||
// for applications and their menu bar to stay active until the user quits
|
||
// explicitly with Cmd + Q.
|
||
app.on('window-all-closed', function () {
|
||
if (process.platform !== 'darwin') {
|
||
app.quit();
|
||
}
|
||
})
|
||
|
||
// In this file you can include the rest of your app's specific main process
|
||
// code. You can also put them in separate files and require them here.
|
||
|
||
|
||
function arrayDifference(arr1, arr2) {
|
||
return arr1.filter(item => !arr2.includes(item));
|
||
}
|