Line Client

通过 Chrome 扩展网关集成 LINE 消息功能,支持收发消息、管理联系人与群组。

已扫描
适合谁
需要自动化处理 LINE 消息的开发者、希望集成 LINE 通信能力的企业用户
不适合谁
普通个人用户日常使用、无网络环境或无法访问 LINE 服务的用户
国内可用性
需网络配置。可能需要网络配置或第三方服务可访问。
安装难度
新手友好(★☆☆)。基于终端操作、依赖、API Key 和本地环境要求的初步判断。

安装与下载

openclaw skills install @2manslkh/line-api

Skill 说明

命令、参数、文件名以原文为准

LINE 客户端技能

通过 Chrome 扩展网关 JSON API 实现的完整 LINE 消息客户端。

仓库与文件

  • 仓库: /data/workspace/line-client ([github.com/2manslkh/line-api](https://github.com/2manslkh/line-api))
  • 主客户端: src/chrome_client.pyLineChromeClient
  • 二维码登录: src/auth/qr_login.pyQRLogin
  • HMAC 签名器: src/hmac/signer.js (Node.js,自动在端口 18944 启动)
  • 令牌存储: ~/.line-client/tokens.json
  • 证书缓存: ~/.line-client/sqr_cert
  • WASM 文件: lstm.wasm + lstmSandbox.js(必需,位于仓库根目录)

快速开始

import json
from pathlib import Path
from src.chrome_client import LineChromeClient

tokens = json.loads((Path.home() / ".line-client" / "tokens.json").read_text())
client = LineChromeClient(auth_token=tokens["auth_token"])

# 发送消息
client.send_message("U...", "Hello!")

# 获取个人资料
profile = client.get_profile()

令牌有效期约为 7 天。若过期(返回 APIError(10051)),需重新执行二维码登录。

二维码登录(认证)

二维码登录需要用户交互:在手机上扫描二维码并输入验证码。

from src.hmac import HmacSigner
from src.auth.qr_login import QRLogin
import qrcode

signer = HmacSigner(mode="server")
login = QRLogin(signer)
result = login.run(
    on_qr=lambda url: send_qr_image_to_user(qrcode.make(url)),
    on_pin=lambda pin: send_pin_to_user_IMMEDIATELY(pin),  # 极其敏感!
    on_status=lambda msg: print(msg),
)
# result.auth_token, result.mid, result.refresh_token

重要提示: 验证码必须在约 60 秒内送达用户。一旦触发 on_pin,应立即发送。

二维码登录状态机

  1. createSession → 生成会话 ID
  2. createQrCode → 返回回调 URL(附加 ?secret={curve25519_pubkey}&e2eeVersion=1
  3. checkQrCodeVerified — 轮询直到被扫描(使用 X-Line-Session-ID,不带 origin 头)
  4. **verifyCertificate** — 即使失败也必须调用(状态转移必需)
  5. createPinCode → 生成 6 位数字验证码(若步骤 4 已验证证书则跳过)
  6. checkPinCodeVerified — 轮询直到用户输入验证码
  7. qrCodeLoginV2 → 返回 JWT 令牌、证书和刷新令牌

服务端登录脚本

python scripts/qr_login_server.py /tmp/qr.png

向标准输出输出 JSON 事件:{"event": "qr", "path": "...", "url": "..."}{"event": "pin", "pin": "123456"}{"event": "done", "mid": "U..."}

所有 API 方法

联系人与好友

方法参数描述
get_profile()获取自己的个人资料(displayName、mid、statusMessage 等)
get_contact(mid)mid: str获取单个联系人的资料
get_contacts(mids)mids: list[str]获取多个联系人资料
get_all_contact_ids()列出所有好友 MID
find_contact_by_userid(userid)userid: str通过 LINE ID 搜索联系人
find_and_add_contact_by_mid(mid)mid: str通过 MID 添加好友
find_contacts_by_phone(phones)phones: list[str]通过手机号搜索联系人
add_friend_by_mid(mid)mid: str添加好友(使用 RelationService 接口)
get_blocked_contact_ids()列出被屏蔽的 MID
get_blocked_recommendation_ids()列出被屏蔽的好友推荐
block_contact(mid)mid: str屏蔽某个联系人
unblock_contact(mid)mid: str取消屏蔽联系人
block_recommendation(mid)mid: str屏蔽某条好友推荐
update_contact_setting(mid, flag, value)mid, flag: int, value: str更新联系人设置(例如静音)
get_favorite_mids()列出收藏的好友 MID
get_recommendation_ids()列出好友推荐列表

消息

方法参数描述
send_message(to, text, ...)to: str, text: str, reply_to: str(可选)发送文本消息。支持通过 reply_to=message_id 回复
unsend_message(message_id)message_id: str取消发送/删除已发送的消息
get_recent_messages(chat_id, count=50)chat_id: str获取指定聊天中的最新消息
get_previous_messages(chat_id, end_seq, count=50)chat_id, end_seq: int分页获取历史消息(更早的消息)
get_messages_by_ids(message_ids)message_ids: list[str]获取指定消息
get_message_boxes(count=50)获取聊天列表及最后一条消息(收件箱视图)
get_message_boxes_by_ids(chat_ids)chat_ids: list[str]获取指定聊天及其最后一条消息
get_message_read_range(chat_ids)chat_ids: list[str]获取已读回执信息
send_chat_checked(chat_id, last_message_id)chat_id, last_message_id: str标记消息为已读
send_chat_removed(chat_id, last_message_id)chat_id, last_message_id: str从收件箱移除聊天
send_postback(to, postback_data)to, postback_data: str发送事件回传(用于机器人交互)

聊天与群组

# Skill: Line Client
Version: 0.2.1
Chunk: 2/2

## 方法

| 方法 | 参数 | 描述 |
|------|------|------|
| `get_chats(chat_ids, with_members=True, with_invitees=True)` | chat_ids: list[str] | 获取聊天/群组详情 |
| `get_all_chat_mids()` | — | 列出所有聊天 MID(群组 + 邀请) |
| `create_chat(name, target_mids)` | name: str, target_mids: list[str] | 创建新群组聊天 |
| `accept_chat_invitation(chat_id)` | chat_id: str | 接受群组邀请 |
| `reject_chat_invitation(chat_id)` | chat_id: str | 拒绝群组邀请 |
| `invite_into_chat(chat_id, mids)` | chat_id: str, mids: list[str] | 将用户邀请至群组 |
| `cancel_chat_invitation(chat_id, mids)` | chat_id: str, mids: list[str] | 取消待发送的邀请 |
| `delete_other_from_chat(chat_id, mids)` | chat_id: str, mids: list[str] | 将成员移出群组 |
| `leave_chat(chat_id)` | chat_id: str | 退出群组聊天 |
| `update_chat(chat_id, updates)` | chat_id: str, updates: dict | 更新群组名称/设置 |
| `set_chat_hidden_status(chat_id, hidden)` | chat_id: str, hidden: bool | 归档/取消归档聊天 |
| `get_rooms(room_ids)` | room_ids: list[str] | 获取旧版房间信息 |
| `invite_into_room(room_id, mids)` | room_id: str, mids: list[str] | 邀请用户加入旧版房间 |
| `leave_room(room_id)` | room_id: str | 退出旧版房间 |

## 回复(表情)

| 方法 | 参数 | 描述 |
|------|------|------|
| `react(message_id, reaction_type)` | message_id: str, type: int | 对消息进行回复。类型:2=点赞,3=爱心,4=大笑,5=惊讶,6=难过,7=生气 |
| `cancel_reaction(message_id)` | message_id: str | 移除你的回复 |

## 个人资料与设置

| 方法 | 参数 | 描述 |
|------|------|------|
| `update_profile_attributes(attr, value, meta={})` | attr: int, value: str | 更新个人资料。属性:2=显示名称,16=状态消息,4=头像状态 |
| `update_status_message(message)` | message: str | 快捷方式:更新状态消息 |
| `update_display_name(name)` | name: str | 快捷方式:更新显示名称 |
| `get_settings()` | — | 获取全部账户设置 |
| `get_settings_attributes(attr_bitset)` | attr_bitset: int | 获取特定设置 |
| `update_settings_attributes(attr_bitset, settings)` | attr_bitset: int, settings: dict | 更新设置 |

## 轮询与事件

| 方法 | 参数 | 描述 |
|------|------|------|
| `get_last_op_revision()` | — | 获取最新的操作版本号 |
| `fetch_ops(count=50)` | — | 获取待处理的操作(可能长时间轮询) |
| `poll()` | — | 生成器,实时接收操作数据 |
| `on_message(handler)` | handler: Callable(msg, client) | 启动轮询线程,在收到新消息时调用 handler。操作类型:26=发送消息,27=接收消息 |
| `stop()` | — | 停止轮询线程 |

## 其他服务

| 方法 | 参数 | 描述 |
|------|------|------|
| `get_server_time()` | — | 获取 LINE 服务器时间戳 |
| `get_configurations()` | — | 获取服务器配置 |
| `get_rsa_key_info()` | — | 获取用于认证的 RSA 密钥信息 |
| `issue_channel_token(channel_id)` | channel_id: str | 发行频道令牌(用于 LINE Login / LIFF) |
| `get_buddy_detail(mid)` | mid: str | 获取官方账号信息 |
| `report_abuse(mid, category=0, reason="")` | mid: str | 举报用户 |
| `add_friend_by_mid(mid)` | mid: str | 添加好友(通过 RelationService) |
| `logout()` | — | 退出登录并失效令牌 |

## MID 格式

LINE 使用 MID 来标识实体:
- `U...` 或 `u...` → 用户(toType=0)
- `C...` 或 `c...` → 群组聊天(toType=2)
- `R...` 或 `r...` → 房间(toType=1)

客户端在发送消息时会自动根据 MID 前缀识别 `toType`。

## HMAC 签名

所有 API 请求都需要 `X-Hmac` 头部。WASM 签名器会自动处理:
- 使用版本号 "3.7.1" 和访问令牌,通过专有 KDF(在 lstm.wasm 中实现)推导密钥
- 对 `path + body` 进行签名,结果转为 base64 编码,作为 `X-Hmac` 值
- 服务端模式:约 13ms/次签名(Node.js HTTP 服务器运行于端口 18944,自动启动)
- 子进程模式:约 2s/次签名(备用方案)

## 错误处理

from src.chrome_client import APIError

try:

client.send_message(mid, "test")

except APIError as e:

print(e.code, e.api_message)

# 10051 = 会话已过期或无效

# 10052 = 后端 HTTP 错误

# 10102 = 参数无效

## 架构

用户的手机(LINE 应用)

↕ (扫描二维码 / 输入 PIN)

LINE 服务器(line-chrome-gw.line-apps.com)

↕ (JSON REST + X-Hmac 签名)

LineChromeClient(本项目)

↕ (通过 Node.js 签名器使用 WASM HMAC)

lstm.wasm + lstmSandbox.js

Chrome 网关内部负责 JSON ↔ Thrift 的转换。我们无需直接处理 Thrift 二进制数据——所有交互均为干净的 JSON 格式。
2
@2manslkh

已收录 1 个 Skill

相关推荐