public E <LocalStr> SendServerMessage(string message) { if (Ts3String.TokenLength(message) > Ts3Const.MaxSizeTextMessage) { return(new LocalStr(strings.error_ts_msg_too_long)); } return(TsFullClient.SendServerMessage(message, 1).FormatLocal()); }
public E <LocalStr> SendMessage(string message, ushort clientId) { if (Ts3String.TokenLength(message) > Ts3Const.MaxSizeTextMessage) { return(new LocalStr(strings.error_ts_msg_too_long)); } return(TsFullClient.SendPrivateMessage(message, clientId).FormatLocal()); }
public R SendServerMessage(string message) { if (Ts3String.TokenLength(message) > Ts3Const.MaxSizeTextMessage) { return("The message to send is longer than the maximum of " + Ts3Const.MaxSizeTextMessage + " characters"); } return(tsBaseClient.SendServerMessage(message, 1).ToR(Extensions.ErrorFormat)); }
public R SendGlobalMessage(string message) { if (Ts3String.TokenLength(message) > Ts3String.MaxMsgLength) { return("The message to send is longer than the maximum of " + Ts3String.MaxMsgLength + " characters"); } try { tsBaseClient.SendMessage(TextMessageTargetMode.Server, 1, message); return(R.OkR); } catch (Ts3CommandException ex) { return(ex.ErrorStatus.ErrorFormat()); } }
public R SendMessage(string message, ushort clientId) { if (Ts3String.TokenLength(message) > Ts3String.MaxMsgLength) { return("The message to send is longer than the maximum of " + Ts3String.MaxMsgLength + " characters"); } try { tsBaseClient.SendPrivateMessage(message, clientId); return(R.OkR); } catch (Ts3CommandException ex) { return(ex.ErrorStatus.ErrorFormat()); } }
/// <summary>Trims a string to have the given token count at max.</summary> /// <param name="value">The string to substring from the left side.</param> /// <param name="token">The max token count.</param> /// <returns>The new substring.</returns> private static string SubstringToken(string value, int token) { int tokens = 0; for (int i = 0; i < value.Length; i++) { int addToken = Ts3String.IsDoubleChar(value[i]) ? 2 : 1; if (tokens + addToken > token) { return(value.Substring(0, i)); } else { tokens += addToken; } } return(value); }
public static IEnumerable <string> Transform(string text, LongTextBehaviour behaviour, int limit = int.MaxValue) { switch (behaviour) { case LongTextBehaviour.Drop: case LongTextBehaviour.SplitHard: int tokenCnt = 0; int lastSplit = 0; for (int i = 0; i < text.Length; i++) { var prevTokenCnt = tokenCnt; tokenCnt += Ts3String.IsDoubleChar(text[i]) ? 2 : 1; if (tokenCnt > Ts3Const.MaxSizeTextMessage) // TODO >= ?? { if (behaviour == LongTextBehaviour.Drop) { yield break; } yield return(text.Substring(lastSplit, i - lastSplit)); limit--; if (limit == 0) { yield break; } lastSplit = i; tokenCnt -= prevTokenCnt; } } yield return(text.Substring(lastSplit)); break; case LongTextBehaviour.Split: tokenCnt = 0; lastSplit = 0; var splitIndices = new (int i, int tok)[SeparatorWeight.Length];
public string ProcessQuery(IEnumerable <AudioLogEntry> entries, Func <AudioLogEntry, string> format) { //! entryLinesRev[0] is the most recent entry var entryLinesRev = entries.Select(e => { string finStr = format(e); return(new Line { Value = finStr, TokenLength = Ts3String.TokenLength(finStr) }); }); //! entryLines[n] is the most recent entry var entryLines = entryLinesRev.Reverse(); var queryTokenLen = entryLines.Sum(eL => eL.TokenLength + LineBreakLen); StringBuilder strb; // If the entire content fits within the ts3 limitation, we can concat and return it. if (queryTokenLen <= Ts3String.MaxMsgLength) { if (queryTokenLen == 0) { return("Nothing found!"); } strb = new StringBuilder(queryTokenLen, queryTokenLen); // we want the most recent entry at the bottom so we reverse the list foreach (var eL in entryLines) { strb.Append(eL.Value).Append(LineBreak); } return(strb.ToString()); } int spareToken = Ts3String.MaxMsgLength; int listStart = 0; // Otherwise we go iteratively through the list to test how many entries we can add with our token foreach (var eL in entryLinesRev) { // if we don't have enough token to fit in the next entry (even in shorted form) // then we break and use the last few tokens in the next step to fill up. if (spareToken < 0 || (spareToken < MinTokenLine && spareToken < eL.TokenLength)) { break; } // now the further execution is legal because of either of those cases // 1) !(spareToken < MinTokenLine): entry will be trimmed to MinTokenLine and fits // 2) !(spareToken < entryLines[i].TokenLength): entry alreay fits into spareTokens if (eL.TokenLength < MinTokenLine) { spareToken -= eL.TokenLength; listStart++; } else { spareToken -= MinTokenLine; listStart++; } } //! useList[0] is the most recent entry var useList = entryLinesRev.Take(listStart).ToList(); if (fairDistribute) { // If the fairDistribute option is active this loop will start out by trying to give each // entry an equal fraction of all spareToken. for (int i = 0; i < useList.Count; i++) { if (spareToken <= 0) { break; } int fairBonus = spareToken / (useList.Count - i); int available = Math.Min(fairBonus, useList[i].TokenLength); useList[i].BonusToken = available; spareToken -= available; } } else { // Now distribute the remaining tokens by first come first serve in reverse order // so the more recent a entry is the more token it gets foreach (var eL in useList) { if (spareToken <= 0) { break; } if (eL.TokenLength > UseableTokenLine) { int available = Math.Min(spareToken, eL.TokenLength - UseableTokenLine); eL.BonusToken = available; spareToken -= available; } } } // now we can just build our result and return strb = new StringBuilder(Ts3String.MaxMsgLength - spareToken, Ts3String.MaxMsgLength); for (int i = useList.Count - 1; i >= 0; i--) { var eL = useList[i]; if (eL.TokenLength < UseableTokenLine + eL.BonusToken) { strb.Append(eL.Value).Append(LineBreak); } else { strb.Append(SubstringToken(eL.Value, UseableTokenLine + eL.BonusToken)).Append(LineBreak); } } return(strb.ToString()); }
public static IEnumerable <string> Transform(string text, LongTextBehaviour behaviour, int limit = int.MaxValue, int maxMessageSize = Ts3Const.MaxSizeTextMessage) { if (maxMessageSize < 4) { throw new ArgumentOutOfRangeException(nameof(maxMessageSize), "The minimum split length must be at least 4 bytes to fit all utf8 characters"); } // Assuming worst case that each UTF-8 character which epands to 4 bytes. // If the message is still shorter we can safely return in 1 block. if (text.Length * 4 <= Ts3Const.MaxSizeTextMessage) { return new[] { text } } ; var bytes = Encoding.UTF8.GetBytes(text); // If the entire text UTF-8 encoded fits in one message we can return early. if (bytes.Length * 2 < Ts3Const.MaxSizeTextMessage) { return new[] { text } } ; var list = new List <string>(); Span <Ind> splitIndices = stackalloc Ind[SeparatorWeight.Length]; var block = bytes.AsSpan(); while (block.Length > 0) { int tokenCnt = 0; int i = 0; bool filled = false; for (; i < block.Length; i++) { tokenCnt += Ts3String.IsDoubleChar(block[i]) ? 2 : 1; if (tokenCnt > maxMessageSize) { if (behaviour == LongTextBehaviour.Drop) { return(Enumerable.Empty <string>()); } filled = true; break; } for (int j = 0; j < SeparatorWeight.Length; j++) { if (block[i] == SeparatorWeight[j]) { splitIndices[j] = new Ind(i, tokenCnt); } } } if (!filled) { list.Add(block.NewUtf8String()); break; } bool hasSplit = false; if (behaviour != LongTextBehaviour.SplitHard) { for (int j = 0; j < SeparatorWeight.Length; j++) { if (!hasSplit && splitIndices[j].i > 0) { list.Add(block.Slice(0, splitIndices[j].i + 1).NewUtf8String()); block = block.Slice(splitIndices[j].i + 1); hasSplit = true; } } splitIndices.Fill(new Ind()); } if (!hasSplit) { // UTF-8 adjustment while (i > 0 && (block[i] & 0xC0) == 0x80) { i--; } list.Add(block.Slice(0, i).NewUtf8String()); block = block.Slice(i); } if (--limit == 0) { break; } } return(list); }