# getbiji_box

Get 笔记 (GetBiji) 非官方 Python SDK，支持笔记管理、知识库操作、AI 生成内容（音频/链接笔记）等功能。

## 功能特性

- **笔记管理** — 创建、编辑、列表、获取笔记
  - 纯文本笔记（手动创建）
  - 链接笔记（AI 从 URL 生成，支持 SSE 流式）
  - 音频笔记（AI 从音频文件生成，支持 SSE 流式）
- **知识库操作** — 创建、浏览、管理知识库及其资源
  - 目录与文件管理
  - 直播/博主关注列表
  - 精选知识库浏览
- **账户管理** — 用户信息、VIP 状态、配额查询
- **自动 Token 刷新** — 内置 JWT 管理与自动续期
- **类型安全** — 所有 API 响应均使用 dataclass 模型

## 安装

```bash
pip install getbiji_box
```

开发环境安装：

```bash
git clone <repo_url>
cd getbiji_box
pip install -e .[dev]
```

## 环境要求

- Python >= 3.8
- requests >= 2.28.0

## 快速开始

### 获取 Token

1. 在浏览器中登录 [Get 笔记](https://getbiji.com)
2. 打开开发者工具（F12）
3. 在控制台执行：
   ```javascript
   console.log(localStorage.getItem('token'))
   console.log(localStorage.getItem('refresh_token'))
   ```
4. 将获取到的值用于初始化客户端

### 基本用法

```python
from getbiji_box import GetBijiClient

# 初始化客户端
client = GetBijiClient(
    token="your_access_token",
    refresh_token="your_refresh_token",
)

# 获取账户信息
user = client.account.get_info()
print(f"你好, {user.nickname}")

# 创建一条笔记
note = client.notes.create_simple_note(
    content="今天学了 Python",
    tags=["学习", "python"],
)
print(f"已创建笔记: {note.id}")

# 列出笔记
result = client.notes.list_notes(limit=20)
for note in result.list:
    print(f"{note.title}: {note.content[:50]}...")
```

## API 参考

### 账户 API (`client.account`)

```python
# 获取用户信息
user = client.account.get_info()
print(f"昵称: {user.nickname}, VIP: {user.is_vip}")

# 检查 VIP 状态
if client.account.is_vip():
    print("VIP 会员")

# 获取剩余音频配额
quota_ms = client.account.get_remaining_audio_quota()
print(f"剩余: {quota_ms / 1000 / 60:.1f} 分钟")

# 检查是否可以创建知识库
if client.account.can_create_knowledge_bases():
    print("可以创建知识库")
```

### 笔记 API (`client.notes`)

#### 创建笔记

```python
# 创建纯文本笔记
note = client.notes.create_simple_note(
    content="笔记内容",
    title="可选标题",
    tags=["标签1", "标签2"],
)

# 从 URL 创建链接笔记（AI 生成，SSE 流式）
def on_progress(msg_type, data):
    if msg_type == -1:
        print(f"笔记 ID: {data.get('note_id')}")
    elif msg_type == 6:
        print(f"处理中: {data}")

note = client.notes.create_link_note(
    url="https://example.com/article",
    callback=on_progress,
)

# 从音频创建笔记（三步流程：获取 token → 上传 OSS → AI 生成）
note = client.notes.create_audio_note(
    audio_path="/path/to/recording.mp3",
    callback=on_progress,
    topic_id="0",  # 可选：关联到知识库
)
```

#### 查询笔记

```python
# 列出笔记（分页）
result = client.notes.list_notes(limit=20)
for note in result.list:
    print(f"{note.title}: {note.content[:50]}...")

# 翻页
if result.has_more:
    next_page = client.notes.list_notes(limit=20, since_id=result.list[-1].id)

# 获取笔记详情
note = client.notes.get_note("note_id")

# 获取链接笔记的原文
detail = client.notes.get_link_note_content("note_id")
print(f"原始 URL: {detail.url}")
print(f"原始标题: {detail.web_title}")

# 获取音频笔记的章节信息
sections = client.notes.get_audio_note_sections(note)
for section in sections:
    print(f"{section['timestamp']}: {section['title']}")

# 获取笔记总数
count = client.notes.get_notes_count()

# 获取正在生成的笔记数量
generating = client.notes.get_generating_count()
```

#### 编辑笔记

```python
# 编辑笔记（全量替换，需要提供 version 做乐观锁）
note = client.notes.get_note("note_id")
updated = client.notes.edit_note(
    note_id=note.id,
    title="新标题",
    content="新内容",
    json_content='{"type":"doc","content":[]}',
    version=note.version,  # 服务端会 +1
)
print(f"新版本: {updated.version}")
```

#### 知识库内笔记

```python
# 获取知识库内的笔记详情
note = client.notes.get_note_in_topic(topic_id="2732516", note_id="note123")

# 获取音频笔记原始转录文本
transcript = client.notes.get_audio_original(topic_id="2732516", note_id="note123")

# 获取子笔记数量
children = client.notes.get_children_count("note_id")
print(f"子笔记: {children.total}/{children.max_child_note_count}")

# 获取导出选项
options = client.notes.get_export_options()
```

### 知识库 API (`client.knowledge`)

#### 创建与查询

```python
# 创建知识库
kb = client.knowledge.create(
    name="我的学习笔记",
    description="学习资料集合",
)

# 获取我的知识库列表
my_kbs = client.knowledge.list_mine()
for kb in my_kbs:
    print(f"{kb.name}: {kb.note_count} 条笔记")

# 获取知识库详情
kb = client.knowledge.get_detail("id_alias")

# 通过分享链接获取知识库
kb = client.knowledge.get_by_share_url("https://getbiji.com/topic/abc123")
```

#### 订阅与精选

```python
# 我订阅的知识库列表（分页）
result = client.knowledge.list_subscribed(page=1, size=20)
for kb in result.list:
    print(f"{kb.name} by {kb.creator}")

# 精选知识库列表
featured = client.knowledge.list_featured(page=1)

# 管理的知识库列表（自己的 + 订阅的）
managed = client.knowledge.list_managed(page=1, size=50)
```

#### 资源与目录

```python
# 列出知识库资源（笔记 + 文件 + 目录）
result = client.knowledge.list_resources(
    topic_id_alias="BJ8lRyAJ",
    resource_type=2,  # 1=仅文件, 2=全部资源
    page=1,
)

# 浏览目录结构
for d in result.directories:
    print(f"📁 {d.name}")
for r in result.resources:
    print(f"📄 {r.resource_type}: {r.resource_note_meta_data or r.resource_file_meta_data}")

# 翻页
if result.has_next:
    next_page = client.knowledge.list_resources("BJ8lRyAJ", page=2)
```

#### 直播与关注

```python
# 列出知识库的直播列表
lives = client.knowledge.list_follow(
    topic_id_alias="lG0Prnaj",
    follow_type=2,  # 1=博主, 2=直播
    page=1,
)
for item in lives.list:
    print(f"{item.name} ({item.platform})")

# 获取直播笔记详情（AI 摘要）
post = client.knowledge.get_live_stream_detail(
    topic_id_alias="lG0Prnaj",
    post_id="123456",
)
print(f"标题: {post.post_title}")
print(f"摘要:\n{post.post_summary}")

# 获取关注统计
stat = client.knowledge.get_follow_stat()
```

#### 知识库内笔记列表

```python
# 列出知识库内的笔记（通过 notes API 过滤）
result = client.knowledge.list_notes_in_knowledge_base(
    topic_id="35",
    limit=20,
)
for note in result.list:
    print(f"{note.title}")
```

## 异常处理

```python
from getbiji_box import (
    GetBijiError,         # 基类
    AuthenticationError,  # 认证失败
    TokenExpiredError,    # Token 过期
    APIError,             # API 错误（含 code/message）
    UploadError,          # 上传失败
    ValidationError,      # 参数校验失败
    RateLimitError,       # 请求频率限制
    NetworkError,         # 网络错误
)

try:
    note = client.notes.create_simple_note(content="测试")
except ValidationError as e:
    print(f"参数错误: {e}")
except AuthenticationError as e:
    print(f"认证失败: {e}")
except APIError as e:
    print(f"API 错误 {e.code}: {e.message}")
```

## 高级用法

### 自定义 Token 刷新时间

```python
# 提前 10 分钟刷新 Token
client = GetBijiClient(
    token="token",
    refresh_token="refresh_token",
    token_refresh_buffer=600,
)
```

### 禁用自动刷新

```python
client = GetBijiClient(
    token="token",
    refresh_token="refresh_token",
    auto_refresh=False,
)

# 手动刷新
token_info = client.refresh_token()
```

### 上下文管理器

```python
with GetBijiClient(token="token") as client:
    notes = client.notes.list_notes()
# Session 自动关闭
```

## 项目结构

```
getbiji_box/
├── __init__.py           # 包导出
├── client.py             # 主客户端（Facade 模式）
├── auth.py               # 认证与 Token 管理
├── account.py            # 账户 API
├── notes.py              # 笔记 API
├── knowledge.py          # 知识库 API
├── models.py             # 数据模型（dataclass）
├── exceptions.py         # 异常体系
├── stream_parser.py      # SSE 流式解析器
└── utils.py              # 工具函数

tests/
├── test_client.py        # 客户端测试
├── test_auth.py          # 认证测试
├── test_notes.py         # 笔记 API 测试
├── test_knowledge.py     # 知识库 API 测试
└── test_models.py        # 数据模型测试

examples/                 # 使用示例
api_captures/             # API 抓包参考文档
```

## 开发

```bash
# 安装开发依赖
pip install -e .[dev]

# 运行测试（默认含覆盖率报告）
pytest

# 运行单个测试文件
pytest tests/test_notes.py -v

# 代码格式化
black getbiji_box tests examples
isort getbiji_box tests examples

# 类型检查
mypy getbiji_box
```

## 许可证

MIT License

## 免责声明

本项目为非官方 SDK，与 Get 笔记官方无关。使用时请遵守 API 服务条款，风险自担。
