# napcat-sdk

> 一个面向 NapCat/OneBot 协议的 Python SDK，主打完整类型覆盖、原生异步与零框架约束。

## 核心设计哲学

### 配置与执行分离
实例化 `NapCatClient` 只是创建配置蓝本，不建立连接。真正的连接在进入上下文或迭代时懒加载建立。

### 生命周期自动管理
- `async with client:` → 进入时自动连接，退出时自动断开
- `async for event in client:` → 自动连接 → 接收事件流 → 迭代结束自动断开

### 强类型优先
- 所有事件都是 dataclass 对象，不是裸 JSON 字典
- 使用 `isinstance` 或 `match case` 进行类型判断和属性解构
- 160+ API 都有完整的 TypedDict 类型定义

### 动态兜底
如果服务端新增了 SDK 尚未适配的 API，可通过 `client.new_feature()` 动态调用，SDK 会自动转换为标准请求。

## 运行模式

### Client 模式（主动连接）
程序作为客户端主动连接 NapCat：

```python
from napcat import NapCatClient, GroupMessageEvent

async with NapCatClient(ws_url="ws://127.0.0.1:3000", token="xxx") as client:
    async for event in client:
        if isinstance(event, GroupMessageEvent):
            await event.reply("收到！")
```

### Server 模式（反向连接）
程序作为服务端，等待 NapCat 主动连接：

```python
from napcat import ReverseWebSocketServer, NapCatClient, GroupMessageEvent

async def handler(client: NapCatClient):
    async for event in client:
        if isinstance(event, GroupMessageEvent):
            await event.reply("收到！")

server = ReverseWebSocketServer(handler, port=8080, token="xxx")
await server.run_forever()
```

**注意**：不要在 handler 内部写 `while True` 保活，连接断开后让 handler 自然退出，等待重连。

### RPC 模式（跨进程）
Event 支持序列化，可跨进程消费：

```python
# 进程 A：接收并序列化
data = event.to_dict()
# 通过消息队列传输...

# 进程 B：反序列化并处理
event = NapCatEvent.from_dict(data, client=client)
await event.reply("来自远端的回复")
```

## 事件处理

### 事件层级
```
NapCatEvent
├── MessageEvent → GroupMessageEvent, PrivateMessageEvent
├── NoticeEvent → PokeEvent, GroupBanEvent, ...
├── RequestEvent → FriendRequestEvent, GroupRequestEvent
└── MetaEvent
```

### 使用 match case 模式匹配（推荐）

```python
from napcat import GroupMessageEvent, PrivateMessageEvent, Text, At, Image

match event:
    # 匹配群消息，解构提取 group_id
    case GroupMessageEvent(group_id=gid, sender=sender):
        print(f"群 {gid} 收到消息")

    # 匹配特定群 + 特定指令
    case GroupMessageEvent(group_id=123456, raw_message="ping"):
        await event.reply("pong")

    # 匹配消息段结构：文本 + @ + 图片
    case GroupMessageEvent(message=[Text(text=t), At(qq=uid), Image(url=url)]):
        print(f"指令: {t}, 目标: {uid}, 图片: {url}")

    # 通配符：消息中包含图片
    case GroupMessageEvent(message=[*_, Image(url=url), *_]):
        print(f"收到图片: {url}")

    case _:
        pass
```

### 消息段类型
常用消息段：`Text`, `At`, `Image`, `Face`, `Record`, `Video`, `Dice`, `Poke`

### ⚠️ 陷阱：变量匹配

```python
# ❌ 错误：Python 会把 target_group 当作新变量赋值
case GroupMessageEvent(group_id=target_group): ...

# ✅ 正确：使用 Guard (if 子句)
case GroupMessageEvent(group_id=gid) if gid == target_group: ...
```

## 发送消息

```python
from napcat import Text, At, Image

# 发送简单文本
await client.send_group_msg(group_id=123, message="Hello")

# 发送混合消息
await client.send_group_msg(
    group_id=123,
    message=[At(qq=456), Text(text=" 来看这个！"), Image(file="https://...")]
)
```

## API 查询

**重要**：API 详细信息请通过 MCP 工具查询：

| 工具 | 用途 |
|------|------|
| `list_apis` | 列出所有可用 API 及其简介 |
| `get_api_details` | 获取指定 API 的参数和返回值结构 |
| `list_code_files` | 列出 SDK 源代码文件路径 |
| `get_code_file` | 读取指定源代码文件 |
| `get_class_definition` | 查找类或函数的定义位置 |
| `get_llms_txt` | 获取本文档内容（核心概念与最佳实践） |

## 常用事件字段速查

### GroupMessageEvent
- `group_id: int` - 群号
- `user_id: int` - 发送者 QQ
- `message: list[MessageSegment]` - 消息段列表
- `raw_message: str` - 纯文本消息
- `sender: MessageSender` - 发送者信息（含 `role`, `nickname`）
- `reply(msg)` - 快捷回复方法

### PrivateMessageEvent
- `user_id: int` - 发送者 QQ
- `message: list[MessageSegment]` - 消息段列表
- `reply(msg)` - 快捷回复方法

### FriendRequestEvent
- `user_id: int` - 申请人 QQ
- `comment: str` - 申请备注
- `approve(remark)` - 同意申请
- `reject()` - 拒绝申请
