NiceDayZc/OkLine
GitHub: NiceDayZc/OkLine
一个非官方的 LINE Chrome 消息 API Python 客户端,通过完整复现官方扩展协议与签名机制,解决从 Python 自动化操作 LINE 账户的问题。
Stars: 1 | Forks: 0
# OkLine — LINE Chrome messaging API 的 Python 客户端 / SDK
[](https://github.com/NiceDayZc/OkLine/actions/workflows/ci.yml)
[](https://www.python.org/)
[](LICENSE)
[](tests/)
[](docs/ENDPOINTS.md)
[](docs/contributing.md)
**OkLine** 是一个非官方的高级 **LINE Python 客户端 / SDK**,它
完整复现了官方 **LINE Chrome 扩展程序**
(`CHROMEOS` 3.7.2) 的**每一个** endpoint。你可以用它**从 Python 中发送和接收 LINE 消息**,
通过**二维码或电子邮件**登录,并自动化操作你自己的账户——逐字节完美复现真实
协议(包括网关、headers、payloads、通过 LINE 真实的 `ltsm.wasm` 实现的强制性
`X-Hmac` 签名、登录加密、SSE 事件流以及 OBS 媒体),并**记录每一次响应**,方便你直接复制粘贴。
`import okline` · `from okline import OkLine`
**核心亮点**
- ✅ 全部 77 个 Thrift endpoint,支持类型提示;也支持通用化调用其中的任何一个。
- ✅ 自动处理强制性的 `X-Hmac` 签名(运行真实的 WASM)。
- ✅ 支持电子邮件 (RSA) **及** 二维码登录 —— 二维码会在你的终端中以 ASCII 形式渲染。
- ✅ **完整的响应记录** —— 可以复制每一个 endpoint 的响应。
- ✅ 提供一个 CLI (`python -m okline …`) 以便从 shell 中调用任何 endpoint。
## ⚠️ 法律 / 免责声明
本项目仅用于**互操作性、研究及操作你自己的账户**。使用
它必须遵守 LINE 的服务条款。请勿用于发送垃圾信息、抓取
他人数据或任何滥用行为。你需要对自己的使用方式负责。
## 安装
```
pip install -r requirements.txt # requests + cryptography
# 可选: pip install qrcode # 用于渲染 QR 登录码
```
需要 Python 3.9+。**Node.js 18+ 也必须配置在你的 PATH 中** —— 因为计算
强制性的 `X-Hmac` 请求签名(见下文)需要用到它。
## ⭐ X-Hmac 请求签名(必需)
网关会拒绝任何缺少有效 **`X-Hmac`** header 的请求
(`REQUEST_INVALID_HMAC`,错误码 10005)。该签名由 LINE 的
安全 WASM 模块 (`ltsm.wasm`) 生成,因此本库内置了真实的模块,并
通过一个微型的持久化 **Node.js bridge** 运行它,像扩展程序一样为每个请求进行签名:
```
X-Hmac = base64( Hmac( deriveKey( SHA256("3.7.2"), SHA256(accessToken) ) )
.digest(path + body) )
```
只要 `node` 在你的 PATH 中,它就能“直接运行”——该 bridge 会在
第一次请求时延迟启动,并会被后续重复使用。配置:
```
from okline import OkLine, LineConfig
api = OkLine(config=LineConfig(
node_path="node", # or an absolute path; env LINE_NODE also works
enable_hmac=True, # set False only for offline/mocked tests
))
```
内置的 `ltsm.wasm` + token 是特定于此扩展版本的
(`chrome-extension://ophjlpahpchlmihnnnihgmmeilfjmjjc`, v3.7.2)。如果你替换了
不同版本的构建产物,请使用 `LineConfig(ltsm_origin=...)` 或环境变量 `LTSM_ORIGIN` 覆盖
origin。
## 协议工作原理
| 层级 | 详情 |
|-------|--------|
| **网关** | `https://line-chrome-gw.line-apps.com` |
| **RPC 形式** | `POST /api/talk/thrift///` |
| **Body** | 一个由位置 Thrift 参数组成的 JSON **数组**;结构体参数是带有**命名** (camelCase) 字段的普通 JSON 对象 |
| **Auth header** | `X-Line-Access: ` |
| **App header** | `X-Line-Application: CHROMEOS\t3.7.2\tChrome_OS\t` |
| **Version header** | `X-Line-Chrome-Version: 3.7.2` |
| **Signature** | 每个请求都带有 `X-Hmac: ` (由 `ltsm.wasm` 计算,见上文) |
| **Locale** | `X-LAL: en_US` + `Accept-Language: en-US` |
| **接收** | SSE `GET /api/operation/receive` (+ 长轮询 `/api/talk/long-polling/LF1`,`/JQ`) |
| **Token 刷新** | `POST /api/auth/tokenRefresh` `{refreshToken}` |
| **媒体** | OBS `obs.line-apps.com` + 网关 `/api/obs/*` |
示例 —— `sendMessage(reqSeq, Message)` 变为:
```
POST /api/talk/thrift/Talk/TalkService/sendMessage
X-Line-Access:
X-Line-Application: CHROMEOS 3.7.2 Chrome_OS
content-type: application/json
[1, {"to":"u...","toType":0,"text":"hi","contentType":0,"contentMetadata":{},"sessionId":0}]
```
包含所有 77 个 endpoint 及其参数字段和示例 payload 的完整生成列表位于
**[`docs/ENDPOINTS.md`](docs/ENDPOINTS.md)**。
## 快速开始
```
from okline import OkLine, enums
# A) 复用现有的 access token (例如: 从运行中的 extension 中捕获的)
api = OkLine(access_token="...", refresh_token="...")
print(api.get_profile())
api.send_text("u0123456789abcdef0123456789abcdef", "hello from python")
# B) 使用 e-mail + password 登录 (RSA flow, 与 extension 完全一致)
api = OkLine()
res = api.auth.email_login("me@example.com", "secret", with_e2ee=False)
if res.success:
api.send_text("u....", "hi!")
# C) 使用手机扫描 QR code 登录
api = OkLine()
api.auth.qr_login(on_qr=print, on_pin=lambda pin: print("PIN:", pin))
```
## 身份验证
共有三种高度还原的流程,均位于 `api.auth` 下(参见 [`auth.py`](okline/auth.py)):
### 电子邮件 + 密码 (RSA)
```
res = api.auth.email_login(email, password, with_e2ee=True)
# 内部: getRSAKeyInfo -> RSA/PKCS1v1.5 encrypt
# chr(len(sessionKey))+sessionKey+chr(len(email))+email+chr(len(pw))+pw
# -> loginV2(LoginRequest{identifier=keynm, password=, ...})
```
### 二维码(辅助设备登录)
```
from okline.qrterm import print_qr
api.auth.qr_login(on_qr=lambda url: print_qr(url), # renders an ASCII QR in the terminal
on_pin=lambda pin: print("PIN:", pin))
# createSession -> createQrCode -> curveKeyGenerate (在 WASM 中)
# -> 显示 QR (callbackUrl + ?secret=&e2eeVersion=1)
# -> checkQrCodeVerified (long-poll) -> verifyCertificate / PIN flow
# -> qrCodeLoginV2 (签发 token) -> 尽力而为的 E2EE keychain unwrap
```
`?secret=…&e2eeVersion=1` 是**强制必需的** —— 如果缺少它,LINE App 在
扫码后会立即显示“发生错误”。本库会在真实的 `ltsm.wasm` 内部生成
Curve25519 密钥(通过与 `X-Hmac` 相同的 Node bridge),并自动将其追加到后面,因此你只需渲染 `on_qr` 提供给你的 URL 即可。
### Token 刷新(自动)
如果你提供了 `refresh_token`,当遇到 `401` 错误时会自动触发
`POST /api/auth/tokenRefresh`,并重试该请求。
## 发送消息
```
api.send_text(to, "plain text")
api.reply_text(to, "a reply", related_message_id="140000...")
api.send_sticker(to, package_id="11537", sticker_id="52002734")
api.send_location(to, 35.6586, 139.7454, title="Tokyo Tower")
api.send_contact(to, contact_mid="u....")
api.send_flex(to, "alt text", {"type": "bubble", ...})
# 底层: 自行构建任何 Message
from okline import Message
api.send_message(Message.text(to, "hi", content_metadata={"AGENT_NAME": "bot"}))
# reactions, unsend, read receipts
api.react("140000...", enums.PredefinedReactionType.LOVE)
api.cancel_reaction("140000...")
api.unsend_message("140000...")
api.send_chat_checked(chat_mid, last_message_id="140000...") # mark read
```
`to` 可以是用户 (`u…`)、房间 (`r…`) 或群组/聊天 (`c…`) 的 mid —— 消息
构建器会自动检测 `toType`。
## 接收消息
```
for op in api.ops.iter_operations(): # SSE stream, auto-reconnect
if op.type == enums.OpType.RECEIVE_MESSAGE and op.message:
print(op.message["from"], op.message.get("text"))
```
或者通过 `api.ops.stream()` 获取原始的 SSE 事件(`ping`、`fullSync` 等)。
## 记录 —— 复制每个 endpoint 的响应
记录功能**默认开启**。每个请求/响应都会被完整捕获
(包括方法、URL、所有 headers、body、状态码、耗时),并保存为一个 `Exchange`:
```
api = OkLine(access_token="...") # record=True, redact=True by default
api.get_profile()
api.send_text("u...", "hi")
print(api.last.pretty()) # the most recent call, as an HTTP transcript
print(api.dump()) # every call this session
api.history # list[Exchange]
api.recorder.find("Talk.TalkService.getProfile") # filter by endpoint
# 导出
api.save_log("session.txt") # plain transcript
api.save_log("session.har", fmt="har") # open in browser devtools
api.save_log("session.json", fmt="json")
# secrets (token / X-Hmac / passwords) 默认会被遮蔽 — 通过以下方式显示:
print(api.last.pretty(redact=False))
api = OkLine(access_token="...", redact=False)
# 对每次 call 实时 react:
@api.on_exchange
def _(ex):
print(ex.seq, ex.endpoint, ex.status, f"{ex.duration_ms:.0f}ms")
```
使用 `OkLine(record=False)` 可禁用此功能。设置 `LINE_DEBUG=1` 还会将原始的 body
输出到 stderr 中。
## CLI
直接从 shell 调用任何 endpoint 并复制其响应:
```
python -m okline endpoints # list every endpoint key (optionally grep)
python -m okline version
# call 任何 endpoint (参数 = 作为 JSON array 的 positional thrift args)
python -m okline call Talk.TalkService.getProfile "[2]" --token "$TOKEN"
python -m okline call Talk.TalkService.sendMessage \
'[0,{"to":"u...","text":"hi","contentType":0,"contentMetadata":{}}]' --token "$TOKEN"
python -m okline call LoginQrCode.SecondaryQrCodeLoginService.createSession "[{}]" --no-auth --raw
# 通过扫描终端 QR 登录, 然后保存 tokens
python -m okline qr-login --save tokens.json
python -m okline profile --token "$TOKEN" --raw # --raw prints the full transcript
```
`--raw` 会打印完整的 HTTP 记录;`--show-secrets` 会显示未被掩盖的 token。Token
来源于 `--token`/`--refresh` 或 `LINE_ACCESS_TOKEN`/`LINE_REFRESH_TOKEN`。
## 完整方法映射表
每个 endpoint 都在 `OkLine` 上有一个带类型提示的方法(并且可以通过
`api.call("Namespace.Service.method", *args)` 进行通用调用)。
| 领域 | 方法 |
|------|---------|
| **Auth** | `auth.email_login`, `auth.qr_login`, `auth.refresh_access_token`, `login_v2`, `logout_v2`, `confirm_e2ee_login`, `get_rsa_key_info`, `get_encrypted_identity_v3`, `acquire_encrypted_access_token` |
| **Messaging** | `send_message`/`send_text`/`send_sticker`/`send_location`/`send_contact`/`send_flex`/`reply_text`, `unsend_message`, `send_postback`, `react`, `cancel_reaction`, `send_chat_checked`, `send_chat_removed`, `set_chat_hidden_status`, `get_recent_messages`, `get_previous_messages`, `get_messages_by_ids`, `get_message_boxes`, `get_message_boxes_by_ids`, `get_message_read_range`, `determine_media_message_flow`, `get_last_op_revision` |
| **Contacts** | `get_all_contact_ids`, `get_contacts`, `find_contact_by_userid`, `find_contacts_by_phone`, `find_and_add_contacts_by_mid`, `block_contact`, `unblock_contact`, `get_blocked_contact_ids`, `update_contact_setting`, `set_favorite`, `hide_contact`, `get_favorite_mids`, `get_recommendation_ids`, `get_blocked_recommendation_ids`, `block_recommendation`, `add_friend_by_mid`, `get_target_profile_notice`, `get_buddy_detail` |
| **Chats / Groups / Rooms** | `create_chat`/`create_group`, `update_chat`, `rename_chat`, `set_chat_favorite`, `invite_into_chat`, `kick_from_chat`, `cancel_chat_invitation`, `leave_chat`, `accept_chat_invitation`, `reject_chat_invitation`, `get_all_chat_mids`, `get_chats`, `invite_into_room`, `leave_room`, `get_rooms` |
| **Profile / Settings** | `get_profile`, `update_profile_attributes`, `set_display_name`, `set_status_message`, `get_settings`, `get_settings_attributes2`, `update_settings_attributes2`, `get_configurations`, `get_server_time`, `report_abuse` |
| **E2EE keys** | `get_e2ee_public_key`, `negotiate_e2ee_public_key`, `get_e2ee_public_keys_ex`, `get_last_e2ee_public_keys`, `register_e2ee_group_key`, `get_e2ee_group_shared_key`, `get_last_e2ee_group_shared_key` |
| **Channel / Shop / OBS** | `issue_channel_token`, `get_owned_product_summaries`, `iter_owned_products`, `preview_customized_image_text`, `set_customized_image_text`, `obs.upload_profile_image`, `obs.upload_object`, `obs.download_object`, `obs.copy_for_message` |
## 包结构
```
okline/
client.py OkLine facade (transport + auth + ops + obs + recorder + services)
transport.py HTTP engine: headers, X-Hmac, JSON encode/decode, errors, recording
hmac_signer.py LtsmBridge — manages the Node bridge (X-Hmac + Curve25519/E2EE)
ltsm/ ltsm.wasm + ltsmSandbox.js + ltsm_bridge.js (LINE's real module)
auth.py email / QR / token-refresh login flows
crypto.py RSA/PKCS1v1.5 login credential encryption
operations.py SSE + long-poll operation receiver
obs.py object storage (media) upload/download
recorder.py Exchange + Recorder (capture/redact/pretty/HAR/JSON)
qrterm.py render a QR as ASCII/Unicode in the terminal
enums.py all enums (OpType, ContentType, ErrorCode, ...) — extracted verbatim
models.py Message builders (text/sticker/location/contact/flex)
endpoints.py complete endpoint registry (all 77 paths)
exceptions.py OkLine error hierarchy
services/ one typed method per endpoint, grouped by area
__main__.py the `python -m okline` CLI
selftest.py live read-only self-test of every endpoint
docs/ full documentation (see below)
example.py runnable examples
tests/ 392 offline tests (conftest fixtures + per-module files)
```
## 📚 文档
| 页面 | 内容 |
|------|---------------|
| [入门指南](docs/getting-started.md) | 安装、你的第一次调用、`OkLine` 对象 |
| [身份验证](docs/authentication.md) | token 复用、电子邮件 (RSA)、二维码登录、刷新、登出 |
| [发送消息](docs/messaging.md) | 文本、贴图、位置、联系人、flex、回应 |
| [接收事件](docs/receiving-events.md) | SSE 流、一个回声机器人 |
| [记录](docs/recording.md) | 捕获、粘贴、脱敏并导出每一次响应 |
| [CLI](docs/cli.md) | `python -m okline` —— 调用任何 endpoint,`selftest`,`qr-login` |
| [架构](docs/architecture.md) | 协议、`X-Hmac`、模块映射 |
| [故障排除](docs/troubleshooting.md) | 常见错误与修复 (FAQ) |
| [贡献指南](docs/contributing.md) | 开发设置、测试、添加 endpoint |
| [Endpoint 参考](docs/ENDPOINTS.md) | 包含参数字段的每一个 endpoint |
## 测试
```
python -m pytest -q # 392 offline tests, no network/Node needed
```
## 关于保真度的说明
- 枚举值、endpoint 路径、header 字符串以及 RSA 登录格式均**逐字**
提取自扩展程序包。
- 每个方法的参数*顺序*与网络传输格式保持一致(已通过调用点验证)。
- E2EE(Letter Sealing)密钥的 **endpoint** 已实现;执行实际的
Curve25519 ECDH + AES 消息加密由调用者自行完成(密钥结构体将
以原始形式返回)。非 E2EE 消息传递可直接开箱即用。
- 当你不传入 `reqSeq` 时,它将自动生成(单调递增)。
## 发布至 GitHub
创建仓库后,请设置一个富含关键字的**描述**和**主题**(这是
影响 GitHub 搜索结果的两个最重要因素),并替换徽章和
`pyproject.toml` URL 中的 `NiceDayZc`:
```
gh repo create OkLine --public --source . --remote origin --push \
--description "Unofficial Python client/SDK for the LINE Chrome messaging API — send/receive LINE messages, QR & e-mail login, X-Hmac signing, full response recording."
# Topics (GitHub 最多允许 20 个) — 它们影响可发现性:
gh repo edit --add-topic line,line-api,line-bot,line-messaging-api,line-chrome \
--add-topic python,python-line,line-sdk,line-client,unofficial \
--add-topic messaging,chatbot,automation,reverse-engineering,chrome-extension
```
推荐的**主题**:`line` · `line-api` · `line-bot` · `line-messaging-api`
· `line-chrome` · `python` · `python-line` · `line-sdk` · `line-client` ·
`unofficial` · `messaging` · `chatbot` · `automation` · `reverse-engineering` ·
`chrome-extension`。
## 免责声明
OkLine 是一个**非官方、独立**的项目,**不隶属于
LINE Corporation,也未获得其认可或赞助**。“LINE”是其
各自所有者的商标。请仅在遵守
LINE [服务条款](https://terms.line.me/line_terms) 的前提下使用**你自己的账户**。你需对
你的使用方式负责。有关凭证的处理,请参阅 [SECURITY.md](SECURITY.md)。
## 许可证
[MIT](LICENSE) © OkLine 贡献者。
标签:MITM代理, Python, 即时通讯, 无后门, 网络调试, 自动化, 逆向工具