campus-skill:从零搭建和平营地多账号管理 Skill 的实战记录

2026年7月29日 兴趣使然 18 分钟阅读 3 次阅读
📖 文章摘要

用 Claude Code 从零搭建一个 Hermes Agent Skill,实现和平营地多账号的抓包解析、token更新、批量管理和服务监控,记录完整的设计思路和踩坑经验。

从零搭建和平营地多账号管理 Skill 的实战记录

前言

和平营地是《和平精英》的官方社区工具,可以通过 API 激活账号保持活跃状态。之前有个项目就是专门处理激活账号的,但是一直是手动管理几个账号,token 过期了就更新,激活失败了就查日志,操作繁琐且容易遗漏。

自从开始用 Hermes Agent(基于 OpenClaw 的聊天机器人)后,一直想实现一个场景:我丢一段抓包数据给 Agent,它自动解析、添加账号、更新配置,我确认一下就行。正好 Agent 已经支持 Skill 扩展,于是决定动手做一个 campus Skill。

这篇文章完整记录了从需求分析到最终可用的全过程。

第一步:摸清需求

做 Skill 之前,先梳理一下现有痛点。

手动操作的痛点

  1. 添加账号要手动编辑 config.json,格式容易出错
  2. 更新 token 要先找到对应账号,再改两个地方(config.json + .env)
  3. 批量操作没有现成工具,10个账号要点10次
  4. 服务状态全靠 ps aux | grep campuscrontab -l 手动查
  5. 定时任务暂停/恢复要手动注释 crontab 行

理想中的交互

用户:[发送抓包数据]
Agent:账号添加成功,备注"我的微信",已开启邮件通知

第二步:设计 Skill 结构

参考 pan Skill 和 article Skill 的设计思路,campus Skill 也是 SKILL.md + scripts 目录:

campus/
├── SKILL.md                      # Skill 说明文档
└── scripts/
    ├── parse_capture.py          # 抓包数据解析
    ├── update_account.py         # 单账号配置更新
    ├── batch_manage.py           # 批量管理
    └── service_manage.py         # 服务和定时任务管理

设计原则:每个脚本只做一件事,Agent 按需调用,SKILL.md 负责串联工作流。

第三步:抓包解析脚本

这是最核心的功能——用户发一段 URL 参数,脚本自动解析并保存账号。

解析逻辑

def parse_and_save(raw_data, note="未备注", is_send_email=1, owner_email=""):
    # 1. 解析URL参数
    params = urllib.parse.parse_qs(raw_data, keep_blank_values=True)
    collected = {k: v[0] for k, v in params.items() if v}
    
    # 2. 检查必要字段
    required = ["openId", "userId", "token", "accessToken"]
    login_type = collected.get("loginType", "")
    
    if login_type == "wx":
        required.append("refreshToken")
    
    missing = [f for f in required if f not in collected]
    if missing:
        print(f"❌ 缺少字段: {', '.join(missing)}")
        return False
    
    # 3. 构建账号配置
    account = {
        "note": note,
        "login_type": "wx" if login_type == "wx" else "qqconnect",
        "openId": collected["openId"],
        "userId": collected["userId"],
        "token": collected["token"],
        "login_accessToken": collected["accessToken"],
        ...
    }
    
    # 4. 保存配置
    config = config_manager.load_config()
    
    # 检查重复
    for acc in config["accounts"]:
        if acc["userId"] == account["userId"]:
            print(f"⚠️  账号 {account['userId']} 已存在")
            return False
    
    config["accounts"].append(account)
    config_manager.save_config(config)

关键设计决策

判断登录类型:根据 loginType 字段区分微信和 QQ,两种登录方式需要的字段不同:

  • 微信:需要 refreshToken
  • QQ:需要 appIdpfgameOpenId

重复检测:用 userId 作为唯一标识,避免重复添加同一个账号。

字段验证:解析后立即检查必要字段是否齐全,缺字段直接报错,不会保存不完整的账号配置。

第四步:账号更新脚本

单账号更新用 argparse 子命令,支持修改备注、开关邮件、更新 token 等操作。

双文件同步

更新 token 时需要同时改两个地方:

def _update_env(key, value):
    """更新.env文件中的环境变量"""
    env_path = os.path.join(os.path.dirname(__file__), '..', 'config', '.env')
    
    lines = []
    found = False
    if os.path.exists(env_path):
        with open(env_path, 'r', encoding='utf-8') as f:
            for line in f:
                if line.strip().startswith(f"{key}="):
                    lines.append(f"{key}={value}\n")
                    found = True
                else:
                    lines.append(line)
    
    if not found:
        lines.append(f"{key}={value}\n")
    
    with open(env_path, 'w', encoding='utf-8') as f:
        f.writelines(lines)

为什么用 .env 存 token:config.json 会被 Git 跟踪,token 是敏感信息不能提交。所以把 token 从 config.json 迁移到 .env,config.json 里只保留 userId 等非敏感字段。

env 变量命名规则CAMPUS_TOKEN_{userId}CAMPUS_ACCESS_TOKEN_{userId},这样每个账号的 token 独立存储,批量更新时逐个匹配。

第五步:批量管理脚本

支持三种批量操作:

batch_manage.py email on/off          # 批量开关邮件
batch_manage.py delete 1 2 3          # 批量删除
batch_manage.py token token "新token"  # 批量更新token
batch_manage.py list --type wx        # 按类型列出

实现要点

  1. 邮件开关和 token 更新支持 --ids 参数指定账号,不指定则操作全部
  2. 删除操作一次性传入多个 userId,用列表推导过滤
  3. token 更新需要同步修改 config.json 和 .env 两个文件

批量更新 token 的实现

def batch_update_token(token_type, token_value, user_ids=None):
    config = config_manager.load_config()
    
    # 读取.env
    env_lines = []
    if os.path.exists(env_path):
        with open(env_path, 'r', encoding='utf-8') as f:
            env_lines = f.readlines()
    
    for acc in config["accounts"]:
        if user_ids and str(acc["userId"]) not in user_ids:
            continue
        
        # 更新config.json
        acc[field] = token_value
        
        # 更新.env
        env_key = f"CAMPUS_TOKEN_{user_id}"
        updated = False
        for i, line in enumerate(env_lines):
            if line.strip().startswith(f"{env_key}="):
                env_lines[i] = f"{env_key}={token_value}\n"
                updated = True
                break
        
        if not updated:
            env_lines.append(f"{env_key}={token_value}\n")
    
    # 保存
    config_manager.save_config(config)
    with open(env_path, 'w', encoding='utf-8') as f:
        f.writelines(env_lines)

设计考量:先读取整个 .env 文件到内存,逐行匹配替换,最后一次性写回。这样避免多次文件 I/O,批量操作时效率更高。

第六步:服务管理脚本

服务管理主要是查看状态、管理定时任务。

状态查看

def get_status():
    # 检查主进程
    stdout, _, _ = run_cmd("ps aux | grep 'campus' | grep -v grep")
    running = bool(stdout)
    
    # 检查定时任务
    stdout, _, _ = run_cmd("crontab -l 2>/dev/null | grep campus")
    cron_enabled = bool(stdout)
    
    # 检查gateway
    stdout, _, _ = run_cmd("pgrep -f hermes-gateway")
    gateway_running = bool(stdout)
    
    print(f"主进程: {'✅ 运行中' if running else '❌ 未运行'}")
    print(f"定时任务: {'✅ 已启用' if cron_enabled else '❌ 未启用'}")
    print(f"Gateway: {'✅ 运行中' if gateway_running else '❌ 未运行'}")

检查三个组件:主进程(激活脚本)、定时任务(crontab)、Gateway(Hermes Agent 网关)。任何一个挂了都能一眼看出来。

定时任务管理

def pause_cron():
    """临时暂停定时任务(注释掉)"""
    run_cmd("crontab -l 2>/dev/null | sed 's|^\(.*campus.*main.py.*\)$|#\1|' | crontab -")

def resume_cron():
    """恢复定时任务(取消注释)"""
    run_cmd("crontab -l 2>/dev/null | sed 's|^#\(.*campus.*main.py.*\)$|\1|' | crontab -")

暂停/恢复:用 sed 注释/取消注释 crontab 行,比删除再添加更安全,不会丢失原有配置。

下次执行时间

def next_run():
    stdout, _, _ = run_cmd("crontab -l 2>/dev/null | grep campus")
    match = re.search(r'(\d+)\s+(\d+)\s+\*\s+\*\s+\*', stdout)
    if match:
        minute, hour = int(match.group(1)), int(match.group(2))
        now = datetime.now()
        next_time = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
        
        if next_time <= now:
            next_time += timedelta(days=1)
        
        print(f"⏰ 下次执行时间: {next_time.strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"   距今: {next_time - now}")

解析 cron 表达式:用正则提取 hour 和 minute,计算距今多久。如果今天的时间点已过,就加一天。

第七步:SKILL.md 的迭代

SKILL.md 是 Agent 的使用手册,定义了工作流和规则。

初版问题

一开始写得太详细,把每个脚本的所有参数都列了一遍,结果:

  1. Agent 加载时 Token 消耗大
  2. Agent 不需要知道所有参数细节,运行时脚本会自己报错提示
  3. 决策逻辑不清晰,Agent 不知道什么时候该调哪个脚本

优化后的结构

重构后的 SKILL.md 只保留核心:

  • Overview — 一句话说明这是什么
  • When to Use — 触发条件
  • 基础命令 — Agent 最常用的几个命令
  • 抓包解析 — 添加新账号的完整流程
  • 更新配置 — 单账号修改
  • 批量管理 — 批量操作
  • 服务管理 — 状态查看和定时任务
  • 故障排查 — 常用排查命令
  • Common Pitfalls — 易错点

精简原则:参数表格、示例输出这些运行时可见的东西不写在文档里,决策树和规则才是 Agent 真正需要的东西。

踩坑记录

1. config.json 和 .env 的职责分离

最初 token 也放在 config.json 里,但 config.json 会被 Git 跟踪。虽然 .gitignore 可以忽略,但多账号场景下逐个配置太麻烦。

解决方案:config.json 只存非敏感信息(userId、备注、登录类型等),token 统一放 .env,用 CAMPUS_TOKEN_{userId} 命名。

2. 微信和 QQ 的字段差异

微信登录需要 refreshToken,QQ 登录需要 appIdpfgameOpenId。一开始只处理了 QQ,后来有用户用微信登录才发现字段缺失。

解决方案:根据 loginType 字段动态构建账号配置,两种登录方式分别处理。

3. 批量更新 .env 的效率问题

最初用逐个读取写入的方式更新 .env,10 个账号要读写 10 次文件,效率低且容易出错。

解决方案:先读取整个 .env 到内存列表,逐行匹配替换,最后一次性写回。

4. 定时任务暂停的安全性

直接删除 crontab 行再恢复,万一恢复时忘记写回原来的配置就麻烦了。

解决方案:用 sed 注释/取消注释,配置始终保留在 crontab 里,只是生效与否的区别。

最终功能

目录结构

campus/
├── SKILL.md
└── scripts/
    ├── parse_capture.py    # 89行
    ├── update_account.py   # 157行
    ├── batch_manage.py     # 136行
    └── service_manage.py   # 107行

核心命令

# 添加账号(解析抓包数据)
python scripts/parse_capture.py 'openId=xxx&userId=123&token=abc&accessToken=def' 我的微信 1 admin@example.com

# 查看账号
campus -l

# 更新配置
python scripts/update_account.py <userId> --show
python scripts/update_account.py <userId> --token "新token"

# 批量操作
python scripts/batch_manage.py email on
python scripts/batch_manage.py delete 1 2 3

# 服务管理
python scripts/service_manage.py status
python scripts/service_manage.py pause
python scripts/service_manage.py next

总结

做这个 Skill 的几个关键经验:

  1. 职责分离,各司其职:config.json 存结构化数据,.env 存敏感信息,每个脚本只做一件事,SKILL.md 负责串联流程。这样任何一部分出问题都能独立排查和修复

  2. 解析即验证:抓包数据解析后立即检查必要字段,缺字段直接报错,不会保存不完整的配置。比保存后再校验更安全

  3. 批量操作要考虑效率:10 个账号逐个读写文件太慢,先读取到内存统一处理再一次性写回,既快又安全

  4. SKILL.md 要精简:参数细节运行时脚本会自己提示,Agent 真正需要的是"什么时候调什么命令"的决策树,不是 API 文档

  5. 暂停比删除更安全:定时任务用 sed 注释/取消注释,配置始终保留,避免恢复时丢失原配置

  6. 双文件同步要原子化:同时改 config.json 和 .env 时,先改 config.json 再改 .env,中间出错至少还有一个是对的。批量操作时先读取到内存,改完再一起写回

整个 Skill 从想法到可用,大概花了 30 分钟。Claude Code 在这个过程中的角色不只是写代码,更像是一个搭档 — 我提需求,它分析、实现、测试,遇到问题一起排查。比如微信登录字段缺失的问题,是实际测试中发现的,它立刻帮我补上了处理逻辑。这种协作模式比自己从零写要高效得多。

文章创建于:2026年7月29日CC BY-NC-SA 4.0
📡

评论

暂无评论,来写第一条吧

© 2026 My Blog. Built with Nuxt.js + FastAPI.