Skip to content

About

每天自动完成 Buddy 加油站签到 + 派猫猫旅行(Node.js + Playwright / Edge)

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

32 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WorkBuddy Daily 🐱

每天自动完成两件事:Buddy 加油站签到 + 派猫猫去旅行。

⏰ 几点跑,你说了算。 这两个脚本是纯手动触发的,里面没有任何定时逻辑 —— 执行时间完全由你在 WorkBuddy 桌面端的「自动化」里自己设置 —— 想几点就几点,一天几次也行。 仓库不规定、也不附带任何默认时间。

两个任务

步骤 脚本 原理 稳定性
① 加油站签到 wb_checkin.js --checkin 复用常驻 Edge(专用 profile)里已登录的 www.workbuddy.cn 页面,同源 fetch 调官方签到接口;不读、不打印任何 token 稳定,幂等;登录态由每日运行自己维持
② 派猫猫旅行 wb_auto_task.js Playwright 驱动 Edge(专用 profile)点击成长中心的「派猫猫旅行」 v4 起整流程自带最多 3 轮重试,一次运行即吸收 SPA 抖动

用法

⭐ 推荐用法:让 WorkBuddy 自己搞定(朋友也适用)

不用你记命令、也不用手动配调度。把这段话直接甩给 WorkBuddy:

帮我安装 WorkBuddy Daily:https://gitee.com/strange_touchannel/workbuddy-daily 按仓库里的 INSTALL.md 执行。装好后把每日签到(wb_checkin.js --checkin) 和自动派猫(wb_auto_task.js)设为定时自动化任务,每天到点自己跑。

它会替你完成:装依赖 → 拉起登录窗等你扫码 → 建自动化任务。 你唯一要自己做的事,是在自动弹出的 Edge 窗口里登录一次(微信扫码或账号密码,以页面为准)—— 这是唯一没法代劳的一步,原因见下方「为什么不复用你已有的浏览器登录态」。 登录成功后永久有效,日常全自动:到点签到领积分、派猫猫去旅行。 Edge 重启/关窗导致的会话失效,后台跑一次 node wb_login_then_run.js:它会弹出登录窗等你扫码, 检测到登录成功后在同一个常驻会话里自动跑完「派猫 → 签到」,不用再手动补跑 (只想要登录窗、不跑任务时才用 node wb_login_once.js --timeout=15。 桌面端令牌自 2026-09-24 起改为加密信封,独立脚本无法解密,「静默续期」路线已废弃)。

时间是建自动化任务时你随口指定的(脚本本身不带定时),想改直接在桌面端的自动化列表里改, 或者跟 WorkBuddy 说一句「改成每天早上 9 点」。

详细步骤、故障兜底、给安装者 AI 的纪律都在 INSTALL.md —— 那是写给帮忙安装的 WorkBuddy 读的。

手动运行

# ① 签到(--status 只查询不领取,--checkin 才真正领取)
node wb_checkin.js --checkin

# ② 派猫猫旅行(输出 JSON)
node wb_auto_task.js

# ③ 看成长任务清单还差什么(只读,无任何写操作)
node wb_tasks.js

# ④ 网页端做成长任务 + 点真实领奖按钮(默认干跑,加 --apply 才真执行)
node wb_start_edge.js && node wb_run_tasks.js --apply

# ⑤ 领活跃地图的连登里程碑奖励(默认干跑,加 --apply 才真领)
node wb_claim_rewards.js --apply

不想敲命令可以双击(会自动切到脚本目录并调用正确的 node):

双击 作用
run_login.bat 扫码登录兜底 —— 常驻 Edge 被关过(重启 / 手动关窗)导致会话失效时运行;只负责登录并让窗口保持常驻。想让扫码成功后自动把当天两步跑完,改用 node wb_login_then_run.js
run_cat.bat 派猫猫旅行
run_tasks.bat 成长任务清单(只读)
run_growth.bat 成长任务:网页端点真实按钮(会先确保常驻 Edge 在跑)
run_rewards.bat 活跃地图连登奖励:先干跑,敲 y 才真领(会先确保常驻 Edge 在跑)

签到结果判定

  • code=0 且出现 credit / streak_days → 领取成功
  • code=10001(今天已签到)→ 幂等,无需重复,视为成功
  • 401/403 或连续网络失败 → 登录态失效,后台跑 node wb_login_then_run.js 扫码,成功后自动补跑两步

派猫结果判定

  • login:true + catTravel 以 dispatched 开头 → 派遣成功
  • already-traveling → 猫还在旅行中,跳过
  • gift-claim-failed → 礼物没领成功,本轮不会继续派遣(看 giftLog 定位)
  • login:false → 常驻 Edge 会话失效(被关过 / 重启过 / 会话 cookie 焚毁)→ 后台跑 node wb_login_then_run.js,扫码成功后自动在同会话内跑完「派猫 → 签到」
  • attempts > 1 → 首轮撞上 SPA 瞬时抖动,脚本自己重载重试后成功(note 里有逐轮结果),属正常自愈
  • attempts = 3 且仍未达成 → 三轮自愈用尽,需人工核对(罕见图)

脚本 v4 起自带重试,一天跑一次就够,不需要再叠一层「稍后补派」的定时任务。

为什么不复用你已有的浏览器登录态?

很多人会问:脚本连我平时用的 Edge(已经登录着 WorkBuddy)不就行了,为什么还要扫码一次? 三条路都实测走不通:

  • 拷贝 cookie 到独立 profile:workbuddy.cn 的会话 cookie 受 App-Bound Encryption(ABE)保护, 密钥绑定 Edge 二进制 + 机器 + profile 实例。跨 profile 移植后 ABE 层解密失败被直接丢弃 (实测 0 条可解密)。
  • attach 正在运行的普通 Edge:CDP 端口必须在 Edge 启动时通过 --remote-debugging-port 开启, 普通 Edge 默认不开;手动重启带端口又慢(1.7GB profile 实测 150s 都绑不上)。
  • attach 桌面端 WorkBuddy:其 CDP(9222)只暴露 file:// 渲染页且禁用 newPage,无法驱动; 桌面端 accessToken 自 2026-09-24 起改为加密信封,独立进程同样拿不到。

所以架构只能是:脚本拉起自己的专用 Edge profile,在里面原生登录一次(扫码或账密), 之后保持常驻、每日运行自己维持会话。扫码是唯一无法代劳的一步,也是一次性的。

成长任务清单(只读)

node wb_tasks.js            # 按状态分组 + 算出每个任务"还差多少"
node wb_tasks.js --all      # 连已领取/未解锁的也列出
node wb_tasks.js --json     # 结构化输出,供自动化消费
node wb_tasks.js --raw      # 打印原始响应(排查上游字段变化用)

拉一次成长中心的任务清单,告诉你 18 个任务里哪些能领、哪些还差几次、哪些有截止日期。 输出分四组:🟢 可领奖 / 🔵 计次进行中(带「还差 N 次」)/ 🟡 无计数待做 / ✅ 已领取(默认折叠)。

它只有 GET,没有任何写操作。 这是刻意的边界:进度由服务端按真实行为点亮, 所以这个脚本只读取、绝不构造或补报行为事件,也绝不伪造客户端身份标识 —— 即「不编造证据」。 它的合规定位与 wb_checkin.js --status 同档:自己的登录态、官方端点、只读不写。 跑它不会让任何进度前进;要达标得去客户端里真实操作(派猫那类可交给 wb_auto_task.js)。

两个实测口径,写脚本时容易踩:

  • 上游对「无计数」的一次性任务给的是 progress: null,不是 target: 0 —— 当成 0 会误判成"还差 0 次"。
  • claimed_button_text 字段不可信:未接受的任务(accept_status=not_accepted)也返回 "已完成"。 判断是否已领只能看 accept_status。
  • 只给一部分任务返回 valid_end(有效期),脚本会显示「⏳ 有效期至 X(剩 N 天)」。

成长任务:网页端真实点击(wb_run_tasks.js)

node wb_start_edge.js                              # 先确保常驻 Edge 在跑(冷启动可能 >30s)
node wb_run_tasks.js                             # 干跑:只报告,不点任何东西(默认)
node wb_run_tasks.js --apply                     # 真执行
node wb_run_tasks.js --apply --only=chat_5       # 只做指定任务
node wb_run_tasks.js --claim-only --apply        # 只领奖

用真实浏览器 UI 点击完成「网页端能做」的任务,并点真实领奖按钮。它会先把 18 个任务 逐个分类(依据 jump_url 协议 + DOM 里的 dt-remark.taskCode):

分类 含义 本脚本行为
🟢 可领奖 进度已足,只差领 点真实领奖按钮并复核
🤖 可网页代做 网页端点击即可完成 代做
🙋 需客户端/真人 跳 workbuddy:// 指向桌面端专属界面,或必须真人 不碰,列出让你自己点

边界(刻意,勿为省事改掉):只做真实点击。不发任何行为上报、不伪造设备标识、 不代做需真人的项。

实测踩到的坑(都写进代码了)

  • wb_start_edge.js 存在的原因:不是"绕过代理",而是冷启动慢。成长中心的常驻 Edge 冷启动可 > 30s,早先内联在派猫脚本里的等待循环只有 30s,于是反复拉起。现在单独成文件、等满 90s。
  • ⚠️ 关于 HTTP_PROXY 的一处曾用错的归因(2026-09-17 实测修正): 本机环境设了 HTTP_PROXY(指向一个本地代理端口),曾判定"代理把 127.0.0.1:9223 的环回请求 也送进代理 → 拿到 502 → 误判「常驻 Edge 未就绪」"。这个归因是错的,实测三种探活方式 全部成功:不清代理 fetch → HTTP 200;清掉代理 + NO_PROXY → HTTP 200;net.connect → 端口在听。 事实是代理能正确转发环回请求:9223 在听就回 200,没人听才回 502(直连则是 ECONNREFUSED)。 也就是说502 == 确实没在听,不是假阴性 —— 真因是 Edge 冷启动还没起来。 仍然保留 TCP 探测,理由是刻意收敛不确定性(代理端口每次会话会变、代理可能消失,TCP 少一层); 但它不是 bug 修复,其余脚本的旧写法可用,不必为此改动。 仍然成立的一条:给 fetch 传 { proxy: undefined } 无效 —— undici 读的是环境变量。
  • 出网不受清代理影响:实测保留/清空代理两种情况下请求 copilot.tencent.com 都返回 401(= 到达服务器、只是没带 token),所以那个 __loopbackNoProxy 块对出网无害。
  • gs-load-more(「全部任务」)是分页式:点一次只多渲染几行,必须循环点到行数不再增长, 否则只能看到 5 行(首屏只渲染"进行中"的那几个)。
  • 「领取更多」不是领奖按钮:点了不弹窗、不发请求、按钮文案不变 —— 它只是个跳转入口 (Hp_Appearance)。按 /领取/ 模糊匹配会把这种跳转钮当领奖点,白点一次还误报成功。 现在用精确文案 ^(收下奖励|领取奖励|领取 N 积分|领取)$ 判定,并把跳转钮显式标注出来。
  • SPA 渲染竞态会伪装成「页面没数据」:成长中心冷启动渲染出 .gs-task-row 需 ~9s。 原先固定 await sleep(4000) 会读到 0 行,并让 expandAll 第一轮就 break —— 而且一条日志都不打,看起来像页面空了/选择器失效了,极难排查。 现改为轮询等首行出现(waitRows),每次 600ms、上限 30s;等不到会明说当前 URL。 教训:凡"等 SPA 渲染完再读 DOM",一律用「等元素出现」,不要用固定 sleep。
  • API 与 DOM 会不一致:/v2/activity/growth/tasks 的 accept_status 有延迟, 实测 DOM 上已出现可领按钮时 API 仍报 claimable=0。以 DOM 为准。
  • 本机后台进程留不住:跨 Bash 调用启动的 Edge 会被回收,所以 run_growth.bat 把「拉起 Edge」和「跑任务」放在同一次调用里。

实测结论(2026-09-17,以 DOM 为准)

18 个成长任务里:可领奖 0 · 可网页代做 0 · 需客户端/真人 7(其余 11 已完成)。

也就是说 没有一个任务能靠网页端代做。4 个原本归为 auto 的 (chat_5 / expert_5 / create_canvas / playbook_prompt)早已全部领完, 剩余 7 项不是跳 workbuddy:// 桌面端专属界面,就是必须真人:

taskCode 分类 为什么本脚本不碰
Buddy_App desktop_only 客户端「发现应用」里进入任一应用
Buddy_App_QQ desktop_only 客户端进入「企鹅教师助手」应用
Expert_team_use_3 desktop_only 客户端召唤 3 次专家团
template_5 desktop_only 客户端用 5 个模板(网页端无模板库)
Expert_lighthouse desktop_only 客户端体验「腾讯轻量云」专家
Hp_Appearance desktop_only 客户端「设置 → 外观」切主题(网页端「领取更多」只是跳转钮)
black_cat human_only 夜间折扣活动,与消费相关

所以这个脚本的真正价值是「分类 + 守边界」 —— 明确告诉你哪些不该碰、 哪些该自己点,而不是代做本身。

活跃地图 · 连登奖励(wb_claim_rewards.js)

「9月活跃地图」里有条连登进度条:连登满 7 / 14 / 28 天可各换一档奖励 (入门档 / 进阶档 / 巅峰档)。这个脚本自动点掉还没领的档位。

node wb_claim_rewards.js            # 干跑:报连登状态 + 打开弹窗列出各档位(不点任何东西)
node wb_claim_rewards.js --apply    # 真领:打开弹窗,点掉所有可领档位
node wb_claim_rewards.js --status   # 极简只读:只读连登 DOM,连弹窗都不开
node wb_claim_rewards.js --probe    # 点击链路自检:验证能否定位/点到档位按钮(不点)

怎么在「没有可领档位」时确认它真能用? —— 用 --probe。它解析 locator、读 位置 / 尺寸 / 可见性 / disabled,但不点击,所以即使本月已兑完也能验证点击链路是通的:

── --probe 点击链路自检(不点击)──
  ✓ 入门档    位置=(720,299)    尺寸=70x32    可见=是  可点=否(locked)  定位正常,但 locked → 点会等到超时(--apply 跳过)
  ✓ 进阶档    位置=(720,367)    尺寸=70x32    可见=是  可点=否(locked)  定位正常,但 locked → 点会等到超时(--apply 跳过)
  ✓ 巅峰档    位置=(734,435)    尺寸=56x32    可见=是  可点=否(locked)  定位正常,但 locked → 点会等到超时(--apply 跳过)
[--probe] 只验可达性,未点任何按钮。「可点=是」的档位才可能被 --apply 领到。

怎么读这三行 —— boundingBox() 返回 {x, y, width, height} 四项:x/y 是元素左上角 在视口里的坐标(位置),width/height 是元素自身尺寸。 ⚠️ x/y 会随窗口尺寸与滚动变化,不是稳定常量;尺寸才由文案长度决定、是可比的。

  • y 逐行递增 68px(299 → 367 → 435)→ 三档是纵向等距的三行,确实是三个独立元素。
  • x 前两档都是 720,巅峰档是 734 → 算 x + width:790 / 790 / 790,右边缘完全对齐。 即这三个按钮是右对齐排布,巅峰档因为窄 14px,左边缘便右移 14px。 这条顺带说明为什么不能用「尺寸相同」判定是同一元素 —— 真正区分元素的是位置。
  • 尺寸由文案长度决定:入门/进阶的文案都是「已兑换」3 个全角字 → 都是 70x32; 巅峰档是「兑换」2 个字 → 56x32。差值 14px 正好是一个全角字宽。 所以尺寸能反推文案:若两档尺寸不一样,说明读到的按钮文案不同(可用来自检)。

⚠️ 「定位成功」不等于「能点」:这三档当时全部 locked(入门/进阶是已兑换 → 按钮 disabled; 巅峰是未解锁)。Playwright 对 disabled 元素的 click() 不是立即失败,而是等到超时, 所以 --apply 在点之前必须再核一次锁态,否则会把整个循环每档卡 8 秒并误报「点击失败」。

实测输出(2026-09-17):

── 活跃地图 · 连登概览 ──
  标题      : 9月活跃地图
  连登天数  : 当前连续登录 17 天   (进度条 60.7143%)
  下一档    : 连登 28 天获得奖励
  本月已兑  : 2 次   · 补登卡: ×4
  里程碑    : 7天   已达成 · 14天  已达成 · 28天  未达成

── 选择奖励 · 档位状态 ──
  入门档    已兑换      [已兑换]    +2 能量 · +1 张补登卡 · +1 次抽奖
  进阶档    已兑换      [已兑换]    +50 积分 · +3 能量 · +1 张补登卡 · +1 次抽奖
  巅峰档    未解锁      [兑换]      +150 积分 · +5 能量 · +1 张补登卡 · +1 次抽奖

实测踩到的坑(都写进代码了)

  • 档位按钮的文案不可信 —— 最关键的一条。巅峰档(28 天)在连登不足时文案就已经是「兑换」, 但它 disabled=true 且 class 含 is-locked。若按文案 /兑换/ 判定可领,就会去点一个 点不动的按钮并误报成功。判定一律看 disabled / is-locked,文案只用来识别「已兑换」。 (与成长任务的 claimed_button_text 是同一类陷阱。)
  • 连登天数在子元素里:.gs-streak-days 的实际 HTML 是 当前连续登录 <b>17</b> 天。 只取直接文本节点会得到「当前连续登录 天」(数字消失)→ 必须用 innerText。
  • .gs-section-title 页面里有多个:第一个是「任务」区块的标题,直接 querySelector('.gs-section-title') 会拿错 → 要用 .gs-streak-row 往上 closest('section') 锚定。
  • 里程碑状态有机器可读标记:.gs-streak-dot.is-reached,不用去解析「7天/14天」文案。
  • 只读接口「时通时不通」,不是"坏":GET /activity/growth/streak 与 /activity/growth/redeem/summary 在页面内 fetch 曾实测 TypeError: Failed to fetch (同页 heatmap 却 200 OK),后来同一台机器、同一登录态又都返回 200。 所以脚本以 DOM 为准,接口只当可选佐证、失败不致命。 两者口径一致时能交叉验证:实测 redeem/summary 返回 starter_count / advanced_count / legendary_count = 1 / 1 / 0, 与 DOM 的「入门/进阶已兑换、巅峰未解锁」吻合。

边界与「补登」

只做真实 UI 点击:打开「兑换奖励」→ 点各档「兑换」。点击用 Playwright 的 click() (CDP 真实输入事件,isTrusted=true),而不是页面内的 element.click() 合成事件 —— 对齐 wb_auto_task.js。 不向 /v2/report 发合成事件、不伪造设备标识,也不直调 POST /activity/growth/redeem (口径已摸清,但刻意走点击:服务端记的才是真实发生的领取)。 关于补登:日历上「未打卡(可补登)」的格子能用补登卡回填 (端点 /activity/growth/makeup-cards/use),把连登天数顶上去、提前解锁高阶档位。 它属于可用功能,但改变的是打卡记录本身而非"领取奖励",语义与领奖不同, 所以本脚本默认不做。要顺手补登请明确说。

⚠️ 该活动规则:完成一次对话才能被记录 —— 只有真实对话才算当天活跃。

换新活动页时的探法(方法论,下次直接照走)

活动每月会换(9月活跃地图 这个标题就是变量),但探法固定。按顺序来,别跳步:

  1. 先写只读探针,别先写点击。 新开一个 _wd_probe_xxx.js(.gitignore 已覆盖 _wd_probe_*.js), 复用常驻 Edge 的登录态,用 page.evaluate 打印候选锚点与 innerText。看清楚再动手。
  2. 锚点认「数据属性」,不认文案。 .gs-task-action 的 dt-remark 里是 JSON (taskCode / title / buttonText);文案会变、会重复、会撒谎(见上面「领取更多」)。
  3. 判定认 DOM 状态,不认按钮文字。 disabled / is-locked / is-reached 这类 class 与属性才是机器可读的真相 —— claimed_button_text 已有实测反例, 巅峰档未解锁时文案就已经是「兑换」。
  4. 接口只当佐证,以 DOM 为准。 同页 fetch 有的通(heatmap 200)有的失败 (streak / redeem/summary → Failed to fetch);accept_status 还是延迟聚合的。
  5. 列表面板可能是「累加式分页」。 gs-load-more(「全部任务」)点一次只多渲染几行, 必须循环点到行数不再增长,否则只看到首屏 5 行。
  6. 等待一律「等元素出现」,不用固定 sleep。 且失败要明确报错 —— 静默 break 会把"没渲染"伪装成"没数据",极难排查(见上面 SPA 竞态那条)。
  7. 默认干跑,--apply 才真执行。 再配一个 --probe(只验 locator 可达、不点击), 这样即使当下没有可操作项,也能证明链路是通的、而不是"从没跑过"的纸面功能。
  8. ⚠️ 点击前必须复核锁态。 Playwright 对 disabled 元素的 click() 不是立即失败, 而是等到超时 —— 不先查 disabled / is-locked,会把整个循环每档白卡 8 秒并误报「点击失败」。
  9. 写操作只走真实 UI 点击(Playwright click() = CDP 真实输入事件,isTrusted=true), 不直调写端点、不发合成上报。这条是刻意的取舍,勿为省事改掉。

排障脚本

node wb_diag_dom.js          # dump 派猫按钮 + 弹窗真实 DOM(加 --click 会点一下主按钮观察弹窗)
node wb_diag_gift_flow.js    # 完整跑一遍领礼物流程,逐步输出耗时与状态变迁

两者都附着在常驻 Edge(9223)上,不会把常驻窗口杀掉。

复盘

仓库镜像到 Gitee 🔁

.github/workflows/sync-to-gitee.yml 把仓库镜像到 Gitee 账号 strange_touchannel。push 到 main 即自动触发,纯 git 直推,约 20 秒完成。

  • 可见性自动跟随 GitHub:由 ensure-gitee-repo.sh 读 GitHub 仓库的 private 字段再写回 Gitee —— GitHub 上公开,Gitee 上就公开,不靠人工同步; 已存在且已一致时不发任何写请求,避免无谓覆盖描述等其他设置。 注意顺序:Gitee 不允许把空仓库设为公开(422 空仓库不支持设置为公开仓库), 所以脚本拆成 ensure(推送前建仓,一律先私有)和 align(推送后改可见性)两个阶段。
  • 手动 Run workflow 勾选 include_all_repos,会并行把 workflow 里 matrix.repo 名单中的所有仓库 一并镜像(fail-fast: false,单个仓库失败不拖累其他)。
  • 只用三个凭据,且都是现成的:GITEE_TOKEN(建仓 / 改可见性)、GITEE_SSH_KEY(推送)、 GITHUB_TOKEN(runner 自带,仅用于读一个 private 字段)。 不需要任何 GitHub PAT,因此不存在「令牌被轮换 → 静默失效」的风险。
  • 唯一维护点:新建仓库后要把名字追加进 matrix.repo 名单,不会自动发现。
  • 2026-09-16 重写原因:旧版用 Yikun/hub-mirror-action,它必须先调 GitHub API 列出账号下的仓库清单,这需要 src_token。该 secret 从未配置 → 请求走匿名 → 撞上 GitHub 匿名限流(60 次/小时,runner 共享出口 IP 几乎必然耗尽)→ 日志里 Total: 0, successed: 0(一个仓库都没同步),但退出码仍是 0 → Actions 上显示绿色 ✓。 实测同步是「时灵时不灵」的抽奖,且失败时没有任何提示。新版全程不碰 GitHub API 的仓库枚举 (git 协议不消耗 API 配额),任何一步失败都会让 job 真失败,不会再出现「绿色空转」。

首次部署

走了上面的「推荐用法」的话,这三步 WorkBuddy 已经替你跑完了,这里只是留档说明每一步在做什么。完整版(含故障兜底)见 INSTALL.md。

  1. 装依赖(Playwright core,走本地 playwright-core,无需下载浏览器):
    npm i playwright-core
  2. 登录一次:
    node wb_login_once.js --timeout=15
    在弹出的 Edge 窗口里登录 www.workbuddy.cn。**登完不要关窗口** —— SSO 会话是浏览器会话级的, 进程一关就焚(2026-09-06 实测踩坑),保持常驻才能让每日任务复用。登录态落在 wb_auto_profile_edge/。 想「登录 + 验证」一步到位,直接跑 node wb_login_then_run.js:扫码成功后它会自动在同一个常驻会话里 依次跑「派猫 → 签到」并打印结果。

不需要关闭 Edge 的 App-Bound Encryption,也不需要改动任何浏览器安全策略。 脚本附着在自己拉起的、带独立 --user-data-dir 的专用 Edge 上,cookie 由 Edge 进程自己解密与维持。

如果早期版本导入过 disable_edge_abe.reg(v1 遗留步骤,已确认不再需要): 在注册表编辑器里把 HKLM\SOFTWARE\Policies\Microsoft\Edge 下的 ApplicationBoundEncryptionEnabled 改为 1(或删除该值),重启 Edge 即恢复系统默认的凭据保护。

设计要点 / 踩过的坑

  • 派猫必须点二次确认框。主按钮点完会弹「确定派出」,不点这个确认框服务端不会真正派遣 —— 早期版本漏了这步导致"假成功"。脚本现在会点击后复核按钮是否切到「旅行中/倒计时」才算真成功。
  • 礼物态要先领再派。猫回家后按钮变成「领取礼物」,需先领奖励,按钮才会回到「派猫猫旅行」。
  • ⚠️ 领取礼物是异步的,别在领取中刷新页面(2026-09-13 故障根因)。点「领取 N 积分」后按钮会变成「领取中…」并 disabled;旧版只等 1.5s 就 page.goto 刷新,把还没完成的领取请求打断 → 礼物其实没领到,刷新后按钮仍是「领取礼物」,而外层 catch(e){} 又把异常静默吞掉,最后报 unknown-state:领取礼物 还谎称"已领礼物"。现在改成:全程轮询(等弹窗、等领取按钮可点、等按钮真正离开「领取」态最多 20s)+ 结果强校验 + 失败重试一轮 + 异常全记进 res.giftLog。
  • SPA 渲染会延迟。getTravelBtn 轮询最多 25s 等按钮出现,否则会误判 no-travel-button(成长中心实测约 5–10s 才渲染出按钮)。
  • 别用固定 sleep 等异步 UI。凡是"点了之后再操作"的地方(礼物弹窗、派遣确认框)一律轮询等目标出现/可点,页面负载一波动固定等待必然偶发漏步。
  • 加油站签到走浏览器同源会话,不读 token。签到 API 与页面同源(www.workbuddy.cn),常驻 Edge 对该域有有效会话 cookie,页面内同源 fetch 即完成鉴权。早期版本读桌面端登录态文件直连 API,2026-09-24 桌面端把 accessToken 改为加密信封后该路线废弃。
  • Edge 会话失效需重新扫码(v3 之后的现实)。SSO 会话 cookie 是会话级的,浏览器进程一关就焚。v3 曾用桌面端长期令牌续期做到重启零扫码,但 2026-09-24 起令牌加密(独立脚本无法解密),该路线已废弃;扫码本身由 wb_login_once.js 在自己的专用 profile 里原生完成,登完保持常驻。掉登录后的自动化兜底是 wb_login_then_run.js(2026-10-07 新增):登录等待与任务执行放在同一个 Node 进程里(本机会回收父进程退出后的 detached Edge),扫码成功后立即在同一常驻会话内依次跑「派猫 → 签到」,彻底免掉「扫完码还要手动补跑」那一步。
  • 签到收尾不能关浏览器。wb_checkin.js 释放连接时只 disconnect() CDP 句柄,不再 browser.close() —— 附着模式下 close() 会把整个常驻 Edge 关掉,连带焚毁会话级 cookie,还会让后续派猫只能冷启动去撞 connectOverCDP 超时(2026-10-07 修复)。同时末尾显式 process.exit(0),避免 disconnect() 之后 playwright 句柄占着事件循环、进程挂住不退(2026-10-11 修复)。
  • 瞬时失败靠「整流程重试」吸收(v4)。SPA 渲染抖动/冷启动竞态会让点击、查找按钮偶发失败(实测 2026-09-15、09-16 每天都要人工复跑 1~2 次才派成功)。现在把「进成长中心 → 判定状态 → 执行动作」抽成单轮函数 runOnce(),外层最多跑 3 轮,每轮重新加载页面,一次运行即自愈。这也是 19:25「补派兜底」自动化被删掉的前提——兜底能力已下沉到脚本内部,比「25 分钟后再跑一次」更准、更省积分。回归测试见 test_round_retry.js。

安全说明 🔒

  • 脚本不读取、不打印、不落盘任何 accessToken。签到通过常驻 Edge 内的同源 fetch 完成,凭据完全留在浏览器进程内;日志只输出积分与连续签到天数。
  • 只请求 www.workbuddy.cn 官方域名(与页面同源),无第三方。
  • wb_auto_profile_edge/ 是浏览器 profile,含真实登录 cookie,已在 .gitignore 中排除,切勿提交。
  • 只读本机登录态文件,不修改 WorkBuddy 本体。
  • 仓库内不存在任何"行为上报":wb_tasks.js 只有 GET;wb_auto_task.js 与 wb_run_tasks.js 只做真实 UI 点击(点了按钮服务端才记账)。没有一条请求是替你 去"声明"某件你没做过的事,也不伪造设备标识/客户端指纹。这条是刻意的取舍, 勿为省事发合成事件。

环境

  • Windows + Edge(macOS / Linux 也能跑,路径会自动探测)
  • Node 22+(fetch 原生可用)
  • playwright-core(npm i playwright-core)

路径是自动探测的

机器相关的路径 —— Edge 可执行文件、浏览器 profile、playwright-core、node.exe —— 全部由 wb_paths.js 自动探测,仓库里不写死任何本机路径,clone 下来就能跑。

优先级(高 → 低):

级别 方式 说明
1 环境变量 WB_EDGE / WB_PROFILE / WB_PLAYWRIGHT / WB_NODE 临时改一次用
2 local.config.js 不提交(已 gitignore),从 local.config.example.js 复制。想永久钉死自己的路径就写这儿
3 自动探测 按平台枚举常见安装位置,找不到再退到 PATH

换机器后想确认探测得对不对:

node wb_paths.js     # 打印 edge / profile / playwright / node 的最终解析结果

About

每天自动完成 Buddy 加油站签到 + 派猫猫旅行(Node.js + Playwright / Edge)

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages