nonebot-plugin-parsehub 0.1.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.
- nonebot_plugin_parsehub-0.1.0/LICENSE +21 -0
- nonebot_plugin_parsehub-0.1.0/PKG-INFO +275 -0
- nonebot_plugin_parsehub-0.1.0/README.md +248 -0
- nonebot_plugin_parsehub-0.1.0/pyproject.toml +109 -0
- nonebot_plugin_parsehub-0.1.0/pyproject.toml.orig +87 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/__init__.py +1298 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/baidu.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/bilibili.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/coolapk.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/douban.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/douyin.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/facebook.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/instagram.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/kuaishou.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/medium.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/pipix.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/snapchat.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/threads.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/tiktok.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/toutiao.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/wechat.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/weibo.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/x.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/xiaoheihe.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/xiaohongshu.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/youtube.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/zhihu.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/assets/logos/zuiyou.png +0 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/card.py +836 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/config.py +95 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/core.py +485 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/mediacache.py +418 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/server.py +241 -0
- nonebot_plugin_parsehub-0.1.0/src/nonebot_plugin_parsehub/switches.py +156 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ByteColtX
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nonebot-plugin-parsehub
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 基于 ParseHub 的社交媒体链接解析插件:群里出现分享链接时自动解析并发送媒体
|
|
5
|
+
Keywords: nonebot,nonebot2,plugin,parsehub,parser,media,onebot
|
|
6
|
+
Author: ByteColtX
|
|
7
|
+
Author-email: ByteColtX <umk@live.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Topic :: Communications :: Chat
|
|
15
|
+
Requires-Dist: httpx>=0.28.0,<1.0.0
|
|
16
|
+
Requires-Dist: nonebot-adapter-onebot>=2.4.6,<3.0.0
|
|
17
|
+
Requires-Dist: nonebot-plugin-localstore>=0.7.4,<1.0.0
|
|
18
|
+
Requires-Dist: nonebot2>=2.5.0,<3.0.0
|
|
19
|
+
Requires-Dist: parsehub>=2.3.3,<3.0.0
|
|
20
|
+
Requires-Dist: pillow>=12.1.0,<13.0.0
|
|
21
|
+
Requires-Dist: pydantic>=2.0.0,<3.0.0
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Project-URL: Homepage, https://github.com/ByteColtX/nonebot-plugin-parsehub
|
|
24
|
+
Project-URL: Repository, https://github.com/ByteColtX/nonebot-plugin-parsehub.git
|
|
25
|
+
Project-URL: Issues, https://github.com/ByteColtX/nonebot-plugin-parsehub/issues
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
## ✨ nonebot-plugin-parsehub ✨
|
|
29
|
+
|
|
30
|
+
[](./LICENSE)
|
|
31
|
+
[](https://pypi.python.org/pypi/nonebot-plugin-parsehub)
|
|
32
|
+
[](https://www.python.org)
|
|
33
|
+
[](https://github.com/astral-sh/uv)
|
|
34
|
+
|
|
35
|
+
[](https://github.com/astral-sh/ruff)
|
|
36
|
+
[](https://github.com/ByteColtX/nonebot-plugin-parsehub/actions/workflows/ci.yml)
|
|
37
|
+
|
|
38
|
+
## 📖 介绍
|
|
39
|
+
|
|
40
|
+
基于 [ParseHub](https://github.com/z-mio/ParseHub) 的社交媒体链接解析插件:群里出现受支持的分享链接时自动解析,
|
|
41
|
+
把视频 / 图集 / 图文发出来,并配一张 App Store「Today」风格的信息卡片。
|
|
42
|
+
|
|
43
|
+
- **自动解析**:群消息里出现受支持的链接时自动处理,也可用命令手动触发
|
|
44
|
+
- **按会话开关**:`解析开关` 可以把某个群 / 某个私聊的解析关掉,超管和群管理可操作
|
|
45
|
+
- **24 个平台**:Bilibili、抖音、小红书、微博、快手、知乎、贴吧、豆瓣、今日头条、微信公众号、微信视频号、酷安、皮皮虾、最右、小黑盒、Bangumi、X/Twitter、Instagram、YouTube、TikTok、Threads、Facebook、Snapchat、Medium
|
|
46
|
+
- **多媒体合并转发**:一个帖子有 2 个以上媒体时合并成一条转发消息(标题那条文字不算);
|
|
47
|
+
转发卡片上的名字取自 `NICKNAME` 的**第一项**(读原始配置保证顺序稳定,没配才退回 `ParseHub`)
|
|
48
|
+
- **信息卡片**:先发一张 App Store「Today」风格的信息卡(封面铺满 + 底部渐变 + 标题 / 时长),再发媒体;
|
|
49
|
+
平台图标与「平台名」同一行(左边缘对齐正文),带品牌色的图标保留原色,只有纯黑白的标在深色封面上才转成白色剪影
|
|
50
|
+
- **实况照片**:图片 + 短视频一起发
|
|
51
|
+
- **视频消息段**:直接发视频,不占用群文件
|
|
52
|
+
- **表情回应**:不引用原消息,改为给触发消息点表情(收到 / 成功 / 失败)
|
|
53
|
+
- **代理按平台分流**:只给海外平台走代理,国内平台直连
|
|
54
|
+
- **体积 / 时长保护 / 去重 / 并发限制 / 临时文件自动清理**(去重只作用于同一会话,跨会话不限制)
|
|
55
|
+
- **时长保护**:视频超过 `PARSEHUB_MAX_SECONDS`(默认 5 分钟)时不下载,只发封面卡片 + 一句「视频太长啦,还是去 xx 看吧」
|
|
56
|
+
- **媒体缓存**:同一作品 24 小时内再出现,直接发本地那份,不再解析下载
|
|
57
|
+
|
|
58
|
+
## 🎨 效果图
|
|
59
|
+
|
|
60
|
+
B 站视频卡片:
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
抖音图集卡片:
|
|
65
|
+
|
|
66
|
+

|
|
67
|
+
|
|
68
|
+
## 💿 安装
|
|
69
|
+
|
|
70
|
+
使用 nb-cli 安装
|
|
71
|
+
|
|
72
|
+
在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
nb plugin install nonebot-plugin-parsehub --upgrade
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
使用 **pypi** 源安装
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
nb plugin install nonebot-plugin-parsehub --upgrade -i "https://pypi.org/simple"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
使用**清华源**安装
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
nb plugin install nonebot-plugin-parsehub --upgrade -i "https://pypi.tuna.tsinghua.edu.cn/simple"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
使用包管理器安装
|
|
91
|
+
|
|
92
|
+
在 nonebot2 项目的插件目录下, 打开命令行, 根据你使用的包管理器, 输入相应的安装命令
|
|
93
|
+
|
|
94
|
+
uv
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
uv add nonebot-plugin-parsehub
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
安装仓库 main 分支
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
uv add git+https://github.com/ByteColtX/nonebot-plugin-parsehub@main
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
pdm
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pdm add nonebot-plugin-parsehub
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
安装仓库 main 分支
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pdm add git+https://github.com/ByteColtX/nonebot-plugin-parsehub@main
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
poetry
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
poetry add nonebot-plugin-parsehub
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
安装仓库 main 分支
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
poetry add git+https://github.com/ByteColtX/nonebot-plugin-parsehub@main
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
打开 nonebot2 项目根目录下的 `pyproject.toml` 文件, 在 `[tool.nonebot]` 部分追加写入
|
|
131
|
+
|
|
132
|
+
```toml
|
|
133
|
+
plugins = ["nonebot_plugin_parsehub"]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
使用 nbr 安装(使用 uv 管理依赖可用)
|
|
137
|
+
|
|
138
|
+
[nbr](https://github.com/fllesser/nbr) 是一个基于 uv 的 nb-cli,可以方便地管理 nonebot2
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
nbr plugin install nonebot-plugin-parsehub
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
使用 **pypi** 源安装
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
nbr plugin install nonebot-plugin-parsehub -i "https://pypi.org/simple"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
使用**清华源**安装
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
nbr plugin install nonebot-plugin-parsehub -i "https://pypi.tuna.tsinghua.edu.cn/simple"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## ⚙️ 配置
|
|
157
|
+
|
|
158
|
+
在 nonebot2 项目的`.env`文件中添加下表中的配置, 全部可选(零配置即可加载运行)
|
|
159
|
+
|
|
160
|
+
| 配置项 | 必填 | 默认值 | 说明 |
|
|
161
|
+
| :---: | :---: | :---: | :--- |
|
|
162
|
+
| `PARSEHUB_AUTO` | 否 | `true` | 群里出现链接时自动解析(总开关) |
|
|
163
|
+
| `PARSEHUB_MAX_MB` | 否 | `100` | 单个媒体文件体积上限(MB),超过直接跳过;`0` = 不限 |
|
|
164
|
+
| `PARSEHUB_MAX_SECONDS` | 否 | `300` | 视频时长上限(秒),超过只发封面 + 一句提示、不下载;`0` = 不限 |
|
|
165
|
+
| `PARSEHUB_DEDUPE_SECONDS` | 否 | `120` | 同一会话内同一链接的去重窗口(秒),`0` = 不去重 |
|
|
166
|
+
| `PARSEHUB_CONCURRENCY` | 否 | `2` | 同时处理的任务数 |
|
|
167
|
+
| `PARSEHUB_PROXY` | 否 | 无 | 解析 / 下载代理,如 `http://127.0.0.1:7890` |
|
|
168
|
+
| `PARSEHUB_PROXY_PLATFORMS` | 否 | 海外 8 平台 | 只对这些平台走代理,留空 = 全部走(列表要用合法 JSON) |
|
|
169
|
+
| `PARSEHUB_COOKIE` | 否 | 无 | 兜底 cookie(优先读 parsehub 自己的 `cookies.toml`) |
|
|
170
|
+
| `PARSEHUB_TIMEOUT` | 否 | `180` | 解析 + 下载总超时(秒) |
|
|
171
|
+
| `PARSEHUB_CACHE_HOURS` | 否 | `24` | 媒体缓存保留小时数,命中就直接发本地那份;`0` = 关闭缓存 |
|
|
172
|
+
| `PARSEHUB_CACHE_MAX_MB` | 否 | `1024` | 媒体缓存总容量上限(MB),超了按最久没用过的删 |
|
|
173
|
+
| `PARSEHUB_CARD` | 否 | `true` | 是否发信息卡片图(失败自动退回文字) |
|
|
174
|
+
| `PARSEHUB_CARD_FONT` | 否 | 无 | 中文字体路径,留空则自动找系统字体 / 下载 |
|
|
175
|
+
| `PARSEHUB_FORWARD_TIMEOUT` | 否 | `60` | 合并转发等待协议端的秒数,超时才逐条发 |
|
|
176
|
+
| `PARSEHUB_SEND_TEXT` | 否 | `true` | 是否发送标题 / 正文 |
|
|
177
|
+
| `PARSEHUB_MAX_CHARS` | 否 | `300` | 正文最多发送多少字符 |
|
|
178
|
+
| `PARSEHUB_FAIL_NOTICE` | 否 | `true` | 视频发送失败时是否额外发文字提示 |
|
|
179
|
+
| `PARSEHUB_FILES_HOST` | 否 | 无 | 媒体中转服务对外地址,留空自动探测内网 IP |
|
|
180
|
+
| `PARSEHUB_FILES_PORT` | 否 | `21473` | 媒体中转服务端口 |
|
|
181
|
+
| `PARSEHUB_KEEP_MINUTES` | 否 | `30` | 临时文件保留分钟数 |
|
|
182
|
+
|
|
183
|
+
> 列表类配置必须是合法 JSON,例如 `PARSEHUB_PROXY_PLATFORMS=["twitter", "youtube"]`。
|
|
184
|
+
> 哪些群 / 私聊解析由命令 `解析开关` 控制(见下),没有对应的配置项。
|
|
185
|
+
|
|
186
|
+
需要登录态的平台(X、Instagram、TikTok、豆瓣、微信视频号 等),cookie 优先从 ParseHub 自己的配置读取
|
|
187
|
+
(`ph set cookie <平台>`),也可以直接用 `PARSEHUB_COOKIE` 兜底。
|
|
188
|
+
|
|
189
|
+
## 🎉 使用
|
|
190
|
+
|
|
191
|
+
### 指令表
|
|
192
|
+
|
|
193
|
+
| 指令 | 权限 | 需要@ | 范围 | 说明 |
|
|
194
|
+
| :---: | :---: | :---: | :---: | :--- |
|
|
195
|
+
| `解析 <链接或分享文案>`(别名 `ph`、`解析链接`) | 群员 | 否 | 群聊/私聊 | 手动解析,不做去重拦截 |
|
|
196
|
+
| `解析平台` | 群员 | 否 | 群聊/私聊 | 列出支持的平台 |
|
|
197
|
+
| `解析开关 [开\|关]`、`解析开`、`解析关` | 主人/群管 | 否 | 群聊/私聊 | 按会话开关解析(私聊仅主人) |
|
|
198
|
+
| `解析状态` | 群员 | 否 | 群聊/私聊 | 查看当前会话的开关状态 |
|
|
199
|
+
|
|
200
|
+
### 触发规则
|
|
201
|
+
|
|
202
|
+
- **自动**:群里发一条分享链接(或直接粘贴分享文案)即可,插件从文本里挑出受支持的链接
|
|
203
|
+
- 一条消息最多处理 **3 个**链接
|
|
204
|
+
- 会话被 `解析关` 关掉后,自动解析停止,手动 `解析` 也只对主人 / 群管理有效
|
|
205
|
+
- 命令前缀支持空前缀与 `/`(`COMMAND_START` 需包含 `""`)
|
|
206
|
+
|
|
207
|
+
### 解析开关
|
|
208
|
+
|
|
209
|
+
以**会话**为维度(群按群号,私聊按对方 QQ),只影响该会话:
|
|
210
|
+
|
|
211
|
+
- **默认值**:群和私聊**都默认开**
|
|
212
|
+
- 关掉之后:该会话里的链接**不再自动解析**;手动 `解析` 也只有超管和群管理能用
|
|
213
|
+
- **谁能操作**:`SUPERUSERS` 里的超管,以及群主 / 群管理员(私聊只有超管)
|
|
214
|
+
- **谁能看状态**:所有人(`解析状态`)
|
|
215
|
+
- 状态存在插件数据目录的 `sessions.json`(`nonebot-plugin-localstore` 的 data dir),
|
|
216
|
+
只记录和默认值不同的会话(关掉的群、打开的私聊),文件一直很小
|
|
217
|
+
|
|
218
|
+
### 媒体缓存
|
|
219
|
+
|
|
220
|
+
下载好的媒体按**作品**存一份,同一个作品再出现时直接发本地那份:
|
|
221
|
+
|
|
222
|
+
- **按作品存,不按会话**:A 群发过的视频,B 群再发也是直接发本地那份
|
|
223
|
+
- **命中即跳过**:不解析、不下载、不画卡(卡片图也一起缓存)
|
|
224
|
+
- **识别不同写法**:`b23.tv/xxx` 与 `bilibili.com/video/BVxxx`、`v.douyin.com/xxx`
|
|
225
|
+
与 `iesdouyin.com/share/video/<id>` 是同一个作品
|
|
226
|
+
- **保留 24 小时**(用过的会续期),总量上限 1GB,超了按最久没用过的删
|
|
227
|
+
- 时间线上的三种情况:**120 秒内**同一会话重复 → 静默(去重);**120 秒后 ~ 24 小时内**
|
|
228
|
+
→ 直接发缓存;**超过 24 小时** → 重新解析下载
|
|
229
|
+
- 手动 `解析 <链接>` 同样吃缓存(只是不做去重拦截)
|
|
230
|
+
|
|
231
|
+
### 说明
|
|
232
|
+
|
|
233
|
+
- 视频走 `video` 消息段,被协议端拒绝时只回应失败表情,**不会**退回群文件
|
|
234
|
+
- 媒体先落到本机临时目录,再通过内置的只读 HTTP 服务给协议端一个 `http://` 地址
|
|
235
|
+
(协议端常在另一台机器上,读不到本机 `file://` 路径),过期自动清理
|
|
236
|
+
- parsehub 全程是同步阻塞的,插件把所有调用放进 `asyncio.to_thread`,不会阻塞事件循环
|
|
237
|
+
- 解析器首次导入需要几秒(numpy + opencv),插件采用懒加载,不影响机器人启动
|
|
238
|
+
- 信息卡片用 Pillow 画,封面三级兜底:`thumb_url` → 本身就是图片的媒体 → 本地视频抽首帧;
|
|
239
|
+
渲染走 `asyncio.to_thread`(armv7 上单张约 0.3s),没装 Pillow 或没有中文字体时自动退回纯文字
|
|
240
|
+
- 中文字体优先用 `PARSEHUB_CARD_FONT`,其次是插件缓存目录里的 `NotoSansSC.ttf`,
|
|
241
|
+
再是系统字体,都没有才下载(首次下载约 18MB,之后走缓存)
|
|
242
|
+
|
|
243
|
+
## 🛠️ 开发
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
uv sync --all-groups # 安装依赖(含测试)
|
|
247
|
+
uv run pytest -q # 跑测试
|
|
248
|
+
uv run ruff check . # 代码检查
|
|
249
|
+
uv run ruff format --check . # 格式检查
|
|
250
|
+
uv run python live_check.py # 真实链路自检(解析 → 下载 → 中转取回)
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### 代码风格
|
|
254
|
+
|
|
255
|
+
遵循 [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html):
|
|
256
|
+
|
|
257
|
+
- 行宽 80,模块 / 类 / 函数一律写 Google 风格文档字符串
|
|
258
|
+
(`Args` / `Returns` / `Raises`,类属性写在 `Attributes` 段)
|
|
259
|
+
- 常量用 `UPPER_SNAKE_CASE`,私有成员以 `_` 开头
|
|
260
|
+
- 第三方与框架模块用绝对导入,由 ruff 的 `isort` 排序
|
|
261
|
+
- 由 ruff 强制:`pydocstyle(google)` + `pep8-naming` + `isort`
|
|
262
|
+
|
|
263
|
+
有意保留的偏差(都写在代码注释或 `pyproject.toml` 里):
|
|
264
|
+
|
|
265
|
+
- **包内用相对导入**(`from .config import ...`):插件既可能作为已安装的包加载,
|
|
266
|
+
也可能作为 `src/plugins` 下的本地插件加载(模块名带前缀),绝对自引用在后一种
|
|
267
|
+
情况下会直接 ImportError
|
|
268
|
+
- 框架惯用法:`from nonebot import on_message` 这类按名字导入无法避免
|
|
269
|
+
(Google 只允许导入模块,而 NoneBot 的插件 API 就是按名字导入的)
|
|
270
|
+
- 中文文档字符串以「。」结尾,因此关闭 `D415`
|
|
271
|
+
- 测试函数名本身就是说明,测试目录不强制文档字符串
|
|
272
|
+
|
|
273
|
+
## 📄 许可
|
|
274
|
+
|
|
275
|
+
[MIT](LICENSE) · 解析能力来自 [ParseHub](https://github.com/z-mio/ParseHub)
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
## ✨ nonebot-plugin-parsehub ✨
|
|
2
|
+
|
|
3
|
+
[](./LICENSE)
|
|
4
|
+
[](https://pypi.python.org/pypi/nonebot-plugin-parsehub)
|
|
5
|
+
[](https://www.python.org)
|
|
6
|
+
[](https://github.com/astral-sh/uv)
|
|
7
|
+
|
|
8
|
+
[](https://github.com/astral-sh/ruff)
|
|
9
|
+
[](https://github.com/ByteColtX/nonebot-plugin-parsehub/actions/workflows/ci.yml)
|
|
10
|
+
|
|
11
|
+
## 📖 介绍
|
|
12
|
+
|
|
13
|
+
基于 [ParseHub](https://github.com/z-mio/ParseHub) 的社交媒体链接解析插件:群里出现受支持的分享链接时自动解析,
|
|
14
|
+
把视频 / 图集 / 图文发出来,并配一张 App Store「Today」风格的信息卡片。
|
|
15
|
+
|
|
16
|
+
- **自动解析**:群消息里出现受支持的链接时自动处理,也可用命令手动触发
|
|
17
|
+
- **按会话开关**:`解析开关` 可以把某个群 / 某个私聊的解析关掉,超管和群管理可操作
|
|
18
|
+
- **24 个平台**:Bilibili、抖音、小红书、微博、快手、知乎、贴吧、豆瓣、今日头条、微信公众号、微信视频号、酷安、皮皮虾、最右、小黑盒、Bangumi、X/Twitter、Instagram、YouTube、TikTok、Threads、Facebook、Snapchat、Medium
|
|
19
|
+
- **多媒体合并转发**:一个帖子有 2 个以上媒体时合并成一条转发消息(标题那条文字不算);
|
|
20
|
+
转发卡片上的名字取自 `NICKNAME` 的**第一项**(读原始配置保证顺序稳定,没配才退回 `ParseHub`)
|
|
21
|
+
- **信息卡片**:先发一张 App Store「Today」风格的信息卡(封面铺满 + 底部渐变 + 标题 / 时长),再发媒体;
|
|
22
|
+
平台图标与「平台名」同一行(左边缘对齐正文),带品牌色的图标保留原色,只有纯黑白的标在深色封面上才转成白色剪影
|
|
23
|
+
- **实况照片**:图片 + 短视频一起发
|
|
24
|
+
- **视频消息段**:直接发视频,不占用群文件
|
|
25
|
+
- **表情回应**:不引用原消息,改为给触发消息点表情(收到 / 成功 / 失败)
|
|
26
|
+
- **代理按平台分流**:只给海外平台走代理,国内平台直连
|
|
27
|
+
- **体积 / 时长保护 / 去重 / 并发限制 / 临时文件自动清理**(去重只作用于同一会话,跨会话不限制)
|
|
28
|
+
- **时长保护**:视频超过 `PARSEHUB_MAX_SECONDS`(默认 5 分钟)时不下载,只发封面卡片 + 一句「视频太长啦,还是去 xx 看吧」
|
|
29
|
+
- **媒体缓存**:同一作品 24 小时内再出现,直接发本地那份,不再解析下载
|
|
30
|
+
|
|
31
|
+
## 🎨 效果图
|
|
32
|
+
|
|
33
|
+
B 站视频卡片:
|
|
34
|
+
|
|
35
|
+

|
|
36
|
+
|
|
37
|
+
抖音图集卡片:
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
## 💿 安装
|
|
42
|
+
|
|
43
|
+
使用 nb-cli 安装
|
|
44
|
+
|
|
45
|
+
在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
nb plugin install nonebot-plugin-parsehub --upgrade
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
使用 **pypi** 源安装
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
nb plugin install nonebot-plugin-parsehub --upgrade -i "https://pypi.org/simple"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
使用**清华源**安装
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
nb plugin install nonebot-plugin-parsehub --upgrade -i "https://pypi.tuna.tsinghua.edu.cn/simple"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
使用包管理器安装
|
|
64
|
+
|
|
65
|
+
在 nonebot2 项目的插件目录下, 打开命令行, 根据你使用的包管理器, 输入相应的安装命令
|
|
66
|
+
|
|
67
|
+
uv
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
uv add nonebot-plugin-parsehub
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
安装仓库 main 分支
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
uv add git+https://github.com/ByteColtX/nonebot-plugin-parsehub@main
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
pdm
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pdm add nonebot-plugin-parsehub
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
安装仓库 main 分支
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pdm add git+https://github.com/ByteColtX/nonebot-plugin-parsehub@main
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
poetry
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
poetry add nonebot-plugin-parsehub
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
安装仓库 main 分支
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
poetry add git+https://github.com/ByteColtX/nonebot-plugin-parsehub@main
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
打开 nonebot2 项目根目录下的 `pyproject.toml` 文件, 在 `[tool.nonebot]` 部分追加写入
|
|
104
|
+
|
|
105
|
+
```toml
|
|
106
|
+
plugins = ["nonebot_plugin_parsehub"]
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
使用 nbr 安装(使用 uv 管理依赖可用)
|
|
110
|
+
|
|
111
|
+
[nbr](https://github.com/fllesser/nbr) 是一个基于 uv 的 nb-cli,可以方便地管理 nonebot2
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
nbr plugin install nonebot-plugin-parsehub
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
使用 **pypi** 源安装
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
nbr plugin install nonebot-plugin-parsehub -i "https://pypi.org/simple"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
使用**清华源**安装
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
nbr plugin install nonebot-plugin-parsehub -i "https://pypi.tuna.tsinghua.edu.cn/simple"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## ⚙️ 配置
|
|
130
|
+
|
|
131
|
+
在 nonebot2 项目的`.env`文件中添加下表中的配置, 全部可选(零配置即可加载运行)
|
|
132
|
+
|
|
133
|
+
| 配置项 | 必填 | 默认值 | 说明 |
|
|
134
|
+
| :---: | :---: | :---: | :--- |
|
|
135
|
+
| `PARSEHUB_AUTO` | 否 | `true` | 群里出现链接时自动解析(总开关) |
|
|
136
|
+
| `PARSEHUB_MAX_MB` | 否 | `100` | 单个媒体文件体积上限(MB),超过直接跳过;`0` = 不限 |
|
|
137
|
+
| `PARSEHUB_MAX_SECONDS` | 否 | `300` | 视频时长上限(秒),超过只发封面 + 一句提示、不下载;`0` = 不限 |
|
|
138
|
+
| `PARSEHUB_DEDUPE_SECONDS` | 否 | `120` | 同一会话内同一链接的去重窗口(秒),`0` = 不去重 |
|
|
139
|
+
| `PARSEHUB_CONCURRENCY` | 否 | `2` | 同时处理的任务数 |
|
|
140
|
+
| `PARSEHUB_PROXY` | 否 | 无 | 解析 / 下载代理,如 `http://127.0.0.1:7890` |
|
|
141
|
+
| `PARSEHUB_PROXY_PLATFORMS` | 否 | 海外 8 平台 | 只对这些平台走代理,留空 = 全部走(列表要用合法 JSON) |
|
|
142
|
+
| `PARSEHUB_COOKIE` | 否 | 无 | 兜底 cookie(优先读 parsehub 自己的 `cookies.toml`) |
|
|
143
|
+
| `PARSEHUB_TIMEOUT` | 否 | `180` | 解析 + 下载总超时(秒) |
|
|
144
|
+
| `PARSEHUB_CACHE_HOURS` | 否 | `24` | 媒体缓存保留小时数,命中就直接发本地那份;`0` = 关闭缓存 |
|
|
145
|
+
| `PARSEHUB_CACHE_MAX_MB` | 否 | `1024` | 媒体缓存总容量上限(MB),超了按最久没用过的删 |
|
|
146
|
+
| `PARSEHUB_CARD` | 否 | `true` | 是否发信息卡片图(失败自动退回文字) |
|
|
147
|
+
| `PARSEHUB_CARD_FONT` | 否 | 无 | 中文字体路径,留空则自动找系统字体 / 下载 |
|
|
148
|
+
| `PARSEHUB_FORWARD_TIMEOUT` | 否 | `60` | 合并转发等待协议端的秒数,超时才逐条发 |
|
|
149
|
+
| `PARSEHUB_SEND_TEXT` | 否 | `true` | 是否发送标题 / 正文 |
|
|
150
|
+
| `PARSEHUB_MAX_CHARS` | 否 | `300` | 正文最多发送多少字符 |
|
|
151
|
+
| `PARSEHUB_FAIL_NOTICE` | 否 | `true` | 视频发送失败时是否额外发文字提示 |
|
|
152
|
+
| `PARSEHUB_FILES_HOST` | 否 | 无 | 媒体中转服务对外地址,留空自动探测内网 IP |
|
|
153
|
+
| `PARSEHUB_FILES_PORT` | 否 | `21473` | 媒体中转服务端口 |
|
|
154
|
+
| `PARSEHUB_KEEP_MINUTES` | 否 | `30` | 临时文件保留分钟数 |
|
|
155
|
+
|
|
156
|
+
> 列表类配置必须是合法 JSON,例如 `PARSEHUB_PROXY_PLATFORMS=["twitter", "youtube"]`。
|
|
157
|
+
> 哪些群 / 私聊解析由命令 `解析开关` 控制(见下),没有对应的配置项。
|
|
158
|
+
|
|
159
|
+
需要登录态的平台(X、Instagram、TikTok、豆瓣、微信视频号 等),cookie 优先从 ParseHub 自己的配置读取
|
|
160
|
+
(`ph set cookie <平台>`),也可以直接用 `PARSEHUB_COOKIE` 兜底。
|
|
161
|
+
|
|
162
|
+
## 🎉 使用
|
|
163
|
+
|
|
164
|
+
### 指令表
|
|
165
|
+
|
|
166
|
+
| 指令 | 权限 | 需要@ | 范围 | 说明 |
|
|
167
|
+
| :---: | :---: | :---: | :---: | :--- |
|
|
168
|
+
| `解析 <链接或分享文案>`(别名 `ph`、`解析链接`) | 群员 | 否 | 群聊/私聊 | 手动解析,不做去重拦截 |
|
|
169
|
+
| `解析平台` | 群员 | 否 | 群聊/私聊 | 列出支持的平台 |
|
|
170
|
+
| `解析开关 [开\|关]`、`解析开`、`解析关` | 主人/群管 | 否 | 群聊/私聊 | 按会话开关解析(私聊仅主人) |
|
|
171
|
+
| `解析状态` | 群员 | 否 | 群聊/私聊 | 查看当前会话的开关状态 |
|
|
172
|
+
|
|
173
|
+
### 触发规则
|
|
174
|
+
|
|
175
|
+
- **自动**:群里发一条分享链接(或直接粘贴分享文案)即可,插件从文本里挑出受支持的链接
|
|
176
|
+
- 一条消息最多处理 **3 个**链接
|
|
177
|
+
- 会话被 `解析关` 关掉后,自动解析停止,手动 `解析` 也只对主人 / 群管理有效
|
|
178
|
+
- 命令前缀支持空前缀与 `/`(`COMMAND_START` 需包含 `""`)
|
|
179
|
+
|
|
180
|
+
### 解析开关
|
|
181
|
+
|
|
182
|
+
以**会话**为维度(群按群号,私聊按对方 QQ),只影响该会话:
|
|
183
|
+
|
|
184
|
+
- **默认值**:群和私聊**都默认开**
|
|
185
|
+
- 关掉之后:该会话里的链接**不再自动解析**;手动 `解析` 也只有超管和群管理能用
|
|
186
|
+
- **谁能操作**:`SUPERUSERS` 里的超管,以及群主 / 群管理员(私聊只有超管)
|
|
187
|
+
- **谁能看状态**:所有人(`解析状态`)
|
|
188
|
+
- 状态存在插件数据目录的 `sessions.json`(`nonebot-plugin-localstore` 的 data dir),
|
|
189
|
+
只记录和默认值不同的会话(关掉的群、打开的私聊),文件一直很小
|
|
190
|
+
|
|
191
|
+
### 媒体缓存
|
|
192
|
+
|
|
193
|
+
下载好的媒体按**作品**存一份,同一个作品再出现时直接发本地那份:
|
|
194
|
+
|
|
195
|
+
- **按作品存,不按会话**:A 群发过的视频,B 群再发也是直接发本地那份
|
|
196
|
+
- **命中即跳过**:不解析、不下载、不画卡(卡片图也一起缓存)
|
|
197
|
+
- **识别不同写法**:`b23.tv/xxx` 与 `bilibili.com/video/BVxxx`、`v.douyin.com/xxx`
|
|
198
|
+
与 `iesdouyin.com/share/video/<id>` 是同一个作品
|
|
199
|
+
- **保留 24 小时**(用过的会续期),总量上限 1GB,超了按最久没用过的删
|
|
200
|
+
- 时间线上的三种情况:**120 秒内**同一会话重复 → 静默(去重);**120 秒后 ~ 24 小时内**
|
|
201
|
+
→ 直接发缓存;**超过 24 小时** → 重新解析下载
|
|
202
|
+
- 手动 `解析 <链接>` 同样吃缓存(只是不做去重拦截)
|
|
203
|
+
|
|
204
|
+
### 说明
|
|
205
|
+
|
|
206
|
+
- 视频走 `video` 消息段,被协议端拒绝时只回应失败表情,**不会**退回群文件
|
|
207
|
+
- 媒体先落到本机临时目录,再通过内置的只读 HTTP 服务给协议端一个 `http://` 地址
|
|
208
|
+
(协议端常在另一台机器上,读不到本机 `file://` 路径),过期自动清理
|
|
209
|
+
- parsehub 全程是同步阻塞的,插件把所有调用放进 `asyncio.to_thread`,不会阻塞事件循环
|
|
210
|
+
- 解析器首次导入需要几秒(numpy + opencv),插件采用懒加载,不影响机器人启动
|
|
211
|
+
- 信息卡片用 Pillow 画,封面三级兜底:`thumb_url` → 本身就是图片的媒体 → 本地视频抽首帧;
|
|
212
|
+
渲染走 `asyncio.to_thread`(armv7 上单张约 0.3s),没装 Pillow 或没有中文字体时自动退回纯文字
|
|
213
|
+
- 中文字体优先用 `PARSEHUB_CARD_FONT`,其次是插件缓存目录里的 `NotoSansSC.ttf`,
|
|
214
|
+
再是系统字体,都没有才下载(首次下载约 18MB,之后走缓存)
|
|
215
|
+
|
|
216
|
+
## 🛠️ 开发
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
uv sync --all-groups # 安装依赖(含测试)
|
|
220
|
+
uv run pytest -q # 跑测试
|
|
221
|
+
uv run ruff check . # 代码检查
|
|
222
|
+
uv run ruff format --check . # 格式检查
|
|
223
|
+
uv run python live_check.py # 真实链路自检(解析 → 下载 → 中转取回)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### 代码风格
|
|
227
|
+
|
|
228
|
+
遵循 [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html):
|
|
229
|
+
|
|
230
|
+
- 行宽 80,模块 / 类 / 函数一律写 Google 风格文档字符串
|
|
231
|
+
(`Args` / `Returns` / `Raises`,类属性写在 `Attributes` 段)
|
|
232
|
+
- 常量用 `UPPER_SNAKE_CASE`,私有成员以 `_` 开头
|
|
233
|
+
- 第三方与框架模块用绝对导入,由 ruff 的 `isort` 排序
|
|
234
|
+
- 由 ruff 强制:`pydocstyle(google)` + `pep8-naming` + `isort`
|
|
235
|
+
|
|
236
|
+
有意保留的偏差(都写在代码注释或 `pyproject.toml` 里):
|
|
237
|
+
|
|
238
|
+
- **包内用相对导入**(`from .config import ...`):插件既可能作为已安装的包加载,
|
|
239
|
+
也可能作为 `src/plugins` 下的本地插件加载(模块名带前缀),绝对自引用在后一种
|
|
240
|
+
情况下会直接 ImportError
|
|
241
|
+
- 框架惯用法:`from nonebot import on_message` 这类按名字导入无法避免
|
|
242
|
+
(Google 只允许导入模块,而 NoneBot 的插件 API 就是按名字导入的)
|
|
243
|
+
- 中文文档字符串以「。」结尾,因此关闭 `D415`
|
|
244
|
+
- 测试函数名本身就是说明,测试目录不强制文档字符串
|
|
245
|
+
|
|
246
|
+
## 📄 许可
|
|
247
|
+
|
|
248
|
+
[MIT](LICENSE) · 解析能力来自 [ParseHub](https://github.com/z-mio/ParseHub)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "nonebot-plugin-parsehub"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "基于 ParseHub 的社交媒体链接解析插件:群里出现分享链接时自动解析并发送媒体"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
keywords = [
|
|
10
|
+
"nonebot",
|
|
11
|
+
"nonebot2",
|
|
12
|
+
"plugin",
|
|
13
|
+
"parsehub",
|
|
14
|
+
"parser",
|
|
15
|
+
"media",
|
|
16
|
+
"onebot",
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Topic :: Communications :: Chat",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"httpx>=0.28.0,<1.0.0",
|
|
27
|
+
"nonebot-adapter-onebot>=2.4.6,<3.0.0",
|
|
28
|
+
"nonebot-plugin-localstore>=0.7.4,<1.0.0",
|
|
29
|
+
"nonebot2>=2.5.0,<3.0.0",
|
|
30
|
+
"parsehub>=2.3.3,<3.0.0",
|
|
31
|
+
"pillow>=12.1.0,<13.0.0",
|
|
32
|
+
"pydantic>=2.0.0,<3.0.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[[project.authors]]
|
|
36
|
+
name = "ByteColtX"
|
|
37
|
+
email = "umk@live.com"
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/ByteColtX/nonebot-plugin-parsehub"
|
|
41
|
+
Repository = "https://github.com/ByteColtX/nonebot-plugin-parsehub.git"
|
|
42
|
+
Issues = "https://github.com/ByteColtX/nonebot-plugin-parsehub/issues"
|
|
43
|
+
|
|
44
|
+
[dependency-groups]
|
|
45
|
+
dev = [
|
|
46
|
+
{ include-group = "test" },
|
|
47
|
+
"nonebot2[fastapi]>=2.5.0,<3.0.0",
|
|
48
|
+
"poethepoet>=0.42.1",
|
|
49
|
+
"ruff>=0.15.2,<1.0.0",
|
|
50
|
+
]
|
|
51
|
+
test = [
|
|
52
|
+
"nonebot-adapter-onebot>=2.4.6,<3.0.0",
|
|
53
|
+
"nonebot2[fastapi]>=2.5.0,<3.0.0",
|
|
54
|
+
"nonebug>=0.4.4,<1.0.0",
|
|
55
|
+
"pytest>=9.0.2,<10.0.0",
|
|
56
|
+
"pytest-asyncio>=1.3.0,<2.0.0",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[build-system]
|
|
60
|
+
requires = ["uv_build>=0.10.0"]
|
|
61
|
+
build-backend = "uv_build"
|
|
62
|
+
|
|
63
|
+
[tool.nonebot]
|
|
64
|
+
plugins = ["nonebot_plugin_parsehub"]
|
|
65
|
+
|
|
66
|
+
[tool.poe.tasks]
|
|
67
|
+
test = "pytest -q"
|
|
68
|
+
|
|
69
|
+
[tool.pytest.ini_options]
|
|
70
|
+
asyncio_mode = "auto"
|
|
71
|
+
asyncio_default_fixture_loop_scope = "session"
|
|
72
|
+
testpaths = ["tests"]
|
|
73
|
+
|
|
74
|
+
[tool.ruff]
|
|
75
|
+
line-length = 80
|
|
76
|
+
target-version = "py312"
|
|
77
|
+
|
|
78
|
+
[tool.ruff.lint]
|
|
79
|
+
select = [
|
|
80
|
+
"E",
|
|
81
|
+
"W",
|
|
82
|
+
"F",
|
|
83
|
+
"I",
|
|
84
|
+
"B",
|
|
85
|
+
"C4",
|
|
86
|
+
"UP",
|
|
87
|
+
"D",
|
|
88
|
+
"N",
|
|
89
|
+
]
|
|
90
|
+
ignore = [
|
|
91
|
+
"B008",
|
|
92
|
+
"C901",
|
|
93
|
+
"D203",
|
|
94
|
+
"D213",
|
|
95
|
+
"N818",
|
|
96
|
+
"D415",
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
[tool.ruff.lint.pydocstyle]
|
|
100
|
+
convention = "google"
|
|
101
|
+
|
|
102
|
+
[tool.ruff.lint.per-file-ignores]
|
|
103
|
+
"tests/**" = [
|
|
104
|
+
"D",
|
|
105
|
+
"E501",
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
[tool.ruff.lint.isort]
|
|
109
|
+
known-first-party = ["nonebot_plugin_parsehub"]
|