Skip to content

Commit

Permalink
fix(app): 优化软件导航页,将ocs-app接口代理删除,全局使用15319端口进行访问,修改浏览器启动选项,使浏览器环境更接近真…
Browse files Browse the repository at this point in the history
…实浏览器
  • Loading branch information
enncy committed Mar 29, 2023
1 parent 5ddce81 commit 9c8d3fd
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 136 deletions.
3 changes: 0 additions & 3 deletions packages/app/src/scripts/automation/wk/cx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,6 @@ function login(
if (area !== null) {
/** 破解验证码 */
if (opts?.ocrApiUrl && opts?.ocrApiImageKey && area) {
/** 每次都点击保证是最新图片 */
await Promise.all([page.waitForLoadState('networkidle'), await area.click()]);

await breakVerifyCode(page, area, {
ocrApiUrl: opts.ocrApiUrl,
ocrApiImageKey: opts.ocrApiImageKey
Expand Down
5 changes: 2 additions & 3 deletions packages/app/src/tasks/startup.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,11 @@ export async function startupServer() {
// 静态资源
app.use(express.static(path.join(getProjectPath(), './public')));

// 使用0作为随机端口号
const server = app.listen(0, () => {
const server = app.listen(15319, () => {
const address = server.address();
if (address && typeof address === 'object') {
// 存储本次服务的端口
store.set('server.port', address.port);
store.set('server.port', 15319);
logger.info(`OCS服务启动成功 => ${address.port}`);
}
});
Expand Down
121 changes: 55 additions & 66 deletions packages/app/src/worker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import path, { basename } from 'path';
import fs from 'fs';
import { chromium, BrowserContext, Page, LaunchOptions } from 'playwright-core';
import { AppStore } from '../../types';
import axios from 'axios';
import { scripts as PlaywrightScripts } from '../scripts/index';
import { Config } from '../scripts/interface';
const { bgRedBright, bgBlueBright, bgYellowBright, bgGray } = new Chalk({ level: 2 });
Expand Down Expand Up @@ -76,42 +75,6 @@ export class ScriptWorker {
onLaunch: (browser) => {
this.browser = browser;

/** 代理 ocs 脚本请求 */
browser.route(/http(?:s):\/\/ocs-app(.+)/, (route) => {
const request = route.request();
const url = request
.url()
.replace(/http(?:s):\/\/ocs-app\/(.+)/, `http://localhost:${this.store?.server.port || 3000}/$1`);

let res;

if (request.method().toLowerCase() === 'get') {
res = axios.get(url, {
headers: { 'browser-uid': this.uid },
timeout: 60 * 1000
});
} else {
res = axios.post(url, request.postDataJSON(), {
headers: { 'browser-uid': this.uid },
timeout: 60 * 1000
});
}

res
.then((result) => {
route.fulfill({
status: 200,
json: result.data
});
})
.catch((err) => {
route.fulfill({
status: 500,
json: { error: err }
});
});
});

/** URL事件解析器 */
this.browser?.on('page', (page) => {
const match = page.url().match(/ocs-action_(.+)/);
Expand All @@ -138,13 +101,21 @@ export class ScriptWorker {
? `http://localhost:${this.store?.server.port || 15319}/index.html#/bookmarks`
: undefined,
serverPort: this.store?.server.port || 15319,
browserUid: this.uid,
...options
});
} catch (err) {
// 浏览器异常关闭
if (err instanceof Error) {
if (err.message.includes('browser has been closed')) {
if (
err.message.includes('browser has been closed') ||
err.message.includes('Target closed') ||
err.message.includes('Browser closed')
) {
console.error('异常关闭,请尝试重启任务。', err.message);
send('browser-closed');
// 浏览器关闭跟随退出
process.exit();
} else {
console.error('错误 : ', err.message);
}
Expand Down Expand Up @@ -236,6 +207,7 @@ export async function launchScripts({
playwrightScripts,
bookmarksPageUrl,
serverPort,
browserUid,
onLaunch
}: Required<Pick<LaunchOptions, 'executablePath' | 'headless' | 'args'>> & {
/** 用户数据目录 */
Expand All @@ -250,16 +222,28 @@ export async function launchScripts({
bookmarksPageUrl?: string;
/** OCS服务器端口 */
serverPort: number;
/** 浏览器UID */
browserUid: string;
onLaunch?: (browser: BrowserContext) => void;
}) {
return new Promise<void>((resolve, reject) => {
chromium
.launchPersistentContext(userDataDir, {
.launchPersistentContext('', {
viewport: null,
executablePath,
ignoreDefaultArgs: ['--disable-popup-blocking'],
ignoreDefaultArgs: true,
ignoreHTTPSErrors: true,
args: ['--window-position=0,0', '--no-first-run', ...args],
args: [
'--window-position=0,0',
'--no-first-run',
`--user-data-dir=${userDataDir}`,
// '--enable-automation',
'--no-default-browser-check',
// 关闭导航检测
'--disable-prompt-on-repost',
'--remote-debugging-pipe',
...args
],
headless
})
.then(async (browser) => {
Expand All @@ -269,6 +253,11 @@ export async function launchScripts({
process.exit();
});

// 防检测
browser.addInitScript({
content: 'Object.defineProperty(navigator, "webdriver", { get: () => false });console.log(navigator)'
});

try {
const html = async (tips: string | string[], opts?: { loading?: boolean; warn?: boolean }) => {
const { loading = true, warn = false } = opts || {};
Expand Down Expand Up @@ -321,7 +310,7 @@ export async function launchScripts({
await script.run(await browser.newPage(), configs, {
ocrApiUrl: `http://localhost:${serverPort}/ocr`,
ocrApiImageKey: 'image',
detBackgroundKey: 'det_background',
detBackgroundKey: 'det_bg',
detTargetKey: 'det_target'
});
} catch (err) {
Expand All @@ -336,30 +325,6 @@ export async function launchScripts({
await html(['初始化完成。'].concat(warn), { loading: false, warn: !!warn.length });
};

const extensionLoadListener = async (page: Page) => {
try {
clearTimeout(extensionLoadListenerInterval);
await page.close();
await setup();
} catch (err) {
reject(err);
}

// 触发onLaunch事件
onLaunch?.(browser);
// 启动完成
resolve();
};

// 等待拓展加载完成
browser.once('page', extensionLoadListener);

// 一分钟后,如果拓展还没加载完成,提示用户重新启动浏览器
const extensionLoadListenerInterval = setTimeout(() => {
browser.off('page', extensionLoadListener);
html('【警告】浏览器拓展加载超时,请尝试重启浏览器。', { loading: false, warn: true }).catch(reject);
}, 60 * 1000);

if (extensionPaths.length === 0) {
await html('【警告】浏览器脚本管理拓展为空!将无法运行脚本,如想运行脚本,请在软件左侧浏览器拓展中安装。', {
loading: false,
Expand All @@ -371,6 +336,30 @@ export async function launchScripts({
// 启动完成
resolve();
} else {
const extensionLoadListener = async (page: Page) => {
try {
clearTimeout(extensionLoadListenerInterval);
await page.close();
await setup();
} catch (err) {
reject(err);
}

// 触发onLaunch事件
onLaunch?.(browser);
// 启动完成
resolve();
};

// 等待拓展加载完成
browser.once('page', extensionLoadListener);

// 一分钟后,如果拓展还没加载完成,提示用户重新启动浏览器
const extensionLoadListenerInterval = setTimeout(() => {
browser.off('page', extensionLoadListener);
html('【警告】浏览器拓展加载超时,请尝试重启浏览器。', { loading: false, warn: true }).catch(reject);
}, 60 * 1000);

await html('【提示】正在等待浏览器拓展加载。。。');
}
} catch (err) {
Expand Down
77 changes: 13 additions & 64 deletions packages/web/src/pages/bookmarks.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,38 +51,25 @@
>
<div class="bookmark-card-body">
<div
v-for="mark of item.values"
:key="mark?.name"
v-for="bookmark of item.values"
:key="bookmark?.name"
class="bookmark"
>
<a
v-if="!!mark"
:href="mark.url"
v-if="!!bookmark"
:href="bookmark.url"
target="_blank"
>
<a-tooltip background-color="#6c6c6ccf">
<template #content>
<div>{{ mark.title }}</div>
<template v-if="mark.description">
<a-divider class="m-1" />
<div>{{ mark.description }}</div>
</template>
<div>{{ bookmark.description || '暂无描述' }}</div>
</template>
<div class="icon col-12">
<template v-if="mark.icon">
<img :src="mark.icon" />
</template>
<object
v-else
:data="mark.favicon"
type="image/png"
>
<img src="https://fonts.gstatic.com/s/i/materialiconsoutlined/public/v13/24px.svg" />
</object>
<img :src="bookmark.icon" />
</div>
</a-tooltip>
<div class="col-12 mt-1 text-black text-decoration-underline">
{{ mark.name }}
{{ bookmark.name }}
</div>
</a>
</div>
Expand All @@ -96,20 +83,10 @@
<script setup lang="ts">
import { onMounted, ref, reactive } from 'vue';
import { getRemoteInfos } from '../utils';
import { BookmarkResource } from '@ocsjs/common/lib/src/api';
import axios from 'axios';
import { Card } from '@arco-design/web-vue';
import { BookmarkResource } from '../utils/apis';
type BookMark = BookmarkResource & {
values: {
name: string;
url: string;
favicon: string;
description: string;
title: string;
icon: string;
}[];
};
type BookMark = BookmarkResource;
const bookmarks = ref<BookMark[]>([]);
Expand All @@ -130,41 +107,13 @@ onMounted(async () => {
// 用 fori 是为了保证每个网站的位置固定
for (let i = 0; i < infos.bookmark.length; i++) {
const mark = infos.bookmark[i] as BookMark;
mark.values.forEach(async (_, j) => {
const site = reactive(mark.values[j]);
const url = new URL(site.url);
const bookmark = infos.bookmark[i] as BookMark;
site.favicon = `${url.origin}/favicon.ico`;
bookmark.values.forEach(async (_, j) => {
const site = reactive(bookmark.values[j]);
bookmarks.value[i] = bookmarks.value[i] || { group: '', values: [] };
bookmarks.value[i].group = mark.group;
bookmarks.value[i].group = bookmark.group;
bookmarks.value[i].values[j] = site;
try {
const { data } = await axios.post(`https://ocs-app/proxy`, {
method: 'get',
url: site.url
});
const html = String(data);
site.title = html.match(/<title>(.+?)<\/title>/)?.[1] || '';
site.description = html.match(/<meta.+?name="description".+?content="(.+?)".+?>/)?.[1] || '';
const icon = html.match(/<link.+?rel="icon".+?href="(.+?)".+?>/)?.[1] || '';
site.icon = icon
? icon.startsWith('http')
? icon
: icon.startsWith('//')
? `${site.url.startsWith('https') ? 'https' : 'http'}:${icon}`
: icon.startsWith('/')
? `${url.origin}${icon}`
: `${url.origin}/${icon}`
: '';
} catch (err) {
console.error(err);
}
});
}
});
Expand Down
2 changes: 2 additions & 0 deletions packages/web/src/utils/apis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export interface BookmarkResource {
values: {
name: string;
url: string;
description?: string;
icon?: string;
}[];
group: string;
}
Expand Down

0 comments on commit 9c8d3fd

Please sign in to comment.