@roll-agent/browser-use-agent 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +53 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +111 -0
- package/dist/index.js.map +1 -0
- package/dist/pages/yupao/chat.d.ts +7 -0
- package/dist/pages/yupao/chat.d.ts.map +1 -0
- package/dist/pages/yupao/chat.js +18 -0
- package/dist/pages/yupao/chat.js.map +1 -0
- package/dist/pages/yupao/message-list.d.ts +11 -0
- package/dist/pages/yupao/message-list.d.ts.map +1 -0
- package/dist/pages/yupao/message-list.js +36 -0
- package/dist/pages/yupao/message-list.js.map +1 -0
- package/dist/pages/yupao/navigation.d.ts +10 -0
- package/dist/pages/yupao/navigation.d.ts.map +1 -0
- package/dist/pages/yupao/navigation.js +34 -0
- package/dist/pages/yupao/navigation.js.map +1 -0
- package/dist/pages/yupao/selectors.d.ts +26 -0
- package/dist/pages/yupao/selectors.d.ts.map +1 -0
- package/dist/pages/yupao/selectors.js +26 -0
- package/dist/pages/yupao/selectors.js.map +1 -0
- package/dist/pages/zhipin/anti-detection.d.ts +18 -0
- package/dist/pages/zhipin/anti-detection.d.ts.map +1 -0
- package/dist/pages/zhipin/anti-detection.js +65 -0
- package/dist/pages/zhipin/anti-detection.js.map +1 -0
- package/dist/pages/zhipin/chat-navigation.d.ts +28 -0
- package/dist/pages/zhipin/chat-navigation.d.ts.map +1 -0
- package/dist/pages/zhipin/chat-navigation.js +158 -0
- package/dist/pages/zhipin/chat-navigation.js.map +1 -0
- package/dist/pages/zhipin/selectors.d.ts +128 -0
- package/dist/pages/zhipin/selectors.d.ts.map +1 -0
- package/dist/pages/zhipin/selectors.js +136 -0
- package/dist/pages/zhipin/selectors.js.map +1 -0
- package/dist/platforms.d.ts +8 -0
- package/dist/platforms.d.ts.map +1 -0
- package/dist/platforms.js +20 -0
- package/dist/platforms.js.map +1 -0
- package/dist/runtime-holder.d.ts +8 -0
- package/dist/runtime-holder.d.ts.map +1 -0
- package/dist/runtime-holder.js +50 -0
- package/dist/runtime-holder.js.map +1 -0
- package/dist/tools/browser-status.d.ts +13 -0
- package/dist/tools/browser-status.d.ts.map +1 -0
- package/dist/tools/browser-status.js +49 -0
- package/dist/tools/browser-status.js.map +1 -0
- package/dist/tools/list-pages.d.ts +13 -0
- package/dist/tools/list-pages.d.ts.map +1 -0
- package/dist/tools/list-pages.js +40 -0
- package/dist/tools/list-pages.js.map +1 -0
- package/dist/tools/navigate-active-tab.d.ts +14 -0
- package/dist/tools/navigate-active-tab.d.ts.map +1 -0
- package/dist/tools/navigate-active-tab.js +49 -0
- package/dist/tools/navigate-active-tab.js.map +1 -0
- package/dist/tools/open-platform.d.ts +9 -0
- package/dist/tools/open-platform.d.ts.map +1 -0
- package/dist/tools/open-platform.js +40 -0
- package/dist/tools/open-platform.js.map +1 -0
- package/dist/tools/select-page.d.ts +15 -0
- package/dist/tools/select-page.d.ts.map +1 -0
- package/dist/tools/select-page.js +38 -0
- package/dist/tools/select-page.js.map +1 -0
- package/dist/tools/yupao-read-messages.d.ts +13 -0
- package/dist/tools/yupao-read-messages.d.ts.map +1 -0
- package/dist/tools/yupao-read-messages.js +36 -0
- package/dist/tools/yupao-read-messages.js.map +1 -0
- package/dist/tools/yupao-send-reply.d.ts +10 -0
- package/dist/tools/yupao-send-reply.d.ts.map +1 -0
- package/dist/tools/yupao-send-reply.js +40 -0
- package/dist/tools/yupao-send-reply.js.map +1 -0
- package/dist/tools/zhipin-close-resume.d.ts +6 -0
- package/dist/tools/zhipin-close-resume.d.ts.map +1 -0
- package/dist/tools/zhipin-close-resume.js +73 -0
- package/dist/tools/zhipin-close-resume.js.map +1 -0
- package/dist/tools/zhipin-exchange-wechat.d.ts +14 -0
- package/dist/tools/zhipin-exchange-wechat.d.ts.map +1 -0
- package/dist/tools/zhipin-exchange-wechat.js +218 -0
- package/dist/tools/zhipin-exchange-wechat.js.map +1 -0
- package/dist/tools/zhipin-get-candidate-info.d.ts +34 -0
- package/dist/tools/zhipin-get-candidate-info.d.ts.map +1 -0
- package/dist/tools/zhipin-get-candidate-info.js +247 -0
- package/dist/tools/zhipin-get-candidate-info.js.map +1 -0
- package/dist/tools/zhipin-get-candidate-list.d.ts +24 -0
- package/dist/tools/zhipin-get-candidate-list.d.ts.map +1 -0
- package/dist/tools/zhipin-get-candidate-list.js +175 -0
- package/dist/tools/zhipin-get-candidate-list.js.map +1 -0
- package/dist/tools/zhipin-get-username.d.ts +6 -0
- package/dist/tools/zhipin-get-username.d.ts.map +1 -0
- package/dist/tools/zhipin-get-username.js +47 -0
- package/dist/tools/zhipin-get-username.js.map +1 -0
- package/dist/tools/zhipin-locate-resume-canvas.d.ts +15 -0
- package/dist/tools/zhipin-locate-resume-canvas.d.ts.map +1 -0
- package/dist/tools/zhipin-locate-resume-canvas.js +90 -0
- package/dist/tools/zhipin-locate-resume-canvas.js.map +1 -0
- package/dist/tools/zhipin-open-chat.d.ts +15 -0
- package/dist/tools/zhipin-open-chat.d.ts.map +1 -0
- package/dist/tools/zhipin-open-chat.js +82 -0
- package/dist/tools/zhipin-open-chat.js.map +1 -0
- package/dist/tools/zhipin-open-resume.d.ts +9 -0
- package/dist/tools/zhipin-open-resume.d.ts.map +1 -0
- package/dist/tools/zhipin-open-resume.js +51 -0
- package/dist/tools/zhipin-open-resume.js.map +1 -0
- package/dist/tools/zhipin-read-messages.d.ts +22 -0
- package/dist/tools/zhipin-read-messages.d.ts.map +1 -0
- package/dist/tools/zhipin-read-messages.js +90 -0
- package/dist/tools/zhipin-read-messages.js.map +1 -0
- package/dist/tools/zhipin-say-hello.d.ts +18 -0
- package/dist/tools/zhipin-say-hello.d.ts.map +1 -0
- package/dist/tools/zhipin-say-hello.js +118 -0
- package/dist/tools/zhipin-say-hello.js.map +1 -0
- package/dist/tools/zhipin-send-reply.d.ts +14 -0
- package/dist/tools/zhipin-send-reply.d.ts.map +1 -0
- package/dist/tools/zhipin-send-reply.js +99 -0
- package/dist/tools/zhipin-send-reply.js.map +1 -0
- package/package.json +63 -0
package/SKILL.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: browser-use-agent
|
|
3
|
+
description: 浏览器操控 Agent。控制浏览器操作招聘平台——读取消息、打开聊天、发送回复、换微信、查看推荐列表、打招呼、查看简历。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Browser Use Agent
|
|
7
|
+
|
|
8
|
+
浏览器自动化 Agent,作为招聘平台消息收发的执行层("手")。通过 Playwright 控制浏览器,提供平台级 workflow 操作。
|
|
9
|
+
|
|
10
|
+
需要先启动 Agent 服务进程(HTTP 常驻),浏览器 session 跨调用持久。
|
|
11
|
+
|
|
12
|
+
## 通用 Tools
|
|
13
|
+
|
|
14
|
+
- `browser_status()` — 查询浏览器运行状态和活跃 session
|
|
15
|
+
- `list_pages(platform?)` — 列出当前浏览器中可见的页面和 pageId
|
|
16
|
+
- `navigate_active_tab(url)` — 将当前激活 tab 导航到指定 URL
|
|
17
|
+
- `open_platform(platform)` — 打开并聚焦招聘平台主页
|
|
18
|
+
- `select_page(platform, pageId)` — 将指定页面绑定为平台当前活跃页
|
|
19
|
+
|
|
20
|
+
## BOSS直聘 — 聊天 Tools
|
|
21
|
+
|
|
22
|
+
- `zhipin_read_messages(limit?, onlyUnread?, sortBy?)` — 读取消息列表中的候选人,支持过滤未读和排序
|
|
23
|
+
- `zhipin_open_chat(candidateName?, index?, preferUnread?)` — 打开指定候选人的聊天窗口(按姓名模糊匹配或列表索引)
|
|
24
|
+
- `zhipin_get_candidate_info(candidateName?, index?, maxMessages?)` — 提取候选人资料和聊天记录。指定 candidateName 会自动打开对应聊天
|
|
25
|
+
- `zhipin_send_reply(message, candidateName?, index?)` — 发送消息。指定 candidateName 会自动打开对应聊天后发送
|
|
26
|
+
- `zhipin_exchange_wechat(candidateName?, index?)` — 换微信。指定 candidateName 会自动打开对应聊天后执行
|
|
27
|
+
- `zhipin_get_username()` — 获取当前登录的招聘者用户名
|
|
28
|
+
|
|
29
|
+
## BOSS直聘 — 推荐列表 Tools
|
|
30
|
+
|
|
31
|
+
- `zhipin_get_candidate_list(maxResults?)` — 获取推荐列表页的候选人卡片信息(姓名、年龄、学历、期望薪资等)
|
|
32
|
+
- `zhipin_say_hello(indices)` — 对推荐列表中的候选人批量点击「打招呼」
|
|
33
|
+
- `zhipin_open_resume(index)` — 点击候选人卡片打开简历详情弹窗
|
|
34
|
+
- `zhipin_locate_resume_canvas()` — 定位简历弹窗中嵌套 iframe 内的 canvas 坐标(用于截图)
|
|
35
|
+
- `zhipin_close_resume()` — 关闭简历详情弹窗
|
|
36
|
+
|
|
37
|
+
## 鱼泡 Tools
|
|
38
|
+
|
|
39
|
+
- `yupao_read_messages(limit?)` — 读取鱼泡未读消息列表
|
|
40
|
+
- `yupao_send_reply(conversationId, message)` — 向鱼泡指定对话发送回复
|
|
41
|
+
|
|
42
|
+
## 典型工作流
|
|
43
|
+
|
|
44
|
+
1. `zhipin_read_messages` → 获取未读候选人列表
|
|
45
|
+
2. `zhipin_open_chat(candidateName)` → 打开某人的聊天
|
|
46
|
+
3. `zhipin_get_candidate_info` → 查看候选人资料和聊天记录
|
|
47
|
+
4. `zhipin_send_reply(message)` → 发送回复
|
|
48
|
+
5. `zhipin_exchange_wechat` → 交换微信(可选)
|
|
49
|
+
|
|
50
|
+
## 支持平台
|
|
51
|
+
|
|
52
|
+
- BOSS直聘 (zhipin)
|
|
53
|
+
- 鱼泡 (yupao)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { defineAgent } from "@roll-agent/sdk";
|
|
2
|
+
import { BrowserRuntimeConfigSchema } from "@roll-agent/browser";
|
|
3
|
+
import { browserStatus } from "./tools/browser-status.js";
|
|
4
|
+
import { listPages } from "./tools/list-pages.js";
|
|
5
|
+
import { navigateActiveTab } from "./tools/navigate-active-tab.js";
|
|
6
|
+
import { openPlatform } from "./tools/open-platform.js";
|
|
7
|
+
import { selectPage } from "./tools/select-page.js";
|
|
8
|
+
// Zhipin — 聊天
|
|
9
|
+
import { zhipinReadMessages } from "./tools/zhipin-read-messages.js";
|
|
10
|
+
import { zhipinOpenChat } from "./tools/zhipin-open-chat.js";
|
|
11
|
+
import { zhipinGetCandidateInfo } from "./tools/zhipin-get-candidate-info.js";
|
|
12
|
+
import { zhipinSendReply } from "./tools/zhipin-send-reply.js";
|
|
13
|
+
import { zhipinExchangeWechat } from "./tools/zhipin-exchange-wechat.js";
|
|
14
|
+
import { zhipinGetUsername } from "./tools/zhipin-get-username.js";
|
|
15
|
+
// Zhipin — 推荐列表
|
|
16
|
+
import { zhipinGetCandidateList } from "./tools/zhipin-get-candidate-list.js";
|
|
17
|
+
import { zhipinSayHello } from "./tools/zhipin-say-hello.js";
|
|
18
|
+
import { zhipinOpenResume } from "./tools/zhipin-open-resume.js";
|
|
19
|
+
import { zhipinLocateResumeCanvas } from "./tools/zhipin-locate-resume-canvas.js";
|
|
20
|
+
import { zhipinCloseResume } from "./tools/zhipin-close-resume.js";
|
|
21
|
+
// Yupao
|
|
22
|
+
import { yupaoReadMessages } from "./tools/yupao-read-messages.js";
|
|
23
|
+
import { yupaoSendReply } from "./tools/yupao-send-reply.js";
|
|
24
|
+
import { initRuntime, shutdownRuntime } from "./runtime-holder.js";
|
|
25
|
+
function parseBooleanEnv(value) {
|
|
26
|
+
if (value === undefined)
|
|
27
|
+
return undefined;
|
|
28
|
+
if (value === "true")
|
|
29
|
+
return true;
|
|
30
|
+
if (value === "false")
|
|
31
|
+
return false;
|
|
32
|
+
throw new Error(`Expected boolean env value "true" or "false", received "${value}".`);
|
|
33
|
+
}
|
|
34
|
+
function parseIntegerEnv(value, label) {
|
|
35
|
+
if (value === undefined)
|
|
36
|
+
return undefined;
|
|
37
|
+
const parsed = Number.parseInt(value, 10);
|
|
38
|
+
if (!Number.isInteger(parsed)) {
|
|
39
|
+
throw new Error(`${label} must be an integer, received "${value}".`);
|
|
40
|
+
}
|
|
41
|
+
return parsed;
|
|
42
|
+
}
|
|
43
|
+
function parseArgsJson(value) {
|
|
44
|
+
if (value === undefined)
|
|
45
|
+
return undefined;
|
|
46
|
+
const parsed = JSON.parse(value);
|
|
47
|
+
if (!Array.isArray(parsed) || !parsed.every((item) => typeof item === "string")) {
|
|
48
|
+
throw new Error("BROWSER_ARGS_JSON must be a JSON string array.");
|
|
49
|
+
}
|
|
50
|
+
return parsed;
|
|
51
|
+
}
|
|
52
|
+
function loadRuntimeConfigFromEnv() {
|
|
53
|
+
return BrowserRuntimeConfigSchema.parse({
|
|
54
|
+
mode: process.env["BROWSER_MODE"],
|
|
55
|
+
headless: parseBooleanEnv(process.env["BROWSER_HEADLESS"]),
|
|
56
|
+
cdpUrl: process.env["BROWSER_CDP_URL"],
|
|
57
|
+
cdpHost: process.env["BROWSER_CDP_HOST"],
|
|
58
|
+
cdpPort: parseIntegerEnv(process.env["BROWSER_CDP_PORT"], "BROWSER_CDP_PORT"),
|
|
59
|
+
channel: process.env["BROWSER_CHANNEL"],
|
|
60
|
+
executablePath: process.env["BROWSER_EXECUTABLE_PATH"],
|
|
61
|
+
userDataDir: process.env["BROWSER_USER_DATA_DIR"],
|
|
62
|
+
args: parseArgsJson(process.env["BROWSER_ARGS_JSON"]),
|
|
63
|
+
sessionsDir: process.env["BROWSER_SESSIONS_DIR"],
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const agent = defineAgent({
|
|
67
|
+
name: "browser-use-agent",
|
|
68
|
+
tools: [
|
|
69
|
+
// 通用
|
|
70
|
+
browserStatus,
|
|
71
|
+
listPages,
|
|
72
|
+
navigateActiveTab,
|
|
73
|
+
openPlatform,
|
|
74
|
+
selectPage,
|
|
75
|
+
// Zhipin 聊天
|
|
76
|
+
zhipinReadMessages,
|
|
77
|
+
zhipinOpenChat,
|
|
78
|
+
zhipinGetCandidateInfo,
|
|
79
|
+
zhipinSendReply,
|
|
80
|
+
zhipinExchangeWechat,
|
|
81
|
+
zhipinGetUsername,
|
|
82
|
+
// Zhipin 推荐列表
|
|
83
|
+
zhipinGetCandidateList,
|
|
84
|
+
zhipinSayHello,
|
|
85
|
+
zhipinOpenResume,
|
|
86
|
+
zhipinLocateResumeCanvas,
|
|
87
|
+
zhipinCloseResume,
|
|
88
|
+
// Yupao
|
|
89
|
+
yupaoReadMessages,
|
|
90
|
+
yupaoSendReply,
|
|
91
|
+
],
|
|
92
|
+
}, {
|
|
93
|
+
onShutdown: shutdownRuntime,
|
|
94
|
+
});
|
|
95
|
+
async function main() {
|
|
96
|
+
await initRuntime(loadRuntimeConfigFromEnv());
|
|
97
|
+
// 以 HTTP 模式启动 MCP Server
|
|
98
|
+
await agent.listen({
|
|
99
|
+
transport: {
|
|
100
|
+
type: "http",
|
|
101
|
+
port: parseInt(process.env["BROWSER_AGENT_PORT"] ?? "3100", 10),
|
|
102
|
+
host: process.env["BROWSER_AGENT_HOST"] ?? "127.0.0.1",
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
main().catch(async (err) => {
|
|
107
|
+
console.error("Fatal error:", err);
|
|
108
|
+
await shutdownRuntime().catch(() => { });
|
|
109
|
+
process.exit(1);
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/pages/yupao/chat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAKhD,mBAAmB;AACnB,wBAAsB,SAAS,CAC7B,IAAI,EAAE,IAAI,EACV,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAa/C"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { waitForSelector, typeText, clickElement } from "@roll-agent/browser";
|
|
2
|
+
import { YUPAO_SELECTORS } from "./selectors.js";
|
|
3
|
+
import { goToConversation } from "./navigation.js";
|
|
4
|
+
/** 在指定对话中发送回复消息 */
|
|
5
|
+
export async function sendReply(page, conversationId, message) {
|
|
6
|
+
try {
|
|
7
|
+
await goToConversation(page, conversationId);
|
|
8
|
+
await typeText(page, YUPAO_SELECTORS.chat.input, message);
|
|
9
|
+
await clickElement(page, YUPAO_SELECTORS.chat.sendButton);
|
|
10
|
+
await waitForSelector(page, YUPAO_SELECTORS.chat.messageItem, { timeout: 5_000 });
|
|
11
|
+
return { success: true };
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
15
|
+
return { success: false, error: errorMessage };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=chat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/pages/yupao/chat.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,mBAAmB;AACnB,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAAU,EACV,cAAsB,EACtB,OAAe;IAEf,IAAI,CAAC;QACH,MAAM,gBAAgB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAE7C,MAAM,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,YAAY,CAAC,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1D,MAAM,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAElF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,YAAY,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IACjD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Page } from "@roll-agent/browser";
|
|
2
|
+
export interface MessageListItem {
|
|
3
|
+
readonly conversationId: string;
|
|
4
|
+
readonly candidateName: string;
|
|
5
|
+
readonly lastMessage: string;
|
|
6
|
+
readonly unreadCount: number;
|
|
7
|
+
readonly timestamp: string;
|
|
8
|
+
}
|
|
9
|
+
/** 解析鱼泡消息列表页 */
|
|
10
|
+
export declare function parseMessageList(page: Page, limit?: number): Promise<ReadonlyArray<MessageListItem>>;
|
|
11
|
+
//# sourceMappingURL=message-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-list.d.ts","sourceRoot":"","sources":["../../../src/pages/yupao/message-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAKhD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,gBAAgB;AAChB,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,IAAI,EACV,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,CAiDzC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { waitForSelector } from "@roll-agent/browser";
|
|
2
|
+
import { YUPAO_SELECTORS } from "./selectors.js";
|
|
3
|
+
import { ensureOnMessageList } from "./navigation.js";
|
|
4
|
+
/** 解析鱼泡消息列表页 */
|
|
5
|
+
export async function parseMessageList(page, limit) {
|
|
6
|
+
await ensureOnMessageList(page);
|
|
7
|
+
await waitForSelector(page, YUPAO_SELECTORS.messageList.item, { timeout: 10_000 });
|
|
8
|
+
const sel = YUPAO_SELECTORS.messageList;
|
|
9
|
+
const items = await page.$$eval(sel.item, (elements, arg) => {
|
|
10
|
+
const result = [];
|
|
11
|
+
const itemsToProcess = arg.maxItems ? elements.slice(0, arg.maxItems) : elements;
|
|
12
|
+
for (const el of itemsToProcess) {
|
|
13
|
+
const nameEl = el.querySelector(arg.sel.candidateName);
|
|
14
|
+
const msgEl = el.querySelector(arg.sel.lastMessage);
|
|
15
|
+
const badgeEl = el.querySelector(arg.sel.unreadBadge);
|
|
16
|
+
const timeEl = el.querySelector(arg.sel.timestamp);
|
|
17
|
+
const conversationId = el.getAttribute("data-id") ??
|
|
18
|
+
el.getAttribute("data-conversation-id") ??
|
|
19
|
+
el
|
|
20
|
+
.querySelector("a")
|
|
21
|
+
?.getAttribute("href")
|
|
22
|
+
?.match(/id=([^&]+)/)?.[1] ??
|
|
23
|
+
"";
|
|
24
|
+
result.push({
|
|
25
|
+
conversationId,
|
|
26
|
+
candidateName: nameEl?.textContent?.trim() ?? "",
|
|
27
|
+
lastMessage: msgEl?.textContent?.trim() ?? "",
|
|
28
|
+
unreadCount: parseInt(badgeEl?.textContent?.trim() ?? "0", 10) || 0,
|
|
29
|
+
timestamp: timeEl?.textContent?.trim() ?? "",
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}, { sel, maxItems: limit });
|
|
34
|
+
return items;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=message-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-list.js","sourceRoot":"","sources":["../../../src/pages/yupao/message-list.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAUtD,gBAAgB;AAChB,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAU,EACV,KAAc;IAEd,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAEnF,MAAM,GAAG,GAAG,eAAe,CAAC,WAAW,CAAC;IAExC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAC7B,GAAG,CAAC,IAAI,EACR,CAAC,QAAmB,EAAE,GAAsD,EAAE,EAAE;QAC9E,MAAM,MAAM,GAMP,EAAE,CAAC;QAER,MAAM,cAAc,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAEjF,KAAK,MAAM,EAAE,IAAI,cAAc,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YACvD,MAAM,KAAK,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACpD,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAEnD,MAAM,cAAc,GAClB,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC;gBAC1B,EAAE,CAAC,YAAY,CAAC,sBAAsB,CAAC;gBACvC,EAAE;qBACC,aAAa,CAAC,GAAG,CAAC;oBACnB,EAAE,YAAY,CAAC,MAAM,CAAC;oBACtB,EAAE,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC5B,EAAE,CAAC;YAEL,MAAM,CAAC,IAAI,CAAC;gBACV,cAAc;gBACd,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;gBAChD,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;gBAC7C,WAAW,EAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC;gBACnE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;aAC7C,CAAC,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC,EACD,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CACzB,CAAC;IAEF,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Page } from "@roll-agent/browser";
|
|
2
|
+
/** 导航到消息列表页 */
|
|
3
|
+
export declare function ensureOnMessageList(page: Page): Promise<void>;
|
|
4
|
+
/** 导航到登录页 */
|
|
5
|
+
export declare function goToLoginPage(page: Page): Promise<void>;
|
|
6
|
+
/** 导航到指定对话 */
|
|
7
|
+
export declare function goToConversation(page: Page, conversationId: string): Promise<void>;
|
|
8
|
+
/** 检测是否已登录 */
|
|
9
|
+
export declare function isLoggedIn(page: Page): Promise<boolean>;
|
|
10
|
+
//# sourceMappingURL=navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../../src/pages/yupao/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAQhD,eAAe;AACf,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMnE;AAED,aAAa;AACb,wBAAsB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7D;AAED,cAAc;AACd,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxF;AAED,cAAc;AACd,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { navigateTo, waitForSelector } from "@roll-agent/browser";
|
|
2
|
+
import { YUPAO_SELECTORS } from "./selectors.js";
|
|
3
|
+
const YUPAO_BASE = "https://www.yupao.com";
|
|
4
|
+
const MESSAGE_LIST_URL = `${YUPAO_BASE}/chat`;
|
|
5
|
+
const LOGIN_URL = `${YUPAO_BASE}/login`;
|
|
6
|
+
/** 导航到消息列表页 */
|
|
7
|
+
export async function ensureOnMessageList(page) {
|
|
8
|
+
const currentUrl = page.url();
|
|
9
|
+
if (!currentUrl.includes("/chat")) {
|
|
10
|
+
await navigateTo(page, MESSAGE_LIST_URL);
|
|
11
|
+
}
|
|
12
|
+
await waitForSelector(page, YUPAO_SELECTORS.messageList.container, { timeout: 15_000 });
|
|
13
|
+
}
|
|
14
|
+
/** 导航到登录页 */
|
|
15
|
+
export async function goToLoginPage(page) {
|
|
16
|
+
await navigateTo(page, LOGIN_URL);
|
|
17
|
+
}
|
|
18
|
+
/** 导航到指定对话 */
|
|
19
|
+
export async function goToConversation(page, conversationId) {
|
|
20
|
+
const url = `${YUPAO_BASE}/chat?id=${encodeURIComponent(conversationId)}`;
|
|
21
|
+
await navigateTo(page, url);
|
|
22
|
+
await waitForSelector(page, YUPAO_SELECTORS.chat.input, { timeout: 15_000 });
|
|
23
|
+
}
|
|
24
|
+
/** 检测是否已登录 */
|
|
25
|
+
export async function isLoggedIn(page) {
|
|
26
|
+
try {
|
|
27
|
+
await waitForSelector(page, YUPAO_SELECTORS.login.loginSuccess, { timeout: 3_000 });
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=navigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../../src/pages/yupao/navigation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,UAAU,GAAG,uBAAuB,CAAC;AAC3C,MAAM,gBAAgB,GAAG,GAAG,UAAU,OAAO,CAAC;AAC9C,MAAM,SAAS,GAAG,GAAG,UAAU,QAAQ,CAAC;AAExC,eAAe;AACf,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAU;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAClC,MAAM,UAAU,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IAC3C,CAAC;IACD,MAAM,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED,aAAa;AACb,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAU;IAC5C,MAAM,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,cAAc;AACd,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAU,EAAE,cAAsB;IACvE,MAAM,GAAG,GAAG,GAAG,UAAU,YAAY,kBAAkB,CAAC,cAAc,CAAC,EAAE,CAAC;IAC1E,MAAM,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,cAAc;AACd,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAU;IACzC,IAAI,CAAC;QACH,MAAM,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACpF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 鱼泡 CSS/aria 选择器常量。
|
|
3
|
+
*
|
|
4
|
+
* DOM 结构变更时只需更新此文件。
|
|
5
|
+
*/
|
|
6
|
+
export declare const YUPAO_SELECTORS: {
|
|
7
|
+
readonly login: {
|
|
8
|
+
readonly qrCode: ".login-qr img, .qr-code img";
|
|
9
|
+
readonly loginSuccess: ".user-info, .header-user";
|
|
10
|
+
};
|
|
11
|
+
readonly messageList: {
|
|
12
|
+
readonly container: ".chat-list, .msg-list";
|
|
13
|
+
readonly item: ".chat-item, .msg-item";
|
|
14
|
+
readonly candidateName: ".chat-item .name, .msg-item .name";
|
|
15
|
+
readonly lastMessage: ".chat-item .msg, .msg-item .content";
|
|
16
|
+
readonly unreadBadge: ".chat-item .unread, .msg-item .badge";
|
|
17
|
+
readonly timestamp: ".chat-item .time, .msg-item .time";
|
|
18
|
+
};
|
|
19
|
+
readonly chat: {
|
|
20
|
+
readonly input: ".chat-input textarea, .msg-input textarea";
|
|
21
|
+
readonly sendButton: ".btn-send, .send-btn";
|
|
22
|
+
readonly messageItem: ".chat-msg, .msg-bubble";
|
|
23
|
+
readonly messageText: ".chat-msg .text, .msg-bubble .text";
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=selectors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.d.ts","sourceRoot":"","sources":["../../../src/pages/yupao/selectors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;CAmBlB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 鱼泡 CSS/aria 选择器常量。
|
|
3
|
+
*
|
|
4
|
+
* DOM 结构变更时只需更新此文件。
|
|
5
|
+
*/
|
|
6
|
+
export const YUPAO_SELECTORS = {
|
|
7
|
+
login: {
|
|
8
|
+
qrCode: ".login-qr img, .qr-code img",
|
|
9
|
+
loginSuccess: ".user-info, .header-user",
|
|
10
|
+
},
|
|
11
|
+
messageList: {
|
|
12
|
+
container: ".chat-list, .msg-list",
|
|
13
|
+
item: ".chat-item, .msg-item",
|
|
14
|
+
candidateName: ".chat-item .name, .msg-item .name",
|
|
15
|
+
lastMessage: ".chat-item .msg, .msg-item .content",
|
|
16
|
+
unreadBadge: ".chat-item .unread, .msg-item .badge",
|
|
17
|
+
timestamp: ".chat-item .time, .msg-item .time",
|
|
18
|
+
},
|
|
19
|
+
chat: {
|
|
20
|
+
input: ".chat-input textarea, .msg-input textarea",
|
|
21
|
+
sendButton: ".btn-send, .send-btn",
|
|
22
|
+
messageItem: ".chat-msg, .msg-bubble",
|
|
23
|
+
messageText: ".chat-msg .text, .msg-bubble .text",
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=selectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../../src/pages/yupao/selectors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK,EAAE;QACL,MAAM,EAAE,6BAA6B;QACrC,YAAY,EAAE,0BAA0B;KACzC;IACD,WAAW,EAAE;QACX,SAAS,EAAE,uBAAuB;QAClC,IAAI,EAAE,uBAAuB;QAC7B,aAAa,EAAE,mCAAmC;QAClD,WAAW,EAAE,qCAAqC;QAClD,WAAW,EAAE,sCAAsC;QACnD,SAAS,EAAE,mCAAmC;KAC/C;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,2CAA2C;QAClD,UAAU,EAAE,sBAAsB;QAClC,WAAW,EAAE,wBAAwB;QACrC,WAAW,EAAE,oCAAoC;KAClD;CACO,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Page } from "@roll-agent/browser";
|
|
2
|
+
/** 随机延迟 */
|
|
3
|
+
export declare function randomDelay(page: Page, min?: number, max?: number): Promise<void>;
|
|
4
|
+
/** 模拟人类操作延迟(概率分布) */
|
|
5
|
+
export declare function humanDelay(page: Page): Promise<void>;
|
|
6
|
+
/** 模拟随机滚动 */
|
|
7
|
+
export declare function performRandomScroll(page: Page, options?: {
|
|
8
|
+
minDistance?: number;
|
|
9
|
+
maxDistance?: number;
|
|
10
|
+
direction?: "up" | "down" | "both";
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
/** 初始浏览模式滚动(模拟用户进入页面时的行为) */
|
|
13
|
+
export declare function performInitialScrollPattern(page: Page): Promise<void>;
|
|
14
|
+
/** 生成打字延迟(模拟键盘输入速度) */
|
|
15
|
+
export declare function generateTypingDelay(): number;
|
|
16
|
+
/** 概率性触发随机行为 */
|
|
17
|
+
export declare function shouldAddRandomBehavior(probability?: number): boolean;
|
|
18
|
+
//# sourceMappingURL=anti-detection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anti-detection.d.ts","sourceRoot":"","sources":["../../../src/pages/zhipin/anti-detection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhD,WAAW;AACX,wBAAsB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,SAAM,EAAE,GAAG,SAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjF;AAED,qBAAqB;AACrB,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAa1D;AAED,aAAa;AACb,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAA;CAAE,GAC3F,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,6BAA6B;AAC7B,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAe3E;AAED,uBAAuB;AACvB,wBAAgB,mBAAmB,IAAI,MAAM,CAK5C;AAED,gBAAgB;AAChB,wBAAgB,uBAAuB,CAAC,WAAW,SAAM,GAAG,OAAO,CAElE"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** 随机延迟 */
|
|
2
|
+
export async function randomDelay(page, min = 300, max = 800) {
|
|
3
|
+
const ms = Math.floor(Math.random() * (max - min)) + min;
|
|
4
|
+
await page.waitForTimeout(ms);
|
|
5
|
+
}
|
|
6
|
+
/** 模拟人类操作延迟(概率分布) */
|
|
7
|
+
export async function humanDelay(page) {
|
|
8
|
+
const rand = Math.random();
|
|
9
|
+
let ms;
|
|
10
|
+
if (rand < 0.5) {
|
|
11
|
+
ms = 800 + Math.random() * 1200;
|
|
12
|
+
}
|
|
13
|
+
else if (rand < 0.8) {
|
|
14
|
+
ms = 500 + Math.random() * 300;
|
|
15
|
+
}
|
|
16
|
+
else if (rand < 0.95) {
|
|
17
|
+
ms = 2000 + Math.random() * 2000;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
ms = 4000 + Math.random() * 2000;
|
|
21
|
+
}
|
|
22
|
+
await page.waitForTimeout(Math.floor(ms));
|
|
23
|
+
}
|
|
24
|
+
/** 模拟随机滚动 */
|
|
25
|
+
export async function performRandomScroll(page, options) {
|
|
26
|
+
const min = options?.minDistance ?? 50;
|
|
27
|
+
const max = options?.maxDistance ?? 200;
|
|
28
|
+
const direction = options?.direction ?? "both";
|
|
29
|
+
const distance = Math.floor(Math.random() * (max - min)) + min;
|
|
30
|
+
const sign = direction === "up" ? -1 : direction === "down" ? 1 : Math.random() > 0.5 ? 1 : -1;
|
|
31
|
+
await page.evaluate((scrollY) => {
|
|
32
|
+
window.scrollBy({ top: scrollY, behavior: "smooth" });
|
|
33
|
+
}, distance * sign);
|
|
34
|
+
await randomDelay(page, 200, 500);
|
|
35
|
+
}
|
|
36
|
+
/** 初始浏览模式滚动(模拟用户进入页面时的行为) */
|
|
37
|
+
export async function performInitialScrollPattern(page) {
|
|
38
|
+
if (Math.random() < 0.8) {
|
|
39
|
+
const distance = 100 + Math.floor(Math.random() * 100);
|
|
40
|
+
await page.evaluate((d) => {
|
|
41
|
+
window.scrollBy({ top: d, behavior: "smooth" });
|
|
42
|
+
}, distance);
|
|
43
|
+
await humanDelay(page);
|
|
44
|
+
}
|
|
45
|
+
if (Math.random() < 0.5) {
|
|
46
|
+
const distance = (50 + Math.floor(Math.random() * 100)) * (Math.random() > 0.5 ? 1 : -1);
|
|
47
|
+
await page.evaluate((d) => {
|
|
48
|
+
window.scrollBy({ top: d, behavior: "smooth" });
|
|
49
|
+
}, distance);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** 生成打字延迟(模拟键盘输入速度) */
|
|
53
|
+
export function generateTypingDelay() {
|
|
54
|
+
let base = 60 + Math.random() * 60;
|
|
55
|
+
if (Math.random() < 0.1)
|
|
56
|
+
base += 200 + Math.random() * 100;
|
|
57
|
+
if (Math.random() < 0.05)
|
|
58
|
+
base = 30 + Math.random() * 30;
|
|
59
|
+
return Math.floor(base);
|
|
60
|
+
}
|
|
61
|
+
/** 概率性触发随机行为 */
|
|
62
|
+
export function shouldAddRandomBehavior(probability = 0.3) {
|
|
63
|
+
return Math.random() < probability;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=anti-detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anti-detection.js","sourceRoot":"","sources":["../../../src/pages/zhipin/anti-detection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Page } from "@roll-agent/browser";
|
|
2
|
+
export interface ChatTarget {
|
|
3
|
+
readonly candidateName: string | undefined;
|
|
4
|
+
readonly index: number | undefined;
|
|
5
|
+
}
|
|
6
|
+
export interface ChatListItem {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly index: number;
|
|
9
|
+
readonly hasUnread: boolean;
|
|
10
|
+
readonly unreadCount: number;
|
|
11
|
+
readonly lastMessageTime: string;
|
|
12
|
+
readonly messagePreview: string;
|
|
13
|
+
}
|
|
14
|
+
export interface OpenChatResult extends ChatListItem {
|
|
15
|
+
readonly found: boolean;
|
|
16
|
+
readonly error?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function selectChatCandidate(candidates: ReadonlyArray<ChatListItem>, target: ChatTarget): ChatListItem | undefined;
|
|
19
|
+
export declare function ensureChatListLoaded(page: Page): Promise<boolean>;
|
|
20
|
+
export declare function getChatCandidates(page: Page): Promise<ReadonlyArray<ChatListItem>>;
|
|
21
|
+
/**
|
|
22
|
+
* 确保指定候选人的聊天窗口已打开。
|
|
23
|
+
*
|
|
24
|
+
* - 有 candidateName/index → 导航到聊天列表 → 选择候选人 → 等待聊天头部切换
|
|
25
|
+
* - 都没有 → 不做任何导航,假设当前窗口已就绪
|
|
26
|
+
*/
|
|
27
|
+
export declare function ensureChatOpen(page: Page, target: ChatTarget): Promise<OpenChatResult | undefined>;
|
|
28
|
+
//# sourceMappingURL=chat-navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-navigation.d.ts","sourceRoot":"","sources":["../../../src/pages/zhipin/chat-navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAGhD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,cAAe,SAAQ,YAAY;IAClD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAcD,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,aAAa,CAAC,YAAY,CAAC,EACvC,MAAM,EAAE,UAAU,GACjB,YAAY,GAAG,SAAS,CA+B1B;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAWvE;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAyBxF;AA+CD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CA+CrC"}
|