Metadata-Version: 2.4
Name: lark-bridge
Version: 0.4.0
Summary: Unofficial Feishu/Lark Web SDK - WebSocket listener, message search, send, and drive operations
Project-URL: Homepage, https://github.com/LiangFu/lark-bridge
Project-URL: Repository, https://github.com/LiangFu/lark-bridge
Author: Ryan Zhu
License-Expression: MIT
License-File: LICENSE
Keywords: feishu,im,lark,protobuf,websocket
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Communications :: Chat
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27.0
Requires-Dist: protobuf3-to-dict>=0.1.0
Requires-Dist: protobuf>=5.0.0
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5.0; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: mcp[cli]>=1.0; extra == 'mcp'
Description-Content-Type: text/markdown

# lark-bridge

Unofficial Feishu/Lark Web SDK using cookie-based authentication. Provides real-time message listening via WebSocket, message search/fetch, sending, and Drive operations.

> ⚠️ This library is reverse-engineered from Feishu's web client. It is **not** an official API and may break without notice.

## Installation

```bash
pip install lark-bridge
```

## Quick Start

```python
import asyncio
from lark_bridge import LarkBridge

bridge = LarkBridge("your_cookie_string_here")

# For enterprise tenants with custom domain:
bridge = LarkBridge("your_cookie_string_here", domain="yourcompany.feishu.cn")
```

### Listen to Messages

```python
async def main():
    async for msg in bridge.listen(watch_chats=["chat_id"]):
        print(f"[{msg['chat_id']}] {msg['from_id']}: {msg['text']}")

asyncio.run(main())
```

### Search History

```python
# Simple: auto-paginate up to limit
result = await bridge.search_messages(
    chat_id="7052636707732193282",
    start_time=1716192000,
    end_time=1716278400,
    limit=50,
)
print(result["msg_ids"])

# Manual pagination:
page = await bridge.search_messages_page(chat_id="7052636707732193282")
while page["has_more"]:
    page = await bridge.search_messages_page(
        chat_id="7052636707732193282",
        page_token=page["page_token"],
    )
    print(page["msg_ids"])
```

### Fetch Messages

```python
messages = await bridge.fetch_messages(["msg_id_1", "msg_id_2"])
for msg in messages:
    print(msg["text"])
# Each message dict contains:
# msg_id, type, from_id, chat_id, chat_type, parent_id, root_id, create_time, text
# chat_type: 0=unknown, 1=P2P(private), 2=GROUP, 3=TOPIC_GROUP
```

### Send Message

```python
await bridge.send_message(
    chat_id="7052636707732193282",
    text="Hello!",
    reply_id="optional_msg_id",
    at_user_ids=["user_id"],
)
```

### Drive Operations

```python
folder = await bridge.create_folder("My Folder", parent_token="root_token")
# folder = {"token": "...", "url": "https://domain/drive/folder/..."}

result = await bridge.upload_file(folder["token"], "report.txt", b"file content")
# result = {"file_token": "...", "node_token": "...", "url": "https://domain/file/..."}
```

### Export Document

```python
# Export a docx/wiki page as markdown
content = await bridge.export_document(
    token="GSeJdHQbQo3b2jxg8CYc1Zqqnah",
    type="docx",              # "docx" | "sheet" | "doc"
    file_extension="markdown",  # "markdown" | "docx" | "pdf" | "xlsx" | "csv"
)
if content:
    Path("output.md").write_bytes(content)
```

Supported combinations:
- `type="docx"` (wiki/docx pages) → markdown, docx, pdf
- `type="sheet"` → xlsx only

## MCP Server

Expose lark-bridge as an [MCP](https://modelcontextprotocol.io/) server so AI clients (Claude Desktop, Cursor, Kiro, etc.) can call Feishu tools directly.

### Install

```bash
pip install lark-bridge[mcp]
```

### Run

```bash
FEISHU_COOKIE="your_cookie_string" lark-bridge-mcp
```

For enterprise tenants with a custom domain:

```bash
FEISHU_COOKIE="your_cookie_string" FEISHU_DOMAIN="yourcompany.feishu.cn" lark-bridge-mcp
```

If your cookie changes frequently, use a file instead of an environment variable. The server reads the file on every tool call, so updates take effect immediately without restarting:

```bash
FEISHU_COOKIE_FILE="/path/to/cookie.txt" lark-bridge-mcp
```

### MCP Client Config

```json
{
  "mcpServers": {
    "lark-bridge": {
      "command": "lark-bridge-mcp",
      "env": {
        "FEISHU_COOKIE": "your_cookie_string"
      }
    }
  }
}
```

Available tools: `send_message`, `search_messages`, `fetch_messages`, `create_folder`, `upload_file`.

## Cookie Setup

1. Open [Feishu Web](https://www.feishu.cn/) in your browser and log in
2. Open DevTools (F12) → Application → Cookies
3. Copy the full cookie string (all key=value pairs joined by `; `)
4. Pass it to `LarkBridge("your_cookie_string")`

Example cookie format:

```python
cookie = "passport_web_did=YOUR_DID; session=YOUR_SESSION; _csrf_token=YOUR_CSRF_TOKEN"

bridge = LarkBridge(cookie)
```

Cookie typically stays valid as long as the WebSocket connection is maintained.

## License

[MIT](LICENSE)
