Ikreb1/mtg-arena-collection-export

GitHub: Ikreb1/mtg-arena-collection-export

通过逆向MTG Arena的Frontdoor协议调用Card_GetAllCards接口,将玩家卡牌收藏导出为JSON的轻量级Python工具。

Stars: 0 | Forks: 0

# MTG Arena 收藏导出 **将你拥有的 MTG Arena (MTGA) 卡牌收藏导出为 JSON —— 即使在 2026 客户端中它已不再写入 `Player.log`。** 这是一个无需依赖的轻量级 Python 工具,它通过使用游戏原生的 **Frontdoor** 网络协议并调用 `Card_GetAllCards`(这是 长期被移除的 `GetPlayerCardsV3` 的现代替代方案),从 **Magic: The Gathering Arena** 中提取你的**拥有的卡牌 收藏**。它会输出一个简单的 `{arena_id: count}` JSON 映射,你可以将其导入到卡组构建器、收藏追踪器、 代理工具、价值计算器或你自己的脚本中。 ## ⚠️ 阅读须知(ToS / 封禁风险) 本项目是**非官方的**,且**不隶属于 Wizards of the Coast 或 Hasbro**。它的工作原理是使用第三方 客户端向 Arena 的实时服务器进行身份验证,这**违反了 MTG Arena 的服务条款 / EULA**,并且**可能导致 你的账号被暂停或封禁**。 - **风险自负**。请**仅在你自己的账号上**使用它,用于获取你**自己的收藏数据**。 - 它被刻意设计为**只读**模式:它仅进行身份验证并调用 `Card_GetAllCards`, 仅此而已。**切勿**添加游戏自动化功能 —— 那才是导致人们被封禁的原因,且 在这里是不受欢迎的。 - 维护者提供此工具是为了**互操作性和个人数据导出**, 对你的账号发生的一切概不负责。 如果你无法接受这种风险,请不要使用它。 ## 为什么会有这个项目 在当前的 MTG Arena 版本中,拥有的收藏**不再存在于 `Player.log` 中**: - 旧的 `PlayerInventory.GetPlayerCardsV3` 日志行在 **2021 年就被移除了**。 - 在客户端内打开收藏/卡组构建器时,它是从内存缓存中渲染的, 并且**不会产生任何记录的 API 调用**。 - 它不会被缓存到磁盘上的任何可读文件中。 因此,那些流行的“只需 grep 你的 Player.log”的追踪器再也看不到你的收藏 了。现在,收藏数据通过游戏的**固定 Frontdoor socket** 进行传输。该工具 重新实现了该协议中刚好足够用的一部分,以便直接向服务器请求这些数据。 ## 工作原理(宏观概述) 1. **OAuth 刷新** —— 使用 Arena *公开的应用级* Steam 客户端凭据,将你捕获的 `refresh_token` 交换为一个短期的 access token。 2. **连接 Frontdoor** —— 根据 “doorbell” 响应,打开一个连接到 Frontdoor 主机的 TLS socket。 3. **身份验证** —— 通过 **2026 线路格式** (frame version 4 + 一个 protobuf `Cmd` 信封;参见 [`docs/PROTOCOL.md`](docs/PROTOCOL.md))发送 `Authenticate` 命令。 4. **`Card_GetAllCards` (命令 551)** —— 请求完整收藏并将其 写入 `data/collection.json`。 完整的逆向工程协议记录在 **[`docs/PROTOCOL.md`](docs/PROTOCOL.md)** 中 —— 即使你打算用其他语言实现,这也很有用。 ## 环境要求 - **Python 3.8+** —— 仅需标准库,无需 `pip install`。 - 需要一次性捕获**你自己的** Arena `refresh_token` (参见 [`docs/CAPTURING_YOUR_TOKEN.md`](docs/CAPTURING_YOUR_TOKEN.md);需要一次性使用 [mitmproxy](https://mitmproxy.org/))。 - 运行此工具时,应**关闭** MTG Arena(同一账号的第二个并发 Frontdoor 会话可能会被拒绝)。 ## 用法 ``` # 1) 将捕获的 token + doorbell response 放入 data/ (参见 docs): # data/token.json <- 包含你的 refresh_token (SECRET, gitignored) # data/doorbell.json <- 包含 fdURI # 2) 拉取 collection: python3 mtga_collection.py # -> 写入 data/collection.json ({arena_id: count}) ``` 实用参数: | 参数 | 默认值 | 用途 | |------|---------|---------| | `--token-file` | `data/token.json` | 包含你的 `refresh_token` 的 JSON 文件。 | | `--doorbell-file` | `data/doorbell.json` | 捕获的 doorbell 响应(包含 `fdURI`)。 | | `--fduri tcp://host:port` | — | 跳过 doorbell 文件并直接连接。 | | `--platform` | 尝试 Steam/Windows/… | 强制使用单个 `PlatformId`。 | | `--out` | `data/collection.json` | `{arena_id: count}` 映射的写入位置。 | | `--raw-out` | `data/getallcards_raw.json` | 导出原始服务器响应以供检查。 | ## 输出格式 `data/collection.json` 是一个扁平化的映射,对应 **Arena 卡牌 ID → 拥有数量**: ``` { "70000": 4, "70001": 2, "68769": 3 } ``` 参见 [`examples/collection.sample.json`](examples/collection.sample.json)。原始 响应 (`--raw-out`) 的格式为 `{"cacheVersion": N, "cards": { "": qty }}`。 使用 [Scryfall](https://scryfall.com/docs/api/bulk-data) 批量数据(每张卡都有一个 `arena_id`)将 Arena ID 映射为真实的卡牌名称。 ## 常见问题 **需要我的 Arena 密码吗?** 不需要。它使用你从自己的客户端捕获的 OAuth `refresh_token`;密码永远不会经过此工具。 **我会被封禁吗?** 有可能 —— 参见上面的警告。这违反了 ToS。它是 只读的,风险比自动化要低,但没有任何保证。 **它能在 Steam / 独立 / Epic 客户端上工作吗?** 它默认使用公开的 Steam 应用凭据,并在失败时回退到独立凭据。在任何客户端上,token 捕获的 原理都是一样的。 **我可以用其他语言使用它吗?** 可以 —— [`docs/PROTOCOL.md`](docs/PROTOCOL.md) 完整规范了线路格式。 ## 致谢 - 协议的基础工作受到了较早的 **MTGate** 项目的启发(2023 年的 JSON/v3 Frontdoor 流程);本仓库记录了 **2026 年**的 protobuf/v4 变更。 - 卡牌数据:**[Scryfall](https://scryfall.com/)**。 ## 许可证 [MIT](LICENSE) © Ikreb1。不隶属于 Wizards of the Coast。 “Magic: The Gathering” 和 “MTG Arena” 是 Wizards of the Coast LLC 的商标。
标签:MTG Arena, Python, 内核驱动, 底层编程, 数字取证, 数据导出, 无后门, 游戏工具, 网络协议, 自动化脚本, 逆向工具