feat: 新增一键打开渠道脚本
This commit is contained in:
@@ -3,14 +3,18 @@ import { ipcMain, app } from 'electron';
|
|||||||
import { IPC_EVENTS } from '@common/constants';
|
import { IPC_EVENTS } from '@common/constants';
|
||||||
import { launchLocalChrome } from '@main/utils/chrome/launchLocalChrome'
|
import { launchLocalChrome } from '@main/utils/chrome/launchLocalChrome'
|
||||||
import { executeScriptService } from '@main/service/execute-script-service';
|
import { executeScriptService } from '@main/service/execute-script-service';
|
||||||
import { chromium } from 'playwright';
|
|
||||||
import { addStealthInit, connectCdpContext, safeDisconnectBrowser } from '@main/utils/chrome/cdp'
|
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import log from 'electron-log';
|
import log from 'electron-log';
|
||||||
|
|
||||||
const openedTabIndexByChannelName = new Map<string, number>()
|
const openedTabIndexByChannelName = new Map<string, number>()
|
||||||
|
|
||||||
|
function getScriptsDir() {
|
||||||
|
return app.isPackaged
|
||||||
|
? path.join(process.resourcesPath, 'scripts')
|
||||||
|
: path.join(process.cwd(), 'src/main/scripts')
|
||||||
|
}
|
||||||
|
|
||||||
export function runTaskOperationService() {
|
export function runTaskOperationService() {
|
||||||
const executeScriptServiceInstance = new executeScriptService();
|
const executeScriptServiceInstance = new executeScriptService();
|
||||||
// 打开渠道
|
// 打开渠道
|
||||||
@@ -18,51 +22,20 @@ export function runTaskOperationService() {
|
|||||||
try {
|
try {
|
||||||
await launchLocalChrome()
|
await launchLocalChrome()
|
||||||
|
|
||||||
const arr = Array.isArray(channels) ? channels : []
|
const scriptsDir = getScriptsDir()
|
||||||
const keys = arr
|
const scriptPath = path.join(scriptsDir, 'open_all_channel.mjs')
|
||||||
.map((it: any) => typeof it === 'string' ? it : it.channelName)
|
|
||||||
.filter(Boolean)
|
|
||||||
if (keys.length === 0) return { success: true }
|
|
||||||
|
|
||||||
const urlMap: Record<string, string> = {}
|
openedTabIndexByChannelName.clear()
|
||||||
|
|
||||||
for (const it of arr) {
|
if (Array.isArray(channels)) {
|
||||||
const name = typeof it === 'string' ? it : it.channelName
|
for (let i = 0; i < channels.length; i++) {
|
||||||
const url = typeof it === 'string' ? undefined : it?.channelUrl
|
const name = channels[i]?.channelName
|
||||||
if (name && url) urlMap[name] = url
|
if (name) openedTabIndexByChannelName.set(String(name), i)
|
||||||
}
|
|
||||||
|
|
||||||
const { browser, context } = await connectCdpContext(chromium)
|
|
||||||
await addStealthInit(context)
|
|
||||||
|
|
||||||
for (let i = 0; i < keys.length; i++) {
|
|
||||||
const key = keys[i]
|
|
||||||
const targetUrl = urlMap[key]
|
|
||||||
|
|
||||||
let pages = await context.pages()
|
|
||||||
|
|
||||||
while (pages.length <= i) {
|
|
||||||
await context.newPage()
|
|
||||||
pages = await context.pages()
|
|
||||||
}
|
|
||||||
|
|
||||||
const page = pages[i]
|
|
||||||
await page.bringToFront()
|
|
||||||
|
|
||||||
if (targetUrl) {
|
|
||||||
const current = page.url()
|
|
||||||
|
|
||||||
if (!current || !current.startsWith(targetUrl)) {
|
|
||||||
await page.goto(targetUrl, { waitUntil: 'domcontentloaded' as any })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openedTabIndexByChannelName.set(key, i)
|
const result = await executeScriptServiceInstance.executeScript(scriptPath, { channels })
|
||||||
}
|
return { success: true, result }
|
||||||
|
|
||||||
await safeDisconnectBrowser(browser)
|
|
||||||
|
|
||||||
return { success: true }
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false, error: (error as any)?.message || 'open channel failed' }
|
return { success: false, error: (error as any)?.message || 'open channel failed' }
|
||||||
}
|
}
|
||||||
@@ -74,9 +47,6 @@ export function runTaskOperationService() {
|
|||||||
// 从options.roomList列表中找到对应的名称
|
// 从options.roomList列表中找到对应的名称
|
||||||
const roomType = options.roomList.find((item: any) => item.id === options.roomType);
|
const roomType = options.roomList.find((item: any) => item.id === options.roomType);
|
||||||
|
|
||||||
// 从roomType找fzName、mtName、dyHotelName、dyHotSpringName、xcName属性,判断是否有值
|
|
||||||
// 如果有值,就找出对应的脚本
|
|
||||||
// 如果没有值,就跳过
|
|
||||||
const pairs: Array<[string, string]> = [
|
const pairs: Array<[string, string]> = [
|
||||||
['fzName', 'fg_trace.mjs'],
|
['fzName', 'fg_trace.mjs'],
|
||||||
['mtName', 'mt_trace.mjs'],
|
['mtName', 'mt_trace.mjs'],
|
||||||
@@ -86,9 +56,7 @@ export function runTaskOperationService() {
|
|||||||
]
|
]
|
||||||
const scriptEntries = pairs.filter(([prop]) => roomType?.[prop])
|
const scriptEntries = pairs.filter(([prop]) => roomType?.[prop])
|
||||||
|
|
||||||
const scriptsDir = app.isPackaged
|
const scriptsDir = getScriptsDir()
|
||||||
? path.join(process.resourcesPath, 'scripts')
|
|
||||||
: path.join(process.cwd(), 'src/main/scripts')
|
|
||||||
|
|
||||||
const scriptPaths = scriptEntries.map(([channel, fileName]) => {
|
const scriptPaths = scriptEntries.map(([channel, fileName]) => {
|
||||||
const p = path.join(scriptsDir, fileName)
|
const p = path.join(scriptsDir, fileName)
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
const log = require('electron-log');
|
|
||||||
|
|
||||||
const checkLoginStatus = async (page) => {
|
|
||||||
try {
|
|
||||||
const currentUrl = await page.url();
|
|
||||||
|
|
||||||
log.info('current url==========>:', currentUrl);
|
|
||||||
|
|
||||||
const loginPagePatterns = ['/login', '/signin', '/auth'];
|
|
||||||
const isLoginPage = loginPagePatterns.some((pattern) => currentUrl.includes(pattern));
|
|
||||||
|
|
||||||
if (!isLoginPage) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pageContent = await page.content();
|
|
||||||
const loginKeywords = ['退出', '房价房量管理'];
|
|
||||||
const hasLoginKeyword = loginKeywords.some((keyword) => pageContent.includes(keyword));
|
|
||||||
|
|
||||||
if (hasLoginKeyword) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
} catch (error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
checkLoginStatus,
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -12,10 +12,12 @@ const preparePage = async (chromium, { tabIndex = Number(process.env.TAB_INDEX),
|
|||||||
|
|
||||||
const idx = Number.isFinite(tabIndex) && tabIndex >= 0 ? Math.floor(tabIndex) : 0;
|
const idx = Number.isFinite(tabIndex) && tabIndex >= 0 ? Math.floor(tabIndex) : 0;
|
||||||
let pages = await context.pages();
|
let pages = await context.pages();
|
||||||
|
|
||||||
while (pages.length <= idx) {
|
while (pages.length <= idx) {
|
||||||
await context.newPage();
|
await context.newPage();
|
||||||
pages = await context.pages();
|
pages = await context.pages();
|
||||||
}
|
}
|
||||||
|
|
||||||
const page = pages[idx];
|
const page = pages[idx];
|
||||||
await page.bringToFront();
|
await page.bringToFront();
|
||||||
|
|
||||||
@@ -24,6 +26,7 @@ const preparePage = async (chromium, { tabIndex = Number(process.env.TAB_INDEX),
|
|||||||
|
|
||||||
const safeDisconnectBrowser = async (browser) => {
|
const safeDisconnectBrowser = async (browser) => {
|
||||||
if (!browser) return;
|
if (!browser) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (typeof browser.disconnect === 'function') {
|
if (typeof browser.disconnect === 'function') {
|
||||||
await browser.disconnect();
|
await browser.disconnect();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { chromium } from 'playwright';
|
import { chromium } from 'playwright';
|
||||||
import log from 'electron-log';
|
import log from 'electron-log';
|
||||||
import tabsPkg from './common/tabs.js';
|
import tabsPkg from './common/tabs';
|
||||||
|
|
||||||
const { preparePage, safeDisconnectBrowser } = tabsPkg;
|
const { preparePage, safeDisconnectBrowser } = tabsPkg;
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ const toggleRoomByDateIndex = async (container, { roomType, dateIndex, operation
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(error);
|
log.error(error);
|
||||||
process.exitCode = 1;
|
process.exitCode = 1;
|
||||||
}finally {
|
} finally {
|
||||||
await safeDisconnectBrowser(browser);
|
await safeDisconnectBrowser(browser);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
72
src/main/scripts/open_all_channel.mjs
Normal file
72
src/main/scripts/open_all_channel.mjs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import { chromium } from 'playwright';
|
||||||
|
import log from 'electron-log';
|
||||||
|
|
||||||
|
const parseChannels = () => {
|
||||||
|
const raw = process.env.CHANNELS || '';
|
||||||
|
if (!raw) return [];
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(raw);
|
||||||
|
return Array.isArray(parsed) ? parsed : [];
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
let browser;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const channels = parseChannels();
|
||||||
|
|
||||||
|
if (!channels.length) {
|
||||||
|
log.info('No channels provided, skip.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
|
||||||
|
const context = browser.contexts()[0];
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('No browser context available');
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.addInitScript(() => {
|
||||||
|
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let i = 0; i < channels.length; i++) {
|
||||||
|
const targetUrl = channels[i]?.channelUrl;
|
||||||
|
|
||||||
|
if (!targetUrl) continue;
|
||||||
|
|
||||||
|
let pages = await context.pages();
|
||||||
|
|
||||||
|
while (pages.length <= i) {
|
||||||
|
await context.newPage();
|
||||||
|
pages = await context.pages();
|
||||||
|
}
|
||||||
|
|
||||||
|
const page = pages[i];
|
||||||
|
await page.bringToFront();
|
||||||
|
|
||||||
|
const current = page.url();
|
||||||
|
|
||||||
|
if (!current || !current.startsWith(targetUrl)) {
|
||||||
|
await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
log.error(error);
|
||||||
|
process.exitCode = 1;
|
||||||
|
} finally {
|
||||||
|
if(browser){
|
||||||
|
try {
|
||||||
|
if (typeof browser.disconnect === 'function') {
|
||||||
|
await browser.disconnect();
|
||||||
|
} else {
|
||||||
|
await browser.close();
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -23,6 +23,8 @@ export class executeScriptService extends EventEmitter {
|
|||||||
const endTime = options?.endTime ?? '';
|
const endTime = options?.endTime ?? '';
|
||||||
const operation = options?.operation ?? '';
|
const operation = options?.operation ?? '';
|
||||||
const tabIndex = options?.tabIndex ?? '';
|
const tabIndex = options?.tabIndex ?? '';
|
||||||
|
const channels = options?.channels ?? '';
|
||||||
|
const startTabIndex = options?.startTabIndex ?? '';
|
||||||
|
|
||||||
const child = spawn('node', [scriptPath], {
|
const child = spawn('node', [scriptPath], {
|
||||||
env: {
|
env: {
|
||||||
@@ -32,6 +34,8 @@ export class executeScriptService extends EventEmitter {
|
|||||||
END_DATE: String(endTime),
|
END_DATE: String(endTime),
|
||||||
OPERATION: String(operation),
|
OPERATION: String(operation),
|
||||||
TAB_INDEX: String(tabIndex),
|
TAB_INDEX: String(tabIndex),
|
||||||
|
CHANNELS: typeof channels === 'string' ? channels : JSON.stringify(channels),
|
||||||
|
START_TAB_INDEX: String(startTabIndex),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
import type { Browser, BrowserContext } from 'playwright'
|
|
||||||
|
|
||||||
export async function connectCdpContext(chromium: any, endpoint = 'http://127.0.0.1:9222'): Promise<{ browser: Browser, context: BrowserContext }> {
|
|
||||||
const browser = await chromium.connectOverCDP(endpoint)
|
|
||||||
const context = browser.contexts()[0]
|
|
||||||
|
|
||||||
if (!context) {
|
|
||||||
throw new Error('No browser context available')
|
|
||||||
}
|
|
||||||
return { browser, context }
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function addStealthInit(context: BrowserContext) {
|
|
||||||
await context.addInitScript(() => {
|
|
||||||
Object.defineProperty(navigator, 'webdriver', { get: () => undefined })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function safeDisconnectBrowser(browser: any) {
|
|
||||||
if (!browser) return
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (typeof browser.disconnect === 'function') {
|
|
||||||
await browser.disconnect()
|
|
||||||
} else {
|
|
||||||
await browser.close()
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user