public static async Task <PostPiece[]> ParseToPost(SourceType sourceType, string source) { var text = sourceType switch { SourceType.Link => await WebUtils.DownloadString(source), _ => source, }; //Parse emotes text = regexEmotes.Replace(text, match => BotUtils.TryGetEmote(match.Groups[1].Value, out string emoteText) ? emoteText : match.Value); var postPieces = new List <PostPiece> { new TextPostPiece(text) }; int tagsParsed = 0; for (int i = 0; i < postPieces.Count; i++) { var piece = postPieces[i]; if (piece.GetType() != typeof(TextPostPiece) || !(piece is TextPostPiece textPiece)) { continue; } var match = regexTags.Match(textPiece.text); if (!match.Success) { continue; } if (textPiece.text == null) { throw new BotError($"textPiece.text is null, i is {i}"); } int matchIndex = match.Index; string type = match.Groups[1].Value.ToLower(); textPiece.text = textPiece.text.Remove(matchIndex, match.Value.Length); string GetGroup(int index) { var group = match.Groups[index]; if (!group.Success) { throw new BotError($"Failed to parse tag #{1+tagsParsed} ({type}): Missing group #{index}."); } return(group.Value); } bool split = false; PostPiece newPiece = null; switch (type) { case "split": split = true; break; case "image": string url = GetGroup(2); string filename = BotUtils.GetValidFileName($"TempFile_{url}"); await WebUtils.DownloadFile(GetGroup(2), filename); newPiece = new FilePostPiece(filename, true); split = true; break; default: throw new BotError($"Invalid tag type: '{type}'."); } tagsParsed++; if (split) { string leftText = matchIndex >= textPiece.text.Length ? null : textPiece.text.Remove(matchIndex); string rightText = matchIndex >= textPiece.text.Length ? null : textPiece.text.Substring(matchIndex); if (rightText == null) { if (newPiece != null) { postPieces[i] = newPiece; } continue; } if (string.IsNullOrWhiteSpace(leftText)) { if (newPiece != null) { postPieces.Insert(i, newPiece); } textPiece.text = rightText; } else { textPiece.text = leftText; if (newPiece != null) { postPieces.Add(newPiece); } postPieces.Add(new TextPostPiece(rightText)); } } } return(postPieces.ToArray()); }