利益相关声明:文中包含营销(如促销活动)和推广(如返利链接)信息

利益相关声明:本文包含我的邀请链接,属于推广信息——通过它注册我会获得积分奖励。本文文字经 AI 辅助校对排版。


起因:每天点一下,但总是忘

WorkBuddy 里有个「Buddy 加油站」的每日签到,签到给积分,积分用来抵扣对话消耗。积分不算多,但每天都有——问题是,每天手动点一下,很容易忘。忘了就是白白少拿一天。

我一开始的解法是设手机提醒。但提醒了还是要点进客户端点一下,纯机械操作。既然它本质上是「点一下领积分」,那它就应该能被脚本替代。

于是我花了一个下午把它自动化了。下面是从零到跑通的完整过程,包括踩的坑。

一、先想清楚:签到到底是什么

动手之前先明确一件事:这类「签到领积分」的功能,在客户端里是一个按钮,但按钮背后一定是一次 HTTP 请求。

所以有两条路:

  1. 模拟点击(UI 自动化)——打开客户端、找到按钮、点它。脆弱,客户端一改版就废。
  2. 直接调接口(HTTP 请求)——找到那个请求,自己发一遍。稳定得多。

我选第二条。

二、找到接口,以及怎么鉴权

在客户端里手动签到一次,看它发出的请求。有两个关键的:

  • POST /v2/billing/meter/checkin-activity-status —— 查询签到状态
  • POST /v2/billing/meter/daily-checkin —— 领取

鉴权方式是 Authorization: Bearer <token>。那 token 从哪来?

不用抓包。WorkBuddy 客户端把登录态存在本地:

%LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth\workbuddy-desktop-ai.info

这是一个 JSON,里面有 auth.accessTokenauth.domain。读出来直接用就行。macOS 的路径在 ~/Library/Application Support/CodeBuddyExtension/... 下,脚本里做了兼容。

三、脚本

只用 Python 标准库,零依赖。核心就三步:读 token → 查状态 → 没签就领。

import os, sys, json, urllib.request, urllib.error
from datetime import datetime

INFO = os.path.join(os.environ.get("LOCALAPPDATA", ""),
                    r"CodeBuddyExtension\Data\Public\auth\workbuddy-desktop-ai.info")
STATUS = "/v2/billing/meter/checkin-activity-status"
CLAIM  = "/v2/billing/meter/daily-checkin"

def load_auth():
    with open(INFO, encoding="utf-8") as f:
        auth = json.load(f).get("auth") or {}
    return auth.get("accessToken", ""), auth.get("domain", "www.workbuddy.ai")

def api(domain, path, token):
    req = urllib.request.Request(
        "https://%s%s" % (domain, path), data=b"{}", method="POST")
    req.add_header("Authorization", "Bearer " + token)
    req.add_header("Content-Type", "application/json")
    try:
        with urllib.request.urlopen(req, timeout=25) as r:
            return json.loads(r.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        return json.loads(e.read().decode("utf-8"))

def main():
    token, domain = load_auth()
    if not token:
        print("未找到本机登录态,请先登录 WorkBuddy 客户端")
        return 1

    st = api(domain, STATUS, token)
    data = st.get("data") or {}
    print("活动: %s | 今日已签到: %s" % (
        "开启" if data.get("active") else "未开启",
        "是" if data.get("today_checked_in") else "否"))

    if data.get("today_checked_in"):
        print("今天已签到,无需重复领取")
        return 0

    res = api(domain, CLAIM, token)
    code, msg = res.get("code"), res.get("msg") or ""
    if code in (0, 200):
        print("签到成功,+%s 积分" % (res.get("data") or {}).get("credit", "?"))
        return 0
    if code == 10001:
        # 活动阶段性下线,不是错误
        print("活动未开启或已过期:%s" % msg)
        return 0
    print("领取失败: code=%s %s" % (code, msg))
    return 1

if __name__ == "__main__":
    sys.exit(main())

它做了几件我觉得必要的事:

  • 幂等:先查状态,今天签过就直接退出,不重复请求
  • 非致命处理:活动下线时记一条日志就退出,不算失败
  • 退出码规范0 表示成功/已签到/活动未开启,1 才是真失败——这样接自动化时不会误报

完整版还支持 --status(只看状态不领取)和 --json(输出结构化结果)。

四、让它每天自己跑

脚本能跑还不够,得让它自己跑。

Windows 用计划任务(PowerShell):

$action  = New-ScheduledTaskAction -Execute "python.exe" `
           -Argument "C:\path\to\workbuddy_checkin.py"
$trigger = New-ScheduledTaskTrigger -Daily -At 09:00
Register-ScheduledTask -TaskName "WorkBuddyDailyCheckin" `
  -Action $action -Trigger $trigger

macOS / Linux 用 cron:

0 9 * * * /usr/bin/python3 /path/to/workbuddy_checkin.py

我设的是每天早上 9 点,跑完的结果追加到脚本同目录的 checkin.log

五、几个坑

1. 活动会阶段性下线。 我第一次跑的时候接口返回 active: false,领取报 10001 签到活动未开启或已过期。这不是脚本写错了,是平台把活动下线了。所以脚本必须把这种情况当正常结果处理——否则你每天都会收到一条假告警,最后就会开始无视告警。

2. token 会过期。 长期不登录客户端,本地 token 会失效,查询会失败。重新登录客户端即可,脚本不用改。

3. 安全边界要自己想清楚。 这类「读本机凭据」的脚本,最容易出问题的地方是顺手把 token 发到某个「云端」去同步。我的原则是:只读本机登录态、只请求官方域名,token 不出本机、不落任何第三方。如果你要用别人的脚本,先看它把 token 发去哪了。

六、结果

现在每天早上 9 点,积分自动到账,我不用再记着这件事。

这类小自动化的价值不在于省了多少时间——每天点一下也就 10 秒。价值在于它从你的待办里消失了。需要靠提醒才能完成的事,本质上还是在占用注意力。

如果你也在用 WorkBuddy,可以用这个链接注册,签到和积分活动是同一套:

👉 https://workbuddy.ai/invite?code=66L9RNCT

脚本我留在本地了,需要的话可以按上面的代码自己拼一个,逻辑就这些。