nonebot-plugin-shitbot 0.6.0__tar.gz → 0.7.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.
Files changed (47) hide show
  1. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/PKG-INFO +2 -1
  2. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/README.md +11 -8
  3. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/__init__.py +2 -0
  4. nonebot_plugin_shitbot-0.7.0/nonebot_plugin_shitbot/commands/bilibili_cmd.py +178 -0
  5. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/help_cmd.py +2 -0
  6. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/md2pic_cmd.py +2 -0
  7. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/randpic_cmd.py +8 -3
  8. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/config.py +9 -0
  9. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/handlers.py +2 -0
  10. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/autoreply.md +1 -0
  11. nonebot_plugin_shitbot-0.7.0/nonebot_plugin_shitbot/help/bilibili.md +39 -0
  12. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/convert.md +1 -1
  13. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/index.md +4 -2
  14. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/md2pic.md +1 -1
  15. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/perm.md +1 -1
  16. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/pixiv.md +2 -2
  17. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/randpic.md +1 -1
  18. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/shitpost.md +3 -3
  19. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot.egg-info/PKG-INFO +2 -1
  20. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot.egg-info/SOURCES.txt +2 -0
  21. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot.egg-info/requires.txt +1 -0
  22. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/pyproject.toml +2 -1
  23. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/LICENSE +0 -0
  24. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/__init__.py +0 -0
  25. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/aux.py +0 -0
  26. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/command.py +0 -0
  27. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/autoreply_cmd.py +0 -0
  28. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/autoreply_main_cmd.py +1 -1
  29. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/convert_cmd.py +0 -0
  30. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/perm_cmd.py +0 -0
  31. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/pixiv_cmd.py +0 -0
  32. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/session_cmd.py +0 -0
  33. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/commands/shitpost_cmd.py +0 -0
  34. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/css/github-markdown-dark-dimmed.css +0 -0
  35. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/help.md +0 -0
  36. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/imgs/md2picex1.png +0 -0
  37. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/imgs/md2picex2.png +0 -0
  38. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/help/session.md +0 -0
  39. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/msgdatabase.py +0 -0
  40. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/msgutils.py +0 -0
  41. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/parser.py +0 -0
  42. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/permissions.py +0 -0
  43. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/session.py +0 -0
  44. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot/tasks.py +0 -0
  45. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot.egg-info/dependency_links.txt +0 -0
  46. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/nonebot_plugin_shitbot.egg-info/top_level.txt +0 -0
  47. {nonebot_plugin_shitbot-0.6.0 → nonebot_plugin_shitbot-0.7.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nonebot-plugin-shitbot
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: NoneBot shitpost plugin
5
5
  Requires-Python: >=3.10
6
6
  License-File: LICENSE
@@ -10,6 +10,7 @@ Requires-Dist: nonebot-plugin-htmlrender>=0.6.7
10
10
  Requires-Dist: fastapi>=0.100
11
11
  Requires-Dist: nonebot-plugin-localstore>=0.3.0
12
12
  Requires-Dist: PixivPy-Async>=1.2.14
13
+ Requires-Dist: yt-dlp>=2026.8.19
13
14
  Requires-Dist: Pillow>=12.2.0
14
15
  Requires-Dist: httpx>=0.28.1
15
16
  Requires-Dist: python-magic>=0.4
@@ -10,6 +10,8 @@
10
10
 
11
11
  - 给定 PID 获取P站图片
12
12
 
13
+ - B站视频解析与下载
14
+
13
15
  - 半自动搬史
14
16
 
15
17
  - Markdown渲染
@@ -23,13 +25,13 @@
23
25
  - 信息处理函数库(msgutils) 涵盖对信息对象的转换、处理、发送 运用函数式方案处理信息
24
26
 
25
27
  - 手搓信息管理数据库
26
- - 数据库由两部分组成: messages以及medias
27
- - messages用于存储信息 通过将 Message 转化为 DumpedMsg 后以 yaml 格式存储
28
+ - 数据库由两部分组成: msgs以及medias
29
+ - msgs用于存储信息 通过将 Message 转化为 DumpedMsg 后以 yaml 格式存储
28
30
  - 文件名为该文件的sha256sum值 通过比较文件名去重
29
- - 维护一个映射表(的yaml文件) 用于记录信息的引用数(由数据库用户维护) 通常若元信息的引用数为0 则删除元信息
30
- - medias用于messages中信息中可能存在的多媒体文件
31
+ - 维护一个映射表(的yaml文件) 用于记录信息的引用数(由数据库用户维护) 通常若信息的引用数为0 则删除信息
32
+ - medias用于msgs中信息中可能存在的多媒体文件
31
33
  - 文件名为该文件的sha256sum值 通过比较文件名去重
32
- - 维护一个映射表(的yaml文件) 用于记录文件的引用数(只会被messages中的信息引用 因此仅由数据库本身维护) 通常若元信息的引用数为0 则删除元信息
34
+ - 维护一个映射表(的yaml文件) 用于记录文件的引用数(只会被msgs中的信息引用 因此仅由数据库本身维护) 通常若文件的引用数为0 则删除文件
33
35
 
34
36
  - 自动回复系统
35
37
 
@@ -37,8 +39,6 @@
37
39
 
38
40
  - 添加单元测试 (技术债务这块 最讨厌的一集 想写哪个就写哪个)
39
41
 
40
- - B站视频解析并下载(支持链接块或者BV号)(6.12更新:我鬼脑意淫后越想越觉得写这个好累 所以把优先级后调)
41
-
42
42
  - 为代码添加更多注释和写文档 (依旧技术债务 依旧最烦 依旧随缘)
43
43
 
44
44
  - 智能化/shitpost (鉴于数据库搓好了 如果我后面认为这个写起来也不难的话我就来搓)
@@ -75,7 +75,7 @@ nb plugin install nonebot-plugin-shitbot
75
75
  |---|---|---|---|---|
76
76
  | `SHITBOT__CLIENT_CACHE` | 路径 | 本地缓存路径 | 否 | 容器端缓存路径。本地缓存路径为 `$LOCALSTORE_CACHE_DIR/nonebot_plugin_shitbot`,容器端需对应挂载 |
77
77
  | `SHITBOT__CLIENT_DATA` | 路径 | 本地数据路径 | 否 | 容器端数据路径。本地数据路径为 `$LOCALSTORE_DATA_DIR/nonebot_plugin_shitbot`,容器端需对应挂载 |
78
- | `SHITBOT__OWNERS` | JSON 字符串列表 | None | 是 | 机器人所有者 QQ 号列表,如 `'["114514"]'` |
78
+ | `SHITBOT__OWNERS` | JSON 字符串列表 | None | 否(强烈建议) | 机器人所有者 QQ 号列表,如 `'["114514"]'`。未配置时 owners 组为空 |
79
79
  | `SHITBOT__MAX_MESSAGE_DEPTH` | 整数 | `16` | 否 | 消息解析最大递归深度 |
80
80
  | `SHITBOT__PIXIV_ACCESS_TOKEN` | 字符串 | "" | 部分必填 | Pixiv API 访问令牌(使用 `/pixiv` 时必填) |
81
81
 
@@ -87,7 +87,9 @@ nb plugin install nonebot-plugin-shitbot
87
87
  | `/perm` | 权限管理 |
88
88
  | `/help` | 查看帮助 |
89
89
  | `/randpic` | 随机二次元图片 |
90
+ | `/涩图` | `/randpic` 的别名 |
90
91
  | `/pixiv` | P站图片检索 |
92
+ | `/bilibili` | B站视频解析与下载 |
91
93
  | `/convert` | 图片格式转换 |
92
94
  | `/shitpost` | 搬史 |
93
95
  | `/md2pic` | Markdown 渲染为图片 |
@@ -97,6 +99,7 @@ nb plugin install nonebot-plugin-shitbot
97
99
 
98
100
  - [ManyACG](https://manyacg.top): 为 /randpic ~~*以及下面的彩蛋*~~ 提供了API
99
101
  - [Lolicon APP](https://lolicon.app): 为 /randpic 提供了API
102
+ - [yt-dlp](https://github.com/yt-dlp/yt-dlp): 为 /bilibili 提供视频解析与下载
100
103
  - [github-markdown-css](https://github.com/sindresorhus/github-markdown-css): 为markdown渲染提供了CSS主题
101
104
 
102
105
  ###### 彩蛋: 千人千面(据说每个人看到的图都不一样):
@@ -1,6 +1,7 @@
1
1
  from ..command import BotCommand
2
2
  from .autoreply_cmd import BotCommandAutoreply
3
3
  from .autoreply_main_cmd import BotCommandAutoReplyMain
4
+ from .bilibili_cmd import BotCommandBilibili
4
5
  from .convert_cmd import BotCommandConvert
5
6
  from .help_cmd import BotCommandHelp
6
7
  from .md2pic_cmd import BotCommandMd2pic
@@ -14,6 +15,7 @@ __all__ = [
14
15
  "BotCommand",
15
16
  "BotCommandAutoReplyMain",
16
17
  "BotCommandAutoreply",
18
+ "BotCommandBilibili",
17
19
  "BotCommandConvert",
18
20
  "BotCommandHelp",
19
21
  "BotCommandMd2pic",
@@ -0,0 +1,178 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ import time
6
+ import random
7
+ import asyncio
8
+ import json
9
+
10
+ from pathlib import Path
11
+ from yt_dlp import YoutubeDL
12
+
13
+ from nonebot.adapters.onebot.v11 import Bot, Message, MessageSegment
14
+ from nonebot.log import logger
15
+
16
+ from ..command import BotCommand
17
+ from ..config import config
18
+ from ..parser import BotArgParser
19
+ from ..msgutils import undump_message
20
+
21
+ if TYPE_CHECKING:
22
+ from ..session import BotSession
23
+ from yt_dlp import _Params
24
+
25
+
26
+ class BotCommandBilibili(BotCommand):
27
+ _name = "bilibili"
28
+
29
+ def __init__(self, bot: Bot, session: BotSession, *, _pid: int, _internal=None):
30
+ super().__init__(bot, session, _pid=_pid, _internal=_internal)
31
+ self._links = []
32
+ self._infos = []
33
+ self._video_paths = []
34
+
35
+ def _init_parser(self):
36
+ parser = BotArgParser()
37
+ parser.set_rule(min=0)
38
+ return parser
39
+
40
+ async def _parse_videos(self, ydl: YoutubeDL, videos_dir: Path):
41
+ def _parseor():
42
+ for link in self._links:
43
+ time.sleep(random.uniform(1, 3))
44
+ try:
45
+ info = ydl.extract_info(link, download=False)
46
+ if info is None:
47
+ raise ValueError(f"链接无效或无法提取信息")
48
+ except Exception as e:
49
+ logger.error(f"提取{link}信息失败: {e}")
50
+ self._infos.append((False, Message(MessageSegment.text(f"提取视频信息失败"))))
51
+ self._video_paths.append(None)
52
+ continue
53
+
54
+ identity = info.get("id") or ""
55
+ title = info.get("title") or ""
56
+ author = info.get("uploader") or ""
57
+ cover = info.get("thumbnail") or ""
58
+ if cover.startswith("http://"):
59
+ cover = "https://" + cover[len("http://") :]
60
+ text = f"标题: {title}\nUP主: {author}\nBV: {identity}"
61
+ msg = Message()
62
+ msg.append(MessageSegment.text(text))
63
+ if cover:
64
+ msg.append(MessageSegment.image(cover))
65
+ self._infos.append((True, msg))
66
+
67
+ try:
68
+ res = ydl.process_ie_result(info, download=True)
69
+ downloads = (res or {}).get("requested_downloads") or []
70
+ video_path_str = downloads[0].get("filepath") if downloads else None
71
+ if not video_path_str or not Path(video_path_str).is_file():
72
+ raise ValueError(f"未产出有效文件")
73
+ self._video_paths.append(Path(video_path_str))
74
+ except Exception as e:
75
+ logger.error(f"下载{link}失败: {e}")
76
+ self._video_paths.append(None)
77
+ continue
78
+
79
+ await asyncio.to_thread(_parseor)
80
+
81
+ async def run(self, args: Message):
82
+ if not self.session:
83
+ return
84
+ pre_argv = []
85
+ if len(args) >= 1 and args[0].type == "reply":
86
+ reply_stuff = await self.bot.get_msg(message_id=args[0].data["id"])
87
+ pre_argv = undump_message(reply_stuff["message"]).extract_plain_text().strip().split()
88
+ for seg in reply_stuff["message"]:
89
+ if seg["type"] != "json":
90
+ continue
91
+ sub_json = json.loads(seg.get("data", {}).get("data") or "{}")
92
+ link = sub_json.get("meta", {}).get("detail_1", {}).get("qqdocurl", "")
93
+ if "b23.tv/" not in link and "bilibili.com/video/" not in link:
94
+ continue
95
+ self._links.append(link)
96
+
97
+ new_argv = args.extract_plain_text().strip().split()
98
+ if not await self._legal_case(new_argv):
99
+ if self._argv is None:
100
+ self.unlock()
101
+ return
102
+
103
+ if not await self._guard_state():
104
+ return
105
+
106
+ self._argv = new_argv
107
+ self._parser.parse_argv(self._argv)
108
+
109
+ if not self._check_perm("bilibili"):
110
+ await self.send_msg("权限不足")
111
+ self.unlock()
112
+ return
113
+
114
+ contexts = pre_argv + self._parser.value
115
+
116
+ for seg in contexts:
117
+ link = ""
118
+ if "b23.tv/" in seg:
119
+ link = f"https://b23.tv/{seg.split('b23.tv/')[-1]}"
120
+ elif "bilibili.com/video/" in seg:
121
+ link = f"https://www.bilibili.com/video/{seg.split('bilibili.com/video/')[-1]}"
122
+ elif "BV" in seg:
123
+ link = f"https://www.bilibili.com/video/BV{seg.split('BV')[-1]}"
124
+ elif "av" in seg:
125
+ link = f"https://www.bilibili.com/video/av{seg.split('av')[-1]}"
126
+ if not link:
127
+ continue
128
+ self._links.append(link)
129
+
130
+ if not self._links:
131
+ await self.send_msg("未检测到有效链接")
132
+ self.unlock()
133
+ return
134
+
135
+ videos_dir = (
136
+ config.cache
137
+ / self.session.group_id
138
+ / self.session.user_id
139
+ / str(self._pid)
140
+ / "videos"
141
+ )
142
+ videos_dir.mkdir(parents=True, exist_ok=True)
143
+
144
+ opts: _Params = {
145
+ "no_warnings": True,
146
+ "noplaylist": True,
147
+ "format_sort": [f"res:{720}", "vcodec:h264"],
148
+ "merge_output_format": "mp4",
149
+ "outtmpl": str(videos_dir / "%(id)s.%(ext)s"),
150
+ }
151
+ with YoutubeDL(opts) as ydl:
152
+ await self._parse_videos(ydl, videos_dir)
153
+
154
+ for video_path, info in zip(self._video_paths, self._infos):
155
+ try:
156
+ await self.send_msg(info[1])
157
+ except Exception as e:
158
+ logger.error(f"发送消息失败: {e}")
159
+ if info[1][-1].type != "image":
160
+ continue
161
+ info[1][-1] = MessageSegment.text("\n封面获取失败")
162
+ await self.send_msg(info[1])
163
+ if not info[0]:
164
+ continue
165
+ if not video_path:
166
+ await self.send_msg("视频下载失败")
167
+ continue
168
+ container_path = config.client_cache / video_path.relative_to(config.cache)
169
+ try:
170
+ await self.send_msg(
171
+ Message(MessageSegment.video(f"file://{container_path}"))
172
+ )
173
+ except Exception as e:
174
+ logger.error(f"发送视频失败: {e}")
175
+ await self.send_msg("视频发送失败")
176
+
177
+
178
+ self.unlock()
@@ -32,6 +32,7 @@ class BotCommandHelp(BotCommand):
32
32
  parser.add_subparser("md2pic")
33
33
  parser.add_subparser("pixiv")
34
34
  parser.add_subparser("autoreply")
35
+ parser.add_subparser("bilibili")
35
36
  return parser
36
37
 
37
38
  async def run(self, args: Message):
@@ -70,6 +71,7 @@ class BotCommandHelp(BotCommand):
70
71
  "md2pic",
71
72
  "pixiv",
72
73
  "autoreply",
74
+ "bilibili",
73
75
  ):
74
76
  tip = f"错误: 帮助文档 {subcmd}.md 不存在"
75
77
  help_path = help_dir / f"{subcmd}.md"
@@ -175,6 +175,8 @@ class BotCommandMd2pic(BotCommand):
175
175
  )
176
176
  self._md = self._parser.value[0]
177
177
 
178
+ self._scale = max(1, self._scale)
179
+ self._scale = min(50, self._scale)
178
180
  self._padding = max(0, self._padding)
179
181
  self._padding = min(50, self._padding)
180
182
  self._max_w = min(10000000, self._max_w)
@@ -1,10 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import random
3
4
  from typing import TYPE_CHECKING, Any
4
5
 
5
6
  import httpx
6
- import random
7
-
8
7
  from nonebot.adapters.onebot.v11 import Bot, Message, MessageSegment
9
8
  from nonebot.log import logger
10
9
 
@@ -158,7 +157,13 @@ class BotCommandRandpic(BotCommand):
158
157
  self._size = "regular"
159
158
 
160
159
  self._keyword = self._parser.opts_value["-k"][0]
161
- if self._keyword.replace(" ", "").replace(",", "").replace("|", "").replace("&", "") == "":
160
+ if (
161
+ self._keyword.replace(" ", "")
162
+ .replace(",", "")
163
+ .replace("|", "")
164
+ .replace("&", "")
165
+ == ""
166
+ ):
162
167
  self._keyword = ""
163
168
 
164
169
  pics = await self._get_pics()
@@ -118,6 +118,15 @@ _DEFAULT_ENTRIES: dict[str, list] = {
118
118
  [],
119
119
  ["banned"],
120
120
  ],
121
+ "bilibili": [
122
+ "是否允许使用bilibili命令",
123
+ False,
124
+ [],
125
+ ["banned"],
126
+ False,
127
+ [],
128
+ ["banned"],
129
+ ],
121
130
  }
122
131
 
123
132
 
@@ -147,6 +147,8 @@ cmd_md2pic = cmd_register("md2pic", BotCommandMd2pic)
147
147
 
148
148
  cmd_autoreply = cmd_register("autoreply", BotCommandAutoreply)
149
149
 
150
+ cmd_bilibili = cmd_register("bilibili", BotCommandBilibili)
151
+
150
152
  cmd_otherwise = cmd_register("", BotCommand, priority=3)
151
153
 
152
154
  # ===Messages handlers=== #
@@ -159,6 +159,7 @@
159
159
  ## 注意
160
160
 
161
161
  - 使用该命令需要 `autoreplymanager` 条目权限
162
+ - 自动回复默认在 bot 启动时开启
162
163
  - `reply` 收集与存储的消息仅支持文字、图片和表情
163
164
  - `reply start` 和 `reply stop` 需要在目标回复已通过 `create` 创建后使用
164
165
  - `reply modify` 仅在目标回复已被设置内容后可用
@@ -0,0 +1,39 @@
1
+ # /bilibili
2
+
3
+ **解析并下载 B 站视频**
4
+
5
+ ## 使用方式
6
+
7
+ ```bash
8
+ /bilibili [链接或 av 号或 BV 号 ...]
9
+ ```
10
+
11
+ ### 支持的输入
12
+
13
+ | 形式 | 示例 |
14
+ |------|------|
15
+ | BV 号 | `BV1GJ411x7h7` |
16
+ | av 号 | `av170001` |
17
+ | 视频链接 | `https://www.bilibili.com/video/XXXXXX` |
18
+ | 短链 | `https://b23.tv/xxxxxxx` |
19
+
20
+ 可以一次给出多个,Bot 会按顺序逐个处理。
21
+
22
+ 也可以回复一条包含 B 站链接或分享卡片的消息,再发送 `/bilibili`,Bot 会自动从被回复的消息中提取链接。
23
+
24
+ 收到链接后,Bot 会先发送视频信息(标题、UP主、BV 号、封面),再发送视频本体。
25
+
26
+ ## 示例
27
+
28
+ ```bash
29
+ /bilibili BV1GJ411x7h7
30
+ /bilibili https://www.bilibili.com/video/BV1GJ411x7h7
31
+ /bilibili BV1GJ411x7h7 BV1uv411q7Mv
32
+
33
+ # 回复一条含 B 站链接的消息
34
+ /bilibili
35
+ ```
36
+
37
+ ## 注意
38
+
39
+ - 使用该命令需要 `bilibili` 权限条目通过
@@ -33,5 +33,5 @@
33
33
 
34
34
  ## 注意
35
35
 
36
- - 此命令默认仅限好友私聊使用
36
+ - 此命令通常只会在私聊下被使用,但仍可通过`/perm`命令修改权限实现在群聊使用
37
37
  - 发送视频时,若视频发送失败,Bot 会尝试以文件的形式发送
@@ -7,10 +7,12 @@
7
7
  | `/session` | 管理当前会话 |
8
8
  | `/perm` | 权限查看与管理 |
9
9
  | `/help` | 显示帮助信息 |
10
- | `/convert` | 收集图片并批量处理后发送(默认仅私聊) |
10
+ | `/convert` | 收集图片并批量处理后发送 |
11
11
  | `/randpic` | 随机获取二次元图片 |
12
+ | `/涩图` | `/randpic` 的别名 |
12
13
  | `/pixiv` | 根据Pixiv ID从P站获取图片 |
13
- | `/shitpost` | 将消息转发到多个群聊(默认仅私聊) |
14
+ | `/bilibili` | 解析并下载 B 站视频 |
15
+ | `/shitpost` | 将消息转发到多个群聊 |
14
16
  | `/md2pic` | 将 markdown 文本转换为图片输出 |
15
17
  | `/autoreply` | 自动回复系统管理 |
16
18
 
@@ -14,7 +14,7 @@
14
14
  | 选项 | 说明 |
15
15
  |------|------|
16
16
  | `-c` | 占位符,用于分割参数项与 Markdown 正文,为必填项 |
17
- | `-s <倍率>` | 设置缩放倍率,可填小数,数值越大生成的图片越清晰,数值应在 0~50 之间,默认为 2 |
17
+ | `-s <倍率>` | 设置缩放倍率,可填小数,数值越大生成的图片越清晰,数值应在 1~50 之间,默认为 2 |
18
18
  | `-t <渲染主题>` | 指定渲染主题,默认为 `github-markdown-dark-dimmed` |
19
19
  | `--padding <留空像素>` | 设置渲染结果四周留空的宽度像素,默认为 30 |
20
20
  | `--min_w <宽度像素>` | 设置最小宽度像素,默认为 20 |
@@ -107,4 +107,4 @@
107
107
  - `/perm check` 仅需 `perm` 条目权限
108
108
  - 除 `check` 外的所有子命令需要 `permmanager` 条目权限,或用户在 `owners` 组中
109
109
  - 非 `owners` 组用户无法修改 `admins` 和 `owners` 用户权限组
110
- - 删除 `owners` 组后原 `owners` 用户将失去对应权限,且不能再通过 `/perm` 恢复,需手动编辑 `config.yaml` 恢复
110
+ - 删除 `owners` 组后原 `owners` 用户将失去对应权限,且不能再通过 `/perm` 恢复,需手动编辑数据目录下的 `permissions/owners.yaml` 恢复
@@ -32,9 +32,9 @@
32
32
  ## 示例
33
33
 
34
34
  ```bash
35
- /pixiv 88326528 获取 松うに 的 ミクさんの日2021 的普通质量图片
35
+ /pixiv 88326528 获取 松うに 的 ミクさんの日2021 的原图质量图片
36
36
  /pixiv -s original 46840684 获取 舘津テト 的 う…うるさい! 的原图质量图片
37
- /pixiv -r on 43935647 获取 KOTSU 的 (出るよ) 的普通质量图片, 不对其内容进行过滤(需要 `nsfw` 权限条目通过)
37
+ /pixiv -r on 43935647 获取 KOTSU 的 (出るよ) 的原图质量图片, 不对其内容进行过滤(需要 `nsfw` 权限条目通过)
38
38
  ```
39
39
 
40
40
  ## 注意
@@ -65,7 +65,7 @@
65
65
  ```bash
66
66
  /randpic 获取 1 张图片
67
67
  /randpic -n 3 -s original -a 2 从 Lolicon API 获取 3 张原图
68
- /randpic -n 5 -t 萝莉|少女&白丝|黑丝
68
+ /randpic -n 5 -k 萝莉|少女&白丝|黑丝
69
69
  获取 (萝莉 或 少女) 且 (白丝 或 黑丝) 的图片,共 5 张
70
70
  ```
71
71
 
@@ -19,9 +19,9 @@
19
19
  | `--min <时间>` | 最短转发间隔时间, 单位为秒, 默认为 0 |
20
20
  | `--max <时间>` | 最长转发间隔时间, 单位为秒, 默认为 0 |
21
21
 
22
- 若 max 值或 min 值为负数, 则会被忽略
22
+ 若 max 值或 min 值为负数, 则会被视为 0
23
23
 
24
- 若 max 值小于 min 值,则不会延迟转发
24
+ 若 max 值不大于 min 值,则不会延迟转发
25
25
 
26
26
  ## 示例
27
27
 
@@ -33,7 +33,7 @@
33
33
 
34
34
  ## 注意
35
35
 
36
- - 此命令默认仅限私聊使用
36
+ - 此命令通常只会在私聊下被使用,但仍可通过`/perm`命令修改权限实现在群聊使用
37
37
  - 至少需要指定 1 个群号
38
38
  - Bot 必须已经在目标群中
39
39
  - 支持文本、图片、视频消息以及合并转发消息
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nonebot-plugin-shitbot
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: NoneBot shitpost plugin
5
5
  Requires-Python: >=3.10
6
6
  License-File: LICENSE
@@ -10,6 +10,7 @@ Requires-Dist: nonebot-plugin-htmlrender>=0.6.7
10
10
  Requires-Dist: fastapi>=0.100
11
11
  Requires-Dist: nonebot-plugin-localstore>=0.3.0
12
12
  Requires-Dist: PixivPy-Async>=1.2.14
13
+ Requires-Dist: yt-dlp>=2026.8.19
13
14
  Requires-Dist: Pillow>=12.2.0
14
15
  Requires-Dist: httpx>=0.28.1
15
16
  Requires-Dist: python-magic>=0.4
@@ -20,6 +20,7 @@ nonebot_plugin_shitbot.egg-info/top_level.txt
20
20
  nonebot_plugin_shitbot/commands/__init__.py
21
21
  nonebot_plugin_shitbot/commands/autoreply_cmd.py
22
22
  nonebot_plugin_shitbot/commands/autoreply_main_cmd.py
23
+ nonebot_plugin_shitbot/commands/bilibili_cmd.py
23
24
  nonebot_plugin_shitbot/commands/convert_cmd.py
24
25
  nonebot_plugin_shitbot/commands/help_cmd.py
25
26
  nonebot_plugin_shitbot/commands/md2pic_cmd.py
@@ -30,6 +31,7 @@ nonebot_plugin_shitbot/commands/session_cmd.py
30
31
  nonebot_plugin_shitbot/commands/shitpost_cmd.py
31
32
  nonebot_plugin_shitbot/css/github-markdown-dark-dimmed.css
32
33
  nonebot_plugin_shitbot/help/autoreply.md
34
+ nonebot_plugin_shitbot/help/bilibili.md
33
35
  nonebot_plugin_shitbot/help/convert.md
34
36
  nonebot_plugin_shitbot/help/help.md
35
37
  nonebot_plugin_shitbot/help/index.md
@@ -4,6 +4,7 @@ nonebot-plugin-htmlrender>=0.6.7
4
4
  fastapi>=0.100
5
5
  nonebot-plugin-localstore>=0.3.0
6
6
  PixivPy-Async>=1.2.14
7
+ yt-dlp>=2026.8.19
7
8
  Pillow>=12.2.0
8
9
  httpx>=0.28.1
9
10
  python-magic>=0.4
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nonebot-plugin-shitbot"
3
- version = "0.6.0"
3
+ version = "0.7.0"
4
4
  description = "NoneBot shitpost plugin"
5
5
  requires-python = ">=3.10"
6
6
  dependencies = [
@@ -10,6 +10,7 @@ dependencies = [
10
10
  "fastapi>=0.100",
11
11
  "nonebot-plugin-localstore>=0.3.0",
12
12
  "PixivPy-Async>=1.2.14",
13
+ "yt-dlp>=2026.8.19",
13
14
  "Pillow>=12.2.0",
14
15
  "httpx>=0.28.1",
15
16
  "python-magic>=0.4",
@@ -9,9 +9,9 @@ from ..aux import validate_schema
9
9
  from ..command import BotCommand
10
10
  from ..config import config
11
11
  from ..msgdatabase import BotMsgDataBase
12
+ from ..permissions import permissions
12
13
  from ..session import BotSession
13
14
  from ..tasks import autoreply_lock
14
- from ..permissions import permissions
15
15
 
16
16
  _TERM_SCHEMA = {
17
17
  "trans": [str],