前言
一套不依赖本地电脑、不用自己买服务器、每天准时跑的自动化方案。包含完整代码、配置步骤和 6 个真实踩坑记录。
一、整体架构
scss
┌─────────────────┐
│ Gitee Go 定时器 │ (每天触发)
└────────┬────────┘
↓
┌─────────────────┐
│ 拉取私有仓库 │ (checkin.py + config.json)
└────────┬────────┘
↓
┌─────────────────┐
│ 执行脚本 │
└────────┬────────┘
↓
┌─────────────────┐
│ Server酱 推微信 │ (通知到个人微信)
└─────────────────┘
核心优势:
- 不依赖本地电脑,云端跑
- 微信实时通知,签到结果一目了然
- 维护成本极低(token 过期前更新一次即可)
二、准备工作
2.1 获取 accessToken
WorkBuddy 客户端登录后,会在本地保存登录态:
- macOS :
~/Library/Application Support/CodeBuddyExtension/Data/Public/auth/workbuddy-desktop.info
打开这个文件,你会看到类似:
json
{
"account": { "nickname": "你的昵称", ... },
"auth": { "accessToken": "eyJhbGc...", "expiresIn": ... }
}
auth.accessToken 就是我们需要的 token(这是你自己账号的合法凭证,不涉及任何破解)。
⚠️ 安全提示 :accessToken 就是你的登录态,绝对不要 提交到公开仓库。下面的方案会用私有仓库 + 配置文件保存。
2.2 注册 Server酱(微信通知)
打开 sct.ftqq.com → 微信扫码登录 → 在页面里看到 SendKey(一串字母数字)。
效果:调用 Server酱 接口就能把消息推送到你的微信(关注"方糖"公众号即可接收)。
三、签到脚本
完整脚本 checkin.py(纯 Python 标准库,零依赖):
python
#!/usr/bin/env python3
"""
WorkBuddy 每日签到脚本
支持本地运行和云端运行
"""
import json
import os
import sys
import urllib.request
import urllib.error
from pathlib import Path
from datetime import datetime
# ─── 配置 ───────────────────────────────────────────────
API_BASE = "https://copilot.tencent.com"
CHECKIN_STATUS_URL = f"{API_BASE}/billing/meter/checkin-status"
DAILY_CHECKIN_URL = f"{API_BASE}/billing/meter/daily-checkin"
SERVERCHAN_URL = "https://sctapi.ftqq.com/{sendkey}.send"
REQUEST_TIMEOUT = 15
# 本地 auth 文件 (macOS)
_LOCAL_AUTH_FILE = (
Path.home()
/ "Library/Application Support/CodeBuddyExtension"
/ "Data/Public/auth/workbuddy-desktop.info"
)
# 云端配置文件
_CLOUD_CONFIG_FILE = Path(__file__).parent / "config.json"
def log(msg: str):
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {msg}", flush=True)
# ─── Token 读取 ─────────────────────────────────────────
def load_access_token() -> tuple[str | None, str]:
"""读取 token,优先级:config.json > 本地 auth > 环境变量"""
# 1. 云端 config.json
if _CLOUD_CONFIG_FILE.exists():
try:
data = json.loads(_CLOUD_CONFIG_FILE.read_text(encoding="utf-8"))
token = data.get("access_token", "").strip()
name = data.get("account_name", "云端账号")
if token:
log(f" 使用云端 config.json token (账号: {name})")
return token, name
except Exception as e:
log(f"⚠️ 读取 config.json 失败: {e}")
# 2. 环境变量
token = os.environ.get("WORKBUDDY_ACCESS_TOKEN", "").strip()
if token:
name = os.environ.get("WORKBUDDY_ACCOUNT_NAME", "环境变量账号")
log(f" 使用环境变量 token (账号: {name})")
return token, name
# 3. 本地 auth 文件
if not _LOCAL_AUTH_FILE.exists():
log("❌ 未找到任何 token 来源,请配置 config.json 或环境变量")
return None, ""
try:
data = json.loads(_LOCAL_AUTH_FILE.read_text(encoding="utf-8"))
token = data.get("auth", {}).get("accessToken", "").strip()
name = data.get("account", {}).get("nickname", "本地账号")
if not token:
log("❌ auth 文件中未找到 accessToken")
return None, ""
log(f" 使用本地 auth 文件 token (账号: {name})")
return token, name
except Exception as e:
log(f"❌ 读取 auth 文件失败: {e}")
return None, ""
# ─── API 调用 ───────────────────────────────────────────
def _request(url: str, token: str) -> dict | None:
req = urllib.request.Request(
url,
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"User-Agent": "WorkBuddy-Checkin/1.0",
},
)
try:
with urllib.request.urlopen(req, timeout=REQUEST_TIMEOUT) as resp:
return json.loads(resp.read().decode("utf-8"))
except urllib.error.HTTPError as e:
log(f" HTTP {e.code}: {e.reason}")
return None
except Exception as e:
log(f" 请求失败: {e}")
return None
def get_checkin_status(token: str) -> dict | None:
return _request(CHECKIN_STATUS_URL, token)
def claim_daily_checkin(token: str) -> dict | None:
return _request(DAILY_CHECKIN_URL, token)
# ─── Server酱 通知 ─────────────────────────────────────
def send_wechat_notification(title: str, content: str, sendkey: str) -> bool:
"""推送消息到微信"""
if not sendkey:
return False
url = SERVERCHAN_URL.format(sendkey=sendkey)
payload = urllib.parse.urlencode({"title": title, "desp": content}).encode()
req = urllib.request.Request(url, data=payload, method="POST")
try:
with urllib.request.urlopen(req, timeout=REQUEST_TIMEOUT) as resp:
result = json.loads(resp.read().decode("utf-8"))
if result.get("code") == 0:
log(f" ✅ 微信通知已发送")
return True
log(f" ⚠️ 微信通知失败: {result.get('message')}")
return False
except Exception as e:
log(f" ⚠️ 微信通知异常: {e}")
return False
# ─── 签到主流程 ─────────────────────────────────────────
def checkin() -> bool:
log("=" * 56)
log(f" WorkBuddy 每日签到 --- {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
log("=" * 56)
sendkey = os.environ.get("SERVERCHAN_SENDKEY", "")
if _CLOUD_CONFIG_FILE.exists():
try:
sendkey = sendkey or json.loads(
_CLOUD_CONFIG_FILE.read_text(encoding="utf-8")
).get("serverchan_sendkey", "")
except Exception:
pass
log("步骤 1/3: 获取 accessToken...")
token, account_name = load_access_token()
if not token:
log("❌ 无法获取 accessToken,签到终止。")
send_wechat_notification(
"❌ WorkBuddy 签到失败", f"账号: {account_name}\n未找到 accessToken", sendkey
)
return False
log("\n步骤 2/3: 查询签到状态...")
status_data = get_checkin_status(token)
if status_data and status_data.get("today_checked_in", False):
log("\nℹ️ 今日已签到,无需重复领取。")
send_wechat_notification(
"✅ WorkBuddy 今日已签到", f"账号: {account_name}\n时间: {datetime.now()}", sendkey
)
return True
log("\n步骤 3/3: 领取签到积分...")
result = claim_daily_checkin(token)
if result:
points = result.get("points", result.get("reward_points", ""))
log(f"\n✅ 签到成功! 获得积分: {points}")
send_wechat_notification(
"✅ WorkBuddy 签到成功",
f"账号: {account_name}\n获得积分: +{points}\n时间: {datetime.now()}",
sendkey,
)
return True
log("\n❌ 签到失败")
send_wechat_notification(
"❌ WorkBuddy 签到失败", f"账号: {account_name}\n请检查 token 是否过期", sendkey
)
return False
if __name__ == "__main__":
sys.exit(0 if checkin() else 1)
配置文件 config.json
json
{
"access_token": "你的_accessToken",
"account_name": "你的昵称",
"serverchan_sendkey": "你的_SendKey"
}
四、本地测试
bash
# 方式 1:用环境变量
export WORKBUDDY_ACCESS_TOKEN="你的token"
export WORKBUDDY_ACCOUNT_NAME="你的昵称"
export SERVERCHAN_SENDKEY="你的SendKey"
python3 checkin.py
# 方式 2:用 config.json (推荐)
# 把 config.json 放到同目录,直接 python3 checkin.py
预期输出:
yaml
[2026-08-03 14:00:00] ========================================================
[2026-08-03 14:00:00] WorkBuddy 每日签到 --- 2026-08-03 14:00:00
[2026-08-03 14:00:00] ========================================================
[2026-08-03 14:00:00] 步骤 1/3: 获取 accessToken...
[2026-08-03 14:00:00] 使用云端 config.json token (账号: X 先生)
...
[2026-08-03 14:00:00] ✅ 签到成功! 获得积分: 100
[2026-08-03 14:00:00] ✅ 微信通知已发送
打开微信,"方糖"公众号会立刻收到推送。
五、云端部署(Gitee Go)
5.1 创建私有仓库
登录 gitee.com → 新建仓库 → 选私有 (重要!token 不能公开)→ 起名 workbuddy-checkin。
5.2 推送代码
bash
cd workbuddy-checkin
git init
git remote add origin https://gitee.com/你的用户名/workbuddy-checkin.git
git add .
git commit -m "init: WorkBuddy 每日签到"
git push -u origin main
5.3 配置流水线
进入仓库 → 流水线 (Gitee Go) → 新建流水线:
- 基本信息 :名字设为
WorkBuddy 每日签到 - 流程编排 :
- 删除默认的"主机部署"步骤
- Python 构建 步骤里,构建命令填:
python3 checkin.py - Python 版本选
3.11
- 高级设置 → 定时触发:
| 字段 | 值 |
|---|---|
| 秒 | 0 |
| 分 | 5 |
| 小时 | 9 |
| 日 | * |
| 月 | * |
| 周 | ? |
| 年 | * |
这个表达式 = 每天北京时间 09:05 触发
5.4 测试
回到流水线列表 → 点 "立即执行" → 看日志输出 + 微信是否收到通知。
云端跑通后,整套就完全自动了:
- 每天 09:05 Gitee Go 自动跑
- 跑完签到脚本自动调 Server酱
- 你微信收到通知
- 不依赖本地电脑开不开机
六、方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| WorkBuddy 自动化 | 配置最简单 | 依赖本地电脑,断签风险高 |
| macOS launchd | 本地稳定,能利用 PowerNap | 还是依赖电脑唤醒 |
| Gitee Go + Server酱 ⭐ | 不依赖电脑、微信通知 | 需要私有仓库 |
| 腾讯云函数 | 定时最准 | 配置复杂,有少量费用 |
| GitHub Actions | 国际化、文档全 | 国内访问慢 |
我的最终选择:Gitee Go + Server酱,国内访问快、维护简单、通知及时。
七、写在最后
核心思路其实就是把"本地自动化"升级成"云端自动化":
- 任何需要定期执行的小任务,都可以按这个套路来
- Token / API Key 用私有仓库 + 配置文件管理
- 通知用 Server酱 这种"零成本"通道
希望对你有帮助,有问题欢迎评论区交流 👇