@@ -55,6 +55,8 @@ def __init__(
5555 self .activity_name = self .config .get ("discord_activity_name" , None )
5656 self .shutdown_event = asyncio .Event ()
5757 self ._polling_task = None
58+ self ._command_sync_lock = asyncio .Lock ()
59+ self ._managed_application_commands : list [Any ] = []
5860
5961 @override
6062 async def send_by_session (
@@ -115,6 +117,14 @@ def meta(self) -> PlatformMetadata:
115117 support_streaming_message = False ,
116118 )
117119
120+ @override
121+ async def refresh_registered_commands (self ) -> None :
122+ if not self .enable_command_register :
123+ return
124+ if not getattr (self , "client" , None ) or self .client .user is None :
125+ return
126+ await self ._collect_and_register_commands ()
127+
118128 @override
119129 async def run (self ) -> None :
120130 """主要运行逻辑"""
@@ -404,10 +414,22 @@ def register_handler(self, handler_info) -> None:
404414 """注册处理器信息"""
405415 self .registered_handlers .append (handler_info )
406416
417+ def _replace_managed_application_commands (self , commands : list [Any ]) -> None :
418+ for command in self ._managed_application_commands :
419+ self .client .remove_application_command (command )
420+ for command in commands :
421+ self .client .add_application_command (command )
422+ self ._managed_application_commands = list (commands )
423+
407424 async def _collect_and_register_commands (self ) -> None :
425+ async with self ._command_sync_lock :
426+ await self ._collect_and_register_commands_unlocked ()
427+
428+ async def _collect_and_register_commands_unlocked (self ) -> None :
408429 """收集所有指令并注册到Discord"""
409430 logger .info ("[Discord] Collecting and registering slash commands..." )
410431 registered_commands = []
432+ application_commands = []
411433
412434 for handler_md in star_handlers_registry :
413435 if not star_map [handler_md .handler_module_path ].activated :
@@ -442,7 +464,7 @@ async def _collect_and_register_commands(self) -> None:
442464 options = options ,
443465 guild_ids = [self .guild_id ] if self .guild_id else None ,
444466 )
445- self . client . add_application_command (slash_command )
467+ application_commands . append (slash_command )
446468 registered_commands .append (cmd_name )
447469
448470 if registered_commands :
@@ -452,12 +474,18 @@ async def _collect_and_register_commands(self) -> None:
452474 else :
453475 logger .info ("[Discord] No commands found for registration." )
454476
477+ previous_commands = list (self ._managed_application_commands )
478+ self ._replace_managed_application_commands (application_commands )
479+
455480 # 使用 Pycord 的方法同步指令
456481 # 注意:这可能需要一些时间,并且有频率限制
457482 try :
458- await self .client .sync_commands ()
483+ await self .client .sync_commands (
484+ check_guilds = [self .guild_id ] if self .guild_id else [],
485+ )
459486 logger .info ("[Discord] Command synchronization completed." )
460487 except discord .HTTPException as e :
488+ self ._replace_managed_application_commands (previous_commands )
461489 if self ._is_daily_command_quota_error (e ):
462490 logger .warning (
463491 "[Discord] Daily application command create quota reached "
@@ -466,6 +494,9 @@ async def _collect_and_register_commands(self) -> None:
466494 )
467495 return
468496 logger .warning (f"[Discord] Sync commands failed: { e } " )
497+ except Exception :
498+ self ._replace_managed_application_commands (previous_commands )
499+ raise
469500
470501 @staticmethod
471502 def _is_daily_command_quota_error (error : discord .HTTPException ) -> bool :
0 commit comments