Browse Source

implement a fix for tags being found in code blocks

still needs polish, consider this a rough draft
pull/1318/head
Chris Johnston 6 years ago
parent
commit
7f43a78686
2 changed files with 113 additions and 0 deletions
  1. +69
    -0
      src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs
  2. +44
    -0
      test/Discord.Net.Tests/MessageHelperTests.cs

+ 69
- 0
src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs View File

@@ -98,14 +98,56 @@ namespace Discord.Rest
public static ImmutableArray<ITag> ParseTags(string text, IMessageChannel channel, IGuild guild, IReadOnlyCollection<IUser> userMentions)
{
var tags = ImmutableArray.CreateBuilder<ITag>();

// gets the next index of a codeblock stop/start
int IndexOfCode(int startIndex)
{
// code block has precedence over inline code
var codeIndex = text.IndexOf("```", startIndex);
if (codeIndex != -1)
return codeIndex + 3;
codeIndex = text.IndexOf('`', startIndex);
if (codeIndex != -1)
return codeIndex + 1;
return -1;
}
int index = 0;
int codeBlockIndex = 0;
while (true)
{
index = text.IndexOf('<', index);
if (index == -1) break;
int endIndex = text.IndexOf('>', index + 1);
if (endIndex == -1) break;

int closeIndex = 0;
bool CheckCloseIndex()
=> closeIndex != -1 && closeIndex < index;

// check for code blocks before the start index, of either type
codeBlockIndex = IndexOfCode(codeBlockIndex);
while (codeBlockIndex != -1)
{
// code block opens before this tag
closeIndex = IndexOfCode(codeBlockIndex);
// not closed at all
if (closeIndex == -1)
break;
// closed somewhere after the start index
if (closeIndex > index)
break;
// advance codeblock start index
codeBlockIndex = IndexOfCode(closeIndex);
}
// unclosed code block
if (closeIndex == -1)
break;
// closed somewhere after the start index
if (closeIndex > index)
break;


string content = text.Substring(index, endIndex - index + 1);

if (MentionUtils.TryParseUser(content, out ulong id))
@@ -148,8 +190,35 @@ namespace Discord.Rest
}

index = 0;
codeBlockIndex = 0;
while (true)
{
int closeIndex = 0;
bool CheckCloseIndex()
=> closeIndex != -1 && closeIndex < index;

// check for code blocks before the start index, of either type
codeBlockIndex = IndexOfCode(codeBlockIndex);
while (codeBlockIndex != -1)
{
// code block opens before this tag
closeIndex = IndexOfCode(codeBlockIndex);
// not closed at all
if (closeIndex == -1)
break;
// closed somewhere after the start index
if (closeIndex > index)
break;
// advance codeblock start index
codeBlockIndex = IndexOfCode(closeIndex);
}
// unclosed code block
if (closeIndex == -1)
break;
// closed somewhere after the start index
if (closeIndex > index)
break;

index = text.IndexOf("@everyone", index);
if (index == -1) break;
var tagIndex = FindIndex(tags, index);


+ 44
- 0
test/Discord.Net.Tests/MessageHelperTests.cs View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Discord
{
/// <summary>
/// Tests for <see cref="Discord.Rest.MessageHelper"/> parsing.
/// </summary>
public class MessageHelperTests
{
/// <summary>
/// Tests that no tags work while they are in code blocks.
/// </summary>
[Theory]
[InlineData("`@everyone`")]
[InlineData("`<@&163184946742034432>`")]
[InlineData("```@everyone```")]
[InlineData("```cs \n @everyone```")]
[InlineData("```cs <@&163184946742034432> ```")]
[InlineData("``` test ``` ```cs <@&163184946742034432> ```")]
public void NoTagsInCodeBlocks(string testData)
{
// don't care that I'm passing in null channels/guilds/users
// as they shouldn't be required
var result = Rest.MessageHelper.ParseTags(testData, null, null, null);
Assert.Empty(result);
}

[Theory]
[InlineData("`` <@&163184946742034432>")]
[InlineData("``` test ``` ``` test ``` <@&163184946742034432>")]
public void TagsWork(string testData) // todo better names
{
// don't care that I'm passing in null channels/guilds/users
// as they shouldn't be required
var result = Rest.MessageHelper.ParseTags(testData, null, null, null);
Assert.NotEmpty(result);
}

}
}


Loading…
Cancel
Save