66import inspect
77import json
88import os
9+ from typing import Generator
910from urllib .parse import urlparse
1011
1112from murainbot .common import save_exc_dump
@@ -1125,6 +1126,43 @@ def get_json(self):
11251126 return json .loads (self .json_data )
11261127
11271128
1129+ def _create_segment_from_dict (segment_dict : dict ) -> Segment :
1130+ """从单个字典(array格式)创建Segment对象"""
1131+ # 这个辅助函数和你代码中的对象化逻辑是一样的
1132+ segment_type = segment_dict .get ("type" )
1133+ if segment_type in segments_map :
1134+ try :
1135+ params = inspect .signature (segments_map [segment_type ]).parameters
1136+ kwargs = {}
1137+ data = segment_dict .get ("data" , {})
1138+ for param in params :
1139+ if param in data :
1140+ kwargs [param ] = data [param ]
1141+ elif param == "id_" :
1142+ kwargs [param ] = data .get ("id" )
1143+ elif param == "type_" :
1144+ kwargs [param ] = data .get ("type" )
1145+ elif params [param ].default != params [param ].empty :
1146+ kwargs [param ] = params [param ].default
1147+
1148+ segment = segments_map [segment_type ](** kwargs )
1149+
1150+ for k , v in data .items ():
1151+ if k not in segment .data :
1152+ segment .set_data (k , v )
1153+ return segment
1154+ except Exception as e :
1155+ if ConfigManager .GlobalConfig ().debug .save_dump :
1156+ dump_path = save_exc_dump (f"转换{ segment_dict } 时失败" )
1157+ else :
1158+ dump_path = None
1159+ Logger .get_logger ().warning (f"转换{ segment_dict } 时失败,报错信息: { repr (e )} "
1160+ f"{ f"\n 已保存异常到 { dump_path } " if dump_path else "" } " ,
1161+ exc_info = True )
1162+ return Segment (segment_dict )
1163+ return Segment (segment_dict )
1164+
1165+
11281166class QQRichText :
11291167 """
11301168 QQ富文本
@@ -1139,70 +1177,36 @@ def __init__(
11391177 Args:
11401178 *rich: 富文本内容,可为 str、dict、list、tuple、Segment、QQRichText
11411179 """
1180+ # __init__ 现在只做一件事:消费一个生成器来构建最终的列表
1181+ self .rich_array : list [Segment ] = list (self ._iter_and_convert_segments (rich ))
11421182
1143- # 特判
1144- self . rich_array : list [ Segment ] = []
1145-
1146- if len ( rich ) == 1 and isinstance ( rich [ 0 ], ( list , tuple )):
1147- rich = rich [ 0 ]
1148-
1149- # 识别输入的是CQCode or json形式的富文本
1150- # 如果输入的是CQCode,则转换为json形式的富文本
1183+ def _iter_and_convert_segments ( self , rich_items ) -> Generator [ Segment , None , None ]:
1184+ """
1185+ 核心优化:单遍处理所有输入,并直接 yield 最终的 Segment 对象。
1186+ 这完美实现了你“合并处理”的想法。
1187+ """
1188+ # 1. 扁平化初始输入
1189+ if len ( rich_items ) == 1 and isinstance ( rich_items [ 0 ], ( list , tuple )):
1190+ rich_items = rich_items [ 0 ]
11511191
1152- # 处理CQCode
1153- array = []
1154- for item in rich :
1155- if isinstance (item , dict ):
1156- array . append ( item )
1157- elif isinstance (item , str ):
1158- array += cq_2_array (item )
1192+ # 2. 单遍处理所有项目
1193+ for item in rich_items :
1194+ # 分类处理,直接生成并yield Segment对象
1195+ if any ( isinstance (item , segment ) for segment in segments ) and not isinstance ( item , Segment ):
1196+ yield item
1197+ elif isinstance (item , Segment ):
1198+ yield _create_segment_from_dict (item . array )
11591199 elif isinstance (item , QQRichText ):
1160- array += item .rich_array
1161- else :
1162- for segment in segments :
1163- if isinstance (item , segment ):
1164- array .append (item .array )
1165- break
1166- else :
1167- raise TypeError ("QQRichText: 输入类型错误" )
1168- rich = array
1169-
1170- # 将rich转换为的Segment
1171- for i in range (len (rich )):
1172- if rich [i ]["type" ] in segments_map :
1173- try :
1174- params = inspect .signature (segments_map [rich [i ]["type" ]]).parameters
1175- kwargs = {}
1176- for param in params :
1177- if param in rich [i ]["data" ]:
1178- kwargs [param ] = rich [i ]["data" ][param ]
1179- else :
1180- if param == "id_" :
1181- kwargs [param ] = rich [i ]["data" ].get ("id" )
1182- elif param == "type_" :
1183- kwargs [param ] = rich [i ]["data" ].get ("type" )
1184- else :
1185- if params [param ].default != params [param ].empty :
1186- kwargs [param ] = params [param ].default
1187- segment = segments_map [rich [i ]["type" ]](** kwargs )
1188- # 检查原cq中是否含有不在segment的data中的参数
1189- for k , v in rich [i ]["data" ].items ():
1190- if k not in segment ["data" ]:
1191- segment .set_data (k , v )
1192- rich [i ] = segment
1193- except Exception as e :
1194- if ConfigManager .GlobalConfig ().debug .save_dump :
1195- dump_path = save_exc_dump (f"转换{ rich [i ]} 时失败" )
1196- else :
1197- dump_path = None
1198- Logger .get_logger ().warning (f"转换{ rich [i ]} 时失败,报错信息: { repr (e )} "
1199- f"{ f"\n 已保存异常到 { dump_path } " if dump_path else "" } " ,
1200- exc_info = True )
1201- rich [i ] = Segment (rich [i ])
1200+ yield from item .rich_array
1201+ elif isinstance (item , str ):
1202+ for arr in cq_2_array (item ):
1203+ yield _create_segment_from_dict (arr )
1204+ elif isinstance (item , dict ):
1205+ yield _create_segment_from_dict (item )
1206+ elif isinstance (item , (list , tuple )):
1207+ yield from self ._iter_and_convert_segments (item )
12021208 else :
1203- rich [i ] = Segment (rich [i ])
1204-
1205- self .rich_array : list [Segment ] = rich
1209+ raise TypeError (f"QQRichText: 不支持的输入类型 { type (item )} " )
12061210
12071211 def render (self , group_id : int | None = None ):
12081212 """
0 commit comments