Metadata-Version: 2.3
Name: ksen-feishu
Version: 0.1.11
Summary: 自用飞书接口封装，基于lark-oapi和pydantic，提供更简洁的接口调用方式。
Author: yongg
Author-email: yongg <2814744065@qq.com>
Requires-Dist: lark-oapi>=1.6.8
Requires-Dist: loguru
Requires-Dist: pydantic>=2.13.4
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# ksen-feishu

基于 [飞书开放平台 Python SDK（lark-oapi）](https://open.feishu.cn/document/server-docs/api-call-guide/sdk-guide/prepare-before-development) 和 Pydantic 封装的飞书 API 工具库，为电子表格、云文档导出、群成员、消息卡片及自定义机器人提供更简洁的 Python 调用方式。

> 本项目当前主要用于内部业务复用，API 仍可能调整。

## 功能

- 创建飞书应用客户端，统一使用 tenant access token 调用开放平台 API
- 查询、创建、删除和更新电子表格中的工作表
- 读取、搜索、分批写入单元格，并设置样式、数据验证、合并与保护范围
- 将字典数据声明式导出到 Sheet，并支持数据库与飞书表格之间的增量同步
- 将飞书文档、电子表格和多维表格导出为 DOCX、PDF、XLSX 或 CSV
- 获取群聊成员，自动处理分页
- 创建和动态更新飞书卡片实体
- 构建带签名的自定义机器人文本、卡片及异常通知
- 统一处理 API 错误、网络异常和限流重试

## 环境要求

- Python >= 3.12
- 一个已创建并启用所需权限的飞书企业自建应用
- 使用电子表格或文档 API 时，应用需要对目标资源具有访问权限

具体权限应按实际使用的 API 在飞书开发者后台配置，例如电子表格、云文档、通讯录或群聊成员读取权限。修改权限后通常还需要发布新版本并由管理员审核。

## 安装

使用 uv：

```bash
uv add ksen-feishu
```

从源码安装并开发：

```bash
git clone <repository-url>
cd xfeishu
uv sync
```

发布包名是 `ksen-feishu`，Python 导入名是 `ksen_feishu`。

## 快速开始

不要把 App Secret、Webhook 地址或签名密钥直接写入代码仓库。建议使用环境变量或密钥管理服务：

```python
import os

from ksen_feishu import FeishuApp, FeishuSpreadSheet

app = FeishuApp(
    app_id=os.environ["FEISHU_APP_ID"],
    app_secret=os.environ["FEISHU_APP_SECRET"],
)

spreadsheet = FeishuSpreadSheet(
    app,
    spreadsheet_token=os.environ["FEISHU_SPREADSHEET_TOKEN"],
)

print([(sheet.get_id(), sheet.get_title()) for sheet in spreadsheet.sheets])
```

`spreadsheet_token` 可从电子表格 URL 中取得：

```text
https://example.feishu.cn/sheets/<spreadsheet_token>
```

如果电子表格位于知识库中，请确认应用或机器人已被授予对应文档的访问权限。

## 常用示例

### 读写电子表格

```python
sheet = spreadsheet.find_sheet_by_name("订单")
if sheet is None:
    created = spreadsheet.add_sheet("订单")
    print(created)
else:
    # 范围不需要包含 sheet_id，库会自动补全。
    sheet.write_range(
        "A1:C3",
        [
            ["订单号", "状态", "金额"],
            ["A001", "待处理", 99.5],
            ["A002", "已完成", 120],
        ],
    )
    values = sheet.get_range("A1:C3")
    print(values)
```

单次写入最多支持 100 列；超过 5,000 行时，`write_range()` 会自动拆分请求。

### 管理工作表

```python
from ksen_feishu.sheet import UpdateSheetRequestModel

spreadsheet.add_sheets(["一月", "二月"])

sheet = spreadsheet.find_sheet_by_name("一月")
if sheet:
    spreadsheet.update_sheets(
        [
            UpdateSheetRequestModel(
                sheetId=sheet.get_id(),
                title="2026-01",
                frozenRowCount=1,
            )
        ]
    )
```

### 导出并下载云文档

```python
from ksen_feishu import (
    FeishuDocExporter,
    FeishuDocType,
    FeishuFileExtension,
)

exporter = FeishuDocExporter(app)
file_path = exporter.export_and_download(
    token=os.environ["FEISHU_DOCUMENT_TOKEN"],
    file_extension=FeishuFileExtension.XLSX,
    doc_type=FeishuDocType.SHEET,
    save_dir="./downloads",
)
print(file_path)
```

支持的文档类型：`DOC`、`DOCX`、`SHEET`、`BITABLE`。支持的目标格式：`DOCX`、`PDF`、`XLSX`、`CSV`；实际可用组合由飞书开放平台决定。

### 获取群成员

```python
from ksen_feishu.robot import FeishuRobot

robot = FeishuRobot(app.get_client())
members = robot.get_chat_members(
    chat_id=os.environ["FEISHU_CHAT_ID"],
    member_id_type="open_id",
)

for member in members:
    print(member["name"], member["member_id"])
```

### 创建卡片实体

```python
from ksen_feishu.card import CardApi

card_api = CardApi(app.get_client())
card_id = card_api.create_template_card(
    template_id=os.environ["FEISHU_CARD_TEMPLATE_ID"],
    template_version_name="1.0.0",
    template_variable={"title": "处理完成"},
)
print(card_id)
```

`CardApi` 还提供卡片组件的新增、完整更新、局部更新、内容更新和删除操作。动态更新时，`sequence` 必须严格递增。

### 自定义机器人消息

```python
import os
import requests

from ksen_feishu import notify

body = notify.build_body(
    "任务执行完成",
    secret=os.getenv("FEISHU_WEBHOOK_SECRET"),
)
response = requests.post(
    os.environ["FEISHU_WEBHOOK_URL"],
    json=body,
    timeout=6,
)
response.raise_for_status()
```

也可以使用 `notify.build_card_body()` 构建交互卡片请求体，或使用 `notify.exception_notify()` 发送异常卡片。

## 声明式 Sheet 导出与同步

`ksen_feishu.sync` 提供 `FieldConfig`、`SheetExportConfig` 和 `FeishuSheetExporter`，可将 `list[dict]` 转换为带表头、样式、列宽、数据验证、冻结行列和合并单元格的 Sheet。

```python
from ksen_feishu.sync import FieldConfig, FeishuSheetExporter, SheetExportConfig

fields = {
    "订单号": FieldConfig("订单号", key="order_id", width=140, protected=True),
    "状态": FieldConfig(
        "状态",
        key="status",
        width=100,
        validation={"conditionType": "LIST", "conditionValues": ["待处理", "已完成"]},
    ),
    "金额": FieldConfig("金额", key="amount", field_type="number", formatter="#,##0.00"),
}

config = SheetExportConfig(
    fields=fields,
    primary_header="订单号",
    frozen_row_count=1,
)

exporter = FeishuSheetExporter(
    app=app,
    token=os.environ["FEISHU_SPREADSHEET_TOKEN"],
    config=config,
)

exporter.export(
    "订单",
    [
        {"order_id": "A001", "status": "待处理", "amount": 99.5},
        {"order_id": "A002", "status": "已完成", "amount": 120},
    ],
)
```

同步器还提供 `db_to_feishu()` 和 `feishu_to_db()`。它们涉及主键匹配、更新时间比较及回调写库，接入前应先在测试表格验证字段配置和数据转换函数。

## 日志

库使用 Loguru 记录日志，但不会在导入时主动添加输出处理器。应用可自行配置 Loguru，也可以调用包内的便捷函数：

```python
import ksen_feishu

ksen_feishu.setup_logging(level="INFO")
```

请勿在日志中输出 App Secret、Webhook Secret、访问令牌或包含敏感信息的完整请求体。

## 主要模块

| 模块 | 用途 |
| --- | --- |
| `ksen_feishu.client` | 创建飞书 SDK 客户端 |
| `ksen_feishu.sheet` | 电子表格和工作表操作 |
| `ksen_feishu.sync` | 声明式导出及双向同步 |
| `ksen_feishu.doc_exporter` | 云文档导出和下载 |
| `ksen_feishu.robot` | 群聊成员等 IM 能力 |
| `ksen_feishu.card` | 卡片实体及组件操作 |
| `ksen_feishu.notify` | 自定义机器人消息体和异常通知 |
| `ksen_feishu.update_utils` | 按列批量更新辅助函数 |

## 开发

```bash
uv sync
uv run python -m compileall src
```

构建发行包：

```bash
uv build
```

## 安全建议

- 凭证只通过环境变量或密钥管理服务注入，不要提交到 Git。
- 为飞书应用配置最小必要权限，并限制目标文档和群聊的授权范围。
- Webhook 请求应设置超时，并在业务侧检查响应状态。
- API 错误上下文可能包含请求信息；生产日志应做好脱敏和访问控制。

## License

仓库当前未声明开源许可证。如需复制、修改或分发，请先联系项目维护者。
