nonebot-plugin-parser 2.5.3__tar.gz → 2.6.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_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/PKG-INFO +23 -28
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/README.md +22 -27
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/pyproject.toml +2 -2
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/config.py +7 -0
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/download/task.py +20 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/helper.py +13 -3
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/__init__.py +0 -2
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/acfun/__init__.py +1 -1
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/base.py +33 -55
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/bilibili/__init__.py +6 -6
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/data.py +27 -24
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/douyin/__init__.py +15 -11
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/douyin/video.py +4 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/kuaishou/__init__.py +2 -2
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/nga.py +1 -1
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/parsers/task.py +47 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/tiktok.py +1 -1
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/twitter.py +12 -6
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/parsers/utils.py +9 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/weibo/__init__.py +10 -5
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/weibo/common.py +13 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/weibo/show.py +5 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/xiaohongshu/__init__.py +15 -11
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/parsers/xiaohongshu/common.py +38 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/xiaohongshu/discovery.py +9 -4
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/xiaohongshu/explore.py +14 -4
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/youtube/__init__.py +2 -2
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/renders/__init__.py +51 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/base.py +26 -18
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/common.py +19 -13
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/default.py +1 -1
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/htmlrender.py +5 -5
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/__init__.py +7 -0
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/renders/resources/fallback_pic/1.jpg +0 -0
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/renders/resources/fallback_pic/2.jpg +0 -0
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/renders/resources/fallback_pic/3.jpg +0 -0
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/renders/resources/fallback_pic/4.jpg +0 -0
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/renders/resources/fallback_pic/5.jpg +0 -0
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/renders/resources/fallback_pic/6.jpg +0 -0
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/renders/resources/fallback_pic/7.jpg +0 -0
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/renders/resources/fallback_pic/8.jpg +0 -0
- nonebot_plugin_parser-2.6.0/src/nonebot_plugin_parser/renders/resources/fallback_pic/9.jpg +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/templates/card.html.jinja2 +36 -9
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/utils.py +23 -17
- nonebot_plugin_parser-2.5.3/src/nonebot_plugin_parser/download/task.py +0 -92
- nonebot_plugin_parser-2.5.3/src/nonebot_plugin_parser/parsers/xiaohongshu/common.py +0 -33
- nonebot_plugin_parser-2.5.3/src/nonebot_plugin_parser/renders/__init__.py +0 -43
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/__init__.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/constants.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/download/__init__.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/download/ytdlp.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/exception.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/matchers/__init__.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/matchers/filter.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/matchers/rule.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/acfun/video.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/bilibili/article.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/bilibili/common.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/bilibili/dynamic.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/bilibili/favlist.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/bilibili/live.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/bilibili/opus.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/bilibili/video.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/cookie.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/douyin/slides.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/kuaishou/states.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/weibo/article.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/parsers/youtube/meta.py +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/HYSongYunLangHeiW.ttf +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/avatar.png +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/bilibili.png +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/douyin.png +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/kuaishou.png +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/play.png +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/tiktok.png +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/twitter.png +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/weibo.png +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/xiaohongshu.png +0 -0
- {nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/renders/resources/youtube.png +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: nonebot-plugin-parser
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.0
|
|
4
4
|
Summary: NoneBot2 链接分享解析 Alconna 版, 现支持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
|
|
@@ -71,7 +71,7 @@ Description-Content-Type: text/markdown
|
|
|
71
71
|
|
|
72
72
|
</div>
|
|
73
73
|
|
|
74
|
-
> [!IMPORTANT]
|
|
74
|
+
> [!IMPORTANT]
|
|
75
75
|
> **收藏项目**,你将从 GitHub 上无延迟地接收所有发布通知~ ⭐️
|
|
76
76
|
|
|
77
77
|
<img width="100%" src="https://starify.komoridevs.icu/api/starify?owner=fllesser&repo=nonebot-plugin-parser" alt="starify" />
|
|
@@ -81,14 +81,14 @@ Description-Content-Type: text/markdown
|
|
|
81
81
|
| 平台 | 触发的消息形态 | 视频 | 图集 | 音频 |
|
|
82
82
|
| ------- | --------------------------------- | ---- | ---- | ---- |
|
|
83
83
|
| B 站 | av 号/BV 号/链接/短链/卡片/小程序 | ✅ | ✅ | ✅ |
|
|
84
|
-
| 抖音 | 链接(分享链接,兼容电脑端链接) | ✅ | ✅ | ❌️
|
|
85
|
-
| 微博 | 链接(博文,视频,show, 文章) | ✅ | ✅ | ❌️
|
|
86
|
-
| 小红书 | 链接(含短链)/卡片 | ✅ | ✅ | ❌️
|
|
87
|
-
| 快手 | 链接(包含标准链接和短链) | ✅ | ✅ | ❌️
|
|
88
|
-
| acfun | 链接 | ✅ | ❌️
|
|
89
|
-
| youtube | 链接(含短链) | ✅ | ❌️
|
|
90
|
-
| tiktok | 链接 | ✅ | ❌️
|
|
91
|
-
| twitter | 链接 | ✅ | ✅ | ❌️
|
|
84
|
+
| 抖音 | 链接(分享链接,兼容电脑端链接) | ✅ | ✅ | ❌️ |
|
|
85
|
+
| 微博 | 链接(博文,视频,show, 文章) | ✅ | ✅ | ❌️ |
|
|
86
|
+
| 小红书 | 链接(含短链)/卡片 | ✅ | ✅ | ❌️ |
|
|
87
|
+
| 快手 | 链接(包含标准链接和短链) | ✅ | ✅ | ❌️ |
|
|
88
|
+
| acfun | 链接 | ✅ | ❌️ | ❌️ |
|
|
89
|
+
| youtube | 链接(含短链) | ✅ | ❌️ | ✅ |
|
|
90
|
+
| tiktok | 链接 | ✅ | ❌️ | ❌️ |
|
|
91
|
+
| twitter | 链接 | ✅ | ✅ | ❌️ |
|
|
92
92
|
|
|
93
93
|
支持的链接,可参考 [测试链接](https://github.com/fllesser/nonebot-plugin-parser/blob/master/tests/others/test_urls.md)
|
|
94
94
|
|
|
@@ -108,7 +108,7 @@ Description-Content-Type: text/markdown
|
|
|
108
108
|
|
|
109
109
|
## 💿 安装
|
|
110
110
|
|
|
111
|
-
> [!Warning]
|
|
111
|
+
> [!Warning]
|
|
112
112
|
> **如果你已经在使用 nonebot-plugin-resolver[2],请在安装此插件前卸载**
|
|
113
113
|
|
|
114
114
|
<details>
|
|
@@ -304,6 +304,9 @@ parser_append_url=False
|
|
|
304
304
|
# 例如: ./config/nonebot_plugin_parser/
|
|
305
305
|
parser_custom_font="LXGWZhenKaiGB-Regular.ttf"
|
|
306
306
|
|
|
307
|
+
# [可选] 用户名及标题字体粗细程度(仅 htmlrender),如果使用 LXGW ZhenKai 字体建议设置为 500~600 之间
|
|
308
|
+
parser_custom_font_weight: int = 700
|
|
309
|
+
|
|
307
310
|
# [可选] 是否需要转发媒体内容(超过 4 项时始终使用合并转发)
|
|
308
311
|
parser_need_forward_contents=True
|
|
309
312
|
|
|
@@ -390,18 +393,19 @@ class ExampleParser(BaseParser):
|
|
|
390
393
|
|
|
391
394
|
# 4. 视频内容
|
|
392
395
|
author = self.create_author(author_name, avatar_url)
|
|
393
|
-
video = self.
|
|
396
|
+
video = self.create_video(video_url, cover_url, duration)
|
|
394
397
|
|
|
395
398
|
# 5. 图集内容
|
|
396
399
|
image_urls = data.get("images")
|
|
397
|
-
images = self.
|
|
400
|
+
images = self.create_image(image_urls)
|
|
398
401
|
|
|
399
402
|
# 6. 返回解析结果
|
|
400
403
|
return self.result(
|
|
401
404
|
title=title,
|
|
402
405
|
text=description,
|
|
403
406
|
author=author,
|
|
404
|
-
|
|
407
|
+
video=video,
|
|
408
|
+
contents=[*images],
|
|
405
409
|
timestamp=timestamp,
|
|
406
410
|
url=f"https://example.com/video/{video_id}",
|
|
407
411
|
)
|
|
@@ -426,7 +430,7 @@ author = self.create_author(
|
|
|
426
430
|
|
|
427
431
|
```python
|
|
428
432
|
# 方式1:传入 URL,自动下载
|
|
429
|
-
video = self.
|
|
433
|
+
video = self.create_video(
|
|
430
434
|
url_or_task="https://example.com/video.mp4",
|
|
431
435
|
cover_url="https://example.com/cover.jpg", # 可选
|
|
432
436
|
duration=120.5 # 可选,单位:秒
|
|
@@ -435,7 +439,7 @@ video = self.create_video_content(
|
|
|
435
439
|
# 方式2:传入已创建的下载任务
|
|
436
440
|
from nonebot_plugin_parser.download import DOWNLOADER
|
|
437
441
|
video_task = DOWNLOADER.download_video(url, ext_headers=self.headers)
|
|
438
|
-
video = self.
|
|
442
|
+
video = self.create_video(
|
|
439
443
|
url_or_task=video_task,
|
|
440
444
|
cover_url=cover_url,
|
|
441
445
|
duration=duration
|
|
@@ -446,21 +450,12 @@ video = self.create_video_content(
|
|
|
446
450
|
|
|
447
451
|
```python
|
|
448
452
|
# 并发下载图集内容
|
|
449
|
-
images = self.
|
|
453
|
+
images = self.create_images([
|
|
450
454
|
"https://example.com/img1.jpg",
|
|
451
455
|
"https://example.com/img2.jpg",
|
|
452
456
|
])
|
|
453
457
|
```
|
|
454
458
|
|
|
455
|
-
> 创建动图内容(GIF),平台一般只提供视频(后续插件会做自动转为 gif 的处理)
|
|
456
|
-
|
|
457
|
-
```python
|
|
458
|
-
dynamics = self.create_dynamic_contents([
|
|
459
|
-
"https://example.com/dynamic1.mp4",
|
|
460
|
-
"https://example.com/dynamic2.mp4",
|
|
461
|
-
])
|
|
462
|
-
```
|
|
463
|
-
|
|
464
459
|
> 重定向 url
|
|
465
460
|
|
|
466
461
|
```python
|
|
@@ -478,5 +473,5 @@ real_url = await self.get_redirect_url(
|
|
|
478
473
|
|
|
479
474
|
## 🎉 致谢
|
|
480
475
|
|
|
481
|
-
[nonebot-plugin-resolver](https://github.com/zhiyu1998/nonebot-plugin-resolver)
|
|
482
|
-
[parse-video-py](https://github.com/wujunwei928/parse-video-py)
|
|
476
|
+
- [nonebot-plugin-resolver](https://github.com/zhiyu1998/nonebot-plugin-resolver) | 初代解析插件
|
|
477
|
+
- [parse-video-py](https://github.com/wujunwei928/parse-video-py) | 借鉴了抖音解析
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
</div>
|
|
19
19
|
|
|
20
|
-
> [!IMPORTANT]
|
|
20
|
+
> [!IMPORTANT]
|
|
21
21
|
> **收藏项目**,你将从 GitHub 上无延迟地接收所有发布通知~ ⭐️
|
|
22
22
|
|
|
23
23
|
<img width="100%" src="https://starify.komoridevs.icu/api/starify?owner=fllesser&repo=nonebot-plugin-parser" alt="starify" />
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
| 平台 | 触发的消息形态 | 视频 | 图集 | 音频 |
|
|
28
28
|
| ------- | --------------------------------- | ---- | ---- | ---- |
|
|
29
29
|
| B 站 | av 号/BV 号/链接/短链/卡片/小程序 | ✅ | ✅ | ✅ |
|
|
30
|
-
| 抖音 | 链接(分享链接,兼容电脑端链接) | ✅ | ✅ | ❌️
|
|
31
|
-
| 微博 | 链接(博文,视频,show, 文章) | ✅ | ✅ | ❌️
|
|
32
|
-
| 小红书 | 链接(含短链)/卡片 | ✅ | ✅ | ❌️
|
|
33
|
-
| 快手 | 链接(包含标准链接和短链) | ✅ | ✅ | ❌️
|
|
34
|
-
| acfun | 链接 | ✅ | ❌️
|
|
35
|
-
| youtube | 链接(含短链) | ✅ | ❌️
|
|
36
|
-
| tiktok | 链接 | ✅ | ❌️
|
|
37
|
-
| twitter | 链接 | ✅ | ✅ | ❌️
|
|
30
|
+
| 抖音 | 链接(分享链接,兼容电脑端链接) | ✅ | ✅ | ❌️ |
|
|
31
|
+
| 微博 | 链接(博文,视频,show, 文章) | ✅ | ✅ | ❌️ |
|
|
32
|
+
| 小红书 | 链接(含短链)/卡片 | ✅ | ✅ | ❌️ |
|
|
33
|
+
| 快手 | 链接(包含标准链接和短链) | ✅ | ✅ | ❌️ |
|
|
34
|
+
| acfun | 链接 | ✅ | ❌️ | ❌️ |
|
|
35
|
+
| youtube | 链接(含短链) | ✅ | ❌️ | ✅ |
|
|
36
|
+
| tiktok | 链接 | ✅ | ❌️ | ❌️ |
|
|
37
|
+
| twitter | 链接 | ✅ | ✅ | ❌️ |
|
|
38
38
|
|
|
39
39
|
支持的链接,可参考 [测试链接](https://github.com/fllesser/nonebot-plugin-parser/blob/master/tests/others/test_urls.md)
|
|
40
40
|
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
|
|
55
55
|
## 💿 安装
|
|
56
56
|
|
|
57
|
-
> [!Warning]
|
|
57
|
+
> [!Warning]
|
|
58
58
|
> **如果你已经在使用 nonebot-plugin-resolver[2],请在安装此插件前卸载**
|
|
59
59
|
|
|
60
60
|
<details>
|
|
@@ -250,6 +250,9 @@ parser_append_url=False
|
|
|
250
250
|
# 例如: ./config/nonebot_plugin_parser/
|
|
251
251
|
parser_custom_font="LXGWZhenKaiGB-Regular.ttf"
|
|
252
252
|
|
|
253
|
+
# [可选] 用户名及标题字体粗细程度(仅 htmlrender),如果使用 LXGW ZhenKai 字体建议设置为 500~600 之间
|
|
254
|
+
parser_custom_font_weight: int = 700
|
|
255
|
+
|
|
253
256
|
# [可选] 是否需要转发媒体内容(超过 4 项时始终使用合并转发)
|
|
254
257
|
parser_need_forward_contents=True
|
|
255
258
|
|
|
@@ -336,18 +339,19 @@ class ExampleParser(BaseParser):
|
|
|
336
339
|
|
|
337
340
|
# 4. 视频内容
|
|
338
341
|
author = self.create_author(author_name, avatar_url)
|
|
339
|
-
video = self.
|
|
342
|
+
video = self.create_video(video_url, cover_url, duration)
|
|
340
343
|
|
|
341
344
|
# 5. 图集内容
|
|
342
345
|
image_urls = data.get("images")
|
|
343
|
-
images = self.
|
|
346
|
+
images = self.create_image(image_urls)
|
|
344
347
|
|
|
345
348
|
# 6. 返回解析结果
|
|
346
349
|
return self.result(
|
|
347
350
|
title=title,
|
|
348
351
|
text=description,
|
|
349
352
|
author=author,
|
|
350
|
-
|
|
353
|
+
video=video,
|
|
354
|
+
contents=[*images],
|
|
351
355
|
timestamp=timestamp,
|
|
352
356
|
url=f"https://example.com/video/{video_id}",
|
|
353
357
|
)
|
|
@@ -372,7 +376,7 @@ author = self.create_author(
|
|
|
372
376
|
|
|
373
377
|
```python
|
|
374
378
|
# 方式1:传入 URL,自动下载
|
|
375
|
-
video = self.
|
|
379
|
+
video = self.create_video(
|
|
376
380
|
url_or_task="https://example.com/video.mp4",
|
|
377
381
|
cover_url="https://example.com/cover.jpg", # 可选
|
|
378
382
|
duration=120.5 # 可选,单位:秒
|
|
@@ -381,7 +385,7 @@ video = self.create_video_content(
|
|
|
381
385
|
# 方式2:传入已创建的下载任务
|
|
382
386
|
from nonebot_plugin_parser.download import DOWNLOADER
|
|
383
387
|
video_task = DOWNLOADER.download_video(url, ext_headers=self.headers)
|
|
384
|
-
video = self.
|
|
388
|
+
video = self.create_video(
|
|
385
389
|
url_or_task=video_task,
|
|
386
390
|
cover_url=cover_url,
|
|
387
391
|
duration=duration
|
|
@@ -392,21 +396,12 @@ video = self.create_video_content(
|
|
|
392
396
|
|
|
393
397
|
```python
|
|
394
398
|
# 并发下载图集内容
|
|
395
|
-
images = self.
|
|
399
|
+
images = self.create_images([
|
|
396
400
|
"https://example.com/img1.jpg",
|
|
397
401
|
"https://example.com/img2.jpg",
|
|
398
402
|
])
|
|
399
403
|
```
|
|
400
404
|
|
|
401
|
-
> 创建动图内容(GIF),平台一般只提供视频(后续插件会做自动转为 gif 的处理)
|
|
402
|
-
|
|
403
|
-
```python
|
|
404
|
-
dynamics = self.create_dynamic_contents([
|
|
405
|
-
"https://example.com/dynamic1.mp4",
|
|
406
|
-
"https://example.com/dynamic2.mp4",
|
|
407
|
-
])
|
|
408
|
-
```
|
|
409
|
-
|
|
410
405
|
> 重定向 url
|
|
411
406
|
|
|
412
407
|
```python
|
|
@@ -424,5 +419,5 @@ real_url = await self.get_redirect_url(
|
|
|
424
419
|
|
|
425
420
|
## 🎉 致谢
|
|
426
421
|
|
|
427
|
-
[nonebot-plugin-resolver](https://github.com/zhiyu1998/nonebot-plugin-resolver)
|
|
428
|
-
[parse-video-py](https://github.com/wujunwei928/parse-video-py)
|
|
422
|
+
- [nonebot-plugin-resolver](https://github.com/zhiyu1998/nonebot-plugin-resolver) | 初代解析插件
|
|
423
|
+
- [parse-video-py](https://github.com/wujunwei928/parse-video-py) | 借鉴了抖音解析
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nonebot-plugin-parser"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.6.0"
|
|
4
4
|
description = "NoneBot2 链接分享解析 Alconna 版, 现支持B站|抖音|快手|微博|小红书|YouTube|TikTok|Twitter|AcFun|NGA"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -118,7 +118,7 @@ nonebug = { git = "https://github.com/nonebot/nonebug", rev = "master" }
|
|
|
118
118
|
[tool.bumpversion]
|
|
119
119
|
tag = true
|
|
120
120
|
commit = true
|
|
121
|
-
current_version = "2.
|
|
121
|
+
current_version = "2.6.0"
|
|
122
122
|
message = "release: bump vesion from {current_version} to {new_version}"
|
|
123
123
|
|
|
124
124
|
[[tool.bumpversion.files]]
|
{nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/config.py
RENAMED
|
@@ -48,6 +48,8 @@ class Config(BaseModel):
|
|
|
48
48
|
"""Renderer 类型"""
|
|
49
49
|
parser_custom_font: str | None = None
|
|
50
50
|
"""自定义字体"""
|
|
51
|
+
parser_custom_font_weight: int = 700
|
|
52
|
+
"""字体粗细程度"""
|
|
51
53
|
parser_need_forward_contents: bool = True
|
|
52
54
|
"""是否需要转发媒体内容"""
|
|
53
55
|
parser_emoji_cdn: str = ELK_SH_CDN
|
|
@@ -160,6 +162,11 @@ class Config(BaseModel):
|
|
|
160
162
|
|
|
161
163
|
return font_path
|
|
162
164
|
|
|
165
|
+
@property
|
|
166
|
+
def custom_font_weight(self) -> int:
|
|
167
|
+
"""字体粗细程度"""
|
|
168
|
+
return self.parser_custom_font_weight
|
|
169
|
+
|
|
163
170
|
@property
|
|
164
171
|
def need_forward_contents(self) -> bool:
|
|
165
172
|
"""是否需要转发媒体内容"""
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from typing import Any, TypeVar, ParamSpec
|
|
2
|
+
from asyncio import Task, create_task
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from functools import wraps
|
|
5
|
+
from collections.abc import Callable, Coroutine
|
|
6
|
+
|
|
7
|
+
P = ParamSpec("P")
|
|
8
|
+
T = TypeVar("T")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def auto_task(func: Callable[P, Coroutine[Any, Any, Path]]) -> Callable[P, Task[Path]]:
|
|
12
|
+
"""装饰器:自动将异步函数调用转换为 Task, 完整保留类型提示"""
|
|
13
|
+
|
|
14
|
+
@wraps(func)
|
|
15
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> Task[Path]:
|
|
16
|
+
coro = func(*args, **kwargs)
|
|
17
|
+
name = " | ".join(str(arg) for arg in args if isinstance(arg, str))
|
|
18
|
+
return create_task(coro, name=func.__name__ + " | " + name)
|
|
19
|
+
|
|
20
|
+
return wrapper
|
{nonebot_plugin_parser-2.5.3 → nonebot_plugin_parser-2.6.0}/src/nonebot_plugin_parser/helper.py
RENAMED
|
@@ -78,7 +78,11 @@ class UniHelper:
|
|
|
78
78
|
return Voice(path=audio_path)
|
|
79
79
|
|
|
80
80
|
@classmethod
|
|
81
|
-
def video_seg(
|
|
81
|
+
def video_seg(
|
|
82
|
+
cls,
|
|
83
|
+
video_path: Path,
|
|
84
|
+
thumbnail: Path | None = None,
|
|
85
|
+
) -> Video | File | Text:
|
|
82
86
|
"""视频 Seg"""
|
|
83
87
|
# 检测文件大小
|
|
84
88
|
file_size_byte_count = int(video_path.stat().st_size)
|
|
@@ -89,9 +93,15 @@ class UniHelper:
|
|
|
89
93
|
return cls.file_seg(video_path, display_name=video_path.name)
|
|
90
94
|
else:
|
|
91
95
|
if pconfig.use_base64:
|
|
92
|
-
|
|
96
|
+
video = Video(raw=video_path.read_bytes())
|
|
97
|
+
if thumbnail and thumbnail.stat().st_size > 0:
|
|
98
|
+
video.thumbnail = cls.img_seg(thumbnail.read_bytes())
|
|
99
|
+
return video
|
|
93
100
|
else:
|
|
94
|
-
|
|
101
|
+
video = Video(path=video_path)
|
|
102
|
+
if thumbnail and thumbnail.stat().st_size > 0:
|
|
103
|
+
video.thumbnail = cls.img_seg(thumbnail)
|
|
104
|
+
return video
|
|
95
105
|
|
|
96
106
|
@staticmethod
|
|
97
107
|
def file_seg(
|
|
@@ -7,6 +7,7 @@ from collections.abc import Callable, Coroutine
|
|
|
7
7
|
from typing_extensions import Unpack, final
|
|
8
8
|
|
|
9
9
|
from .data import Platform, ParseResult, ImageContent, ParseResultKwargs
|
|
10
|
+
from .task import PathTask
|
|
10
11
|
from ..config import pconfig as pconfig
|
|
11
12
|
from ..download import DOWNLOADER
|
|
12
13
|
from ..constants import IOS_HEADER, COMMON_HEADER, ANDROID_HEADER, COMMON_TIMEOUT
|
|
@@ -15,7 +16,6 @@ from ..constants import PlatformEnum as PlatformEnum
|
|
|
15
16
|
from ..exception import ParseException
|
|
16
17
|
from ..exception import IgnoreException as IgnoreException
|
|
17
18
|
from ..exception import DownloadException as DownloadException
|
|
18
|
-
from ..download.task import PathTask, OptionalPathTask
|
|
19
19
|
|
|
20
20
|
T = TypeVar("T", bound="BaseParser")
|
|
21
21
|
HandlerFunc = Callable[[T, Match[str]], Coroutine[Any, Any, ParseResult]]
|
|
@@ -167,34 +167,45 @@ class BaseParser:
|
|
|
167
167
|
"""创建作者对象"""
|
|
168
168
|
from .data import Author
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
author = Author(name=name, description=description)
|
|
171
|
+
|
|
171
172
|
if avatar_url:
|
|
172
|
-
|
|
173
|
-
|
|
173
|
+
author.avatar = PathTask(DOWNLOADER.download_img(avatar_url, ext_headers=self.headers))
|
|
174
|
+
|
|
175
|
+
return author
|
|
174
176
|
|
|
175
|
-
def
|
|
177
|
+
def create_video(
|
|
176
178
|
self,
|
|
177
|
-
url_or_task: str | Task[Path]
|
|
179
|
+
url_or_task: str | Task[Path],
|
|
178
180
|
cover_url: str | None = None,
|
|
179
181
|
duration: float | None = None,
|
|
180
182
|
):
|
|
181
183
|
"""创建视频内容"""
|
|
182
184
|
from .data import VideoContent
|
|
183
|
-
|
|
184
|
-
cover_task = None
|
|
185
|
-
if cover_url:
|
|
186
|
-
cover_task = DOWNLOADER.download_img(cover_url, ext_headers=self.headers)
|
|
185
|
+
from ..utils import extract_video_cover
|
|
187
186
|
|
|
188
187
|
if isinstance(url_or_task, str):
|
|
189
188
|
path_task = DOWNLOADER.download_video(url_or_task, ext_headers=self.headers)
|
|
190
189
|
elif isinstance(url_or_task, Task):
|
|
191
|
-
path_task = PathTask(url_or_task)
|
|
192
|
-
elif isinstance(url_or_task, PathTask):
|
|
193
190
|
path_task = url_or_task
|
|
194
191
|
|
|
195
|
-
|
|
192
|
+
if cover_url:
|
|
193
|
+
cover_task = DOWNLOADER.download_img(cover_url, ext_headers=self.headers)
|
|
194
|
+
else:
|
|
195
|
+
# 如果没有封面 URL,尝试从视频中提取封面
|
|
196
|
+
async def extract_cover():
|
|
197
|
+
video_path = await path_task
|
|
198
|
+
return await extract_video_cover(video_path)
|
|
199
|
+
|
|
200
|
+
cover_task = extract_cover()
|
|
201
|
+
|
|
202
|
+
return VideoContent(
|
|
203
|
+
PathTask(path_task),
|
|
204
|
+
cover=PathTask(cover_task),
|
|
205
|
+
duration=duration,
|
|
206
|
+
)
|
|
196
207
|
|
|
197
|
-
def
|
|
208
|
+
def create_images(
|
|
198
209
|
self,
|
|
199
210
|
image_urls: list[str],
|
|
200
211
|
):
|
|
@@ -202,56 +213,25 @@ class BaseParser:
|
|
|
202
213
|
contents: list[ImageContent] = []
|
|
203
214
|
for url in image_urls:
|
|
204
215
|
task = DOWNLOADER.download_img(url, ext_headers=self.headers)
|
|
205
|
-
contents.append(ImageContent(task))
|
|
216
|
+
contents.append(ImageContent(PathTask(task)))
|
|
206
217
|
return contents
|
|
207
218
|
|
|
208
|
-
def
|
|
219
|
+
def create_image(
|
|
209
220
|
self,
|
|
210
|
-
url_or_task: str | Task[Path]
|
|
221
|
+
url_or_task: str | Task[Path],
|
|
211
222
|
alt: str | None = None,
|
|
212
223
|
):
|
|
213
|
-
"""
|
|
224
|
+
"""创建单个图片内容"""
|
|
214
225
|
if isinstance(url_or_task, str):
|
|
215
226
|
path_task = DOWNLOADER.download_img(url_or_task, ext_headers=self.headers)
|
|
216
227
|
elif isinstance(url_or_task, Task):
|
|
217
|
-
path_task = PathTask(url_or_task)
|
|
218
|
-
elif isinstance(url_or_task, PathTask):
|
|
219
|
-
path_task = url_or_task
|
|
220
|
-
|
|
221
|
-
return ImageContent(path_task, alt=alt)
|
|
222
|
-
|
|
223
|
-
def create_dynamic_contents(
|
|
224
|
-
self,
|
|
225
|
-
dynamic_urls: list[str],
|
|
226
|
-
):
|
|
227
|
-
"""创建动态图片内容列表"""
|
|
228
|
-
from .data import DynamicContent
|
|
229
|
-
|
|
230
|
-
contents: list[DynamicContent] = []
|
|
231
|
-
for url in dynamic_urls:
|
|
232
|
-
task = DOWNLOADER.download_video(url, ext_headers=self.headers)
|
|
233
|
-
contents.append(DynamicContent(task))
|
|
234
|
-
return contents
|
|
235
|
-
|
|
236
|
-
def create_dynamic_content(
|
|
237
|
-
self,
|
|
238
|
-
url_or_task: str | Task[Path] | PathTask,
|
|
239
|
-
):
|
|
240
|
-
"""创建动态图片内容"""
|
|
241
|
-
from .data import DynamicContent
|
|
242
|
-
|
|
243
|
-
if isinstance(url_or_task, str):
|
|
244
|
-
path_task = DOWNLOADER.download_video(url_or_task, ext_headers=self.headers)
|
|
245
|
-
elif isinstance(url_or_task, Task):
|
|
246
|
-
path_task = PathTask(url_or_task)
|
|
247
|
-
elif isinstance(url_or_task, PathTask):
|
|
248
228
|
path_task = url_or_task
|
|
249
229
|
|
|
250
|
-
return
|
|
230
|
+
return ImageContent(PathTask(path_task), alt=alt)
|
|
251
231
|
|
|
252
|
-
def
|
|
232
|
+
def create_audio(
|
|
253
233
|
self,
|
|
254
|
-
url_or_task: str | Task[Path]
|
|
234
|
+
url_or_task: str | Task[Path],
|
|
255
235
|
duration: float = 0.0,
|
|
256
236
|
):
|
|
257
237
|
"""创建音频内容"""
|
|
@@ -260,11 +240,9 @@ class BaseParser:
|
|
|
260
240
|
if isinstance(url_or_task, str):
|
|
261
241
|
path_task = DOWNLOADER.download_audio(url_or_task, ext_headers=self.headers)
|
|
262
242
|
elif isinstance(url_or_task, Task):
|
|
263
|
-
path_task = PathTask(url_or_task)
|
|
264
|
-
elif isinstance(url_or_task, PathTask):
|
|
265
243
|
path_task = url_or_task
|
|
266
244
|
|
|
267
|
-
return AudioContent(path_task, duration)
|
|
245
|
+
return AudioContent(PathTask(path_task), duration)
|
|
268
246
|
|
|
269
247
|
@property
|
|
270
248
|
def downloader(self):
|
|
@@ -148,7 +148,7 @@ class BilibiliParser(BaseParser):
|
|
|
148
148
|
)
|
|
149
149
|
return path
|
|
150
150
|
|
|
151
|
-
video_content = self.
|
|
151
|
+
video_content = self.create_video(
|
|
152
152
|
asyncio.create_task(download_video()),
|
|
153
153
|
page_info.cover,
|
|
154
154
|
page_info.duration,
|
|
@@ -188,7 +188,7 @@ class BilibiliParser(BaseParser):
|
|
|
188
188
|
# 下载图片
|
|
189
189
|
author = self.create_author(dynamic_info.name, dynamic_info.avatar)
|
|
190
190
|
contents: list[MediaContent] = []
|
|
191
|
-
contents.extend(self.
|
|
191
|
+
contents.extend(self.create_images(dynamic_info.image_urls))
|
|
192
192
|
|
|
193
193
|
repost = None
|
|
194
194
|
if dynamic_info.type == "DYNAMIC_TYPE_FORWARD" and dynamic_info.orig is not None:
|
|
@@ -234,7 +234,7 @@ class BilibiliParser(BaseParser):
|
|
|
234
234
|
if isinstance(node, str):
|
|
235
235
|
result.graphics.append(node)
|
|
236
236
|
else:
|
|
237
|
-
result.graphics.append(self.
|
|
237
|
+
result.graphics.append(self.create_image(node.url, alt=node.alt))
|
|
238
238
|
|
|
239
239
|
return result
|
|
240
240
|
|
|
@@ -252,12 +252,12 @@ class BilibiliParser(BaseParser):
|
|
|
252
252
|
# 下载封面
|
|
253
253
|
if cover := room_data.cover:
|
|
254
254
|
cover_task = self.downloader.download_img(cover, ext_headers=self.headers)
|
|
255
|
-
contents.append(
|
|
255
|
+
contents.append(self.create_image(cover_task))
|
|
256
256
|
|
|
257
257
|
# 下载关键帧
|
|
258
258
|
if keyframe := room_data.keyframe:
|
|
259
259
|
keyframe_task = self.downloader.download_img(keyframe, ext_headers=self.headers)
|
|
260
|
-
contents.append(
|
|
260
|
+
contents.append(self.create_image(keyframe_task))
|
|
261
261
|
|
|
262
262
|
author = self.create_author(room_data.name, room_data.avatar)
|
|
263
263
|
|
|
@@ -288,7 +288,7 @@ class BilibiliParser(BaseParser):
|
|
|
288
288
|
|
|
289
289
|
graphics: list[str | ImageContent] = []
|
|
290
290
|
for fav in favdata.medias:
|
|
291
|
-
graphics.append(self.
|
|
291
|
+
graphics.append(self.create_image(fav.cover, alt=fav.desc))
|
|
292
292
|
graphics.append(fav.desc)
|
|
293
293
|
|
|
294
294
|
return self.result(
|