extends RefCounted # 统一转换后端聊天载荷,避免 WebSocket 实时消息和 HTTP 历史消息 # 各自维护一套时间戳兼容规则。 static func normalize_history(messages: Array, current_username: String) -> Array[Dictionary]: var normalized: Array[Dictionary] = [] for message_variant: Variant in messages: if not (message_variant is Dictionary): continue var message: Dictionary = message_variant var sender := str(message.get("sender", message.get("from_user", ""))) normalized.append({ "from_user": sender, "from_user_id": str(message.get("fromUserId", message.get("from_user_id", ""))), "content": str(message.get("content", "")), "timestamp": parse_timestamp(message.get("timestamp", 0.0)), "is_self": sender == current_username, "scope": str(message.get("scope", "local")), "show_bubble": bool(message.get("bubble", false)), "is_history": true, }) return normalized static func parse_timestamp(timestamp_raw: Variant) -> float: if typeof(timestamp_raw) == TYPE_INT or typeof(timestamp_raw) == TYPE_FLOAT: var numeric_timestamp := float(timestamp_raw) return numeric_timestamp if numeric_timestamp > 0.0 else Time.get_unix_time_from_system() var timestamp_text := str(timestamp_raw) if timestamp_text.strip_edges().is_empty(): return Time.get_unix_time_from_system() var numeric_regex := RegEx.new() numeric_regex.compile("^\\s*-?\\d+(?:\\.\\d+)?\\s*$") if numeric_regex.search(timestamp_text) != null: var parsed_numeric := float(timestamp_text) return parsed_numeric if parsed_numeric > 0.0 else Time.get_unix_time_from_system() var iso_regex := RegEx.new() iso_regex.compile("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})") var match_result := iso_regex.search(timestamp_text) if match_result == null: return Time.get_unix_time_from_system() var utc_datetime := { "year": int(match_result.get_string(1)), "month": int(match_result.get_string(2)), "day": int(match_result.get_string(3)), "hour": int(match_result.get_string(4)), "minute": int(match_result.get_string(5)), "second": int(match_result.get_string(6)), } return Time.get_unix_time_from_datetime_dict(utc_datetime)