Browse Source

fix: refactored changes discussed in PR

pull/1253/head
Christopher Felegy 6 years ago
parent
commit
f30f228fb7
13 changed files with 105 additions and 34 deletions
  1. +1
    -1
      src/Discord.Net/Discord.Net.csproj
  2. +13
    -1
      src/Discord.Net/Entities/Emotes/IEmote.cs
  3. +5
    -1
      src/Discord.Net/Entities/Emotes/IGuildEmote.cs
  4. +0
    -7
      src/Discord.Net/Entities/IMentionable.cs
  5. +7
    -0
      src/Discord.Net/Entities/ITaggable.cs
  6. +1
    -1
      src/Discord.Net/Entities/Roles/IRole.cs
  7. +5
    -2
      src/Discord.Net/Models/Emotes/AttachedGuildEmote.cs
  8. +1
    -1
      src/Discord.Net/Models/Emotes/Emoji.cs
  9. +1
    -1
      src/Discord.Net/Models/Emotes/Emote.cs
  10. +47
    -3
      src/Discord.Net/Models/Emotes/EmoteBuilder.cs
  11. +1
    -1
      src/Discord.Net/Models/Roles/Role.cs
  12. +17
    -10
      src/Discord.Net/Utilities/EmoteUtilities.cs
  13. +6
    -5
      test/Discord.Tests.Unit/Utilities/EmoteTests.cs

+ 1
- 1
src/Discord.Net/Discord.Net.csproj View File

@@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>7.1</LangVersion>
<LangVersion>7.3</LangVersion>
</PropertyGroup>

<ItemGroup>


+ 13
- 1
src/Discord.Net/Entities/Emotes/IEmote.cs View File

@@ -1,7 +1,19 @@
namespace Discord
{
public interface IEmote : IMentionable // TODO: Is `Mention` the correct verbage here?
/// <summary>
/// An emote which may be used as a reaction or embedded in chat.
///
/// This includes Unicode emoji as well as unattached guild emotes.
/// </summary>
public interface IEmote : ITaggable
{
/// <summary>
/// The display-name of the emote.
/// </summary>
/// <remarks>
/// For Unicode emoji, this is the raw value of the character, not its
/// Unicode display name.
/// </remarks>
string Name { get; }
}
}

+ 5
- 1
src/Discord.Net/Entities/Emotes/IGuildEmote.cs View File

@@ -3,13 +3,17 @@ using System.Threading.Tasks;

namespace Discord
{
/// <summary>
/// An emote attached to a guild. This differs from an <see cref="IEmote"/> in that it contains
/// information relevant to the source guild.
/// </summary>
public interface IGuildEmote : IEmote, ISnowflakeEntity, IDeletable
{
/// <summary>
/// Gets whether this emoji is managed by an integration.
/// </summary>
/// <returns>
/// A boolean that determines whether or not this emote is managed by a Twitch integration.
/// A boolean that determines whether or not this emote is managed by an external integration, such as Twitch.
/// </returns>
bool IsManaged { get; }
/// <summary>


+ 0
- 7
src/Discord.Net/Entities/IMentionable.cs View File

@@ -1,7 +0,0 @@
namespace Discord
{
public interface IMentionable
{
string Mention { get; }
}
}

+ 7
- 0
src/Discord.Net/Entities/ITaggable.cs View File

@@ -0,0 +1,7 @@
namespace Discord
{
public interface ITaggable
{
string Tag { get; }
}
}

+ 1
- 1
src/Discord.Net/Entities/Roles/IRole.cs View File

@@ -8,7 +8,7 @@ namespace Discord
/// <summary>
/// Represents a generic role object to be given to a guild user.
/// </summary>
public interface IRole : ISnowflakeEntity, IDeletable, IMentionable, IComparable<IRole>
public interface IRole : ISnowflakeEntity, IDeletable, ITaggable, IComparable<IRole>
{
/// <summary>
/// Gets the guild that owns this role.


+ 5
- 2
src/Discord.Net/Models/Emotes/AttachedGuildEmote.cs View File

@@ -22,6 +22,7 @@ namespace Discord
Guild = guild;
}

// IGuildEmote
public bool IsManaged { get; set; }
public bool RequireColons { get; set; }
public IReadOnlyList<IRole> Roles { get; set; }
@@ -29,12 +30,14 @@ namespace Discord
public string Name { get; set; }
public IGuild Guild { get; set; }

// IMentionable
public string Mention => EmoteUtilities.FormatGuildEmote(Id, Name);
// ITaggable
public string Tag => EmoteUtilities.FormatGuildEmote(Id, Name);

// IDeleteable
public Task DeleteAsync()
=> Discord.Rest.DeleteGuildEmojiAsync(Guild.Id, Id);

// IGuildEmote
public Task ModifyAsync() // TODO
{
throw new System.NotImplementedException();


+ 1
- 1
src/Discord.Net/Models/Emotes/Emoji.cs View File

@@ -9,6 +9,6 @@ namespace Discord
}

public string Name { get; set; }
public string Mention => Name;
public string Tag => Name;
}
}

+ 1
- 1
src/Discord.Net/Models/Emotes/Emote.cs View File

@@ -13,6 +13,6 @@ namespace Discord
public ulong Id { get; set; }
public string Name { get; set; }

public string Mention => EmoteUtilities.FormatGuildEmote(Id, Name);
public string Tag => EmoteUtilities.FormatGuildEmote(Id, Name);
}
}

+ 47
- 3
src/Discord.Net/Models/Emotes/EmoteBuilder.cs View File

@@ -2,12 +2,56 @@ using System;

namespace Discord
{
/// <summary>
/// Methods to create an <see cref="IEmote"/>.
/// </summary>
public static class EmoteBuilder
{
public static IEmote FromEmoji(string emoji)
/// <summary>
/// Creates an emote from a raw unicode emoji.
/// </summary>
/// <param name="emoji">The unicode character this emoji should be created from.</param>
public static IEmote FromUnicodeEmoji(string emoji)
=> new Emoji(emoji);
public static IEmote FromMention(string mention)
=> throw new NotImplementedException(); // TODO: emoteutil

/// <summary>
/// Creates an emote from an escaped tag.
/// </summary>
/// <param name="mention">The escaped mention tag for an emote.</param>
/// <exception cref="ArgumentException">Throws if the passed tag was of an invalid format.</exception>
public static IEmote FromTag(string tag)
{
if (EmoteUtilities.TryParseGuildEmote(tag.AsSpan(), out var result))
{
var (id, name) = result;
return new Emote(id, name);
}
throw new ArgumentException("Passed emote tag was of an invalid format", nameof(tag));
}

/// <summary>
/// Creates an emote from an escaped tag.
/// </summary>
/// <param name="tag">The escaped mention tag for an emote.</param>
/// <returns>Returns true if the emote could be created; returns false if it was of an invalid format.</returns>
public static bool TryFromTag(string tag, out IEmote result)
{
if (EmoteUtilities.TryParseGuildEmote(tag.AsSpan(), out var r))
{
var (id, name) = r;
result = new Emote(id, name);
return true;
}

result = default;
return false;
}

/// <summary>
/// Creates an emote from a raw snowflake and name.
/// </summary>
/// <param name="id">The snowflake ID of the guild emote.</param>
/// <param name="name">The name of the guild emote.</param>
public static IEmote FromID(ulong id, string name)
=> new Emote(id, name);
}


+ 1
- 1
src/Discord.Net/Models/Roles/Role.cs View File

@@ -31,7 +31,7 @@ namespace Discord
public string Name { get; set; }
public GuildPermissions Permissions { get; set; }
public int Position { get; set; }
public string Mention => throw new NotImplementedException(); // TODO: MentionUtils
public string Tag => throw new NotImplementedException(); // TODO: MentionUtils

public Task DeleteAsync()
=> Discord.Rest.DeleteGuildRoleAsync(Guild.Id, Id);


+ 17
- 10
src/Discord.Net/Utilities/EmoteUtilities.cs View File

@@ -7,21 +7,28 @@ namespace Discord
public static string FormatGuildEmote(ulong id, string name)
=> $"<:{name}:{id}>";

public static (ulong, string) ParseGuildEmote(string formatted)
// TODO: perf: bench whether this should be passed by ref (in)
public static bool TryParseGuildEmote(ReadOnlySpan<char> formatted, out (ulong, string) result)
{
if (formatted.IndexOf('<') != 0 || formatted.IndexOf(':') != 1 || formatted.IndexOf('>') != formatted.Length-1)
throw new ArgumentException("passed string does not match a guild emote format", nameof(formatted)); // TODO: grammar
result = default;

int closingIndex = formatted.IndexOf(':', 2);
if (formatted.IndexOf('<') != 0 || formatted.IndexOf(':') != 1 || formatted.IndexOf('>') != formatted.Length - 1)
return false;

int closingIndex = formatted.LastIndexOf(':');
if (closingIndex < 0)
throw new ArgumentException("passed string does not match a guild emote format", nameof(formatted));
return false;

ReadOnlySpan<char> name = formatted.Slice(2, closingIndex-2);
ReadOnlySpan<char> idStr = formatted.Slice(closingIndex + 1, formatted.Length - (name.Length + 4));
idStr = idStr.Slice(0, idStr.Length - 1); // ignore closing >

if (!ulong.TryParse(idStr.ToString(), out ulong id))
return false;

string name = formatted.Substring(2, closingIndex-2);
string idStr = formatted.Substring(closingIndex + 1);
idStr = idStr.Substring(0, idStr.Length - 1); // ignore closing >
ulong id = ulong.Parse(idStr); // TODO: TryParse here?
result = (id, name.ToString());

return (id, name);
return true;
}
}
}

+ 6
- 5
test/Discord.Tests.Unit/Utilities/EmoteTests.cs View File

@@ -1,4 +1,3 @@
using System;
using Xunit;

namespace Discord.Tests.Unit
@@ -9,9 +8,10 @@ namespace Discord.Tests.Unit
public void Parse()
{
string input = "<:gopher:243902586946715658>";
var (resultId, resultName) = EmoteUtilities.ParseGuildEmote(input);
Assert.Equal(243902586946715658UL, resultId);
Assert.Equal("gopher", resultName);
var success = EmoteUtilities.TryParseGuildEmote(input, out var result);
var (id, name) = result;
Assert.Equal(243902586946715658UL, id);
Assert.Equal("gopher", name);
}

[Theory]
@@ -21,7 +21,8 @@ namespace Discord.Tests.Unit
[InlineData("<:foo>")]
public void Parse_Fail(string data)
{
Assert.Throws<ArgumentException>(() => EmoteUtilities.ParseGuildEmote(data));
var success = EmoteUtilities.TryParseGuildEmote(data, out _);
Assert.False(success);
}

[Fact]


Loading…
Cancel
Save