From abcaa48be4a63b220f164e822a4228a3d78ac8ec Mon Sep 17 00:00:00 2001 From: barelyprofessional <150058423+barelyprofessional@users.noreply.github.com> Date: Sat, 28 Feb 2026 18:18:08 -0600 Subject: [PATCH] Refactored Xeet embed so it uses the fancy split extension method instead of the one cohle cooked up --- KfChatDotNetBot/Commands/XeetEmbedCommand.cs | 148 +------------------ 1 file changed, 8 insertions(+), 140 deletions(-) diff --git a/KfChatDotNetBot/Commands/XeetEmbedCommand.cs b/KfChatDotNetBot/Commands/XeetEmbedCommand.cs index 28a92a7..cbecdc8 100644 --- a/KfChatDotNetBot/Commands/XeetEmbedCommand.cs +++ b/KfChatDotNetBot/Commands/XeetEmbedCommand.cs @@ -53,7 +53,8 @@ public class XeetEmbedCommand : ICommand var loadingMessage = await botInstance.SendChatMessageAsync($"{LoadingGif} Fetching tweet...", true); - await botInstance.WaitForChatMessageAsync(loadingMessage, TimeSpan.FromSeconds(5), ctx); + var success = await botInstance.WaitForChatMessageAsync(loadingMessage, TimeSpan.FromSeconds(10), ctx); + if (!success) throw new InvalidOperationException(); try { @@ -75,9 +76,9 @@ public class XeetEmbedCommand : ICommand var messages = await BuildTweetMessagesAsync(tweet, xeetId, mediaUrls, ctx); - if (loadingMessage.ChatMessageId.HasValue) + if (loadingMessage.ChatMessageUuid != null) { - await botInstance.KfClient.DeleteMessageAsync(loadingMessage.ChatMessageId.Value); + await botInstance.KfClient.DeleteMessageAsync(loadingMessage.ChatMessageUuid); } if (messages.Count == 0) @@ -104,9 +105,9 @@ public class XeetEmbedCommand : ICommand catch { // Delete loading message on error - if (loadingMessage.ChatMessageId.HasValue) + if (loadingMessage.ChatMessageUuid != null) { - await botInstance.KfClient.DeleteMessageAsync(loadingMessage.ChatMessageId.Value); + await botInstance.KfClient.DeleteMessageAsync(loadingMessage.ChatMessageUuid); } throw; } @@ -296,13 +297,12 @@ public class XeetEmbedCommand : ICommand private async Task> BuildTweetMessagesAsync(FxTweet tweet, string xeetId, List mediaUrls, CancellationToken ctx) { - var headerBuilder = new StringBuilder(); var bodyBuilder = new StringBuilder(); var footerBuilder = new StringBuilder(); // Build header - main tweet author and timestamp (always goes first) var created = DateTimeOffset.FromUnixTimeSeconds(tweet.CreatedTimestamp); - headerBuilder.Append($"[b]{tweet.Author.Name}[/b] (@{tweet.Author.ScreenName}) - {created.Humanize(DateTimeOffset.UtcNow)}[br]"); + var header = $"[b]{tweet.Author.Name}[/b] (@{tweet.Author.ScreenName}) - {created.Humanize(DateTimeOffset.UtcNow)}[br]"; // Handle reply chain (if this tweet is a reply) if (!string.IsNullOrEmpty(tweet.ReplyingToStatus)) @@ -367,139 +367,7 @@ public class XeetEmbedCommand : ICommand footerBuilder.Append($"[url={tweet.Url}]X.com[/url] | [url=https://xcancel.com/{tweet.Author.ScreenName}/status/{xeetId}]Xcancel[/url]"); // Split message if needed, with header always first and footer always last - var messages = SplitMessageByBytes(headerBuilder.ToString(), bodyBuilder.ToString(), footerBuilder.ToString(), 1024); - - return messages; - } - - private List SplitMessageByBytes(string header, string bodyContent, string footer, int maxBytes) - { - var messages = new List(); - var headerBytes = Encoding.UTF8.GetByteCount(header); - var footerBytes = Encoding.UTF8.GetByteCount(footer); - - // Check if entire message (header + body + footer) fits in one message - var fullMessage = header + bodyContent + footer; - if (Encoding.UTF8.GetByteCount(fullMessage) <= maxBytes) - { - messages.Add(fullMessage); - return messages; - } - - // Need to split - calculate available space for body content - // First message needs room for header, last message needs room for footer - var availableForFirstMessage = maxBytes - headerBytes - 5; // 5 bytes safety margin - var availableForLastMessage = maxBytes - footerBytes - 5; - var availableForMiddleMessages = maxBytes - 10; // safety margin - - // Split body by [br] tags - var parts = bodyContent.Split(new[] { "[br]" }, StringSplitOptions.None); - var bodyMessages = new List(); - var currentMessage = new StringBuilder(); - var currentBytes = 0; - var isFirstBodyMessage = true; - - for (int i = 0; i < parts.Length; i++) - { - var part = parts[i]; - var isLastPart = i == parts.Length - 1; - var partWithBreak = isLastPart ? part : part + "[br]"; - var partBytes = Encoding.UTF8.GetByteCount(partWithBreak); - - // Determine available space based on whether this is first or middle message - var availableSpace = isFirstBodyMessage ? availableForFirstMessage : availableForMiddleMessages; - - // If this single part is too large, split it by words - if (partBytes > availableSpace) - { - // Flush current message if it has content - if (currentBytes > 0) - { - bodyMessages.Add(currentMessage.ToString()); - currentMessage.Clear(); - currentBytes = 0; - isFirstBodyMessage = false; - } - - // Split the large part by words - var words = part.Split(' '); - var lineSb = new StringBuilder(); - var lineBytes = 0; - - foreach (var word in words) - { - var wordWithSpace = word + " "; - var wordBytes = Encoding.UTF8.GetByteCount(wordWithSpace); - - availableSpace = isFirstBodyMessage ? availableForFirstMessage : availableForMiddleMessages; - - if (lineBytes + wordBytes > availableSpace) - { - if (lineSb.Length > 0) - { - bodyMessages.Add(lineSb.ToString().TrimEnd()); - lineSb.Clear(); - lineBytes = 0; - isFirstBodyMessage = false; - } - } - - lineSb.Append(wordWithSpace); - lineBytes += wordBytes; - } - - if (lineSb.Length > 0) - { - currentMessage.Append(lineSb.ToString().TrimEnd()); - if (!isLastPart) - { - currentMessage.Append("[br]"); - } - currentBytes = Encoding.UTF8.GetByteCount(currentMessage.ToString()); - } - continue; - } - - // Check if adding this part would exceed the limit - if (currentBytes + partBytes > availableSpace && currentBytes > 0) - { - // Save current message and start new one - bodyMessages.Add(currentMessage.ToString()); - currentMessage.Clear(); - currentBytes = 0; - isFirstBodyMessage = false; - } - - currentMessage.Append(partWithBreak); - currentBytes += partBytes; - } - - // Add remaining body content - if (currentMessage.Length > 0) - { - bodyMessages.Add(currentMessage.ToString()); - } - - // Assemble final messages with header first and footer last - if (bodyMessages.Count > 0) - { - // First message: header + first body part - messages.Add(header + bodyMessages[0]); - - // Middle messages (if any) - for (int i = 1; i < bodyMessages.Count; i++) - { - messages.Add(bodyMessages[i]); - } - - // Add footer to the last message - messages[messages.Count - 1] = messages[messages.Count - 1] + footer; - } - else - { - // Only header and footer - messages.Add(header + footer); - } + var messages = (header + bodyBuilder + footerBuilder).FancySplitMessage(); return messages; }