using System.Globalization; namespace WxAgent.Core; public static class WechatTextInput { public const int MaxSegmentLength = 4000; public const int MaxTextLength = 20_000; public static string Prepare(string text) { var normalized = PrepareLongText(text); if (normalized.Length > MaxSegmentLength) throw new WxAgentException(WxAgentErrorCode.InvalidArgument, $"Message text must not exceed {MaxSegmentLength} characters."); return normalized; } public static string PrepareLongText(string text) { if (string.IsNullOrWhiteSpace(text)) throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "Message text must not be empty."); var normalized = text.ReplaceLineEndings("\n"); if (normalized.Length > MaxTextLength || normalized.Any(character => char.IsControl(character) && character is not ('\n' or '\t'))) throw new WxAgentException(WxAgentErrorCode.InvalidArgument, $"Message text must not exceed {MaxTextLength} characters or contain unsupported control characters."); return normalized; } public static IReadOnlyList SplitForSend(string text) { var normalized = PrepareLongText(text); if (normalized.Length <= MaxSegmentLength) return [normalized]; var textElementStarts = StringInfo.ParseCombiningCharacters(normalized); var segments = new List(); var start = 0; while (start < normalized.Length) { var end = Math.Min(start + MaxSegmentLength, normalized.Length); if (end < normalized.Length) { var boundaryIndex = Array.BinarySearch(textElementStarts, end); if (boundaryIndex < 0) boundaryIndex = ~boundaryIndex - 1; if (boundaryIndex < 0 || textElementStarts[boundaryIndex] <= start) throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "A text element exceeds the per-message length limit."); end = textElementStarts[boundaryIndex]; } segments.Add(normalized[start..end]); start = end; } return segments; } }