nonebot-plugin-parser 2.2.2__tar.gz → 2.2.3__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_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/PKG-INFO +14 -10
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/README.md +4 -1
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/pyproject.toml +72 -72
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/config.py +12 -6
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/download/__init__.py +7 -7
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/download/task.py +2 -2
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/download/ytdlp.py +33 -31
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/helper.py +9 -9
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/matchers/__init__.py +5 -5
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/__init__.py +18 -15
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/acfun.py +7 -7
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/base.py +10 -10
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/bilibili/__init__.py +11 -11
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/bilibili/opus.py +5 -2
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/data.py +4 -4
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/douyin/__init__.py +13 -3
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/kuaishou.py +7 -7
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/nga.py +6 -6
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/twitter.py +4 -4
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/weibo.py +4 -4
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/xiaohongshu.py +12 -6
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/youtube.py +12 -5
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/base.py +14 -7
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/common.py +36 -12
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/default.py +2 -2
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/weibo.py +1 -1
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/__init__.py +1 -1
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/constants.py +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/exception.py +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/matchers/filter.py +1 -1
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/matchers/rule.py +4 -4
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/bilibili/article.py +1 -1
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/bilibili/common.py +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/bilibili/dynamic.py +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/bilibili/favlist.py +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/bilibili/live.py +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/bilibili/video.py +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/cookie.py +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/douyin/slides.py +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/douyin/video.py +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/parsers/tiktok.py +1 -1
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/__init__.py +1 -1
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/resources/HYSongYunLangHeiW-1.ttf +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/resources/bilibili.png +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/resources/douyin.png +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/resources/kuaishou.png +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/resources/media_button.png +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/resources/tiktok.png +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/resources/twitter.png +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/resources/weibo.png +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/resources/xiaohongshu.png +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/resources/youtube.png +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/renders/templates/weibo.html.jinja +0 -0
- {nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/utils.py +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: nonebot-plugin-parser
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.3
|
|
4
4
|
Summary: NoneBot2 链接分享解析 Alconna 版, 通用媒体卡片渲染(PIL 实现), 支持 B站/抖音/快手/微博/小红书/youtube/tiktok/twitter/acfun/nga
|
|
5
5
|
Keywords: acfun,bilibili,douyin,kuaishou,nga,nonebot,nonebot2,tiktok,twitter,video,weibo,xiaohongshu,youtube
|
|
6
6
|
Author: fllesser
|
|
@@ -15,23 +15,24 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
19
|
Classifier: Topic :: Communications :: Chat
|
|
19
20
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
20
21
|
Classifier: Topic :: Multimedia :: Video
|
|
22
|
+
Requires-Dist: nonebot2>=2.4.3,<3.0.0
|
|
23
|
+
Requires-Dist: pillow>=11.0.0
|
|
24
|
+
Requires-Dist: pilmoji-for-parser>=0.1.2
|
|
25
|
+
Requires-Dist: tqdm>=4.67.1,<5.0.0
|
|
21
26
|
Requires-Dist: aiofiles>=25.1.0
|
|
22
|
-
Requires-Dist: beautifulsoup4>=4.12.0,<5.0.0
|
|
23
|
-
Requires-Dist: bilibili-api-python>=17.4.0,<18.0.0
|
|
24
27
|
Requires-Dist: curl-cffi>=0.13.0,<1.0.0
|
|
25
28
|
Requires-Dist: httpx>=0.27.2,<1.0.0
|
|
26
29
|
Requires-Dist: msgspec>=0.20.0,<1.0.0
|
|
27
|
-
Requires-Dist:
|
|
30
|
+
Requires-Dist: beautifulsoup4>=4.12.0,<5.0.0
|
|
31
|
+
Requires-Dist: bilibili-api-python>=17.4.0,<18.0.0
|
|
32
|
+
Requires-Dist: nonebot-plugin-alconna>=0.59.4,<1.0.0
|
|
28
33
|
Requires-Dist: nonebot-plugin-apscheduler>=0.5.0,<1.0.0
|
|
29
34
|
Requires-Dist: nonebot-plugin-localstore>=0.7.4,<1.0.0
|
|
30
|
-
Requires-Dist: nonebot-plugin-uninfo>=0.10.0
|
|
31
|
-
Requires-Dist: nonebot2>=2.4.3,<3.0.0
|
|
32
|
-
Requires-Dist: pillow>=11.0.0
|
|
33
|
-
Requires-Dist: pilmoji-for-parser>=0.1.0
|
|
34
|
-
Requires-Dist: tqdm>=4.67.1,<5.0.0
|
|
35
|
+
Requires-Dist: nonebot-plugin-uninfo>=0.10.1,<1.0.0
|
|
35
36
|
Requires-Dist: nonebot-plugin-htmlkit>=0.1.0rc4 ; extra == 'all'
|
|
36
37
|
Requires-Dist: yt-dlp[default]>=2025.11.12 ; extra == 'all'
|
|
37
38
|
Requires-Dist: nonebot-plugin-htmlkit>=0.1.0rc4 ; extra == 'htmlkit'
|
|
@@ -53,7 +54,7 @@ Description-Content-Type: text/markdown
|
|
|
53
54
|
## ✨ [Nonebot2](https://github.com/nonebot/nonebot2) 链接分享自动解析插件 ✨
|
|
54
55
|
[](./LICENSE)
|
|
55
56
|
[](https://pypi.python.org/pypi/nonebot-plugin-parser)
|
|
56
|
-
[](https://python.org)
|
|
57
|
+
[](https://python.org)
|
|
57
58
|
[](https://github.com/astral-sh/uv)
|
|
58
59
|
[](https://github.com/astral-sh/ruff)
|
|
59
60
|
<br/>
|
|
@@ -256,6 +257,9 @@ parser_custom_font="LXGWZhenKaiGB-Regular.ttf"
|
|
|
256
257
|
|
|
257
258
|
# [可选] 是否需要转发媒体内容(超过 4 项时始终使用合并转发)
|
|
258
259
|
parser_need_forward_contents=True
|
|
260
|
+
|
|
261
|
+
# [可选] emoji 渲染样式 "apple", "google", "twitter", "facebook"(默认)
|
|
262
|
+
parser_emoji_style="facebook"
|
|
259
263
|
```
|
|
260
264
|
|
|
261
265
|
</details>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
## ✨ [Nonebot2](https://github.com/nonebot/nonebot2) 链接分享自动解析插件 ✨
|
|
7
7
|
[](./LICENSE)
|
|
8
8
|
[](https://pypi.python.org/pypi/nonebot-plugin-parser)
|
|
9
|
-
[](https://python.org)
|
|
9
|
+
[](https://python.org)
|
|
10
10
|
[](https://github.com/astral-sh/uv)
|
|
11
11
|
[](https://github.com/astral-sh/ruff)
|
|
12
12
|
<br/>
|
|
@@ -209,6 +209,9 @@ parser_custom_font="LXGWZhenKaiGB-Regular.ttf"
|
|
|
209
209
|
|
|
210
210
|
# [可选] 是否需要转发媒体内容(超过 4 项时始终使用合并转发)
|
|
211
211
|
parser_need_forward_contents=True
|
|
212
|
+
|
|
213
|
+
# [可选] emoji 渲染样式 "apple", "google", "twitter", "facebook"(默认)
|
|
214
|
+
parser_emoji_style="facebook"
|
|
212
215
|
```
|
|
213
216
|
|
|
214
217
|
</details>
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
#:tombi schema.strict = false
|
|
2
|
-
|
|
3
1
|
[project]
|
|
4
2
|
name = "nonebot-plugin-parser"
|
|
5
|
-
version = "2.2.
|
|
3
|
+
version = "2.2.3"
|
|
6
4
|
description = "NoneBot2 链接分享解析 Alconna 版, 通用媒体卡片渲染(PIL 实现), 支持 B站/抖音/快手/微博/小红书/youtube/tiktok/twitter/acfun/nga"
|
|
7
5
|
readme = "README.md"
|
|
8
6
|
requires-python = ">=3.10"
|
|
@@ -20,8 +18,9 @@ keywords = [
|
|
|
20
18
|
"video",
|
|
21
19
|
"weibo",
|
|
22
20
|
"xiaohongshu",
|
|
23
|
-
"youtube"
|
|
21
|
+
"youtube",
|
|
24
22
|
]
|
|
23
|
+
|
|
25
24
|
classifiers = [
|
|
26
25
|
"Development Status :: 5 - Production/Stable",
|
|
27
26
|
"Framework :: AsyncIO",
|
|
@@ -33,25 +32,27 @@ classifiers = [
|
|
|
33
32
|
"Programming Language :: Python :: 3.11",
|
|
34
33
|
"Programming Language :: Python :: 3.12",
|
|
35
34
|
"Programming Language :: Python :: 3.13",
|
|
35
|
+
"Programming Language :: Python :: 3.14",
|
|
36
36
|
"Topic :: Communications :: Chat",
|
|
37
37
|
"Topic :: Internet :: WWW/HTTP",
|
|
38
38
|
"Topic :: Multimedia :: Video",
|
|
39
39
|
]
|
|
40
|
+
|
|
40
41
|
dependencies = [
|
|
42
|
+
"nonebot2>=2.4.3,<3.0.0",
|
|
43
|
+
"pillow>=11.0.0",
|
|
44
|
+
"pilmoji-for-parser>=0.1.2",
|
|
45
|
+
"tqdm>=4.67.1,<5.0.0",
|
|
41
46
|
"aiofiles>=25.1.0",
|
|
42
|
-
"beautifulsoup4>=4.12.0,<5.0.0",
|
|
43
|
-
"bilibili-api-python>=17.4.0,<18.0.0",
|
|
44
47
|
"curl_cffi>=0.13.0,<1.0.0",
|
|
45
48
|
"httpx>=0.27.2,<1.0.0",
|
|
46
49
|
"msgspec>=0.20.0,<1.0.0",
|
|
47
|
-
"
|
|
50
|
+
"beautifulsoup4>=4.12.0,<5.0.0",
|
|
51
|
+
"bilibili-api-python>=17.4.0,<18.0.0",
|
|
52
|
+
"nonebot-plugin-alconna>=0.59.4,<1.0.0",
|
|
48
53
|
"nonebot-plugin-apscheduler>=0.5.0,<1.0.0",
|
|
49
54
|
"nonebot-plugin-localstore>=0.7.4,<1.0.0",
|
|
50
|
-
"nonebot-plugin-uninfo>=0.10.0",
|
|
51
|
-
"nonebot2>=2.4.3,<3.0.0",
|
|
52
|
-
"pillow>=11.0.0",
|
|
53
|
-
"pilmoji-for-parser>=0.1.0",
|
|
54
|
-
"tqdm>=4.67.1,<5.0.0",
|
|
55
|
+
"nonebot-plugin-uninfo>=0.10.1,<1.0.0",
|
|
55
56
|
]
|
|
56
57
|
|
|
57
58
|
[project.urls]
|
|
@@ -67,32 +68,50 @@ ytdlp = ["yt-dlp[default]>=2025.11.12"]
|
|
|
67
68
|
[dependency-groups]
|
|
68
69
|
dev = [
|
|
69
70
|
"nonebot2[fastapi]>=2.4.3,<3.0.0",
|
|
70
|
-
"ruff>=0.14.
|
|
71
|
+
"ruff>=0.14.7,<1.0.0",
|
|
72
|
+
{ include-group = "extras" },
|
|
73
|
+
{ include-group = "test" },
|
|
74
|
+
]
|
|
75
|
+
extras = [
|
|
76
|
+
"nonebot-plugin-htmlkit>=0.1.0rc4",
|
|
77
|
+
"yt-dlp[default]>=2025.11.12",
|
|
78
|
+
"types-yt-dlp>=2025.11.12.20251115",
|
|
71
79
|
]
|
|
72
|
-
extras = ["nonebot-plugin-htmlkit>=0.1.0rc4", "yt-dlp[default]>=2025.11.12"]
|
|
73
|
-
pydantic-v1 = ["pydantic<2.0.0"] # renovate:ignore
|
|
74
|
-
pydantic-v2 = ["pydantic>=2.0.0"]
|
|
75
|
-
telegram = ["nonebot-adapter-telegram>=0.1.0b20"]
|
|
76
80
|
test = [
|
|
77
81
|
"nonebot-adapter-onebot>=2.4.6",
|
|
78
82
|
"nonebot2[fastapi]>=2.4.3,<3.0.0",
|
|
79
83
|
"nonebug>=0.4.3,<1.0.0",
|
|
80
|
-
"poethepoet>=0.
|
|
84
|
+
"poethepoet>=0.38.0",
|
|
81
85
|
"pytest-asyncio>=1.3.0,<1.4.0",
|
|
82
86
|
"pytest-cov>=7.0.0",
|
|
83
87
|
"pytest-xdist>=3.8.0,<4.0.0",
|
|
84
88
|
"respx>=0.22.0",
|
|
85
89
|
]
|
|
90
|
+
pydantic-v1 = ["pydantic<2.0.0"]
|
|
91
|
+
pydantic-v2 = ["pydantic>=2.0.0"]
|
|
92
|
+
telegram = ["nonebot-adapter-telegram>=0.1.0b20"]
|
|
86
93
|
|
|
87
94
|
[build-system]
|
|
88
95
|
requires = ["uv_build>=0.9.0,<0.10.0"]
|
|
89
96
|
build-backend = "uv_build"
|
|
90
97
|
|
|
98
|
+
[tool.uv]
|
|
99
|
+
conflicts = [
|
|
100
|
+
[
|
|
101
|
+
{ group = "pydantic-v1" },
|
|
102
|
+
{ group = "pydantic-v2" },
|
|
103
|
+
{ group = "telegram" },
|
|
104
|
+
],
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
[tool.uv.sources]
|
|
108
|
+
nonebug = { git = "https://github.com/fllesser/nonebug", rev = "dev/migrate-uv" }
|
|
109
|
+
|
|
91
110
|
[tool.bumpversion]
|
|
92
|
-
|
|
111
|
+
tag = true
|
|
93
112
|
commit = true
|
|
113
|
+
current_version = "2.2.3"
|
|
94
114
|
message = "release: bump vesion from {current_version} to {new_version}"
|
|
95
|
-
tag = true
|
|
96
115
|
|
|
97
116
|
[[tool.bumpversion.files]]
|
|
98
117
|
filename = "uv.lock"
|
|
@@ -100,9 +119,7 @@ search = "name = \"nonebot-plugin-parser\"\nversion = \"{current_version}\""
|
|
|
100
119
|
replace = "name = \"nonebot-plugin-parser\"\nversion = \"{new_version}\""
|
|
101
120
|
|
|
102
121
|
[tool.coverage.report]
|
|
103
|
-
show_missing = true
|
|
104
|
-
# omit = [ # 排除不需要统计的文件
|
|
105
|
-
# ]
|
|
122
|
+
show_missing = true
|
|
106
123
|
exclude_lines = [
|
|
107
124
|
"raise NotImplementedError",
|
|
108
125
|
"if TYPE_CHECKING:",
|
|
@@ -119,9 +136,9 @@ adapters = [
|
|
|
119
136
|
plugins = ["nonebot_plugin_parser"]
|
|
120
137
|
|
|
121
138
|
[tool.poe.tasks]
|
|
122
|
-
test_others = "pytest tests/others --cov=src --cov-report=xml
|
|
123
|
-
test_parsers = "pytest tests/parsers --cov=src --cov-report=xml
|
|
124
|
-
test_render = "pytest tests/render --cov=src --cov-report=xml
|
|
139
|
+
test_others = "pytest tests/others --cov=src --cov-report=xml --junitxml=junit.xml -n auto"
|
|
140
|
+
test_parsers = "pytest tests/parsers --cov=src --cov-report=xml --junitxml=junit.xml -n auto"
|
|
141
|
+
test_render = "pytest tests/render --cov=src --cov-report=xml --junitxml=junit.xml"
|
|
125
142
|
bump = "bump-my-version bump"
|
|
126
143
|
show-bump = "bump-my-version show-bump"
|
|
127
144
|
|
|
@@ -138,14 +155,14 @@ executionEnvironments = [
|
|
|
138
155
|
typeCheckingMode = "standard"
|
|
139
156
|
disableBytesTypePromotions = true
|
|
140
157
|
|
|
141
|
-
[tool.pytest
|
|
158
|
+
[tool.pytest]
|
|
142
159
|
addopts = [
|
|
143
|
-
"-
|
|
144
|
-
"-
|
|
145
|
-
"--tb=short",
|
|
146
|
-
"-ra",
|
|
147
|
-
"
|
|
148
|
-
"
|
|
160
|
+
"--import-mode=prepend", # 导入模式
|
|
161
|
+
"--strict-markers", # 严格标记模式
|
|
162
|
+
"--tb=short", # 简短的错误回溯
|
|
163
|
+
"-ra", # 显示所有测试结果摘要
|
|
164
|
+
"-s", # 显示打印信息
|
|
165
|
+
"-v", # 详细输出
|
|
149
166
|
]
|
|
150
167
|
pythonpath = ["src"]
|
|
151
168
|
asyncio_mode = "auto"
|
|
@@ -153,58 +170,41 @@ asyncio_default_fixture_loop_scope = "session"
|
|
|
153
170
|
|
|
154
171
|
[tool.ruff]
|
|
155
172
|
line-length = 120
|
|
156
|
-
target-version = "py310"
|
|
157
173
|
|
|
158
174
|
[tool.ruff.format]
|
|
159
175
|
line-ending = "lf"
|
|
160
176
|
|
|
161
177
|
[tool.ruff.lint]
|
|
162
178
|
select = [
|
|
163
|
-
"F",
|
|
164
|
-
"W",
|
|
165
|
-
"E",
|
|
166
|
-
"I",
|
|
167
|
-
"UP",
|
|
168
|
-
"
|
|
169
|
-
"
|
|
170
|
-
"T10",
|
|
171
|
-
"T20",
|
|
172
|
-
"
|
|
173
|
-
"PT",
|
|
174
|
-
"
|
|
175
|
-
"
|
|
176
|
-
"RUF",
|
|
179
|
+
"F", # Pyflakes
|
|
180
|
+
"W", # pycodestyle warnings
|
|
181
|
+
"E", # pycodestyle errors
|
|
182
|
+
"I", # isort
|
|
183
|
+
"UP", # pyupgrade
|
|
184
|
+
"Q", # flake8-quotes
|
|
185
|
+
"PYI", # flake8-pyi
|
|
186
|
+
"T10", # flake8-debugger
|
|
187
|
+
"T20", # flake8-print
|
|
188
|
+
"C4", # flake8-comprehensions
|
|
189
|
+
"PT", # flake8-pytest-style
|
|
190
|
+
"TID", # flake8-tidy-imports
|
|
191
|
+
"ASYNC", # flake8-async
|
|
192
|
+
"RUF", # Ruff-specific rules
|
|
177
193
|
]
|
|
178
194
|
ignore = [
|
|
179
|
-
"E402",
|
|
195
|
+
"E402", # module-import-not-at-top-of-file
|
|
180
196
|
"UP037", # quoted-annotation
|
|
181
|
-
"RUF001",
|
|
182
|
-
"RUF002",
|
|
183
|
-
"RUF003",
|
|
184
|
-
"W191",
|
|
185
|
-
|
|
186
|
-
"TID252", # 相对导入
|
|
197
|
+
"RUF001", # ambiguous-unicode-character-string
|
|
198
|
+
"RUF002", # ambiguous-unicode-character-docstring
|
|
199
|
+
"RUF003", # ambiguous-unicode-character-comment
|
|
200
|
+
"W191", # indentation contains tabs
|
|
201
|
+
"TID252", # relative-import
|
|
187
202
|
]
|
|
188
203
|
|
|
189
204
|
[tool.ruff.lint.isort]
|
|
190
|
-
|
|
191
|
-
known-first-party = ["tests/*"]
|
|
205
|
+
length-sort = true
|
|
206
|
+
known-first-party = ["nonebot_plugin_parser", "tests/*"]
|
|
192
207
|
extra-standard-library = ["typing_extensions"]
|
|
193
208
|
|
|
194
|
-
[tool.ruff.lint.flake8-pytest-style]
|
|
195
|
-
fixture-parentheses = false
|
|
196
|
-
mark-parentheses = false
|
|
197
|
-
|
|
198
209
|
[tool.ruff.lint.pyupgrade]
|
|
199
210
|
keep-runtime-typing = true
|
|
200
|
-
|
|
201
|
-
[tool.uv]
|
|
202
|
-
required-version = ">=0.9.7"
|
|
203
|
-
default-groups = ["test", "dev", "extras"]
|
|
204
|
-
conflicts = [
|
|
205
|
-
[
|
|
206
|
-
{ group = "pydantic-v1" },
|
|
207
|
-
{ group = "pydantic-v2" },
|
|
208
|
-
{ group = "telegram" },
|
|
209
|
-
],
|
|
210
|
-
]
|
{nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/config.py
RENAMED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
|
|
4
|
-
from
|
|
5
|
-
from
|
|
4
|
+
from nonebot import require, get_driver, get_plugin_config
|
|
5
|
+
from pilmoji import EmojiStyle
|
|
6
6
|
from pydantic import BaseModel
|
|
7
|
+
from bilibili_api.video import VideoCodecs, VideoQuality
|
|
7
8
|
|
|
8
9
|
from .constants import PlatformEnum
|
|
9
10
|
|
|
10
|
-
_nickname: str = next(iter(get_driver().config.nickname), "")
|
|
11
|
-
"""全局名称"""
|
|
12
|
-
|
|
13
11
|
require("nonebot_plugin_localstore")
|
|
14
12
|
import nonebot_plugin_localstore as _store
|
|
15
13
|
|
|
14
|
+
_nickname: str = next(iter(get_driver().config.nickname), "")
|
|
16
15
|
_cache_dir: Path = _store.get_plugin_cache_dir()
|
|
17
16
|
_config_dir: Path = _store.get_plugin_config_dir()
|
|
18
17
|
_data_dir: Path = _store.get_plugin_data_dir()
|
|
@@ -57,10 +56,12 @@ class Config(BaseModel):
|
|
|
57
56
|
"""自定义字体"""
|
|
58
57
|
parser_need_forward_contents: bool = True
|
|
59
58
|
"""是否需要转发媒体内容"""
|
|
59
|
+
parser_emoji_style: EmojiStyle = EmojiStyle.FACEBOOK
|
|
60
|
+
"""Pilmoji 表情样式"""
|
|
60
61
|
|
|
61
62
|
@property
|
|
62
63
|
def nickname(self) -> str:
|
|
63
|
-
"""
|
|
64
|
+
"""机器人昵称"""
|
|
64
65
|
return _nickname
|
|
65
66
|
|
|
66
67
|
@property
|
|
@@ -148,6 +149,11 @@ class Config(BaseModel):
|
|
|
148
149
|
"""是否需要转发媒体内容"""
|
|
149
150
|
return self.parser_need_forward_contents
|
|
150
151
|
|
|
152
|
+
@property
|
|
153
|
+
def emoji_style(self) -> EmojiStyle:
|
|
154
|
+
"""Pilmoji 表情样式"""
|
|
155
|
+
return self.parser_emoji_style
|
|
156
|
+
|
|
151
157
|
|
|
152
158
|
pconfig: Config = get_plugin_config(Config)
|
|
153
159
|
"""配置"""
|
|
@@ -2,15 +2,15 @@ import asyncio
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
|
|
4
4
|
import aiofiles
|
|
5
|
-
from httpx import
|
|
5
|
+
from httpx import HTTPError, AsyncClient
|
|
6
6
|
from nonebot import logger
|
|
7
7
|
from tqdm.asyncio import tqdm
|
|
8
8
|
|
|
9
|
+
from .task import auto_task
|
|
10
|
+
from ..utils import merge_av, safe_unlink, generate_file_name
|
|
9
11
|
from ..config import pconfig
|
|
10
12
|
from ..constants import COMMON_HEADER, DOWNLOAD_TIMEOUT
|
|
11
|
-
from ..exception import DownloadException,
|
|
12
|
-
from ..utils import generate_file_name, merge_av, safe_unlink
|
|
13
|
-
from .task import auto_task
|
|
13
|
+
from ..exception import DownloadException, ZeroSizeException, SizeLimitException
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class StreamDownloader:
|
|
@@ -63,7 +63,7 @@ class StreamDownloader:
|
|
|
63
63
|
raise ZeroSizeException
|
|
64
64
|
|
|
65
65
|
if (file_size := content_length / 1024 / 1024) > pconfig.max_size:
|
|
66
|
-
logger.warning(f"媒体 url: {url} 大小 {file_size:.2f} MB 超过 {pconfig.max_size} MB, 取消下载")
|
|
66
|
+
logger.warning(f"媒体 url: {url} 大小 {file_size:.2f} MB 超过 {{pconfig.max_size}} MB, 取消下载")
|
|
67
67
|
raise SizeLimitException
|
|
68
68
|
|
|
69
69
|
with self.get_progress_bar(file_name, content_length) as bar:
|
|
@@ -136,7 +136,7 @@ class StreamDownloader:
|
|
|
136
136
|
|
|
137
137
|
Args:
|
|
138
138
|
url (str): url address
|
|
139
|
-
audio_name (str | None ): audio name. Defaults to
|
|
139
|
+
audio_name (str | None ): audio name. Defaults to generate from url.
|
|
140
140
|
ext_headers (dict[str, str] | None): ext headers. Defaults to None.
|
|
141
141
|
|
|
142
142
|
Returns:
|
|
@@ -161,7 +161,7 @@ class StreamDownloader:
|
|
|
161
161
|
|
|
162
162
|
Args:
|
|
163
163
|
url (str): url
|
|
164
|
-
img_name (str | None): image name. Defaults to
|
|
164
|
+
img_name (str | None): image name. Defaults to generate from url.
|
|
165
165
|
ext_headers (dict[str, str] | None): ext headers. Defaults to None.
|
|
166
166
|
|
|
167
167
|
Returns:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
from typing import Any, TypeVar, ParamSpec
|
|
1
2
|
from asyncio import Task, create_task
|
|
2
|
-
from collections.abc import Callable, Coroutine
|
|
3
3
|
from functools import wraps
|
|
4
|
-
from
|
|
4
|
+
from collections.abc import Callable, Coroutine
|
|
5
5
|
|
|
6
6
|
P = ParamSpec("P")
|
|
7
7
|
T = TypeVar("T")
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
2
3
|
from pathlib import Path
|
|
3
|
-
from typing import Any
|
|
4
4
|
|
|
5
|
-
from msgspec import Struct, convert
|
|
6
5
|
import yt_dlp
|
|
6
|
+
from msgspec import Struct, convert
|
|
7
7
|
|
|
8
|
-
from ..config import pconfig
|
|
9
|
-
from ..exception import DurationLimitException, ParseException
|
|
10
|
-
from ..utils import LimitedSizeDict, generate_file_name
|
|
11
8
|
from .task import auto_task
|
|
9
|
+
from ..utils import LimitedSizeDict, generate_file_name
|
|
10
|
+
from ..config import pconfig
|
|
11
|
+
from ..exception import ParseException, DurationLimitException
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class VideoInfo(Struct):
|
|
@@ -38,16 +38,19 @@ class YtdlpDownloader:
|
|
|
38
38
|
"""YtdlpDownloader class"""
|
|
39
39
|
|
|
40
40
|
def __init__(self):
|
|
41
|
+
if TYPE_CHECKING:
|
|
42
|
+
from yt_dlp import _Params
|
|
43
|
+
|
|
41
44
|
self._video_info_mapping = LimitedSizeDict[str, VideoInfo]()
|
|
42
|
-
self.
|
|
45
|
+
self._extract_base_opts: _Params = {
|
|
43
46
|
"quiet": True,
|
|
44
|
-
"skip_download":
|
|
47
|
+
"skip_download": "1",
|
|
45
48
|
"force_generic_extractor": True,
|
|
46
49
|
}
|
|
47
|
-
self.
|
|
50
|
+
self._download_base_opts: _Params = {}
|
|
48
51
|
if proxy := pconfig.proxy:
|
|
49
|
-
self.
|
|
50
|
-
self.
|
|
52
|
+
self._download_base_opts["proxy"] = proxy
|
|
53
|
+
self._extract_base_opts["proxy"] = proxy
|
|
51
54
|
|
|
52
55
|
async def extract_video_info(self, url: str, cookiefile: Path | None = None) -> VideoInfo:
|
|
53
56
|
"""get video info by url
|
|
@@ -62,12 +65,12 @@ class YtdlpDownloader:
|
|
|
62
65
|
video_info = self._video_info_mapping.get(url, None)
|
|
63
66
|
if video_info:
|
|
64
67
|
return video_info
|
|
65
|
-
ydl_opts = self.
|
|
68
|
+
ydl_opts = self._extract_base_opts.copy()
|
|
66
69
|
|
|
67
70
|
if cookiefile:
|
|
68
71
|
ydl_opts["cookiefile"] = str(cookiefile)
|
|
69
72
|
|
|
70
|
-
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
73
|
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
71
74
|
info_dict = await asyncio.to_thread(ydl.extract_info, url, download=False)
|
|
72
75
|
if not info_dict:
|
|
73
76
|
raise ParseException("获取视频信息失败")
|
|
@@ -95,17 +98,17 @@ class YtdlpDownloader:
|
|
|
95
98
|
video_path = pconfig.cache_dir / generate_file_name(url, ".mp4")
|
|
96
99
|
if video_path.exists():
|
|
97
100
|
return video_path
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
|
|
102
|
+
ydl_opts = self._download_base_opts.copy()
|
|
103
|
+
ydl_opts["outtmpl"] = str(video_path)
|
|
104
|
+
ydl_opts["merge_output_format"] = "mp4"
|
|
105
|
+
ydl_opts["format"] = f"bv[filesize<={duration // 10 + 10}M]+ba/b[filesize<={duration // 8 + 10}M]"
|
|
106
|
+
ydl_opts["postprocessors"] = [{"key": "FFmpegVideoConvertor", "preferedformat": "mp4"}]
|
|
104
107
|
|
|
105
108
|
if cookiefile:
|
|
106
109
|
ydl_opts["cookiefile"] = str(cookiefile)
|
|
107
110
|
|
|
108
|
-
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
111
|
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
109
112
|
await asyncio.to_thread(ydl.download, [url])
|
|
110
113
|
return video_path
|
|
111
114
|
|
|
@@ -125,20 +128,19 @@ class YtdlpDownloader:
|
|
|
125
128
|
if audio_path.exists():
|
|
126
129
|
return audio_path
|
|
127
130
|
|
|
128
|
-
ydl_opts =
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
} | self._ydl_download_base_opts
|
|
131
|
+
ydl_opts = self._download_base_opts.copy()
|
|
132
|
+
ydl_opts["outtmpl"] = f"{pconfig.cache_dir / file_name}.%(ext)s"
|
|
133
|
+
ydl_opts["format"] = "bestaudio/best"
|
|
134
|
+
ydl_opts["postprocessors"] = [
|
|
135
|
+
{
|
|
136
|
+
"key": "FFmpegExtractAudio",
|
|
137
|
+
"preferredcodec": "flac",
|
|
138
|
+
"preferredquality": "0",
|
|
139
|
+
}
|
|
140
|
+
]
|
|
139
141
|
|
|
140
142
|
if cookiefile:
|
|
141
143
|
ydl_opts["cookiefile"] = str(cookiefile)
|
|
142
|
-
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
144
|
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
143
145
|
await asyncio.to_thread(ydl.download, [url])
|
|
144
146
|
return audio_path
|
{nonebot_plugin_parser-2.2.2 → nonebot_plugin_parser-2.2.3}/src/nonebot_plugin_parser/helper.py
RENAMED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
from
|
|
2
|
-
from functools import wraps
|
|
1
|
+
from typing import Any, Literal, ClassVar
|
|
3
2
|
from pathlib import Path
|
|
4
|
-
from
|
|
3
|
+
from functools import wraps
|
|
4
|
+
from collections.abc import Callable, Sequence, Awaitable
|
|
5
5
|
|
|
6
6
|
from nonebot import logger
|
|
7
|
-
from nonebot.adapters import Event
|
|
8
7
|
from nonebot.matcher import current_bot, current_event
|
|
8
|
+
from nonebot.adapters import Event
|
|
9
9
|
from nonebot_plugin_alconna import SupportAdapter, uniseg
|
|
10
10
|
from nonebot_plugin_alconna.uniseg import (
|
|
11
|
-
CustomNode,
|
|
12
11
|
File,
|
|
13
|
-
Image,
|
|
14
|
-
Reference,
|
|
15
|
-
Segment,
|
|
16
12
|
Text,
|
|
17
|
-
|
|
13
|
+
Image,
|
|
18
14
|
Video,
|
|
19
15
|
Voice,
|
|
16
|
+
Segment,
|
|
17
|
+
Reference,
|
|
18
|
+
CustomNode,
|
|
19
|
+
UniMessage,
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
from .config import pconfig
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""统一的解析器 matcher"""
|
|
2
2
|
|
|
3
|
-
from nonebot import
|
|
3
|
+
from nonebot import logger, get_driver
|
|
4
4
|
|
|
5
|
+
from .rule import Searched, SearchResult, on_keyword_regex
|
|
6
|
+
from ..utils import LimitedSizeDict
|
|
5
7
|
from ..config import pconfig
|
|
6
8
|
from ..helper import UniHelper
|
|
7
9
|
from ..parsers import BaseParser, ParseResult
|
|
8
10
|
from ..renders import get_renderer
|
|
9
|
-
from ..utils import LimitedSizeDict
|
|
10
|
-
from .rule import Searched, SearchResult, on_keyword_regex
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def _get_enabled_parser_classes() -> list[type[BaseParser]]:
|
|
@@ -75,12 +75,12 @@ import re
|
|
|
75
75
|
from typing import cast
|
|
76
76
|
|
|
77
77
|
from nonebot import on_command
|
|
78
|
-
from nonebot.adapters import Message
|
|
79
78
|
from nonebot.params import CommandArg
|
|
79
|
+
from nonebot.adapters import Message
|
|
80
80
|
from nonebot_plugin_alconna import UniMessage
|
|
81
81
|
|
|
82
|
-
from ..download import DOWNLOADER
|
|
83
82
|
from ..parsers import BilibiliParser
|
|
83
|
+
from ..download import DOWNLOADER
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
@on_command("bm", priority=3, block=True).handle()
|
|
@@ -1,32 +1,35 @@
|
|
|
1
1
|
# 导出所有 Parser 类
|
|
2
|
-
from
|
|
3
|
-
from .acfun import AcfunParser as AcfunParser
|
|
2
|
+
from .nga import NGAParser as NGAParser
|
|
4
3
|
from .base import BaseParser as BaseParser
|
|
5
|
-
from .
|
|
4
|
+
from .acfun import AcfunParser as AcfunParser
|
|
5
|
+
from .weibo import WeiBoParser as WeiBoParser
|
|
6
6
|
from .douyin import DouyinParser as DouyinParser
|
|
7
|
-
from .kuaishou import KuaiShouParser as KuaiShouParser
|
|
8
|
-
from .nga import NGAParser as NGAParser
|
|
9
7
|
from .twitter import TwitterParser as TwitterParser
|
|
10
|
-
from .
|
|
8
|
+
from .bilibili import BilibiliParser as BilibiliParser
|
|
9
|
+
from .kuaishou import KuaiShouParser as KuaiShouParser
|
|
10
|
+
from ..download import YTDLP_DOWNLOADER
|
|
11
11
|
from .xiaohongshu import XiaoHongShuParser as XiaoHongShuParser
|
|
12
12
|
|
|
13
13
|
if YTDLP_DOWNLOADER is not None:
|
|
14
14
|
from .tiktok import TikTokParser as TikTokParser
|
|
15
15
|
from .youtube import YouTubeParser as YouTubeParser
|
|
16
16
|
|
|
17
|
-
from .base import handle
|
|
18
|
-
from .data import
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
from .base import handle
|
|
18
|
+
from .data import (
|
|
19
|
+
Author,
|
|
20
|
+
Platform,
|
|
21
|
+
ParseResult,
|
|
22
|
+
AudioContent,
|
|
23
|
+
ImageContent,
|
|
24
|
+
VideoContent,
|
|
25
|
+
DynamicContent,
|
|
26
|
+
GraphicsContent,
|
|
27
|
+
)
|
|
26
28
|
|
|
27
29
|
__all__ = [
|
|
28
30
|
"AudioContent",
|
|
29
31
|
"Author",
|
|
32
|
+
"BaseParser",
|
|
30
33
|
"DynamicContent",
|
|
31
34
|
"GraphicsContent",
|
|
32
35
|
"ImageContent",
|