写了个简单的 ArchiSteamFarm Python API 库

5 条回复
33 次浏览

ASFConnector 已开源在 GitHub

ASFConnector 已开源在 GitHub( https://github.com/ANGJustinl/ASFConnector ),欢迎大家试用并提出宝贵意见。项目采用 GPL-3.0 许可证

ASFConnector 项目截图

最近在考虑制作基于 ASF(ArchiSteamFarm)的自动化脚本时,我发现现存的 ASF IPC 类客户端普遍存在三个痛点:不支持 Python 3.10+ 的类型提示、配置管理混乱、错误调试如同猜谜。更让人头疼的是,这些库大多停留在 Python 3.6 时代,完全无法满足现代异步应用的性能需求。

作为一个闲的没事干的人,我决定自己动手解决这些问题。经过半周的开发和测试,我实现了一个基于 Pydantic v2 和 httpx 构建的现代化客户端 ASFConnector,解决了兼容性问题,而且具备连接池复用和更精细的错误溯源。

为什么需要重新造轮子

现存的 ASF IPC 库主要面临四个核心问题:

  1. 配置管理混乱:大多数库要么要求硬编码参数,要么使用简单的字典存储配置,既没有类型校验也不支持环境变量。
  2. 错误处理原始:当 ASF 返回 404 或 500 错误时,直接使用 http method 的库只会抛出模糊的 HTTP 异常,开发者需要手动解析响应体才能定位问题。更糟糕的是,不同错误场景的异常类型完全一致,无法通过 try-except 块精准捕获。
  3. 性能瓶颈:在批量操作多个 Bot 时,每个 API 请求都创建新的 HTTP 连接,100 次连续调用耗时超过 1 秒。
  4. Python 版本滞后:官方 wiki 上现有的相关库仍在使用 Python 3.6 的语法,不支持 asyncio 的最新特性,更别提类型注解了。

核心特性:现代 Python 技术栈的实践

ASFConnector 从设计之初就坚持“现代化”和“开发者友好”两个原则,主要体现在以下四个方面:

Pydantic v2 驱动的配置系统

我采用 Pydantic v2 构建了完整的配置管理体系。通过 ASFConfig 类,配置参数不仅支持自动验证(比如端口号必须是 1-65535 之间的整数),还能从 .env 文件、环境变量或字典中灵活加载。

复制
from ASFConnector.config import ASFConfig

# 自动从 .env 文件加载配置并验证
config = ASFConfig.from_env()

# 或者手动构建配置
config = ASFConfig(
    asf_host="192.168.1.100",
    asf_port=1242,
    asf_password="your_secure_password"
)

最实用的是,Pydantic 会自动处理类型转换和默认值。比如当你传入字符串类型的端口号 "1242",它会自动转换为整数;如果忘记设置 asf_path,会默认使用 "/Api"。这种设计极大减少了配置相关的 bug。

模块化控制器架构

借鉴了 FastAPI 的路由设计思想,我将 ASF 的 API 按功能拆分为多个控制器:

  • ASFController:处理全局操作(获取信息、更新配置、重启等)
  • BotController:管理 Bot 相关操作(启动、停止、激活密钥等)
  • NLogController:日志文件检索功能
  • TypeController:类型信息查询接口

这种设计让代码结构更清晰,也让按需加载成为可能。使用时通过主连接器对象直接访问:

复制
async with ASFConnector.from_config() as connector:
    # 获取 ASF 版本信息
    asf_info = await connector.asf.get_info()
    print(f"ASF Version: {asf_info['Result']['Version']}")

    # 激活游戏密钥
    result = await connector.bot.redeem('main_bot', 'XXXXX-XXXXX-XXXXX')

连接池带来的性能飞跃

性能优化是 ASFConnector 的重头戏。通过 httpx.AsyncClient 的连接池功能,我的这个库实现了异步对 TCP 连接的复用。测试数据显示,在连续执行 10 次 API 调用时:

  • 传统无连接池方式:总耗时 0.111 秒(平均 11.1ms/请求)
  • ASFConnector 连接池模式:总耗时 0.004 秒(平均 0.4ms/请求)

28.51 倍的速度提升意味着什么?对于需要同时管理 50 个 Bot 的场景,批量操作时间从原来的 22 秒缩短到 0.77 秒,这在生产环境中是质的飞跃。

实现这一优化的核心是上下文管理器设计:

复制
# 推荐用法:连接池自动管理
async with ASFConnector.from_config() as connector:
    for bot in bot_list:
        await connector.bot.start(bot) # 所有请求复用同一连接池

结构化错误溯源系统

调试 ASF API 我觉得会是用户往往最经常出现问题的地方。为此,我设计了完整的错误处理体系:

所有 API 调用返回统一格式的字典,包含 Success、Result/Message 字段。当发生错误时,还会附加 ExceptionType、StatusCode 和 ResponsePayload:

复制
response = await connector.bot.get_info('invalid_bot')
if not response['Success']:
    print(f"错误类型: {response['ExceptionType']}") # ASF_NotFound
    print(f"状态码: {response['StatusCode']}") # 404
    print(f"原始响应: {response['ResponsePayload']}") # ASF 返回的详细错误信息

同时定义了 12 种细分异常类型,从 ASF_BadRequest 到 ASF_NotImplemented,覆盖所有可能的 HTTP 状态码和业务错误场景。这意味着你可以精准捕获特定异常:

复制
from ASFConnector import ASF_NotFound

try:
    await connector.type.get_type('UnknownType')
except ASF_NotFound as e:
    print(f"类型不存在: {e.status_code}")

快速上手:5 分钟集成指南

前置配置

使用前需要确保 ASF 已正确设置 DefaultBot(在 ASF.json 中):

复制
{
    "DefaultBot": "your_primary_bot_name"
}

然后创建 .env 配置文件(可从 .env.example 复制):

复制
ASF_HOST=127.0.0.1
ASF_PORT=1242
ASF_PASSWORD=your_ipc_password

基础用法示例

下面是一个完整的示例,演示如何连接 ASF 并获取 Bot 信息:

复制
import asyncio
from ASFConnector import ASFConnector

async def main():
    # 从 .env 文件加载配置并创建连接器
    async with ASFConnector.from_config() as connector:
        # 获取指定 Bot 的信息
        bot_info = await connector.bot.get_info('main_bot')

        if bot_info['Success']:
            print(f"Bot 状态: {bot_info['Result']['Status']}")
            print(f"在线时间: {bot_info['Result']['OnlineTime']}")
        else:
            print(f"获取失败: {bot_info['Message']}")

asyncio.run(main())

高级场景:批量操作与日志跟踪

对于需要批量管理多个 Bot 的场景,ASFConnector 的异步特性可以充分发挥威力:

复制
async def batch_redeem_keys(connector, bot_names, keys):
    """批量为多个 Bot 激活密钥"""
    results = []
    for bot in bot_names:
        for key in keys:
            result = await connector.bot.redeem(bot, key)
            results.append({
                'bot': bot,
                'key': key,
                'success': result['Success'],
                'message': result.get('Message', '')
            })
    return results

# 使用示例
async with ASFConnector.from_config() as connector:
    bots = ['bot1', 'bot2', 'bot3']
    keys = ['KEY1', 'KEY2', 'KEY3']
    results = await batch_redeem_keys(connector, bots, keys)

未来 roadmap

目前 ASFConnector 已实现 ASF IPC API 的核心功能,接下来计划添加:

  1. 完整的单元测试和集成测试(当前测试覆盖率 85%)
  2. 命令行工具,支持无需编写代码的快速操作
  3. WebSocket 支持,用于实时日志流监控(可能)

所有这些功能都会保持对现代 Python 特性的拥抱,包括更完善的类型注解和异步支持。

如何获取与贡献

ASFConnector 已开源在 GitHub( https://github.com/ANGJustinl/ASFConnector ),欢迎大家试用并提出宝贵意见。项目采用 GPL-3.0 许可证,完全免费商用

如果你在使用过程中遇到问题,或者有功能建议,欢迎提交 issue 或 PR。我特别期待社区能帮助完善文档和测试用例,让这个工具变得更加健壮。

作为一个希望解决实际痛点而开发的工具(天啊我是重复造轮子高手),希望这个项目能帮助更多开发者更高效地使用 ASF,让 Steam 卡牌 farming 和游戏管理变得更加自动化、智能化。

期待你的 Star 和贡献!

大平衡者
Admin

感谢分享,我对代码格式做了一些修正,方便阅读。

大平衡者
Admin

在帖子下方有一排按钮的,编辑窗口时间为 10 分钟。image

发表一个评论

R保持