Metadata-Version: 2.4
Name: luke_qywechat
Version: 1.1.0
Summary: A simple SDK for sending messages through Luke's WeCom application.
Author: Luke
License-Expression: MIT
Project-URL: Homepage, https://github.com/luke9012/luke_qywechat
Keywords: wecom,wechat-work,qywechat,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Communications :: Chat
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.25.0
Requires-Dist: httpx>=0.27.0

# luke_qywechat

luke 的企业微信 SDK。包含两个独立的客户端类：

| 类 | 用途 | 后端 |
|----|------|------|
| `WeChatPub`（已有） | 直接调企业微信 API 发文本/图片 | `https://qyapi.weixin.qq.com`（或反代）|
| `WeChatHub`（新增） | 通过 [qywechat_hub](https://github.com/luke9012/qywechat_hub) 服务收发消息，不感知企业微信细节 | hub 的 HTTP/SSE API |

两个类**并存**，旧代码 `from qy_wechat import WeChatPub` 不变。新代码推荐用 `WeChatHub`：业务方完全不用管 access_token / media_id / 加解密 / IP 白名单。

## 安装

```bash
pip install luke_qywechat
```

## WeChatPub：直接调企业微信（兼容老用法）

只需要传入企业微信应用的 `agentId` 和 `secret`：

```python
from qy_wechat import WeChatPub

wechat = WeChatPub(agentId=1000001, secret="your-secret")
wechat.send_msg("hello")
wechat.send_image_msg("/path/to/image.jpg")
wechat.send_image_msg("https://example.com/image.jpg")
```

兼容旧写法：

```python
wechat = WeChatPub(1000001, "your-secret")
wechat.send_msg("hello", d_ids="5")
```

### 命令行测试

不要把 `agentId` 和 `secret` 写进代码或提交到仓库。命令行测试可以使用环境变量：

```bash
export QY_WECHAT_AGENT_ID=1000001
export QY_WECHAT_SECRET=your-secret
qy-wechat "测试消息"
```

## WeChatHub：通过 qywechat_hub 服务（推荐）

业务方代码完全不接触企业微信——所有发送/接收都通过 hub 中转，由 hub 处理鉴权、加解密、IP 白名单。

### 配置（环境变量）

```bash
export QYWECHAT_HUB_URL=https://qywechat.luke9012.cn     # 或 dev 域名
export QYWECHAT_HUB_TOKEN=tok_xxxxxxxx                    # 找 hub 管理员发
export QYWECHAT_AGENT_ID=1000006                          # 默认 agent，可调用时覆盖
```

### 发消息

```python
from wechat_hub import WeChatHub

hub = WeChatHub.from_env()

hub.send_text("hello", touser="luke")
hub.send_markdown("# 标题\n正文", touser="luke")
hub.send_image("/path/to/qrcode.png", touser="luke")
hub.send_image(png_bytes, touser="luke")               # bytes 也行
```

### 收消息（SSE 阻塞迭代器）

```python
for msg in hub.messages(user="luke", types="text"):
    if msg.content and msg.content.startswith("登录 "):
        platform = msg.content.split(" ", 1)[1]
        ...
        break
```

迭代器是真的"流式"——hub 推一条 yield 一条。`break` 出循环时连接会自动断开。

### 异常处理

```python
from wechat_hub import HubError

try:
    hub.send_text("hi", touser="not-a-real-user")
except HubError as e:
    print(e.status_code, e.detail)
```

`HubError.status_code` 是 HTTP 状态，`detail` 是 hub 返回的 body（502 时包含企业微信原始 `errcode/errmsg`）。

## 发布到 PyPI

本项目不会在包内保存 `agentId`、`secret` 或 PyPI token。发布前请使用环境变量或本机 keyring 管理令牌。

```bash
python -m build
python -m twine check dist/*
python -m twine upload dist/*
```

如果使用 token：

```bash
export TWINE_USERNAME=__token__
export TWINE_PASSWORD=<your API token>
python -m twine upload dist/*
```
