time-attack/OpenPigeon

GitHub: time-attack/OpenPigeon

OpenPigeon 是一个 TypeScript SDK,通过逆向工程 GamePigeon 的 iMessage 传输协议,让开发者能以纯数据方式读写 11 款游戏的棋盘状态并以 URL 发送操作。

Stars: 4 | Forks: 0

OpenPigeon # OpenPigeon **只需几行 TypeScript,即可将 GamePigeon iMessage 游戏集成到你的应用中。** 以纯数据形式读取棋盘。以 URL 形式发送操作。通过 Linq 和 Photon 工作 —— 无需 AI,无需 SQLite,无需 Mac。 [![license](https://img.shields.io/badge/license-MIT-3178c6.svg)](LICENSE) [![npm](https://img.shields.io/badge/npm-openpigeon-cb3837?logo=npm&logoColor=white)](https://www.npmjs.com/package/openpigeon) [![node](https://img.shields.io/badge/node-%E2%89%A5%2022-339933?logo=node.js&logoColor=white)](https://nodejs.org) [![typescript](https://img.shields.io/badge/TypeScript-strict-3178c6?logo=typescript&logoColor=white)](https://www.typescriptlang.org) [![dependencies](https://img.shields.io/badge/runtime%20deps-0-2ea44f)](package.json) [![games](https://img.shields.io/badge/games-11-7c3aed)](docs/GAMES.md) [![byte-exact](https://img.shields.io/badge/codec-byte--exact-0ea5a4)](test/) [![PRs](https://img.shields.io/badge/PRs-welcome-ff69b4.svg)](#adding-a-game)
8-Ball rendering natively in iMessage
8-Ball — sent via API, rendered natively by GamePigeon
Cup Pong rendering natively in iMessage
Cup Pong — the recipient's own GamePigeon draws the board
Real device. Invites are sent through OpenPigeon and render natively — no attached image (Linq ships liveLayoutInfo).
## 原因 GamePigeon 是一个黑盒:游戏以加密的 `imessage_app` 气泡形式搭载 iMessage。 OpenPigeon 对该传输格式进行了逆向工程,让你的机器人能够**理解**游戏 并对其**做出响应** —— 将不透明的气泡转换为普通对象并还原: ``` import * as op from "openpigeon"; const m = op.read(url); // decode any GamePigeon URL m.game; // "connect4" m.turn; // 2 (whose turn is next) m.state; // { grid: [...], move: {...} } ← the board, as data const reply = m.reply({ botId: "MY-ID", state: m.state }); // your move → a URL op.invite("sea_battle"); // start a fresh game → { url, id } ``` 无需密码、无需 percent-encoding、无需 MSMessage 管道 —— SDK 会处理这一切。 ``` npm install openpigeon ``` ## 接收 —— 来自 webhook/stream,绝非 SQLite
Linq (webhook)Photon (stream)
``` import express from "express"; import * as op from "openpigeon"; const linq = new op.Linq({ token: process.env.LINQ_TOKEN!, fromNumber: "+1...", }); app.post("/webhook", async (req, res) => { res.sendStatus(200); const inb = op.fromWebhook(req.body); if (!inb || inb.move.isInvite) return; const m = inb.move; // your move logic here const url = m.reply({ botId: BOT, state: m.state }); await linq.send(url, { to: inb.replyTo!, chatId: inb.chatId ?? undefined, }); }); ``` ``` import { customizedMiniApp } from "spectrum-ts/providers/imessage"; import * as op from "openpigeon"; for await (const [space, message] of app.messages) { const inb = op.fromPhotonMessage(message); if (!inb || inb.move.isInvite) continue; const m = inb.move; // your move logic here const url = m.reply({ botId: BOT, state: m.state, https: true, // https carrier }); await space.send( customizedMiniApp(op.Photon.balloon(url)), ); } ```
完整示例:[`examples/linq-express-bot.ts`](examples/linq-express-bot.ts) · [`examples/photon-bot.ts`](examples/photon-bot.ts) · [`examples/quickstart.ts`](examples/quickstart.ts) ## 查看棋盘 ``` import { render } from "openpigeon/games/connect4"; console.log(render(op.read(url).state)); // . . O X X X O // . . X O . . . // . . . . . . . ``` ## 支持的游戏 所有 11 款游戏都能解码为有文档记录的 `state`,并且在与真实捕获的消息对比时实现**字节精确**的往返转换。 | 游戏 | `game=` token(s) | state 来源 | 你可以读取的内容 | |---|---|---|---| | 🎱 **pool** (8球) | `pool` · `pool2` · `pool3` | replay | 击球(瞄准/力度/旋转)+ 每个球 `{x,y,rot,alpha,num,v…,pocketed}` | | 🎯 **darts** | `darts` | replay | 倒计时分数 + 投掷 `{x,y,points,segment,mult,ring}` | | ⛳ **mini_golf** | `golf` | replay | 逐洞击球记录 `{power,angle}`(+ 对手的) | | 🔴 **connect4** | `connect` | replay | 7×6 棋盘网格 + `{col,row,player}` + `render()` | | 🏹 **archery** | `archery` | replay | 回合状态 + 投掷 `{player,x,y,z}` | | 🏀 **basketball** | `basketball` | replay ×4 | 跨回合投篮 `{t,arc,spin,made}` | | 🥤 **cup_pong** | `beer` | replay | 双方剩余杯子 + 投掷记录 | | 🚢 **sea_battle** | `sea` | envelope+replay | 尺寸、战舰 `{pos,hits,rot}`、射击网格、上一次射击 | | 🔤 **word_hunt** | `hunt` | envelope | 字母网格、每位玩家的分数 + 找到的单词 | | 🔀 **anagrams** | `anagrams` | envelope | 字母池、每位玩家的分数 + 找到的单词 | | 🧩 **wordbites** | `wordbites` | envelope | 字母块、每位玩家的分数 + 找到的单词 | 各游戏的 `state` 结构 → [docs/GAMES.md](docs/GAMES.md) · 添加游戏只需一个文件 → [`src/games/pool.ts`](src/games/pool.ts)。 ## 支持的服务提供商 | 提供商 | 发送 | 接收 | 说明 | |---|:--:|:--:|---| | **Linq** | ✅ 气泡 + 文本 | ✅ `message.received` webhook | 端到端纯 TypeScript;**原生渲染** (`liveLayoutInfo`) | | **Photon** | ✅ 通过 `spectrum-ts` | ✅ gRPC 消息流 | 单进程,无需 bridge;操作通过 https 载体传输 | ## 🚫 OpenPigeon *不*做什么 ## 工作原理 完整的逆向工程协议 —— 气泡身份标识、基于长度种子的 anagram 密码、state envelope、回合规则 —— 详见 [docs/PROTOCOL.md](docs/PROTOCOL.md)。 ## 添加游戏 在 [`src/games/`](src/games) 中添加一个文件。复制 [`pool.ts`](src/games/pool.ts):导出 `parse(replay, env) → state`、`build(state, env) → replay` 和 `register({...})`。 ## 开发 ``` npm test # codecs (byte-exact vs real captures) + receive paths node examples/quickstart.ts npm run build # tsc → dist/ ``` Node ≥ 22(通过 type-stripping 直接运行 `.ts`;使用 tsc 5.7+ 构建)。 ## 许可证 **MIT** — © 2026 **time-attack**。详情见 [LICENSE](LICENSE)。 你可以自由在自己项目中使用、修改和重新分发 OpenPigeon, **包括商业用途 —— 但你必须保留版权和许可声明** (即,必须标明原作者)。MIT 许可证要求上述声明必须 包含在软件的所有副本或大部分内容中。 “GamePigeon” 是其所有者的商标;本项目不附属于他们,也未获得他们的认可。
标签:API, iMessage, MITM代理, Python工具, TypeScript, 云资产清单, 安全插件, 暗色界面, 游戏开发, 网络通信协议, 自动化攻击, 逆向工程