Compare commits

...

Author SHA1 Message Date
  Christopher F ac9b575230 Clean up Emoji validation 7 years ago
  Christopher F 40ba298331 Added emoji validation 7 years ago
6 changed files with 169 additions and 2 deletions
Split View
  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. +28
    -2
      src/Discord.Net.Core/Entities/Emotes/Emoji.cs
  5. +3
    -0
      test/Discord.Net.Tests/Discord.Net.Tests.csproj
  6. +54
    -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 #>, <# } #>
};
}
}

+ 28
- 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,29 @@
/// <param name="unicode">The pure UTF-8 encoding of an emoji</param>
public Emoji(string unicode)
{
// NETStandard1.1 doesn't support UTF32
#if !NETSTANDARD1_1
byte[] utf32 = Encoding.UTF32.GetBytes(unicode);
for (var i = 0; i < utf32.Length; i += 4)
{
int codepoint = BitConverter.ToInt32(utf32, i);
bool any = false;

for (var j = 0; j < Codepoints.Length; j++)
{
if (Codepoints[j] == codepoint)
{
any = true;
break;
}
}

if (any) continue;
else
throw new ArgumentException("One or more characters was not a valid Emoji", nameof(unicode));
}
#endif

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" />


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

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

namespace Discord
{
public class EmoteTests
{
const string Smiley = "\U0001F603";
const string Man = "\U0001F468";
const string Woman = "\U0001F469";
const string Girl = "\U0001F467";
const string Boy = "\U0001F466";
const string Join = "\u200D";

[Fact]
public void Single_Emoji()
{
Assert.Equal(Smiley, new Emoji(Smiley).Name);
Assert.Equal(Man, new Emoji(Man).Name);
Assert.Equal(Woman, new Emoji(Woman).Name);
Assert.Equal(Girl, new Emoji(Girl).Name);
Assert.Equal(Boy, new Emoji(Boy).Name);
}
[Fact]
public void Multipart_Emoji()
{
string family = string.Concat(Man, Join, Woman, Join, Girl, Join, Boy);
Assert.Equal(family, new Emoji(family).Name);
}
[Fact]
public void Emoji_Fail()
{
Assert.Throws<ArgumentException>(() => new Emoji("foxDab"));
}

[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