diff --git a/ArchiSteamFarm.Tests/SteamChatMessage.cs b/ArchiSteamFarm.Tests/SteamChatMessage.cs index 8f7735a45..f82774c9b 100644 --- a/ArchiSteamFarm.Tests/SteamChatMessage.cs +++ b/ArchiSteamFarm.Tests/SteamChatMessage.cs @@ -50,9 +50,6 @@ namespace ArchiSteamFarm.Tests { [TestMethod] public void ContinuationCharacterSizeIsProperlyCalculated() => Assert.AreEqual(ContinuationCharacterBytes, Encoding.UTF8.GetByteCount(ContinuationCharacter.ToString())); - [TestMethod] - public void ParagraphCharacterSizeIsLessOrEqualToContinuationCharacterSize() => Assert.IsTrue(ContinuationCharacterBytes >= Encoding.UTF8.GetByteCount(ParagraphCharacter.ToString())); - [TestMethod] public async Task DoesntSkipEmptyNewlines() { string message = "asdf" + Environment.NewLine + Environment.NewLine + "asdf"; @@ -148,6 +145,9 @@ namespace ArchiSteamFarm.Tests { Assert.AreEqual(message, output.First()); } + [TestMethod] + public void ParagraphCharacterSizeIsLessOrEqualToContinuationCharacterSize() => Assert.IsTrue(ContinuationCharacterBytes >= Encoding.UTF8.GetByteCount(ParagraphCharacter.ToString())); + [TestMethod] public async Task ProperlyEscapesCharacters() { const string message = @"[b]bold[/b] \n"; diff --git a/ArchiSteamFarm/Steam/Integration/SteamChatMessage.cs b/ArchiSteamFarm/Steam/Integration/SteamChatMessage.cs index 54a900984..cbfd40a5f 100644 --- a/ArchiSteamFarm/Steam/Integration/SteamChatMessage.cs +++ b/ArchiSteamFarm/Steam/Integration/SteamChatMessage.cs @@ -33,11 +33,11 @@ namespace ArchiSteamFarm.Steam.Integration { internal static class SteamChatMessage { internal const char ContinuationCharacter = '…'; // A character used for indicating that the next newline part is a continuation of the previous line internal const byte ContinuationCharacterBytes = 3; // The continuation character specified above uses 3 bytes in UTF-8 - internal const char ParagraphCharacter = '¶'; // A character used for indicating that this is not the last part of message (2 bytes, so it fits in ContinuationCharacterBytes) internal const ushort MaxMessageBytesForLimitedAccounts = 1945; // This is a limitation enforced by Steam internal const ushort MaxMessageBytesForUnlimitedAccounts = 6340; // This is a limitation enforced by Steam internal const ushort MaxMessagePrefixBytes = MaxMessageBytesForLimitedAccounts - ReservedContinuationMessageBytes - ReservedEscapeMessageBytes; // Simplified calculation, nobody should be using prefixes even close to that anyway internal const byte NewlineWeight = 61; // This defines how much weight a newline character is adding to the output, limitation enforced by Steam + internal const char ParagraphCharacter = '¶'; // A character used for indicating that this is not the last part of message (2 bytes, so it fits in ContinuationCharacterBytes) internal const byte ReservedContinuationMessageBytes = ContinuationCharacterBytes * 2; // Up to 2 optional continuation characters internal const byte ReservedEscapeMessageBytes = 5; // 2 characters total, escape one '\' of 1 byte and real one of up to 4 bytes @@ -108,6 +108,7 @@ namespace ArchiSteamFarm.Steam.Integration { if (messagePart.Length > prefixLength) { if (messagePartBytes + NewlineWeight + lineBytes.Length > maxMessageBytes) { messagePart.Append(ParagraphCharacter); + yield return messagePart.ToString(); messagePartBytes = prefixBytes; @@ -156,7 +157,11 @@ namespace ArchiSteamFarm.Steam.Integration { charPool.Return(lineChunk); } + bool midLineSplitting = false; + if (lineBytesRead < lineBytes.Length) { + midLineSplitting = true; + messagePartBytes += ContinuationCharacterBytes; messagePart.Append(ContinuationCharacter); } @@ -166,7 +171,7 @@ namespace ArchiSteamFarm.Steam.Integration { continue; } - if (stringReader.Peek() != -1 && messagePart[messagePart.Length-1] != ContinuationCharacter) { + if ((stringReader.Peek() != -1) && !midLineSplitting) { messagePart.Append(ParagraphCharacter); }