Browse Source

Added emoji validation

experiment/emoji-validation
Christopher F 7 years ago
parent
commit
40ba298331
6 changed files with 150 additions and 2 deletions
  1. +16
    -0
      src/Discord.Net.Core/Discord.Net.Core.csproj
  2. +9
    -0
      src/Discord.Net.Core/Entities/Emotes/Emoji.Codepoints.cs
  3. +59
    -0
      src/Discord.Net.Core/Entities/Emotes/Emoji.Codepoints.tt
  4. +30
    -2
      src/Discord.Net.Core/Entities/Emotes/Emoji.cs
  5. +3
    -0
      test/Discord.Net.Tests/Discord.Net.Tests.csproj
  6. +33
    -0
      test/Discord.Net.Tests/Tests.Emotes.cs

+ 16
- 0
src/Discord.Net.Core/Discord.Net.Core.csproj View File

@@ -11,4 +11,20 @@
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="System.Interactive.Async" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
<None Update="Entities\Emotes\Emoji.Codepoints.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Emoji.Codepoints.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<ItemGroup>
<Compile Update="Entities\Emotes\Emoji.Codepoints.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Emoji.Codepoints.tt</DependentUpon>
</Compile>
</ItemGroup>
</Project>

+ 9
- 0
src/Discord.Net.Core/Entities/Emotes/Emoji.Codepoints.cs
File diff suppressed because it is too large
View File


+ 59
- 0
src/Discord.Net.Core/Entities/Emotes/Emoji.Codepoints.tt View File

@@ -0,0 +1,59 @@
<#@ output extension=".cs" #>
<#@ template language="C#" #>
<#@ assembly name="System.Net.Http.dll" #>
<#@ import namespace="System.Net.Http" #>
<#@ assembly name="System.Core.dll" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#
const string DataUrl = "http://www.unicode.org/Public/emoji/6.0/emoji-data.txt";

List<int> codepoints = new List<int>();

void FetchData()
{
var client = new HttpClient();
try
{
var response = client.GetAsync(DataUrl).GetAwaiter().GetResult();
response.EnsureSuccessStatusCode();
string body = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

foreach (var line in body.Split('\n'))
{
if (line.StartsWith("#")) continue;
var split = line.Split(';');
if (split.Length < 1) continue;
var code = split[0].Trim();
if (string.IsNullOrEmpty(code)) continue;
var ranges = code.Split("..".ToCharArray());
if (ranges.Length == 3)
{
var lower = Convert.ToInt32(ranges[0], 16);
var upper = Convert.ToInt32(ranges[2], 16);
codepoints.AddRange(Enumerable.Range(lower, (upper-lower)+1));
}
else
{
var point = Convert.ToInt32(code, 16);
codepoints.Add(point);
}
}
}
catch
{
}
}

FetchData();
#>
namespace Discord
{
public partial class Emoji
{
internal readonly int[] Codepoints = new int[]
{
<# foreach (var codepoint in codepoints) { #><#= codepoint #>, <# } #>
};
}
}

+ 30
- 2
src/Discord.Net.Core/Entities/Emotes/Emoji.cs View File

@@ -1,9 +1,12 @@
namespace Discord
using System;
using System.Text;

namespace Discord
{
/// <summary>
/// A unicode emoji
/// </summary>
public class Emoji : IEmote
public partial class Emoji : IEmote
{
// TODO: need to constrain this to unicode-only emojis somehow

@@ -20,6 +23,31 @@
/// <param name="unicode">The pure UTF-8 encoding of an emoji</param>
public Emoji(string unicode)
{
byte[] utf32 = Encoding.Unicode.GetBytes(unicode);
bool safe = false, any = false;
int codepoint = 0;
for (var i = 0; i < utf32.Length; i += 4)
{
codepoint = BitConverter.ToInt32(utf32, i);
any = false;
for (var j = 0; j < Codepoints.Length; j++)
{
if (Codepoints[j] == codepoint)
{
any = true;
break;
}
}
if (any)
safe = true;
else
{
safe = false;
break;
}
}
if (!safe)
throw new ArgumentException("One or more characters was not a valid Emoji", nameof(unicode));
Name = unicode;
}



+ 3
- 0
test/Discord.Net.Tests/Discord.Net.Tests.csproj View File

@@ -11,6 +11,9 @@
</Content>
</ItemGroup>
<ItemGroup>
<None Include="Tests.Emotes.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../src/Discord.Net.Commands/Discord.Net.Commands.csproj" />
<ProjectReference Include="../../src/Discord.Net.Core/Discord.Net.Core.csproj" />
<ProjectReference Include="../../src/Discord.Net.Rest/Discord.Net.Rest.csproj" />


+ 33
- 0
test/Discord.Net.Tests/Tests.Emotes.cs View File

@@ -0,0 +1,33 @@
using System;
using Xunit;

namespace Discord
{
public class EmoteTests
{
[Fact]
public void Emoji()
{
// Future: Validate emoji parsing
Assert.Equal("🦅", new Emoji("🦅").Name);
}

[Fact]
public void Emote()
{
Assert.Equal(true, Discord.Emote.TryParse("<:foxDab:280494667093508096>", out var emote));
Assert.NotNull(emote);
Assert.Equal("foxDab", emote.Name);
Assert.Equal(280494667093508096UL, emote.Id);
Assert.Equal(DateTimeOffset.FromUnixTimeMilliseconds(1486945539974), emote.CreatedAt);
}
[Fact]
public void Emote_Parse_Fail()
{
Assert.Equal(false, Discord.Emote.TryParse("", out _));
Assert.Equal(false, Discord.Emote.TryParse(":foxDab", out _));
Assert.Equal(false, Discord.Emote.TryParse(":foxDab:", out _));
Assert.Throws<ArgumentException>(() => Discord.Emote.Parse(":foxDab:"));
}
}
}

Loading…
Cancel
Save