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