nonebot-plugin-jmdownloader 1.0.3__py3-none-any.whl → 1.1.0__py3-none-any.whl
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_jmdownloader/__init__.py +23 -600
- nonebot_plugin_jmdownloader/bot/__init__.py +18 -0
- nonebot_plugin_jmdownloader/bot/dependencies.py +176 -0
- nonebot_plugin_jmdownloader/bot/handlers/__init__.py +26 -0
- nonebot_plugin_jmdownloader/bot/handlers/ban_id_tag.py +62 -0
- nonebot_plugin_jmdownloader/bot/handlers/blacklist.py +113 -0
- nonebot_plugin_jmdownloader/bot/handlers/download.py +210 -0
- nonebot_plugin_jmdownloader/bot/handlers/group_control.py +172 -0
- nonebot_plugin_jmdownloader/bot/handlers/query.py +76 -0
- nonebot_plugin_jmdownloader/bot/handlers/scheduled.py +38 -0
- nonebot_plugin_jmdownloader/bot/handlers/search.py +224 -0
- nonebot_plugin_jmdownloader/bot/nonebot_utils.py +22 -0
- nonebot_plugin_jmdownloader/config.py +30 -58
- nonebot_plugin_jmdownloader/core/__init__.py +11 -0
- nonebot_plugin_jmdownloader/core/data_models.py +179 -0
- nonebot_plugin_jmdownloader/core/enums.py +10 -0
- nonebot_plugin_jmdownloader/core/search_session.py +74 -0
- nonebot_plugin_jmdownloader/infra/__init__.py +15 -0
- nonebot_plugin_jmdownloader/infra/data_manager.py +104 -0
- nonebot_plugin_jmdownloader/infra/image_utils.py +38 -0
- nonebot_plugin_jmdownloader/infra/jm_service.py +368 -0
- nonebot_plugin_jmdownloader/infra/pdf_utils.py +82 -0
- nonebot_plugin_jmdownloader/infra/search_session.py +43 -0
- nonebot_plugin_jmdownloader/migration.py +232 -0
- nonebot_plugin_jmdownloader-1.1.0.dist-info/METADATA +221 -0
- nonebot_plugin_jmdownloader-1.1.0.dist-info/RECORD +27 -0
- {nonebot_plugin_jmdownloader-1.0.3.dist-info → nonebot_plugin_jmdownloader-1.1.0.dist-info}/WHEEL +1 -2
- nonebot_plugin_jmdownloader/data_source.py +0 -247
- nonebot_plugin_jmdownloader/utils.py +0 -217
- nonebot_plugin_jmdownloader-1.0.3.dist-info/METADATA +0 -219
- nonebot_plugin_jmdownloader-1.0.3.dist-info/RECORD +0 -9
- nonebot_plugin_jmdownloader-1.0.3.dist-info/licenses/LICENSE +0 -21
- nonebot_plugin_jmdownloader-1.0.3.dist-info/top_level.txt +0 -1
|
@@ -1,615 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
import hashlib
|
|
3
|
-
import os
|
|
4
|
-
import random
|
|
5
|
-
from re import A
|
|
6
|
-
import shutil
|
|
7
|
-
import time
|
|
1
|
+
"""NoneBot JMComic 插件
|
|
8
2
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
MissingAlbumPhotoException, create_option_by_str)
|
|
12
|
-
from nonebot import logger, on_command, require, get_bot
|
|
13
|
-
from nonebot.adapters.onebot.v11 import (GROUP_ADMIN, GROUP_OWNER,
|
|
14
|
-
ActionFailed, Bot, GroupMessageEvent,
|
|
15
|
-
Message, MessageEvent, MessageSegment,
|
|
16
|
-
PrivateMessageEvent, NetworkError)
|
|
17
|
-
from nonebot.params import ArgPlainText, CommandArg
|
|
18
|
-
from nonebot.permission import SUPERUSER
|
|
19
|
-
from nonebot.plugin import PluginMetadata
|
|
20
|
-
|
|
21
|
-
from .config import (Config, cache_dir, config_data, plugin_cache_dir,
|
|
22
|
-
plugin_config)
|
|
23
|
-
from .data_source import data_manager, search_manager, SearchState
|
|
24
|
-
from .utils import (blur_image_async, check_group_and_user, check_permission,
|
|
25
|
-
download_avatar, download_photo_async,
|
|
26
|
-
get_photo_info_async, modify_pdf_md5, search_album_async,
|
|
27
|
-
send_forward_message)
|
|
3
|
+
JMComic 搜索、下载插件,支持全局屏蔽 jm 号和 tag,仅支持 OnebotV11 协议。
|
|
4
|
+
"""
|
|
28
5
|
|
|
29
|
-
|
|
6
|
+
from nonebot.plugin import PluginMetadata
|
|
30
7
|
|
|
31
|
-
from
|
|
8
|
+
from .config import PluginConfig
|
|
32
9
|
|
|
33
10
|
__plugin_meta__ = PluginMetadata(
|
|
34
11
|
name="JMComic插件",
|
|
35
12
|
description="JMComic搜索、下载插件,支持全局屏蔽jm号和tag,仅支持OnebotV11协议。",
|
|
36
13
|
usage="jm下载 [jm号]:下载指定jm号的本子\n"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
type="application",
|
|
14
|
+
"jm查询 [jm号]:查询指定jm号的本子\n"
|
|
15
|
+
"jm搜索 [关键词]:搜索包含关键词的本子\n"
|
|
16
|
+
"jm设置文件夹 [文件夹名]:设置本群的本子储存文件夹\n",
|
|
17
|
+
type="application",
|
|
41
18
|
homepage="https://github.com/Misty02600/nonebot-plugin-jmdownloader",
|
|
42
|
-
config=
|
|
19
|
+
config=PluginConfig,
|
|
43
20
|
supported_adapters={"~onebot.v11"},
|
|
44
21
|
extra={"author": "Misty02600 <xiao02600@gmail.com>"},
|
|
45
22
|
)
|
|
46
23
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
try:
|
|
50
|
-
client = option.build_jm_client()
|
|
51
|
-
downloader = JmDownloader(option)
|
|
52
|
-
except JmcomicException as e:
|
|
53
|
-
logger.error(f"初始化失败: { e }")
|
|
54
|
-
|
|
55
|
-
results_per_page = plugin_config.jmcomic_results_per_page
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# region jm功能指令
|
|
59
|
-
jm_download = on_command("jm下载", aliases={"JM下载"}, block=True, rule=check_group_and_user)
|
|
60
|
-
@jm_download.handle()
|
|
61
|
-
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
|
62
|
-
photo_id = arg.extract_plain_text().strip()
|
|
63
|
-
user_id = event.user_id
|
|
64
|
-
|
|
65
|
-
if not photo_id.isdigit():
|
|
66
|
-
await jm_download.finish("请输入要下载的jm号")
|
|
67
|
-
|
|
68
|
-
if str(user_id) not in bot.config.superusers:
|
|
69
|
-
user_limit = data_manager.get_user_limit(user_id)
|
|
70
|
-
if user_limit <= 0:
|
|
71
|
-
await jm_download.finish(MessageSegment.at(user_id) + f"你的下载次数已经用完了!")
|
|
72
|
-
|
|
73
|
-
try:
|
|
74
|
-
photo = await get_photo_info_async(client, photo_id)
|
|
75
|
-
except MissingAlbumPhotoException:
|
|
76
|
-
await jm_download.finish("未查找到本子")
|
|
77
|
-
|
|
78
|
-
if photo is None:
|
|
79
|
-
await jm_download.finish("查询时发生错误")
|
|
80
|
-
|
|
81
|
-
if data_manager.is_jm_id_restricted(photo.id) or data_manager.has_restricted_tag(photo.tags):
|
|
82
|
-
if isinstance(event, GroupMessageEvent):
|
|
83
|
-
try:
|
|
84
|
-
await bot.set_group_ban(group_id=event.group_id, user_id=user_id, duration=86400)
|
|
85
|
-
except ActionFailed:
|
|
86
|
-
pass
|
|
87
|
-
data_manager.add_blacklist(event.group_id, user_id)
|
|
88
|
-
await jm_download.finish(MessageSegment.at(user_id) + "该本子(或其tag)被禁止下载!你已被加入本群jm黑名单")
|
|
89
|
-
else:
|
|
90
|
-
await jm_download.finish("该本子(或其tag)被禁止下载!")
|
|
91
|
-
|
|
92
|
-
try:
|
|
93
|
-
if str(user_id) not in bot.config.superusers:
|
|
94
|
-
data_manager.decrease_user_limit(user_id, 1)
|
|
95
|
-
user_limit_new = data_manager.get_user_limit(user_id)
|
|
96
|
-
message = Message()
|
|
97
|
-
message += f"jm{photo.id} | {photo.title}\n"
|
|
98
|
-
message += f"🎨 作者: {photo.author}\n"
|
|
99
|
-
message += "🔖 标签: " + " ".join(f"#{tag}" for tag in photo.tags) + "\n"
|
|
100
|
-
message += f"开始下载...\n你本周还有{user_limit_new}次下载次数!"
|
|
101
|
-
await jm_download.send(message)
|
|
102
|
-
else:
|
|
103
|
-
message = Message()
|
|
104
|
-
message += f"jm{photo.id} | {photo.title}\n"
|
|
105
|
-
message += f"🎨 作者: {photo.author}\n"
|
|
106
|
-
message += "🔖 标签: " + " ".join(f"#{tag}" for tag in photo.tags) + "\n"
|
|
107
|
-
message += "开始下载..."
|
|
108
|
-
await jm_download.send(message)
|
|
109
|
-
except ActionFailed:
|
|
110
|
-
await jm_download.send("本子信息可能被屏蔽,已开始下载")
|
|
111
|
-
except NetworkError as e:
|
|
112
|
-
logger.warning(f"{e},可能是协议端发送文件时间太长导致的报错")
|
|
113
|
-
|
|
114
|
-
pdf_path = f"{cache_dir}/{photo.id}.pdf"
|
|
115
|
-
|
|
116
|
-
# 如果不存在,则下载
|
|
117
|
-
if not os.path.exists(pdf_path):
|
|
118
|
-
if not await download_photo_async(downloader, photo):
|
|
119
|
-
await jm_download.finish("下载失败")
|
|
120
|
-
|
|
121
|
-
try:
|
|
122
|
-
# 根据配置决定是否需要修改MD5
|
|
123
|
-
if plugin_config.jmcomic_modify_real_md5:
|
|
124
|
-
random_suffix = hashlib.md5(str(time.time() + random.random()).encode()).hexdigest()[:8]
|
|
125
|
-
renamed_pdf_path = f"{cache_dir}/{photo.id}_{random_suffix}.pdf"
|
|
126
|
-
|
|
127
|
-
modified = await asyncio.to_thread(modify_pdf_md5, pdf_path, renamed_pdf_path)
|
|
128
|
-
if modified:
|
|
129
|
-
pdf_path = renamed_pdf_path
|
|
130
|
-
except Exception as e:
|
|
131
|
-
logger.error(f"处理PDF文件时出错: {e}")
|
|
132
|
-
await jm_download.finish("处理文件失败")
|
|
133
|
-
|
|
134
|
-
try:
|
|
135
|
-
if isinstance(event, GroupMessageEvent):
|
|
136
|
-
folder_id = data_manager.get_group_folder_id(event.group_id)
|
|
137
|
-
|
|
138
|
-
if folder_id:
|
|
139
|
-
await bot.call_api(
|
|
140
|
-
"upload_group_file",
|
|
141
|
-
group_id=event.group_id,
|
|
142
|
-
file=pdf_path,
|
|
143
|
-
name=f"{photo.id}.pdf",
|
|
144
|
-
folder_id=folder_id
|
|
145
|
-
)
|
|
146
|
-
else:
|
|
147
|
-
await bot.call_api(
|
|
148
|
-
"upload_group_file",
|
|
149
|
-
group_id=event.group_id,
|
|
150
|
-
file=pdf_path,
|
|
151
|
-
name=f"{photo.id}.pdf"
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
elif isinstance(event, PrivateMessageEvent):
|
|
155
|
-
await bot.call_api(
|
|
156
|
-
"upload_private_file",
|
|
157
|
-
user_id=event.user_id,
|
|
158
|
-
file=pdf_path,
|
|
159
|
-
name=f"{photo.id}.pdf"
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
except ActionFailed:
|
|
163
|
-
await jm_download.send("发送文件失败")
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
jm_query = on_command("jm查询", aliases={"JM查询"}, block=True, rule=check_group_and_user)
|
|
168
|
-
@jm_query.handle()
|
|
169
|
-
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
|
170
|
-
photo_id = arg.extract_plain_text().strip()
|
|
171
|
-
if not photo_id.isdigit():
|
|
172
|
-
await jm_query.finish("请输入要查询的jm号")
|
|
173
|
-
try:
|
|
174
|
-
photo = await get_photo_info_async(client, photo_id)
|
|
175
|
-
except MissingAlbumPhotoException:
|
|
176
|
-
await jm_query.finish("未查找到本子")
|
|
177
|
-
if photo is None:
|
|
178
|
-
await jm_query.finish("查询时发生错误")
|
|
179
|
-
|
|
180
|
-
message = Message()
|
|
181
|
-
message += f"查询到jm{photo.id}: {photo.title}\n"
|
|
182
|
-
message += f"🎨 作者: {photo.author}\n"
|
|
183
|
-
tags_text = " ".join(f"#{tag}" for tag in photo.tags)
|
|
184
|
-
message += f"🔖 标签: {tags_text}\n"
|
|
185
|
-
|
|
186
|
-
avatar = await download_avatar(photo.id)
|
|
187
|
-
if avatar:
|
|
188
|
-
avatar = await blur_image_async(avatar)
|
|
189
|
-
message += MessageSegment.image(avatar)
|
|
190
|
-
|
|
191
|
-
message_node = MessageSegment("node", {"name": "jm查询结果", "uin": bot.self_id, "content": message})
|
|
192
|
-
messages = [message_node]
|
|
193
|
-
|
|
194
|
-
try:
|
|
195
|
-
await send_forward_message(bot, event, messages)
|
|
196
|
-
except ActionFailed:
|
|
197
|
-
await jm_query.finish("查询结果发送失败", reply_message=True)
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
jm_search = on_command("jm搜索", aliases={"JM搜索"}, block=True, rule=check_group_and_user)
|
|
201
|
-
@jm_search.handle()
|
|
202
|
-
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
|
203
|
-
search_query = arg.extract_plain_text().strip()
|
|
204
|
-
if not search_query:
|
|
205
|
-
await jm_search.finish("请输入要搜索的内容")
|
|
206
|
-
|
|
207
|
-
searching_msg_id = (await jm_search.send("正在搜索中..."))['message_id']
|
|
208
|
-
|
|
209
|
-
page = await search_album_async(client, search_query)
|
|
210
|
-
if page is None:
|
|
211
|
-
await bot.delete_msg(message_id=searching_msg_id)
|
|
212
|
-
await jm_search.finish("搜索失败", reply_message=True)
|
|
213
|
-
|
|
214
|
-
search_results = list(page.iter_id())
|
|
215
|
-
if not search_results:
|
|
216
|
-
await bot.delete_msg(message_id=searching_msg_id)
|
|
217
|
-
await jm_search.finish("未搜索到本子", reply_message=True)
|
|
218
|
-
|
|
219
|
-
current_results = search_results[:results_per_page]
|
|
220
|
-
photos = await asyncio.gather(*(get_photo_info_async(client, photo_id) for photo_id in current_results))
|
|
221
|
-
avatars = await asyncio.gather(*(download_avatar(photo_id) for photo_id in current_results))
|
|
222
|
-
|
|
223
|
-
messages = []
|
|
224
|
-
blocked_message = plugin_config.jmcomic_blocked_message
|
|
225
|
-
|
|
226
|
-
for photo, avatar in zip(photos, avatars):
|
|
227
|
-
if photo is None:
|
|
228
|
-
continue
|
|
229
|
-
|
|
230
|
-
if data_manager.has_restricted_tag(photo.tags):
|
|
231
|
-
message_node = MessageSegment("node", {
|
|
232
|
-
"name": "jm搜索结果",
|
|
233
|
-
"uin": bot.self_id,
|
|
234
|
-
"content": blocked_message
|
|
235
|
-
})
|
|
236
|
-
else:
|
|
237
|
-
node_content = Message()
|
|
238
|
-
node_content += f"jm{photo.id} | {photo.title}\n"
|
|
239
|
-
node_content += f"🎨 作者: {photo.author}\n"
|
|
240
|
-
node_content += "🔖 标签: " + " ".join(f"#{tag}" for tag in photo.tags)
|
|
241
|
-
|
|
242
|
-
if avatar:
|
|
243
|
-
avatar = await blur_image_async(avatar)
|
|
244
|
-
node_content += MessageSegment.image(avatar)
|
|
245
|
-
|
|
246
|
-
message_node = MessageSegment("node", {
|
|
247
|
-
"name": "jm搜索结果",
|
|
248
|
-
"uin": bot.self_id,
|
|
249
|
-
"content": node_content
|
|
250
|
-
})
|
|
251
|
-
messages.append(message_node)
|
|
252
|
-
|
|
253
|
-
try:
|
|
254
|
-
await send_forward_message(bot, event, messages)
|
|
255
|
-
except ActionFailed:
|
|
256
|
-
await jm_search.finish("搜索结果发送失败", reply_message=True)
|
|
257
|
-
|
|
258
|
-
if len(search_results) > results_per_page:
|
|
259
|
-
search_manager.set_state(str(event.user_id), SearchState(
|
|
260
|
-
query=search_query,
|
|
261
|
-
start_idx=results_per_page,
|
|
262
|
-
total_results=search_results,
|
|
263
|
-
api_page=1
|
|
264
|
-
))
|
|
265
|
-
await jm_search.send("搜索有更多结果,使用'jm下一页'指令查看更多")
|
|
266
|
-
else:
|
|
267
|
-
await jm_search.send("已发送所有搜索结果")
|
|
268
|
-
|
|
269
|
-
await bot.delete_msg(message_id=searching_msg_id)
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
jm_next_page = on_command("jm 下一页", aliases={"JM 下一页", "jm下一页", "JM下一页"}, block=True, rule=check_group_and_user)
|
|
275
|
-
@jm_next_page.handle()
|
|
276
|
-
async def handle_jm_next_page(bot: Bot, event: MessageEvent):
|
|
277
|
-
state = search_manager.get_state(str(event.user_id))
|
|
278
|
-
if not state:
|
|
279
|
-
await jm_next_page.finish("没有进行中的搜索,请先使用'jm搜索'命令")
|
|
280
|
-
|
|
281
|
-
searching_msg_id = (await jm_search.send("正在搜索更多内容..."))['message_id']
|
|
282
|
-
|
|
283
|
-
end_idx = state.start_idx + results_per_page
|
|
284
|
-
# 本次是否已经返回所有结果
|
|
285
|
-
is_return_all = False
|
|
286
|
-
|
|
287
|
-
# 需要尝试调用api搜索下一页?
|
|
288
|
-
if end_idx >= len(state.total_results):
|
|
289
|
-
# 如果当前页数是80的倍数,说明可能还有下一页,80是JM搜索每页数量
|
|
290
|
-
if len(state.total_results) % 80 == 0:
|
|
291
|
-
state.api_page += 1
|
|
292
|
-
next_page = await search_album_async(client, state.query, page=state.api_page)
|
|
293
|
-
|
|
294
|
-
if next_page is None:
|
|
295
|
-
logger.warning(f"获取下一页失败: {state.query} {state.api_page}")
|
|
296
|
-
is_return_all = True
|
|
297
|
-
else:
|
|
298
|
-
next_results = list(next_page.iter_id())
|
|
299
|
-
# 严格检查是否达到最后一页
|
|
300
|
-
if not next_results or next_results[-1] == state.total_results[-1]:
|
|
301
|
-
is_return_all = True
|
|
302
|
-
else:
|
|
303
|
-
state.total_results.extend(next_results)
|
|
304
|
-
else:
|
|
305
|
-
is_return_all = True
|
|
306
|
-
|
|
307
|
-
current_results = state.total_results[state.start_idx:end_idx]
|
|
308
|
-
photos = await asyncio.gather(*(get_photo_info_async(client, album_id) for album_id in current_results))
|
|
309
|
-
avatars = await asyncio.gather(*(download_avatar(album_id) for album_id in current_results))
|
|
310
|
-
|
|
311
|
-
messages = []
|
|
312
|
-
blocked_message = plugin_config.jmcomic_blocked_message
|
|
313
|
-
|
|
314
|
-
for photo, avatar in zip(photos, avatars):
|
|
315
|
-
if photo is None:
|
|
316
|
-
continue
|
|
317
|
-
|
|
318
|
-
if data_manager.has_restricted_tag(photo.tags):
|
|
319
|
-
message_node = MessageSegment("node", {
|
|
320
|
-
"name": "jm搜索结果",
|
|
321
|
-
"uin": bot.self_id,
|
|
322
|
-
"content": blocked_message
|
|
323
|
-
})
|
|
324
|
-
else:
|
|
325
|
-
node_content = Message()
|
|
326
|
-
node_content += f"jm{photo.id} | {photo.title}\n"
|
|
327
|
-
node_content += f"🎨 作者: {photo.author}\n"
|
|
328
|
-
node_content += "🔖 标签: " + " ".join(f"#{tag}" for tag in photo.tags)
|
|
329
|
-
|
|
330
|
-
if avatar:
|
|
331
|
-
avatar = await blur_image_async(avatar)
|
|
332
|
-
node_content += MessageSegment.image(avatar)
|
|
333
|
-
|
|
334
|
-
message_node = MessageSegment("node", {
|
|
335
|
-
"name": "jm搜索结果",
|
|
336
|
-
"uin": bot.self_id,
|
|
337
|
-
"content": node_content
|
|
338
|
-
})
|
|
339
|
-
messages.append(message_node)
|
|
340
|
-
|
|
341
|
-
try:
|
|
342
|
-
await send_forward_message(bot, event, messages)
|
|
343
|
-
except ActionFailed:
|
|
344
|
-
search_manager.remove_state(str(event.user_id))
|
|
345
|
-
await bot.delete_msg(message_id=searching_msg_id)
|
|
346
|
-
await jm_next_page.finish("下一页结果发送失败", reply_message=True)
|
|
347
|
-
|
|
348
|
-
if is_return_all:
|
|
349
|
-
search_manager.remove_state(str(event.user_id))
|
|
350
|
-
await jm_next_page.send("已显示所有搜索结果")
|
|
351
|
-
else:
|
|
352
|
-
await jm_next_page.send("搜索有更多结果,使用'jm下一页'指令查看更多")
|
|
353
|
-
state.start_idx = end_idx
|
|
354
|
-
|
|
355
|
-
await bot.delete_msg(message_id=searching_msg_id)
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
jm_set_folder = on_command("jm设置文件夹", aliases={"JM设置文件夹"}, permission=SUPERUSER | GROUP_ADMIN | GROUP_OWNER, block=True)
|
|
359
|
-
@jm_set_folder.handle()
|
|
360
|
-
async def _( bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
|
361
|
-
folder_name = arg.extract_plain_text().strip()
|
|
362
|
-
if not folder_name:
|
|
363
|
-
await jm_set_folder.finish("请输入要设置的文件夹名称")
|
|
364
|
-
|
|
365
|
-
group_id = event.group_id
|
|
24
|
+
# 检测并迁移旧数据
|
|
25
|
+
from .migration import run_migration
|
|
366
26
|
|
|
367
|
-
|
|
27
|
+
run_migration()
|
|
368
28
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
data_manager.set_group_folder_id(group_id, found_folder_id)
|
|
380
|
-
await jm_set_folder.finish(f"已设置本子储存文件夹")
|
|
381
|
-
else:
|
|
382
|
-
try:
|
|
383
|
-
create_result = await bot.call_api(
|
|
384
|
-
"create_group_file_folder",
|
|
385
|
-
group_id=group_id,
|
|
386
|
-
folder_name=folder_name
|
|
387
|
-
)
|
|
388
|
-
|
|
389
|
-
ret_code = create_result["result"]["retCode"]
|
|
390
|
-
if ret_code != 0:
|
|
391
|
-
await jm_set_folder.finish("未找到该文件夹,创建文件夹失败")
|
|
392
|
-
|
|
393
|
-
folder_id = create_result["groupItem"]["folderInfo"]["folderId"]
|
|
394
|
-
data_manager.set_group_folder_id(group_id, folder_id)
|
|
395
|
-
await jm_set_folder.finish(f"已设置本子储存文件夹")
|
|
396
|
-
|
|
397
|
-
except ActionFailed as e:
|
|
398
|
-
logger.warning("创建文件夹失败")
|
|
399
|
-
await jm_set_folder.finish("未找到该文件夹,主动创建文件夹失败")
|
|
400
|
-
|
|
401
|
-
# endregion
|
|
402
|
-
|
|
403
|
-
# region jm成员黑名单指令
|
|
404
|
-
jm_ban_user = on_command("jm拉黑", aliases={"JM拉黑"}, permission=SUPERUSER | GROUP_ADMIN | GROUP_OWNER, block=True)
|
|
405
|
-
@jm_ban_user.handle()
|
|
406
|
-
async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
|
407
|
-
"""将用户加入当前群的黑名单"""
|
|
408
|
-
at_segment = arg[0]
|
|
409
|
-
if at_segment.type != "at":
|
|
410
|
-
await jm_unban_user.finish("请使用@指定要拉黑的用户")
|
|
411
|
-
|
|
412
|
-
user_id = at_segment.data["qq"]
|
|
413
|
-
|
|
414
|
-
user_id = int(user_id)
|
|
415
|
-
group_id = event.group_id
|
|
416
|
-
operator_id = event.user_id
|
|
417
|
-
|
|
418
|
-
if user_id == operator_id:
|
|
419
|
-
await jm_ban_user.finish("你拉黑你自己?")
|
|
420
|
-
|
|
421
|
-
has_permission = await check_permission(bot, group_id, operator_id, user_id)
|
|
422
|
-
if not has_permission:
|
|
423
|
-
await jm_unban_user.finish("权限不足")
|
|
424
|
-
|
|
425
|
-
data_manager.add_blacklist(group_id, user_id)
|
|
426
|
-
await jm_ban_user.finish(MessageSegment.at(user_id) + f"已加入本群jm黑名单")
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
jm_unban_user = on_command("jm解除拉黑", aliases={"JM解除拉黑"}, permission=SUPERUSER | GROUP_ADMIN | GROUP_OWNER, block=True)
|
|
430
|
-
@jm_unban_user.handle()
|
|
431
|
-
async def handle_jm_unban_user(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
|
432
|
-
"""将用户移出当前群的黑名单"""
|
|
433
|
-
at_segment = arg[0]
|
|
434
|
-
if at_segment.type != "at":
|
|
435
|
-
await jm_unban_user.finish("请使用@指定要解除拉黑的用户")
|
|
436
|
-
|
|
437
|
-
user_id = at_segment.data["qq"]
|
|
438
|
-
|
|
439
|
-
user_id = int(user_id)
|
|
440
|
-
group_id = event.group_id
|
|
441
|
-
operator_id = event.user_id
|
|
442
|
-
|
|
443
|
-
if user_id == operator_id:
|
|
444
|
-
await jm_ban_user.finish("想都别想!")
|
|
445
|
-
|
|
446
|
-
has_permission = await check_permission(bot, group_id, operator_id, user_id)
|
|
447
|
-
if not has_permission:
|
|
448
|
-
await jm_unban_user.finish("权限不足")
|
|
449
|
-
|
|
450
|
-
data_manager.remove_blacklist(group_id, user_id)
|
|
451
|
-
await jm_unban_user.finish(MessageSegment.at(user_id) + f"已从本群jm黑名单中移除")
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
jm_blacklist = on_command( "jm黑名单", aliases={"JM黑名单"}, permission=SUPERUSER | GROUP_ADMIN | GROUP_OWNER, block=True)
|
|
455
|
-
@jm_blacklist.handle()
|
|
456
|
-
async def handle_jm_list_blacklist(bot: Bot, event: GroupMessageEvent):
|
|
457
|
-
"""列出当前群的黑名单列表"""
|
|
458
|
-
group_id = event.group_id
|
|
459
|
-
blacklist = data_manager.list_blacklist(group_id)
|
|
460
|
-
|
|
461
|
-
if not blacklist:
|
|
462
|
-
await jm_blacklist.finish("当前群的黑名单列表为空")
|
|
463
|
-
|
|
464
|
-
msg = "当前群的黑名单列表:\n"
|
|
465
|
-
for user_id in blacklist:
|
|
466
|
-
msg += MessageSegment.at(user_id)
|
|
467
|
-
|
|
468
|
-
await jm_blacklist.finish(msg)
|
|
469
|
-
|
|
470
|
-
# endregion
|
|
471
|
-
|
|
472
|
-
# region 群功能开关指令
|
|
473
|
-
jm_enable_group = on_command("jm启用群", permission=SUPERUSER, block=True)
|
|
474
|
-
@jm_enable_group.handle()
|
|
475
|
-
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
|
476
|
-
""" 启用指定群号,可用空格隔开多个群 """
|
|
477
|
-
raw_text = arg.extract_plain_text().strip()
|
|
478
|
-
|
|
479
|
-
group_ids = raw_text.split()
|
|
480
|
-
success_list = []
|
|
481
|
-
|
|
482
|
-
for group_id_str in group_ids:
|
|
483
|
-
if not group_id_str.isdigit():
|
|
484
|
-
continue
|
|
485
|
-
|
|
486
|
-
group_id = int(group_id_str)
|
|
487
|
-
data_manager.set_group_enabled(group_id, True)
|
|
488
|
-
success_list.append(group_id_str)
|
|
489
|
-
|
|
490
|
-
msg = ""
|
|
491
|
-
if success_list:
|
|
492
|
-
msg += "以下群已启用插件功能:\n" + " ".join(success_list)
|
|
493
|
-
|
|
494
|
-
await jm_enable_group.finish(msg.strip() or "没有做任何处理。")
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
jm_disable_group = on_command("jm禁用群", permission=SUPERUSER, block=True)
|
|
498
|
-
@jm_disable_group.handle()
|
|
499
|
-
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
|
500
|
-
""" 禁用指定群号,可用空格隔开多个群 """
|
|
501
|
-
raw_text = arg.extract_plain_text().strip()
|
|
502
|
-
|
|
503
|
-
group_ids = raw_text.split()
|
|
504
|
-
success_list = []
|
|
505
|
-
|
|
506
|
-
for group_id_str in group_ids:
|
|
507
|
-
if not group_id_str.isdigit():
|
|
508
|
-
continue
|
|
509
|
-
|
|
510
|
-
group_id = int(group_id_str)
|
|
511
|
-
data_manager.set_group_enabled(group_id, False)
|
|
512
|
-
success_list.append(group_id_str)
|
|
513
|
-
|
|
514
|
-
msg = ""
|
|
515
|
-
if success_list:
|
|
516
|
-
msg += "以下群已禁用插件功能:\n" + " ".join(success_list)
|
|
517
|
-
|
|
518
|
-
await jm_disable_group.finish(msg.strip() or "没有做任何处理。")
|
|
519
|
-
|
|
520
|
-
jm_enable_here = on_command("开启jm", aliases={"开启JM"}, permission=SUPERUSER, block=True)
|
|
521
|
-
@jm_enable_here.handle()
|
|
522
|
-
async def handle_jm_enable_here(event: GroupMessageEvent):
|
|
523
|
-
group_id = event.group_id
|
|
524
|
-
data_manager.set_group_enabled(group_id, True)
|
|
525
|
-
await jm_enable_here.finish("已启用本群jm功能!")
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
jm_disable_here = on_command("关闭jm", aliases={"关闭JM"}, permission=SUPERUSER | GROUP_ADMIN | GROUP_OWNER, block=True)
|
|
529
|
-
@jm_disable_here.got("confirm", prompt="禁用后只能请求神秘存在再次开启该功能!确认要关闭吗?发送'确认'关闭")
|
|
530
|
-
async def _(event: GroupMessageEvent, confirm: str = ArgPlainText()):
|
|
531
|
-
if confirm == "确认":
|
|
532
|
-
group_id = event.group_id
|
|
533
|
-
data_manager.set_group_enabled(group_id, False)
|
|
534
|
-
await jm_disable_here.finish("已禁用本群jm功能!")
|
|
535
|
-
|
|
536
|
-
# endregion
|
|
537
|
-
|
|
538
|
-
# region 添加屏蔽tags和jm号
|
|
539
|
-
jm_forbid_id = on_command("jm禁用id", aliases={"JM禁用id"}, permission=SUPERUSER, block=True)
|
|
540
|
-
@jm_forbid_id.handle()
|
|
541
|
-
async def handle_jm_forbid_id(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
|
542
|
-
raw_text = arg.extract_plain_text().strip()
|
|
543
|
-
|
|
544
|
-
jm_ids = raw_text.split()
|
|
545
|
-
success_list = []
|
|
546
|
-
|
|
547
|
-
for jm_id in jm_ids:
|
|
548
|
-
if not jm_id.isdigit():
|
|
549
|
-
continue
|
|
550
|
-
data_manager.add_restricted_jm_id(jm_id)
|
|
551
|
-
success_list.append(jm_id)
|
|
552
|
-
|
|
553
|
-
msg = ""
|
|
554
|
-
if success_list:
|
|
555
|
-
msg += "以下jm号已加入禁止下载列表:\n" + " ".join(success_list)
|
|
556
|
-
|
|
557
|
-
await jm_forbid_id.finish(msg.strip() or "没有做任何处理")
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
jm_forbid_tag = on_command("jm禁用tag", aliases={"JM禁用tag"}, permission=SUPERUSER, block=True)
|
|
561
|
-
@jm_forbid_tag.handle()
|
|
562
|
-
async def handle_jm_forbid_tag(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
|
563
|
-
raw_text = arg.extract_plain_text().strip()
|
|
564
|
-
|
|
565
|
-
tags = raw_text.split()
|
|
566
|
-
success_list = []
|
|
567
|
-
|
|
568
|
-
for tag in tags:
|
|
569
|
-
if not tag:
|
|
570
|
-
continue
|
|
571
|
-
data_manager.add_restricted_tag(tag)
|
|
572
|
-
success_list.append(tag)
|
|
573
|
-
|
|
574
|
-
msg = ""
|
|
575
|
-
if success_list:
|
|
576
|
-
msg += "以下tag已加入禁止下载列表:\n" + " ".join(success_list)
|
|
577
|
-
|
|
578
|
-
await jm_forbid_tag.finish(msg.strip() or "没有做任何处理")
|
|
579
|
-
|
|
580
|
-
# endregion
|
|
581
|
-
|
|
582
|
-
@scheduler.scheduled_job("cron", day_of_week="mon", hour=0, minute=0, id="reset_user_limits")
|
|
583
|
-
async def reset_user_limits():
|
|
584
|
-
""" 每周一凌晨0点重置所有用户的下载次数 """
|
|
585
|
-
try:
|
|
586
|
-
user_limits = data_manager.data.get("user_limits", {})
|
|
587
|
-
|
|
588
|
-
if not user_limits:
|
|
589
|
-
logger.info("无用户下载数据可供重置。")
|
|
590
|
-
return
|
|
591
|
-
|
|
592
|
-
for user_id in user_limits.keys():
|
|
593
|
-
data_manager.set_user_limit(int(user_id), plugin_config.jmcomic_user_limits)
|
|
594
|
-
|
|
595
|
-
logger.info("所有用户的下载次数已成功刷新")
|
|
596
|
-
|
|
597
|
-
except Exception as e:
|
|
598
|
-
logger.error(f"刷新用户下载次数时出错:{e}")
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
@scheduler.scheduled_job("cron", hour=3, minute=0)
|
|
602
|
-
async def clear_cache_dir():
|
|
603
|
-
""" 每天凌晨3点清理缓存文件夹 """
|
|
604
|
-
try:
|
|
605
|
-
if plugin_cache_dir.exists():
|
|
606
|
-
shutil.rmtree(plugin_cache_dir)
|
|
607
|
-
plugin_cache_dir.mkdir(parents=True, exist_ok=True)
|
|
608
|
-
logger.info(f"已成功清理缓存目录:{cache_dir}")
|
|
609
|
-
except Exception as e:
|
|
610
|
-
logger.error(f"清理缓存目录失败:{e}")
|
|
611
|
-
|
|
612
|
-
@scheduler.scheduled_job("interval", minutes=10)
|
|
613
|
-
async def clean_expired_search_states():
|
|
614
|
-
""" 定期清理过期的搜索状态 """
|
|
615
|
-
search_manager.clean_expired()
|
|
29
|
+
# 导入命令模块以注册所有命令处理器
|
|
30
|
+
from .bot.handlers import ( # noqa: F401
|
|
31
|
+
ban_id_tag,
|
|
32
|
+
blacklist,
|
|
33
|
+
download,
|
|
34
|
+
group_control,
|
|
35
|
+
query,
|
|
36
|
+
scheduled,
|
|
37
|
+
search,
|
|
38
|
+
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Bot 层
|
|
2
|
+
|
|
3
|
+
NoneBot 相关的依赖注入。
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .dependencies import (
|
|
7
|
+
DataManagerDep,
|
|
8
|
+
JmServiceDep,
|
|
9
|
+
SessionsDep,
|
|
10
|
+
plugin_cache_dir,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"DataManagerDep",
|
|
15
|
+
"JmServiceDep",
|
|
16
|
+
"SessionsDep",
|
|
17
|
+
"plugin_cache_dir",
|
|
18
|
+
]
|