# ⚡ Litetower

**QQ Bot SDK powered by Letoderea**

Litetower 是一个基于 [Arclet Letoderea](https://github.com/ArcletProject/Letoderea) 和 [Launart](https://github.com/GraiaProject/Launart) 构建的现代化 QQ 机器人 SDK。它提供了优雅的事件系统、依赖注入、异步 IO 支持以及精美的 Rich 日志输出。

## ✨ 特性

- **现代化事件系统**: 基于 Letoderea 的高性能事件分发与依赖注入 (DI)。
- **生命周期管理**: 使用 Launart 管理服务启动、运行与关闭。
- **全异步设计**: 基于 `httpx` 和 `uvicorn` 的全异步架构。
- **类型安全**: 全面的类型注解，通过 pyright 严格模式检查。
- **Rich 日志**: 内置精美的彩色日志输出与启动横幅。
- **OpenAPI 封装**: 完整的 QQ 开放平台 API 封装，支持自动 Token 刷新。

## 📦 安装

需 Python 3.9+。

```bash
uv sync --frozen
# 或直接安装
pip install .
```

## 🚀 快速开始

### 1. 配置

创建 `main.py`：

```python
import arclet.letoderea as leto
from launart import Launart
from litetower import Litetower, GroupMessage, Content, Target

# 创建 Launart 管理器
mgr = Launart()

# 初始化机器人
bot = Litetower(
    appid="YOUR_APPID",
    clientSecret="YOUR_SECRET",
    mgr=mgr,
    sand_box=True,  # 是否使用沙箱环境
)

# 注册事件处理器
@leto.on(GroupMessage)
async def on_group_message(app: Litetower, content: Content, target: Target):
    """
    参数说明：
    - app: 自动注入 Litetower 实例
    - content: 消息内容
    - target: 发送目标
    """
    print(f"收到群消息: {content.content}")
    
    # 发送回复
    await app.send_group_message(target, f"你好！你说了: {content.content}")

# 启动
if __name__ == "__main__":
    bot.launch_blocking()
```

### 2. 运行

```bash
python main.py
```

您将看到精美的启动横幅与日志：

```
╭───────────────────────────────────╮
│     ⚡ Litetower  QQ Bot SDK      │
│     powered by Letoderea          │
╰───────────────────────────────────╯
[INFO] Litetower 启动中 [appid=xxx]
[INFO] HTTP 客户端已启动
[INFO] 认证成功，token 有效期: 7200s
[INFO] QQAPI 客户端初始化完成
[INFO] 应用就绪事件已发布
```

## 📚 核心概念

### 事件系统

Litetower 使用 `@make_event` 定义事件，支持自动解析与依赖注入。

**内置事件**:
- `GroupMessage` / `C2CMessage`: 消息事件
- `DirectMessage` / `ChannelMessage`: 频道消息
- `ApplicationReady`: 应用启动完成
- `FriendAdd` / `GroupAddRobot`: 机器人关系变更

### 依赖注入

事件处理函数的参数由 Letoderea 自动注入。常用类型：

- `Litetower`: 机器人实例
- `Target`: 发送目标（自动封装 ID）
- `Content`: 消息内容
- `Author` / `Member` / `Group`: 发送者与来源信息

### 异常处理

API 调用失败会抛出 `OpenAPIError` 异常：

```python
from litetower import OpenAPIError

try:
    await app.send_group_message(...)
except OpenAPIError as e:
    logger.error(f"发送失败: {e.code} - {e.message}")
```

## 🧩 Beacon 模块化系统

Litetower 内置了名为 **Beacon** (原 Graia/Saya) 的模块化系统，提供插件管理与事件分发。

### 1. 启用 Beacon (推荐)

```python
from litetower.beacon import Beacon

# 在 bot 初始化后
beacon = Beacon(bot)
# 加载插件目录
beacon.load_all("plugins")
```

### 2. 编写插件

使用 `listen` 监听事件，配合 `propagator` (传播器) 和 `provider` (提供者) 进行过滤与参数注入。

```python
from litetower.beacon import listen, propagator, provider
from litetower.events.message import GroupMessage
from litetower.message.parser.base import DetectPrefix
from litetower.message.parser.msgsaw import MessageSaw, QSubResult

# 定义指令解析器
saw_echo = MessageSaw("/echo")

@listen(GroupMessage)
@provider(DetectPrefix("!"))  # 1. 过滤：仅处理以 "!" 开头的消息
@provider(saw_echo)           # 2. 解析：匹配 "/echo" 指令
async def on_echo(event: GroupMessage, result: QSubResult):
    """
    流程：
    1. DetectPrefix 检测到 "!" 前缀 (如 "!/echo hello")，通过则继续。
    2. MessageSaw 解析 "/echo hello"，注入 result。
    """
    await app.send_group_message(event.target, f"你发送了: {result.args}")
```

**核心装饰器**:

- `@listen(Event)`: 注册监听器到当前频道 (Channel)。
- `@propagator(Propagator)`: 挂载 Letoderea 传播器 (如 Aux 等)。
- `@provider(Source)`: 挂载依赖提供者。
  - **DetectPrefix("!")**: 既是过滤器 (不匹配则停止)，也是提供者 (提供去除前缀后的内容)。
  - **MessageSaw("/cmd")**: 专业的指令解析器，提供解析结果 `QSubResult`。

## 📄 许可证

MIT License
