forked from kjqwer/astrbot_plugin_sy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommands.py
More file actions
707 lines (589 loc) · 32.3 KB
/
commands.py
File metadata and controls
707 lines (589 loc) · 32.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
from astrbot.api.event import AstrMessageEvent
from astrbot.api import logger
from .utils import save_reminder_data, check_permission_and_return_error
from .command_utils import UnifiedCommandProcessor
import functools
def check_permission(func):
'''权限检查装饰器'''
@functools.wraps(func)
async def wrapper(self, event, *args, **kwargs):
error_msg = check_permission_and_return_error(event, self.star.whitelist)
if error_msg:
yield event.plain_result(error_msg)
return
async for result in func(self, event, *args, **kwargs):
yield result
return wrapper
class ReminderCommands:
def __init__(self, star_instance):
self.star = star_instance
self.context = star_instance.context
self.reminder_data = star_instance.reminder_data
self.data_file = star_instance.data_file
self.scheduler_manager = star_instance.scheduler_manager
self.unique_session = star_instance.unique_session
self.tools = star_instance.tools
# 初始化统一处理器
self.processor = UnifiedCommandProcessor(star_instance)
@check_permission
async def list_reminders(self, event: AstrMessageEvent):
'''列出所有提醒和任务'''
# 获取用户ID,用于会话隔离
creator_id = event.get_sender_id()
# 获取会话ID
raw_msg_origin = event.unified_msg_origin
if self.unique_session:
# 使用会话隔离
msg_origin = self.tools.get_session_id(raw_msg_origin, creator_id)
else:
msg_origin = raw_msg_origin
# 使用兼容性处理器获取提醒列表
reminders = self.star.compatibility_handler.get_reminders(msg_origin)
if not reminders:
yield event.plain_result("当前没有设置任何提醒或任务。")
return
provider = self.context.get_using_provider()
if provider:
try:
# 分离提醒、任务和指令任务
reminder_items = []
task_items = []
command_task_items = []
for r in reminders:
if r.get("is_command_task", False):
# 指令任务,显示完整指令
command_text = r['text']
command_task_items.append(f"- {command_text} (时间: {r['datetime']})")
elif r.get("is_task", False):
# 普通任务
task_items.append(f"- {r['text']} (时间: {r['datetime']})")
else:
# 提醒
reminder_items.append(f"- {r['text']} (时间: {r['datetime']})")
# 构建提示
prompt = "请帮我整理并展示以下提醒和任务列表,用自然的语言表达:\n"
if reminder_items:
prompt += f"\n提醒列表:\n" + "\n".join(reminder_items)
if task_items:
prompt += f"\n\n任务列表:\n" + "\n".join(task_items)
if command_task_items:
prompt += f"\n\n指令任务列表:\n" + "\n".join(command_task_items)
prompt += "\n\n同时告诉用户可以使用/rmd rm <序号>删除提醒、任务或指令任务,或者直接命令你来删除。直接发出对话内容,就是你说的话,不要有其他的背景描述。"
response = await provider.text_chat(
prompt=prompt,
session_id=event.session_id,
contexts=[] # 确保contexts是一个空列表而不是None
)
yield event.plain_result(response.completion_text)
except Exception as e:
logger.error(f"在list_reminders中调用LLM时出错: {str(e)}")
# 如果LLM调用失败,回退到基本显示
reminder_str = "当前的提醒和任务:\n"
# 分类显示
reminders_list = [r for r in reminders if not r.get("is_task", False)]
tasks_list = [r for r in reminders if r.get("is_task", False) and not r.get("is_command_task", False)]
command_tasks_list = [r for r in reminders if r.get("is_command_task", False)]
if reminders_list:
reminder_str += "\n提醒:\n"
for i, reminder in enumerate(reminders_list):
reminder_str += f"{i+1}. {reminder['text']} - {reminder['datetime']}\n"
if tasks_list:
reminder_str += "\n任务:\n"
for i, task in enumerate(tasks_list):
reminder_str += f"{len(reminders_list)+i+1}. {task['text']} - {task['datetime']}\n"
if command_tasks_list:
reminder_str += "\n指令任务:\n"
current_index = len(reminders_list) + len(tasks_list)
for i, cmd_task in enumerate(command_tasks_list):
reminder_str += f"{current_index+i+1}. /{cmd_task['text']} - {cmd_task['datetime']}\n"
reminder_str += "\n使用 /rmd rm <序号> 删除提醒、任务或指令任务"
yield event.plain_result(reminder_str)
else:
reminder_str = "当前的提醒和任务:\n"
# 分类显示
reminders_list = [r for r in reminders if not r.get("is_task", False)]
tasks_list = [r for r in reminders if r.get("is_task", False) and not r.get("is_command_task", False)]
command_tasks_list = [r for r in reminders if r.get("is_command_task", False)]
if reminders_list:
reminder_str += "\n提醒:\n"
for i, reminder in enumerate(reminders_list):
reminder_str += f"{i+1}. {reminder['text']} - {reminder['datetime']}\n"
if tasks_list:
reminder_str += "\n任务:\n"
for i, task in enumerate(tasks_list):
reminder_str += f"{len(reminders_list)+i+1}. {task['text']} - {task['datetime']}\n"
if command_tasks_list:
reminder_str += "\n指令任务:\n"
current_index = len(reminders_list) + len(tasks_list)
for i, cmd_task in enumerate(command_tasks_list):
reminder_str += f"{current_index+i+1}. /{cmd_task['text']} - {cmd_task['datetime']}\n"
reminder_str += "\n使用 /rmd rm <序号> 删除提醒、任务或指令任务"
yield event.plain_result(reminder_str)
@check_permission
async def remove_reminder(self, event: AstrMessageEvent, index: int):
'''删除提醒、任务或指令任务
Args:
index(int): 提醒、任务或指令任务的序号
'''
# 获取用户ID,用于会话隔离
creator_id = event.get_sender_id()
# 获取会话ID
raw_msg_origin = event.unified_msg_origin
if self.unique_session:
# 使用会话隔离
msg_origin = self.tools.get_session_id(raw_msg_origin, creator_id)
else:
msg_origin = raw_msg_origin
# 使用兼容性处理器获取提醒列表
reminders = self.star.compatibility_handler.get_reminders(msg_origin)
if not reminders:
yield event.plain_result("没有设置任何提醒或任务。")
return
if index < 1 or index > len(reminders):
yield event.plain_result("序号无效。")
return
# 使用兼容性处理器删除提醒
removed_item, actual_key = self.star.compatibility_handler.remove_reminder(msg_origin, index - 1)
if removed_item is None:
yield event.plain_result(actual_key) # actual_key 包含错误信息
return
# 尝试删除调度任务 - 优先使用保存的任务ID
job_found = False
# 如果有保存的任务ID,直接删除
if removed_item.get('job_id'):
try:
self.scheduler_manager.remove_job(removed_item['job_id'])
logger.info(f"Successfully removed job by stored ID: {removed_item['job_id']}")
job_found = True
except Exception as e:
logger.warning(f"Failed to remove job by stored ID {removed_item['job_id']}: {str(e)}")
# 如果直接删除失败,则通过内容匹配删除
if not job_found:
for job in self.scheduler_manager.scheduler.get_jobs():
if job.id.startswith(f"reminder_") and len(job.args) >= 2:
try:
# 检查任务参数中的提醒内容是否匹配
job_session_id = job.args[0]
job_reminder = job.args[1]
if (job_session_id == actual_key and
isinstance(job_reminder, dict) and
job_reminder.get('text') == removed_item.get('text') and
job_reminder.get('datetime') == removed_item.get('datetime')):
self.scheduler_manager.remove_job(job.id)
logger.info(f"Successfully removed job by content match: {job.id}")
job_found = True
break
except Exception as e:
logger.error(f"Error checking job {job.id}: {str(e)}")
if not job_found:
logger.warning(f"No matching job found for removed item: {removed_item.get('text', 'unknown')}")
await save_reminder_data(self.data_file, self.reminder_data)
is_command_task = removed_item.get("is_command_task", False)
is_task = removed_item.get("is_task", False)
if is_command_task:
item_type = "指令任务"
display_text = f"{removed_item['text']}"
elif is_task:
item_type = "任务"
display_text = removed_item['text']
else:
item_type = "提醒"
display_text = removed_item['text']
provider = self.context.get_using_provider()
if provider:
prompt = f"用户删除了一个{item_type},内容是'{display_text}'。请用自然的语言确认删除操作。直接发出对话内容,就是你说的话,不要有其他的背景描述。"
response = await provider.text_chat(
prompt=prompt,
session_id=event.session_id,
contexts=[] # 确保contexts是一个空列表而不是None
)
yield event.plain_result(response.completion_text)
else:
yield event.plain_result(f"已删除{item_type}:{display_text}")
@check_permission
async def add_reminder(self, event: AstrMessageEvent, text: str, time_str: str, week: str = None, repeat: str = None, holiday_type: str = None):
'''手动添加提醒
Args:
text(string): 提醒内容
time_str(string): 时间,格式为 HH:MM 或 HHMM
week(string): 可选,开始星期:mon,tue,wed,thu,fri,sat,sun
repeat(string): 可选,重复类型:daily,weekly,monthly,yearly或带节假日类型的组合(如daily workday)
holiday_type(string): 可选,节假日类型:workday(仅工作日执行),holiday(仅法定节假日执行)
'''
# 使用统一处理器处理添加提醒的逻辑
async for result in self.processor.process_add_item(
event, 'reminder', text, time_str, week, repeat, holiday_type
):
yield result
@check_permission
async def add_task(self, event: AstrMessageEvent, text: str, time_str: str, week: str = None, repeat: str = None, holiday_type: str = None):
'''手动添加任务
Args:
text(string): 任务内容
time_str(string): 时间,格式为 HH:MM 或 HHMM
week(string): 可选,开始星期:mon,tue,wed,thu,fri,sat,sun
repeat(string): 可选,重复类型:daily,weekly,monthly,yearly或带节假日类型的组合(如daily workday)
holiday_type(string): 可选,节假日类型:workday(仅工作日执行),holiday(仅法定节假日执行)
'''
# 使用统一处理器处理添加任务的逻辑
async for result in self.processor.process_add_item(
event, 'task', text, time_str, week, repeat, holiday_type
):
yield result
@check_permission
async def show_help(self, event: AstrMessageEvent):
'''显示帮助信息'''
help_text = """提醒与任务功能指令说明:
【提醒】:到时间后会提醒你做某事
【任务】:到时间后AI会自动执行指定的操作
【指令任务】:到时间后直接执行指定的指令并转发结果
1. 添加提醒:
/rmd add <内容> <时间> [开始星期] [重复类型] [--holiday_type=...]
时间格式支持:
- HH:MM 或 HH:MM (如 8:05)
- HHMM (如 0805)
- YYYYMMDDHHII (如 202509170600)
- YYYY-MM-DD-HH:MM (如 2025-09-17-06:00)
- MM-DD-HH:MM (如 09-17-06:00)
- MMDDHHII (如 09170600)
例如:
- /rmd add 写周报 8:05
- /rmd add 吃饭 8:05 sun daily (从周日开始每天)
- /rmd add 开会 2025-09-17-08:00 (指定具体日期)
- /rmd add 交房租 09-01-08:00 monthly (每月1号)
- /rmd add 上班打卡 8:30 daily workday (每个工作日,法定节假日不触发)
- /rmd add 休息提醒 9:00 daily holiday (每个法定节假日触发)
2. 添加任务:
/rmd task <内容> <时间> [开始星期] [重复类型] [--holiday_type=...]
时间格式同上,例如:
- /rmd task 发送天气预报 8:00
- /rmd task 汇总今日新闻 18:00 daily
- /rmd task 推送工作安排 09-01-09:00 monthly workday (每月1号工作日推送)
2.5. 添加指令任务:
/rmd command <指令> <时间> [开始星期] [重复类型] [--holiday_type=...]
例如:
- /rmd command /memory_config 8:00
- /rmd command /weather 9:00 daily
- /rmd command /news 18:00 mon weekly (每周一推送)
- /rmd command /rmd--ls 8:00 daily (使用--避免指令被错误分割)
- /rmd command /rmd--ls----before--每日提醒 8:00 daily (自定义标识放在开头)
- /rmd command /rmd--ls----after--执行完成 8:00 daily (自定义标识放在末尾)
3. 查看提醒和任务:
/rmd ls - 列出所有提醒和任务
4. 删除提醒或任务:
/rmd rm <序号> - 删除指定提醒或任务,注意任务序号是提醒序号继承,比如提醒有两个,任务1的序号就是3(llm会自动重编号)
5. 星期可选值:
- mon: 周一
- tue: 周二
- wed: 周三
- thu: 周四
- fri: 周五
- sat: 周六
- sun: 周日
6. 重复类型:
- daily: 每天重复
- weekly: 每周重复
- monthly: 每月重复
- yearly: 每年重复
7. 节假日类型:
- workday: 仅工作日触发(法定节假日不触发)
- holiday: 仅法定节假日触发
8. AI智能提醒与任务
正常对话即可,AI会自己设置提醒或任务,但需要AI支持LLM
9. 会话隔离功能
{session_isolation_status}
- 关闭状态:群聊中所有成员共享同一组提醒和任务
- 开启状态:群聊中每个成员都有自己独立的提醒和任务
可以通过管理面板的插件配置开启或关闭此功能
注:时间格式为 HH:MM 或 HHMM,如 8:05 或 0805
10. 数量限制
每个用户最多可创建 {max_reminders} 个提醒和任务
{limit_scope_description}
指令任务自定义标识说明:
- 使用 ---- 分隔符可以自定义指令任务的标识文字
- 格式:指令----位置--自定义文字
- 位置可选:before(开头)、after(末尾)、start(开头)、end(末尾)
- 示例:/rmd--ls----before--每日提醒 或 /rmd--ls----after--执行完成
- 如果不使用 ---- 分隔符,默认显示 [指令任务]
法定节假日数据来源:http://timor.tech/api/holiday""".format(
session_isolation_status="当前已开启会话隔离" if self.unique_session else "当前未开启会话隔离",
max_reminders=self.star.max_reminders_per_user if self.star.max_reminders_per_user > 0 else "无限制",
limit_scope_description="- 会话隔离开启:每个用户在每个群聊中独立计算" if self.unique_session else "- 会话隔离关闭:全局共享限制(所有用户共用)"
)
yield event.plain_result(help_text)
@check_permission
async def add_command_task(self, event: AstrMessageEvent, command: str, time_str: str, week: str = None, repeat: str = None, holiday_type: str = None):
'''设置指令任务
Args:
command(string): 要执行的指令,如"/memory_config"或"/rmd--ls"(多个指令用--分隔)
time_str(string): 时间,格式为 HH:MM 或 HHMM
week(string): 可选,开始星期:mon,tue,wed,thu,fri,sat,sun
repeat(string): 可选,重复类型:daily,weekly,monthly,yearly
holiday_type(string): 可选,节假日类型:workday(仅工作日执行),holiday(仅法定节假日执行)
'''
# 使用统一处理器处理添加指令任务的逻辑
async for result in self.processor.process_add_item(
event, 'command_task', command, time_str, week, repeat, holiday_type
):
yield result
@check_permission
async def add_remote_reminder(self, event: AstrMessageEvent, group_id: str, text: str, time_str: str, week: str = None, repeat: str = None, holiday_type: str = None):
'''在指定群聊中手动添加提醒'''
async for result in self.processor.process_add_item(
event, 'reminder', text, time_str, week, repeat, holiday_type, group_id
):
yield result
@check_permission
async def add_remote_task(self, event: AstrMessageEvent, group_id: str, text: str, time_str: str, week: str = None, repeat: str = None, holiday_type: str = None):
'''在指定群聊中手动添加任务'''
async for result in self.processor.process_add_item(
event, 'task', text, time_str, week, repeat, holiday_type, group_id
):
yield result
@check_permission
async def add_remote_command_task(self, event: AstrMessageEvent, group_id: str, command: str, time_str: str, week: str = None, repeat: str = None, holiday_type: str = None):
'''在指定群聊中设置指令任务'''
async for result in self.processor.process_add_item(
event, 'command_task', command, time_str, week, repeat, holiday_type, group_id
):
yield result
@check_permission
async def show_remote_help(self, event: AstrMessageEvent):
'''显示远程群聊帮助信息'''
help_text = """远程群聊提醒与任务功能指令说明:
【功能】:在指定的群聊中设置、查看和管理提醒、任务或指令任务
1. 在指定群聊中添加提醒:
/rmdg add <群聊ID> <内容> <时间> [开始星期] [重复类型] [--holiday_type=...]
例如:
- /rmdg add 1001914995 写周报 8:05
- /rmdg add 1001914995 吃饭 8:05 sun daily (从周日开始每天)
- /rmdg add 1001914995 开会 8:05 mon weekly (每周一)
- /rmdg add 1001914995 交房租 8:05 fri monthly (从周五开始每月)
- /rmdg add 1001914995 上班打卡 8:30 daily workday (每个工作日,法定节假日不触发)
2. 在指定群聊中添加任务:
/rmdg task <群聊ID> <内容> <时间> [开始星期] [重复类型] [--holiday_type=...]
例如:
- /rmdg task 1001914995 发送天气预报 8:00
- /rmdg task 1001914995 汇总今日新闻 18:00 daily
- /rmdg task 1001914995 推送工作安排 9:00 mon weekly workday (每周一工作日推送)
3. 在指定群聊中添加指令任务:
/rmdg command <群聊ID> <指令> <时间> [开始星期] [重复类型] [--holiday_type=...]
例如:
- /rmdg command 1001914995 /memory_config 8:00
- /rmdg command 1001914995 /weather 9:00 daily
- /rmdg command 1001914995 /news 18:00 mon weekly (每周一推送)
- /rmdg command 1001914995 /rmd--ls----before--每日提醒 8:00 daily (自定义标识放在开头)
- /rmdg command 1001914995 /rmd--ls----after--执行完成 8:00 daily (自定义标识放在末尾)
4. 查看指定群聊的提醒和任务:
/rmdg ls <群聊ID>
例如:
- /rmdg ls 1001914995
5. 删除指定群聊中的提醒或任务:
/rmdg rm <群聊ID> <序号>
例如:
- /rmdg rm 1001914995 1 (删除序号为1的提醒或任务)
6. 群聊ID获取方法:
- QQ群:群号,如 1001914995
- 微信群:群聊的wxid,如 wxid_hbjtu1j2gf5x22
- 其他平台:对应的群聊标识符
7. 星期可选值:
- mon: 周一
- tue: 周二
- wed: 周三
- thu: 周四
- fri: 周五
- sat: 周六
- sun: 周日
8. 重复类型:
- daily: 每天重复
- weekly: 每周重复
- monthly: 每月重复
- yearly: 每年重复
9. 节假日类型:
- workday: 仅工作日触发(法定节假日不触发)
- holiday: 仅法定节假日触发
10. 数量限制
每个用户最多可创建 {} 个提醒和任务
{}
注:时间格式为 HH:MM 或 HHMM,如 8:05 或 0805
指令任务自定义标识说明:
- 使用 ---- 分隔符可以自定义指令任务的标识文字
- 格式:指令----位置--自定义文字
- 位置可选:before(开头)、after(末尾)、start(开头)、end(末尾)
- 示例:/rmd--ls----before--每日提醒 或 /rmd--ls----after--执行完成
- 如果不使用 ---- 分隔符,默认显示 [指令任务]
法定节假日数据来源:http://timor.tech/api/holiday""".format(
self.star.max_reminders_per_user if self.star.max_reminders_per_user > 0 else "无限制",
"- 会话隔离开启:每个用户在每个群聊中独立计算" if self.unique_session else "- 会话隔离关闭:全局共享限制(所有用户共用)"
)
yield event.plain_result(help_text)
@check_permission
async def list_remote_reminders(self, event: AstrMessageEvent, group_id: str):
'''列出指定群聊中的所有提醒和任务'''
# 获取用户ID,用于会话隔离
creator_id = event.get_sender_id()
# 获取平台名称
platform_name = event.get_platform_name()
# 构建远程群聊的会话ID
if self.unique_session:
# 使用会话隔离
msg_origin = f"{platform_name}:GroupMessage:{group_id}_{creator_id}"
else:
msg_origin = f"{platform_name}:GroupMessage:{group_id}"
# 使用兼容性处理器获取提醒列表
reminders = self.star.compatibility_handler.get_reminders(msg_origin)
if not reminders:
yield event.plain_result(f"群聊 {group_id} 中没有设置任何提醒或任务。")
return
provider = self.context.get_using_provider()
if provider:
try:
# 分离提醒、任务和指令任务
reminder_items = []
task_items = []
command_task_items = []
for r in reminders:
if r.get("is_command_task", False):
# 指令任务,显示完整指令
command_text = r['text']
command_task_items.append(f"- {command_text} (时间: {r['datetime']})")
elif r.get("is_task", False):
# 普通任务
task_items.append(f"- {r['text']} (时间: {r['datetime']})")
else:
# 提醒
reminder_items.append(f"- {r['text']} (时间: {r['datetime']})")
# 构建提示
prompt = f"请帮我整理并展示群聊 {group_id} 的以下提醒和任务列表,用自然的语言表达:\n"
if reminder_items:
prompt += f"\n提醒列表:\n" + "\n".join(reminder_items)
if task_items:
prompt += f"\n\n任务列表:\n" + "\n".join(task_items)
if command_task_items:
prompt += f"\n\n指令任务列表:\n" + "\n".join(command_task_items)
prompt += f"\n\n同时告诉用户可以使用/rmdg rm {group_id} <序号>删除提醒、任务或指令任务,或者直接命令你来删除。直接发出对话内容,就是你说的话,不要有其他的背景描述。"
response = await provider.text_chat(
prompt=prompt,
session_id=event.session_id,
contexts=[] # 确保contexts是一个空列表而不是None
)
yield event.plain_result(response.completion_text)
except Exception as e:
logger.error(f"在list_remote_reminders中调用LLM时出错: {str(e)}")
# 如果LLM调用失败,回退到基本显示
reminder_str = f"群聊 {group_id} 的提醒和任务:\n"
# 分类显示
reminders_list = [r for r in reminders if not r.get("is_task", False)]
tasks_list = [r for r in reminders if r.get("is_task", False) and not r.get("is_command_task", False)]
command_tasks_list = [r for r in reminders if r.get("is_command_task", False)]
if reminders_list:
reminder_str += "\n提醒:\n"
for i, reminder in enumerate(reminders_list):
reminder_str += f"{i+1}. {reminder['text']} - {reminder['datetime']}\n"
if tasks_list:
reminder_str += "\n任务:\n"
for i, task in enumerate(tasks_list):
reminder_str += f"{len(reminders_list)+i+1}. {task['text']} - {task['datetime']}\n"
if command_tasks_list:
reminder_str += "\n指令任务:\n"
current_index = len(reminders_list) + len(tasks_list)
for i, cmd_task in enumerate(command_tasks_list):
reminder_str += f"{current_index+i+1}. /{cmd_task['text']} - {cmd_task['datetime']}\n"
reminder_str += f"\n使用 /rmdg rm {group_id} <序号> 删除提醒、任务或指令任务"
yield event.plain_result(reminder_str)
else:
reminder_str = f"群聊 {group_id} 的提醒和任务:\n"
# 分类显示
reminders_list = [r for r in reminders if not r.get("is_task", False)]
tasks_list = [r for r in reminders if r.get("is_task", False) and not r.get("is_command_task", False)]
command_tasks_list = [r for r in reminders if r.get("is_command_task", False)]
if reminders_list:
reminder_str += "\n提醒:\n"
for i, reminder in enumerate(reminders_list):
reminder_str += f"{i+1}. {reminder['text']} - {reminder['datetime']}\n"
if tasks_list:
reminder_str += "\n任务:\n"
for i, task in enumerate(tasks_list):
reminder_str += f"{len(reminders_list)+i+1}. {task['text']} - {task['datetime']}\n"
if command_tasks_list:
reminder_str += "\n指令任务:\n"
current_index = len(reminders_list) + len(tasks_list)
for i, cmd_task in enumerate(command_tasks_list):
reminder_str += f"{current_index+i+1}. /{cmd_task['text']} - {cmd_task['datetime']}\n"
reminder_str += f"\n使用 /rmdg rm {group_id} <序号> 删除提醒、任务或指令任务"
yield event.plain_result(reminder_str)
@check_permission
async def remove_remote_reminder(self, event: AstrMessageEvent, group_id: str, index: int):
'''删除指定群聊中的提醒、任务或指令任务
Args:
group_id(string): 群聊ID
index(int): 提醒、任务或指令任务的序号
'''
# 获取用户ID,用于会话隔离
creator_id = event.get_sender_id()
# 获取平台名称
platform_name = event.get_platform_name()
# 构建远程群聊的会话ID
if self.unique_session:
# 使用会话隔离
msg_origin = f"{platform_name}:GroupMessage:{group_id}_{creator_id}"
else:
msg_origin = f"{platform_name}:GroupMessage:{group_id}"
# 使用兼容性处理器删除提醒
removed_item, actual_key = self.star.compatibility_handler.remove_reminder(msg_origin, index - 1)
if removed_item is None:
yield event.plain_result(actual_key) # actual_key 包含错误信息
return
# 尝试删除调度任务 - 优先使用保存的任务ID
job_found = False
# 如果有保存的任务ID,直接删除
if removed_item.get('job_id'):
try:
self.scheduler_manager.remove_job(removed_item['job_id'])
logger.info(f"Successfully removed job by stored ID: {removed_item['job_id']}")
job_found = True
except Exception as e:
logger.warning(f"Failed to remove job by stored ID {removed_item['job_id']}: {str(e)}")
# 如果直接删除失败,则通过内容匹配删除
if not job_found:
for job in self.scheduler_manager.scheduler.get_jobs():
if job.id.startswith(f"reminder_") and len(job.args) >= 2:
try:
# 检查任务参数中的提醒内容是否匹配
job_session_id = job.args[0]
job_reminder = job.args[1]
if (job_session_id == actual_key and
isinstance(job_reminder, dict) and
job_reminder.get('text') == removed_item.get('text') and
job_reminder.get('datetime') == removed_item.get('datetime')):
self.scheduler_manager.remove_job(job.id)
logger.info(f"Successfully removed job by content match: {job.id}")
job_found = True
break
except Exception as e:
logger.error(f"Error checking job {job.id}: {str(e)}")
if not job_found:
logger.warning(f"No matching job found for removed item: {removed_item.get('text', 'unknown')}")
await save_reminder_data(self.data_file, self.reminder_data)
is_command_task = removed_item.get("is_command_task", False)
is_task = removed_item.get("is_task", False)
if is_command_task:
item_type = "指令任务"
display_text = f"/{removed_item['text']}"
elif is_task:
item_type = "任务"
display_text = removed_item['text']
else:
item_type = "提醒"
display_text = removed_item['text']
provider = self.context.get_using_provider()
if provider:
prompt = f"用户删除了群聊 {group_id} 中的一个{item_type},内容是'{display_text}'。请用自然的语言确认删除操作。直接发出对话内容,就是你说的话,不要有其他的背景描述。"
response = await provider.text_chat(
prompt=prompt,
session_id=event.session_id,
contexts=[] # 确保contexts是一个空列表而不是None
)
yield event.plain_result(response.completion_text)
else:
yield event.plain_result(f"已删除群聊 {group_id} 中的{item_type}:{display_text}")