2222 MessageContentType ,
2323 UnifiedMessage ,
2424)
25- from ....shared .trace_context import REPORT_CAPTION_PATTERN
2625from ....utils .logger import logger
2726from ..base import PlatformAdapter
2827
@@ -494,7 +493,7 @@ async def send_image(
494493 """
495494 try :
496495 use_base64 = False
497- plugin = self .config .get ("plugin_instance" ) if self .config else None
496+ plugin : Any = self .config .get ("plugin_instance" ) if self .config else None
498497 if plugin and hasattr (plugin , "config_manager" ):
499498 use_base64 = plugin .config_manager .get_enable_base64_image ()
500499
@@ -574,150 +573,16 @@ async def send_image(
574573 logger .info (f"Base64 回退模式发送图片成功: 群 { group_id } " )
575574 return True
576575
577- except Exception as e :
578- # 识别 OneBot 的“假失败”情况:如果由于图片过大导致超时,其实图片往往已在后台由 OneBot 自动重传并最终会成功。
579- error_str = str (e ).lower ()
580- # 判定为“疑似成功”的特征:超时、1200、网络错误
581- is_potential_success = (
582- "timeout" in error_str or "1200" in error_str or "网络错误" in error_str
576+ await self .bot .call_action (
577+ "send_group_msg" ,
578+ group_id = int (group_id ),
579+ message = message ,
583580 )
581+ logger .info (f"Base64 回退模式发送图片成功: 群 { group_id } " )
582+ return True
584583
585- if is_potential_success :
586- logger .warning (
587- f"OneBot 发送群 { group_id } 图片出现疑似超时 ({ e } )。 "
588- "进入多轮观察期,尝试通过历史回显核实..."
589- )
590-
591- # Multi-stage observation. Some OneBot implementations commit
592- # history with delay after timeout-like errors.
593- observe_windows = (10 , 20 , 30 )
594- for wait_seconds in observe_windows :
595- await asyncio .sleep (wait_seconds )
596- if await self .was_image_sent_recently (
597- group_id , seconds = 420 , token = caption
598- ):
599- logger .info (
600- f"[OneBot] [真相拦截] 群 { group_id } 在 { wait_seconds } s 观察后确认已送达,拦截重试。"
601- )
602- return True
603-
604- return False # 没找回,返回 False,由上层 RetryManager 接管(带 20s 延迟观察期)
605-
606- logger .error (f"OneBot 图片发送最终失败: { e } " )
607- return False
608-
609- async def was_image_sent_recently (
610- self , group_id : str , seconds : int = 60 , token : str | None = None
611- ) -> bool :
612- """
613- [真相检查] 检查最近 X 秒内,机器人是否已经向该群发送过图片。
614- 用于判断之前的“超时/1200”错误是否其实已经在后台发送成功。
615- """
616- try :
617- # 1. 获取最近的消息历史 (OneBot 标准 API)
618- try :
619- history = await self .bot .call_action (
620- "get_group_msg_history" ,
621- group_id = int (group_id ),
622- count = 100 , # 增大扫描深度以应对高频群聊
623- )
624- except Exception as e :
625- logger .warning (
626- f"[OneBot] was_image_sent_recently: get_group_msg_history 失败 (可能 API 繁忙): { e } "
627- )
628- return False # API 失败时,我们保持谨慎,但不阻止重试
629-
630- if not history or "messages" not in history :
631- messages = history if isinstance (history , list ) else []
632- else :
633- messages = history ["messages" ]
634-
635- # 2. 逆序检查
636- import time
637-
638- now = time .time ()
639- # 1. 优先从内存缓存中获取机器人 ID
640- self_id = self .bot_self_ids [0 ] if self .bot_self_ids else ""
641-
642- if not self_id :
643- # 尝试从 bot 实例中获取多个可能的 ID 属性
644- self_id = (
645- str (getattr (self .bot , "self_id" , "" ))
646- or str (getattr (self .bot , "uin" , "" ))
647- or str (getattr (self .bot , "user_id" , "" ))
648- )
649-
650- if not self_id :
651- # 最后的 API 兜底:尝试从 login_info 获取
652- try :
653- login_info = await self .bot .call_action ("get_login_info" )
654- if login_info and "user_id" in login_info :
655- self_id = str (login_info ["user_id" ])
656- # 更新缓存,下次无需重复请求
657- if self_id not in self .bot_self_ids :
658- self .bot_self_ids .append (self_id )
659- logger .info (f"[OneBot] 成功通过 API 获取到机器人 ID: { self_id } " )
660- except Exception as e :
661- logger .debug (
662- f"[OneBot] was_image_sent_recently: get_login_info API 调用失败: { e } "
663- )
664-
665- if not self_id :
666- logger .warning (
667- "[OneBot] was_image_sent_recently: 无法确定机器人 ID,历史回显校验可能不准确"
668- )
669-
670- # [优化] 从 Caption 中提取基于时间戳的去重 Token
671- search_token = None
672- if token :
673- match = REPORT_CAPTION_PATTERN .search (token )
674- if match :
675- search_token = match .group (0 ) # 例如 "| 03-12 17:33:20"
676-
677- for msg in reversed (messages ):
678- msg_time = msg .get ("time" , 0 )
679- # 只检查约定时间范围内的消息
680- if now - msg_time > seconds :
681- break
682-
683- # 检查发送者是否是机器人自己
684- user_id = str (
685- msg .get ("user_id" , msg .get ("sender" , {}).get ("user_id" , "" ))
686- )
687- if user_id not in self .bot_self_ids :
688- # 如果内存中没有,尝试最后一次实时提取作为兜底
689- if not self_id or user_id != self_id :
690- continue
691-
692- # 检查消息内容是否包含图片
693- raw_message = msg .get ("message" , [])
694- # 适配字符串形式或列表形式的消息
695- msg_str = str (raw_message )
696-
697- has_image = "[CQ:image" in msg_str or '"type": "image"' in msg_str
698-
699- if has_image :
700- if search_token :
701- # 精确匹配 TraceID
702- if search_token in msg_str :
703- logger .info (
704- f"[OneBot] [真相检查] 发现匹配 ID ({ search_token } ) 的历史图片。拦截重复发送。群: { group_id } "
705- )
706- return True
707- else :
708- logger .debug (
709- f"[OneBot] [真相检查] 发现机器人发送的图片,但 ID 不匹配。跳过。群: { group_id } "
710- )
711- else :
712- # 广义匹配(回退模式)
713- logger .info (
714- f"[OneBot] [真相检查] 发现近期发送过的图片回显 (广义匹配)。无需重试。群: { group_id } "
715- )
716- return True
717-
718- return False
719584 except Exception as e :
720- logger .debug (f"回显自检失败 : { e } " )
585+ logger .error (f"OneBot 图片发送最终失败 : { e } " )
721586 return False
722587
723588 async def send_file (
@@ -761,10 +626,13 @@ async def send_file(
761626 file = file_b64 ,
762627 name = filename or os .path .basename (file_path ),
763628 )
764- logger .info (f"Base64 回退模式发送文件成功: { filename or file_path } " )
765- return True
629+ # ... 实现省略 ...
630+ logger .info (
631+ f"[OneBot] 文件发送成功(Base64 模式): { filename or file_path } "
632+ )
633+ return True
766634 except Exception as e :
767- logger .error (f"OneBot 文件发送最终失败: { e } " )
635+ logger .error (f"[ OneBot] 文件发送最终失败: { e } " )
768636 return False
769637
770638 async def send_forward_msg (
@@ -774,13 +642,6 @@ async def send_forward_msg(
774642 ) -> bool :
775643 """
776644 发送群合并转发消息。
777-
778- Args:
779- group_id (str): 目标群号
780- nodes (list[dict]): 转发节点列表
781-
782- Returns:
783- bool: 是否发送成功
784645 """
785646 if not hasattr (self .bot , "call_action" ):
786647 return False
@@ -799,7 +660,7 @@ async def send_forward_msg(
799660 )
800661 return True
801662 except Exception as e :
802- logger .warning (f"OneBot 发送合并转发消息失败: { e } " )
663+ logger .warning (f"[ OneBot] 发送合并转发消息失败: { e } " )
803664 return False
804665
805666 # ==================== IGroupInfoRepository 实现 ====================
0 commit comments