perk-pushplus-sdk 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- perk_pushplus_sdk-1.0.0/PKG-INFO +233 -0
- perk_pushplus_sdk-1.0.0/README.md +201 -0
- perk_pushplus_sdk-1.0.0/pyproject.toml +56 -0
- perk_pushplus_sdk-1.0.0/setup.cfg +4 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/__init__.py +155 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/access_key.py +77 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/__init__.py +33 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/access_key.py +44 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/base.py +210 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/channel.py +47 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/clawbot.py +49 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/friend.py +58 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/message.py +151 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/message_token.py +52 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/open_message.py +51 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/pre.py +40 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/setting.py +90 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/topic.py +89 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/topic_user.py +35 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/user.py +34 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/api/webhook.py +35 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/callback_parser.py +51 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/client.py +169 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/config.py +85 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/enums.py +214 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/exceptions.py +61 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/http.py +158 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/__init__.py +90 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/base.py +246 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/callback.py +76 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_access.py +18 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_channel.py +57 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_clawbot.py +34 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_friend.py +31 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_message.py +36 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_pre.py +51 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_setting.py +46 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_token.py +49 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_topic.py +166 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_user.py +44 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/open_webhook.py +43 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/models/send.py +255 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/py.typed +0 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus/rate_limit.py +124 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus_sdk.egg-info/PKG-INFO +233 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus_sdk.egg-info/SOURCES.txt +51 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus_sdk.egg-info/dependency_links.txt +1 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus_sdk.egg-info/requires.txt +6 -0
- perk_pushplus_sdk-1.0.0/src/perk_pushplus_sdk.egg-info/top_level.txt +1 -0
- perk_pushplus_sdk-1.0.0/tests/test_enums_and_exceptions.py +53 -0
- perk_pushplus_sdk-1.0.0/tests/test_message_api.py +166 -0
- perk_pushplus_sdk-1.0.0/tests/test_models.py +160 -0
- perk_pushplus_sdk-1.0.0/tests/test_open_api.py +148 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: perk-pushplus-sdk
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: pushplus(推送加) 官方接口的 Python SDK,覆盖消息发送接口与全部开放接口。
|
|
5
|
+
Author: perk-net
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://www.pushplus.plus
|
|
8
|
+
Project-URL: Documentation, https://www.pushplus.plus/doc/guide/api.html
|
|
9
|
+
Project-URL: Source, https://github.com/pushplus/perk-pushplus-python-sdk
|
|
10
|
+
Project-URL: Issues, https://github.com/pushplus/perk-pushplus-python-sdk/issues
|
|
11
|
+
Keywords: pushplus,wechat,notify,sdk,webhook
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Topic :: Communications
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
Requires-Dist: requests>=2.25.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
31
|
+
Requires-Dist: responses>=0.23; extra == "dev"
|
|
32
|
+
|
|
33
|
+
# perk-pushplus-python-sdk
|
|
34
|
+
|
|
35
|
+
[pushplus(推送加)](https://www.pushplus.plus) 官方接口的 Python SDK,覆盖 **消息接口** 与 **全部开放接口**。
|
|
36
|
+
|
|
37
|
+
- **消息接口**(`/send`、`/batchSend`):单渠道 + 多渠道发送,含 Builder API。
|
|
38
|
+
- **开放接口**(`/api/open/...`):用户、消息、消息 token、群组、群组用户、好友、webhook、渠道、ClawBot、功能设置、预处理信息。
|
|
39
|
+
- **AccessKey 自动管理**:缓存 + 过期前自动刷新;`code=401` 自动刷新并重试一次。
|
|
40
|
+
- **本地限流守卫**:命中 `code=900` 后按 token 短路同 token 后续发送,避免被服务端长期封禁。
|
|
41
|
+
- **回调解析**:`message_complate`、`add_topic_user`、`add_friend` 三类回调统一解析。
|
|
42
|
+
- **类型友好**:`dataclass` + `Enum`,附带 `py.typed`。
|
|
43
|
+
|
|
44
|
+
> 接口文档:
|
|
45
|
+
> - 消息接口:<https://www.pushplus.plus/doc/guide/api.html>
|
|
46
|
+
> - 开放接口:<https://www.pushplus.plus/doc/guide/openApi.html>
|
|
47
|
+
|
|
48
|
+
## 安装
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install perk-pushplus-sdk
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 快速开始
|
|
55
|
+
|
|
56
|
+
### 1. 构建客户端
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from perk_pushplus import PushPlusClient
|
|
60
|
+
|
|
61
|
+
client = (
|
|
62
|
+
PushPlusClient.builder()
|
|
63
|
+
.token("your_user_token") # 个人中心 -> 一对一推送
|
|
64
|
+
.secret_key("your_secret_key") # 个人中心 -> 开发设置(开放接口必填)
|
|
65
|
+
.build()
|
|
66
|
+
)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
> `PushPlusClient` 线程安全,建议作为单例长期持有。
|
|
70
|
+
|
|
71
|
+
### 2. 发送消息
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from perk_pushplus import Channel, SendRequest, Template
|
|
75
|
+
|
|
76
|
+
# 最简:默认 wechat / html
|
|
77
|
+
short_code = client.send_simple("标题", "<b>内容</b>")
|
|
78
|
+
|
|
79
|
+
# 完整:使用 Builder
|
|
80
|
+
short_code = client.send(
|
|
81
|
+
SendRequest.builder()
|
|
82
|
+
.title("CPU 告警")
|
|
83
|
+
.content("# CPU > 90%\n请尽快处理")
|
|
84
|
+
.template(Template.MARKDOWN)
|
|
85
|
+
.channel(Channel.WECHAT)
|
|
86
|
+
.topic("ops")
|
|
87
|
+
.callback_url("https://your.host/pushplus/callback")
|
|
88
|
+
.build()
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 3. 多渠道发送
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from perk_pushplus import BatchSendRequest, Channel
|
|
96
|
+
|
|
97
|
+
results = client.batch_send(
|
|
98
|
+
BatchSendRequest.builder()
|
|
99
|
+
.title("多渠道告警")
|
|
100
|
+
.content("CPU > 90%")
|
|
101
|
+
.channel(Channel.WECHAT).option("")
|
|
102
|
+
.channel(Channel.WEBHOOK).option("bark")
|
|
103
|
+
.channel(Channel.EXTENSION).option("")
|
|
104
|
+
.build()
|
|
105
|
+
)
|
|
106
|
+
for r in results:
|
|
107
|
+
print(r.channel, r.shortCode, r.code, r.message)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 4. 开放接口
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
# 用户
|
|
114
|
+
info = client.user.my_info()
|
|
115
|
+
limit = client.user.get_limit_time()
|
|
116
|
+
|
|
117
|
+
# 消息
|
|
118
|
+
page = client.open_message.list()
|
|
119
|
+
result = client.open_message.query_result("short-code")
|
|
120
|
+
|
|
121
|
+
# 消息 token
|
|
122
|
+
from perk_pushplus import MessageTokenAddRequest
|
|
123
|
+
new_token = client.message_token.add(MessageTokenAddRequest(name="for-jenkins"))
|
|
124
|
+
|
|
125
|
+
# 群组
|
|
126
|
+
from perk_pushplus import TopicListQuery
|
|
127
|
+
topics = client.topic.list(TopicListQuery.of(1, 20, topic_type=0))
|
|
128
|
+
detail = client.topic.detail(topic_id=123)
|
|
129
|
+
|
|
130
|
+
# 好友
|
|
131
|
+
qr = client.friend.get_qr_code(content="welcome")
|
|
132
|
+
friends = client.friend.list()
|
|
133
|
+
|
|
134
|
+
# webhook 渠道
|
|
135
|
+
webhooks = client.webhook.list()
|
|
136
|
+
|
|
137
|
+
# 设置
|
|
138
|
+
client.setting.change_is_send(1) # 启用发送
|
|
139
|
+
|
|
140
|
+
# 预处理(会员)
|
|
141
|
+
client.pre.test(...)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 5. 异步发送
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
fut = client.send_async(SendRequest(content="hello"))
|
|
148
|
+
print(fut.result(timeout=10))
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 6. 回调解析
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from perk_pushplus import CallbackEvent, callback_parser
|
|
155
|
+
|
|
156
|
+
# 在你的 web 框架(Flask/FastAPI/Django/...)的回调入口里:
|
|
157
|
+
def on_pushplus_callback(raw_body: str) -> str:
|
|
158
|
+
payload = callback_parser.parse(raw_body)
|
|
159
|
+
if payload.event is CallbackEvent.MESSAGE_COMPLETE:
|
|
160
|
+
info = payload.messageInfo
|
|
161
|
+
print("发送结果", info.shortCode, info.get_send_status_enum())
|
|
162
|
+
elif payload.event is CallbackEvent.ADD_TOPIC_USER:
|
|
163
|
+
print("新订阅", payload.topicUserInfo.openId)
|
|
164
|
+
elif payload.event is CallbackEvent.ADD_FRIEND:
|
|
165
|
+
print("新好友", payload.friendInfo.token, payload.qrCode)
|
|
166
|
+
return "ok"
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## 配置
|
|
170
|
+
|
|
171
|
+
`PushPlusClient.builder()` 支持的全部参数:
|
|
172
|
+
|
|
173
|
+
| 方法 | 默认值 | 说明 |
|
|
174
|
+
| ------------------------------------- | ------------------------- | ---------------------------------------------------- |
|
|
175
|
+
| `token(str)` | - | 用户 token 或消息 token;发送消息接口默认使用 |
|
|
176
|
+
| `secret_key(str)` | - | 开放接口 secretKey |
|
|
177
|
+
| `base_url(str)` | `https://www.pushplus.plus` | 服务地址 |
|
|
178
|
+
| `connect_timeout(float)` | `10.0` 秒 | 连接超时 |
|
|
179
|
+
| `read_timeout(float)` | `30.0` 秒 | 读超时 |
|
|
180
|
+
| `access_key_refresh_ahead_seconds(int)` | `300` | 在 AccessKey 过期前多少秒主动刷新 |
|
|
181
|
+
| `log_request(bool)` | `False` | 打印 DEBUG 级请求/响应日志 |
|
|
182
|
+
| `rate_limit_guard_enabled(bool)` | `True` | 是否启用本地限流守卫(命中 900 后短路) |
|
|
183
|
+
| `rate_limit_cooldown_seconds(float)` | `None`(次日 0 点) | 命中 900 后的本地禁推时长(秒) |
|
|
184
|
+
| `user_agent(str)` | `perk-pushplus-python-sdk/<v>` | UA 头 |
|
|
185
|
+
| `http_requester(HttpRequester)` | 内置 `requests` 实现 | 自定义 HTTP 客户端(aiohttp/httpx 等可适配) |
|
|
186
|
+
|
|
187
|
+
## 错误处理
|
|
188
|
+
|
|
189
|
+
所有请求异常都会抛出 `PushPlusError`:
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
from perk_pushplus import ErrorCode, PushPlusError
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
client.send_simple("t", "c")
|
|
196
|
+
except PushPlusError as exc:
|
|
197
|
+
if exc.is_rate_limited():
|
|
198
|
+
print("命中 code=900,已被本地守卫拒绝")
|
|
199
|
+
elif exc.error_code is ErrorCode.NOT_VERIFIED:
|
|
200
|
+
print("账号未实名")
|
|
201
|
+
else:
|
|
202
|
+
print(exc.code, exc.message)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`PushPlusError` 暴露:
|
|
206
|
+
|
|
207
|
+
- `code`:业务 code 或 HTTP 状态码
|
|
208
|
+
- `message`:错误描述
|
|
209
|
+
- `error_code` -> `ErrorCode` 枚举
|
|
210
|
+
- `is_rate_limited()`:是否为 `code=900`
|
|
211
|
+
|
|
212
|
+
## 自定义 HTTP 客户端
|
|
213
|
+
|
|
214
|
+
实现 `HttpRequester`(`Protocol`)即可:
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from perk_pushplus import HttpRequester, HttpResponse
|
|
218
|
+
|
|
219
|
+
class MyRequester(HttpRequester):
|
|
220
|
+
def execute(self, method, url, headers, body) -> HttpResponse:
|
|
221
|
+
...
|
|
222
|
+
|
|
223
|
+
client = PushPlusClient.builder().http_requester(MyRequester()).build()
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## 兼容性
|
|
227
|
+
|
|
228
|
+
- Python `>= 3.8`
|
|
229
|
+
- 仅依赖 `requests`
|
|
230
|
+
|
|
231
|
+
## 许可证
|
|
232
|
+
|
|
233
|
+
Apache License 2.0
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# perk-pushplus-python-sdk
|
|
2
|
+
|
|
3
|
+
[pushplus(推送加)](https://www.pushplus.plus) 官方接口的 Python SDK,覆盖 **消息接口** 与 **全部开放接口**。
|
|
4
|
+
|
|
5
|
+
- **消息接口**(`/send`、`/batchSend`):单渠道 + 多渠道发送,含 Builder API。
|
|
6
|
+
- **开放接口**(`/api/open/...`):用户、消息、消息 token、群组、群组用户、好友、webhook、渠道、ClawBot、功能设置、预处理信息。
|
|
7
|
+
- **AccessKey 自动管理**:缓存 + 过期前自动刷新;`code=401` 自动刷新并重试一次。
|
|
8
|
+
- **本地限流守卫**:命中 `code=900` 后按 token 短路同 token 后续发送,避免被服务端长期封禁。
|
|
9
|
+
- **回调解析**:`message_complate`、`add_topic_user`、`add_friend` 三类回调统一解析。
|
|
10
|
+
- **类型友好**:`dataclass` + `Enum`,附带 `py.typed`。
|
|
11
|
+
|
|
12
|
+
> 接口文档:
|
|
13
|
+
> - 消息接口:<https://www.pushplus.plus/doc/guide/api.html>
|
|
14
|
+
> - 开放接口:<https://www.pushplus.plus/doc/guide/openApi.html>
|
|
15
|
+
|
|
16
|
+
## 安装
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install perk-pushplus-sdk
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 快速开始
|
|
23
|
+
|
|
24
|
+
### 1. 构建客户端
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from perk_pushplus import PushPlusClient
|
|
28
|
+
|
|
29
|
+
client = (
|
|
30
|
+
PushPlusClient.builder()
|
|
31
|
+
.token("your_user_token") # 个人中心 -> 一对一推送
|
|
32
|
+
.secret_key("your_secret_key") # 个人中心 -> 开发设置(开放接口必填)
|
|
33
|
+
.build()
|
|
34
|
+
)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> `PushPlusClient` 线程安全,建议作为单例长期持有。
|
|
38
|
+
|
|
39
|
+
### 2. 发送消息
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from perk_pushplus import Channel, SendRequest, Template
|
|
43
|
+
|
|
44
|
+
# 最简:默认 wechat / html
|
|
45
|
+
short_code = client.send_simple("标题", "<b>内容</b>")
|
|
46
|
+
|
|
47
|
+
# 完整:使用 Builder
|
|
48
|
+
short_code = client.send(
|
|
49
|
+
SendRequest.builder()
|
|
50
|
+
.title("CPU 告警")
|
|
51
|
+
.content("# CPU > 90%\n请尽快处理")
|
|
52
|
+
.template(Template.MARKDOWN)
|
|
53
|
+
.channel(Channel.WECHAT)
|
|
54
|
+
.topic("ops")
|
|
55
|
+
.callback_url("https://your.host/pushplus/callback")
|
|
56
|
+
.build()
|
|
57
|
+
)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 3. 多渠道发送
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from perk_pushplus import BatchSendRequest, Channel
|
|
64
|
+
|
|
65
|
+
results = client.batch_send(
|
|
66
|
+
BatchSendRequest.builder()
|
|
67
|
+
.title("多渠道告警")
|
|
68
|
+
.content("CPU > 90%")
|
|
69
|
+
.channel(Channel.WECHAT).option("")
|
|
70
|
+
.channel(Channel.WEBHOOK).option("bark")
|
|
71
|
+
.channel(Channel.EXTENSION).option("")
|
|
72
|
+
.build()
|
|
73
|
+
)
|
|
74
|
+
for r in results:
|
|
75
|
+
print(r.channel, r.shortCode, r.code, r.message)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 4. 开放接口
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
# 用户
|
|
82
|
+
info = client.user.my_info()
|
|
83
|
+
limit = client.user.get_limit_time()
|
|
84
|
+
|
|
85
|
+
# 消息
|
|
86
|
+
page = client.open_message.list()
|
|
87
|
+
result = client.open_message.query_result("short-code")
|
|
88
|
+
|
|
89
|
+
# 消息 token
|
|
90
|
+
from perk_pushplus import MessageTokenAddRequest
|
|
91
|
+
new_token = client.message_token.add(MessageTokenAddRequest(name="for-jenkins"))
|
|
92
|
+
|
|
93
|
+
# 群组
|
|
94
|
+
from perk_pushplus import TopicListQuery
|
|
95
|
+
topics = client.topic.list(TopicListQuery.of(1, 20, topic_type=0))
|
|
96
|
+
detail = client.topic.detail(topic_id=123)
|
|
97
|
+
|
|
98
|
+
# 好友
|
|
99
|
+
qr = client.friend.get_qr_code(content="welcome")
|
|
100
|
+
friends = client.friend.list()
|
|
101
|
+
|
|
102
|
+
# webhook 渠道
|
|
103
|
+
webhooks = client.webhook.list()
|
|
104
|
+
|
|
105
|
+
# 设置
|
|
106
|
+
client.setting.change_is_send(1) # 启用发送
|
|
107
|
+
|
|
108
|
+
# 预处理(会员)
|
|
109
|
+
client.pre.test(...)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 5. 异步发送
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
fut = client.send_async(SendRequest(content="hello"))
|
|
116
|
+
print(fut.result(timeout=10))
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 6. 回调解析
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from perk_pushplus import CallbackEvent, callback_parser
|
|
123
|
+
|
|
124
|
+
# 在你的 web 框架(Flask/FastAPI/Django/...)的回调入口里:
|
|
125
|
+
def on_pushplus_callback(raw_body: str) -> str:
|
|
126
|
+
payload = callback_parser.parse(raw_body)
|
|
127
|
+
if payload.event is CallbackEvent.MESSAGE_COMPLETE:
|
|
128
|
+
info = payload.messageInfo
|
|
129
|
+
print("发送结果", info.shortCode, info.get_send_status_enum())
|
|
130
|
+
elif payload.event is CallbackEvent.ADD_TOPIC_USER:
|
|
131
|
+
print("新订阅", payload.topicUserInfo.openId)
|
|
132
|
+
elif payload.event is CallbackEvent.ADD_FRIEND:
|
|
133
|
+
print("新好友", payload.friendInfo.token, payload.qrCode)
|
|
134
|
+
return "ok"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 配置
|
|
138
|
+
|
|
139
|
+
`PushPlusClient.builder()` 支持的全部参数:
|
|
140
|
+
|
|
141
|
+
| 方法 | 默认值 | 说明 |
|
|
142
|
+
| ------------------------------------- | ------------------------- | ---------------------------------------------------- |
|
|
143
|
+
| `token(str)` | - | 用户 token 或消息 token;发送消息接口默认使用 |
|
|
144
|
+
| `secret_key(str)` | - | 开放接口 secretKey |
|
|
145
|
+
| `base_url(str)` | `https://www.pushplus.plus` | 服务地址 |
|
|
146
|
+
| `connect_timeout(float)` | `10.0` 秒 | 连接超时 |
|
|
147
|
+
| `read_timeout(float)` | `30.0` 秒 | 读超时 |
|
|
148
|
+
| `access_key_refresh_ahead_seconds(int)` | `300` | 在 AccessKey 过期前多少秒主动刷新 |
|
|
149
|
+
| `log_request(bool)` | `False` | 打印 DEBUG 级请求/响应日志 |
|
|
150
|
+
| `rate_limit_guard_enabled(bool)` | `True` | 是否启用本地限流守卫(命中 900 后短路) |
|
|
151
|
+
| `rate_limit_cooldown_seconds(float)` | `None`(次日 0 点) | 命中 900 后的本地禁推时长(秒) |
|
|
152
|
+
| `user_agent(str)` | `perk-pushplus-python-sdk/<v>` | UA 头 |
|
|
153
|
+
| `http_requester(HttpRequester)` | 内置 `requests` 实现 | 自定义 HTTP 客户端(aiohttp/httpx 等可适配) |
|
|
154
|
+
|
|
155
|
+
## 错误处理
|
|
156
|
+
|
|
157
|
+
所有请求异常都会抛出 `PushPlusError`:
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
from perk_pushplus import ErrorCode, PushPlusError
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
client.send_simple("t", "c")
|
|
164
|
+
except PushPlusError as exc:
|
|
165
|
+
if exc.is_rate_limited():
|
|
166
|
+
print("命中 code=900,已被本地守卫拒绝")
|
|
167
|
+
elif exc.error_code is ErrorCode.NOT_VERIFIED:
|
|
168
|
+
print("账号未实名")
|
|
169
|
+
else:
|
|
170
|
+
print(exc.code, exc.message)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`PushPlusError` 暴露:
|
|
174
|
+
|
|
175
|
+
- `code`:业务 code 或 HTTP 状态码
|
|
176
|
+
- `message`:错误描述
|
|
177
|
+
- `error_code` -> `ErrorCode` 枚举
|
|
178
|
+
- `is_rate_limited()`:是否为 `code=900`
|
|
179
|
+
|
|
180
|
+
## 自定义 HTTP 客户端
|
|
181
|
+
|
|
182
|
+
实现 `HttpRequester`(`Protocol`)即可:
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
from perk_pushplus import HttpRequester, HttpResponse
|
|
186
|
+
|
|
187
|
+
class MyRequester(HttpRequester):
|
|
188
|
+
def execute(self, method, url, headers, body) -> HttpResponse:
|
|
189
|
+
...
|
|
190
|
+
|
|
191
|
+
client = PushPlusClient.builder().http_requester(MyRequester()).build()
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## 兼容性
|
|
195
|
+
|
|
196
|
+
- Python `>= 3.8`
|
|
197
|
+
- 仅依赖 `requests`
|
|
198
|
+
|
|
199
|
+
## 许可证
|
|
200
|
+
|
|
201
|
+
Apache License 2.0
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "perk-pushplus-sdk"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "pushplus(推送加) 官方接口的 Python SDK,覆盖消息发送接口与全部开放接口。"
|
|
9
|
+
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "Apache-2.0" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "perk-net" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["pushplus", "wechat", "notify", "sdk", "webhook"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 5 - Production/Stable",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: Apache Software License",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
23
|
+
"Programming Language :: Python :: 3.8",
|
|
24
|
+
"Programming Language :: Python :: 3.9",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Topic :: Communications",
|
|
29
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
30
|
+
]
|
|
31
|
+
dependencies = [
|
|
32
|
+
"requests>=2.25.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
dev = [
|
|
37
|
+
"pytest>=7.0",
|
|
38
|
+
"pytest-cov>=4.0",
|
|
39
|
+
"responses>=0.23",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://www.pushplus.plus"
|
|
44
|
+
Documentation = "https://www.pushplus.plus/doc/guide/api.html"
|
|
45
|
+
Source = "https://github.com/pushplus/perk-pushplus-python-sdk"
|
|
46
|
+
Issues = "https://github.com/pushplus/perk-pushplus-python-sdk/issues"
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.packages.find]
|
|
49
|
+
where = ["src"]
|
|
50
|
+
|
|
51
|
+
[tool.setuptools.package-data]
|
|
52
|
+
perk_pushplus = ["py.typed"]
|
|
53
|
+
|
|
54
|
+
[tool.pytest.ini_options]
|
|
55
|
+
testpaths = ["tests"]
|
|
56
|
+
addopts = "-ra"
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""perk-pushplus-python-sdk: PushPlus 推送加官方接口的 Python SDK。
|
|
2
|
+
|
|
3
|
+
提供消息接口(``/send``、``/batchSend``)以及全部开放接口的封装,
|
|
4
|
+
内置 AccessKey 自动管理与本地限流守卫。
|
|
5
|
+
|
|
6
|
+
参考文档:
|
|
7
|
+
- 消息接口:https://www.pushplus.plus/doc/guide/api.html
|
|
8
|
+
- 开放接口:https://www.pushplus.plus/doc/guide/openApi.html
|
|
9
|
+
|
|
10
|
+
快速使用::
|
|
11
|
+
|
|
12
|
+
from perk_pushplus import PushPlusClient
|
|
13
|
+
|
|
14
|
+
client = PushPlusClient.builder() \
|
|
15
|
+
.token("your_user_token") \
|
|
16
|
+
.secret_key("your_secret_key") \
|
|
17
|
+
.build()
|
|
18
|
+
|
|
19
|
+
short_code = client.send_simple("标题", "内容")
|
|
20
|
+
"""
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from . import callback_parser
|
|
24
|
+
from .access_key import AccessKeyManager
|
|
25
|
+
from .client import PushPlusClient, PushPlusClientBuilder
|
|
26
|
+
from .config import DEFAULT_BASE_URL, PushPlusConfig
|
|
27
|
+
from .enums import (
|
|
28
|
+
CallbackEvent,
|
|
29
|
+
Channel,
|
|
30
|
+
ErrorCode,
|
|
31
|
+
SendStatus,
|
|
32
|
+
Template,
|
|
33
|
+
WebhookType,
|
|
34
|
+
)
|
|
35
|
+
from .exceptions import PushPlusError, PushPlusException
|
|
36
|
+
from .http import HttpRequester, HttpResponse, RequestsHttpRequester
|
|
37
|
+
from .models import (
|
|
38
|
+
AccessKeyResult,
|
|
39
|
+
ApiResponse,
|
|
40
|
+
BatchSendRequest,
|
|
41
|
+
BatchSendResult,
|
|
42
|
+
CallbackFriendInfo,
|
|
43
|
+
CallbackPayload,
|
|
44
|
+
ClawBotInfo,
|
|
45
|
+
ClawBotMessage,
|
|
46
|
+
ClawBotQrCode,
|
|
47
|
+
CpItem,
|
|
48
|
+
FriendItem,
|
|
49
|
+
FriendQrCode,
|
|
50
|
+
MailDetail,
|
|
51
|
+
MailItem,
|
|
52
|
+
MessageCompleteInfo,
|
|
53
|
+
MessageItem,
|
|
54
|
+
MessageTokenAddRequest,
|
|
55
|
+
MessageTokenEditRequest,
|
|
56
|
+
MessageTokenItem,
|
|
57
|
+
MessageTokenOption,
|
|
58
|
+
MpItem,
|
|
59
|
+
PageQuery,
|
|
60
|
+
PageResult,
|
|
61
|
+
PreDetail,
|
|
62
|
+
PreItem,
|
|
63
|
+
PreSaveRequest,
|
|
64
|
+
PreTestRequest,
|
|
65
|
+
SendCount,
|
|
66
|
+
SendMessageResult,
|
|
67
|
+
SendRequest,
|
|
68
|
+
TopicAddRequest,
|
|
69
|
+
TopicDetail,
|
|
70
|
+
TopicEditRequest,
|
|
71
|
+
TopicItem,
|
|
72
|
+
TopicListQuery,
|
|
73
|
+
TopicQrCode,
|
|
74
|
+
TopicUserInfo,
|
|
75
|
+
TopicUserItem,
|
|
76
|
+
TopicUserListQuery,
|
|
77
|
+
UserDefaultDetail,
|
|
78
|
+
UserDefaultItem,
|
|
79
|
+
UserDefaultSaveRequest,
|
|
80
|
+
UserInfo,
|
|
81
|
+
UserLimitTime,
|
|
82
|
+
WebhookItem,
|
|
83
|
+
WebhookSaveRequest,
|
|
84
|
+
)
|
|
85
|
+
from .rate_limit import RateLimitGuard
|
|
86
|
+
|
|
87
|
+
__version__ = "1.0.0"
|
|
88
|
+
|
|
89
|
+
__all__ = [
|
|
90
|
+
"__version__",
|
|
91
|
+
"PushPlusClient",
|
|
92
|
+
"PushPlusClientBuilder",
|
|
93
|
+
"PushPlusConfig",
|
|
94
|
+
"DEFAULT_BASE_URL",
|
|
95
|
+
"PushPlusError",
|
|
96
|
+
"PushPlusException",
|
|
97
|
+
"AccessKeyManager",
|
|
98
|
+
"RateLimitGuard",
|
|
99
|
+
"HttpRequester",
|
|
100
|
+
"HttpResponse",
|
|
101
|
+
"RequestsHttpRequester",
|
|
102
|
+
"callback_parser",
|
|
103
|
+
"Channel",
|
|
104
|
+
"Template",
|
|
105
|
+
"CallbackEvent",
|
|
106
|
+
"SendStatus",
|
|
107
|
+
"WebhookType",
|
|
108
|
+
"ErrorCode",
|
|
109
|
+
"ApiResponse",
|
|
110
|
+
"PageQuery",
|
|
111
|
+
"PageResult",
|
|
112
|
+
"SendRequest",
|
|
113
|
+
"BatchSendRequest",
|
|
114
|
+
"BatchSendResult",
|
|
115
|
+
"CallbackPayload",
|
|
116
|
+
"MessageCompleteInfo",
|
|
117
|
+
"TopicUserInfo",
|
|
118
|
+
"CallbackFriendInfo",
|
|
119
|
+
"AccessKeyResult",
|
|
120
|
+
"MessageItem",
|
|
121
|
+
"SendMessageResult",
|
|
122
|
+
"UserInfo",
|
|
123
|
+
"UserLimitTime",
|
|
124
|
+
"SendCount",
|
|
125
|
+
"MessageTokenItem",
|
|
126
|
+
"MessageTokenOption",
|
|
127
|
+
"MessageTokenAddRequest",
|
|
128
|
+
"MessageTokenEditRequest",
|
|
129
|
+
"TopicItem",
|
|
130
|
+
"TopicDetail",
|
|
131
|
+
"TopicQrCode",
|
|
132
|
+
"TopicListQuery",
|
|
133
|
+
"TopicUserListQuery",
|
|
134
|
+
"TopicUserItem",
|
|
135
|
+
"TopicAddRequest",
|
|
136
|
+
"TopicEditRequest",
|
|
137
|
+
"FriendItem",
|
|
138
|
+
"FriendQrCode",
|
|
139
|
+
"WebhookItem",
|
|
140
|
+
"WebhookSaveRequest",
|
|
141
|
+
"MpItem",
|
|
142
|
+
"CpItem",
|
|
143
|
+
"MailItem",
|
|
144
|
+
"MailDetail",
|
|
145
|
+
"ClawBotQrCode",
|
|
146
|
+
"ClawBotInfo",
|
|
147
|
+
"ClawBotMessage",
|
|
148
|
+
"UserDefaultItem",
|
|
149
|
+
"UserDefaultDetail",
|
|
150
|
+
"UserDefaultSaveRequest",
|
|
151
|
+
"PreItem",
|
|
152
|
+
"PreDetail",
|
|
153
|
+
"PreSaveRequest",
|
|
154
|
+
"PreTestRequest",
|
|
155
|
+
]
|