Browse Source

Added ordered user mentions, fixed role and channel mention resolving

pull/108/head
RogueException 9 years ago
parent
commit
bfea0ef0a2
4 changed files with 69 additions and 50 deletions
  1. +1
    -0
      src/Discord.Net.Commands/Results/TypeReaderResult.cs
  2. +3
    -3
      src/Discord.Net/Entities/Messages/IMessage.cs
  3. +27
    -23
      src/Discord.Net/Entities/Messages/Message.cs
  4. +38
    -24
      src/Discord.Net/Utilities/MentionUtils.cs

+ 1
- 0
src/Discord.Net.Commands/Results/TypeReaderResult.cs View File

@@ -1,4 +1,5 @@
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices;


namespace Discord.Commands namespace Discord.Commands
{ {


+ 3
- 3
src/Discord.Net/Entities/Messages/IMessage.cs View File

@@ -30,9 +30,9 @@ namespace Discord
IReadOnlyCollection<IEmbed> Embeds { get; } IReadOnlyCollection<IEmbed> Embeds { get; }
/// <summary> Returns a collection of channel ids mentioned in this message. </summary> /// <summary> Returns a collection of channel ids mentioned in this message. </summary>
IReadOnlyCollection<ulong> MentionedChannelIds { get; } IReadOnlyCollection<ulong> MentionedChannelIds { get; }
/// <summary> Returns a collection of role ids mentioned in this message. </summary>
IReadOnlyCollection<ulong> MentionedRoleIds { get; }
/// <summary> Returns a collection of user ids mentioned in this message. </summary>
/// <summary> Returns a collection of roles mentioned in this message. </summary>
IReadOnlyCollection<IRole> MentionedRoles { get; }
/// <summary> Returns a collection of users mentioned in this message. </summary>
IReadOnlyCollection<IUser> MentionedUsers { get; } IReadOnlyCollection<IUser> MentionedUsers { get; }


/// <summary> Modifies this message. </summary> /// <summary> Modifies this message. </summary>


+ 27
- 23
src/Discord.Net/Entities/Messages/Message.cs View File

@@ -23,11 +23,11 @@ namespace Discord
public IMessageChannel Channel { get; } public IMessageChannel Channel { get; }
public IUser Author { get; } public IUser Author { get; }
public ImmutableArray<Attachment> Attachments { get; private set; }
public ImmutableArray<Embed> Embeds { get; private set; }
public ImmutableArray<ulong> MentionedChannelIds { get; private set; }
public ImmutableArray<ulong> MentionedRoleIds { get; private set; }
public ImmutableArray<User> MentionedUsers { get; private set; }
public IReadOnlyCollection<Attachment> Attachments { get; private set; }
public IReadOnlyCollection<IEmbed> Embeds { get; private set; }
public IReadOnlyCollection<ulong> MentionedChannelIds { get; private set; }
public IReadOnlyCollection<IRole> MentionedRoles { get; private set; }
public IReadOnlyCollection<IUser> MentionedUsers { get; private set; }


public override DiscordClient Discord => (Channel as Entity<ulong>).Discord; public override DiscordClient Discord => (Channel as Entity<ulong>).Discord;
public DateTimeOffset? EditedTimestamp => DateTimeUtils.FromTicks(_editedTimestampTicks); public DateTimeOffset? EditedTimestamp => DateTimeUtils.FromTicks(_editedTimestampTicks);
@@ -41,9 +41,9 @@ namespace Discord


if (channel is IGuildChannel) if (channel is IGuildChannel)
{ {
MentionedUsers = ImmutableArray.Create<User>();
MentionedUsers = ImmutableArray.Create<IUser>();
MentionedChannelIds = ImmutableArray.Create<ulong>(); MentionedChannelIds = ImmutableArray.Create<ulong>();
MentionedRoleIds = ImmutableArray.Create<ulong>();
MentionedRoles = ImmutableArray.Create<IRole>();
} }


Update(model, UpdateSource.Creation); Update(model, UpdateSource.Creation);
@@ -106,21 +106,31 @@ namespace Discord
MentionedUsers = ImmutableArray.Create(mentions); MentionedUsers = ImmutableArray.Create(mentions);
} }
else else
MentionedUsers = ImmutableArray.Create<User>();
MentionedUsers = ImmutableArray.Create<IUser>();
} }


if (model.Content.IsSpecified) if (model.Content.IsSpecified)
{ {
RawText = model.Content.Value; RawText = model.Content.Value;
if (Channel is IGuildChannel)
if (guildChannel != null)
{ {
Text = MentionUtils.CleanUserMentions(RawText, MentionedUsers);
MentionedChannelIds = MentionUtils.GetChannelMentions(RawText);
var mentionedRoleIds = MentionUtils.GetRoleMentions(RawText);
if (_isMentioningEveryone)
mentionedRoleIds = mentionedRoleIds.Add(guildChannel.Guild.EveryoneRole.Id);
MentionedRoleIds = mentionedRoleIds;
var orderedMentionedUsers = ImmutableArray.CreateBuilder<IUser>(5);
Text = MentionUtils.CleanUserMentions(RawText, Channel.IsAttached ? Channel : null, MentionedUsers, orderedMentionedUsers);
MentionedUsers = orderedMentionedUsers.ToImmutable();

var roles = ImmutableArray.CreateBuilder<IRole>(5);
Text = MentionUtils.CleanRoleMentions(Text, guildChannel.Guild, roles);
MentionedRoles = roles.ToImmutable();

if (guildChannel.IsAttached) //It's too expensive to do a channel lookup in REST mode
{
var channelIds = ImmutableArray.CreateBuilder<ulong>(5);
Text = MentionUtils.CleanChannelMentions(Text, guildChannel.Guild, channelIds);
MentionedChannelIds = channelIds.ToImmutable();
}
else
MentionedChannelIds = MentionUtils.GetChannelMentions(RawText);
} }
else else
Text = RawText; Text = RawText;
@@ -172,12 +182,6 @@ namespace Discord
} }


public override string ToString() => Text; public override string ToString() => Text;
private string DebuggerDisplay => $"{Author}: {Text}{(Attachments.Length > 0 ? $" [{Attachments.Length} Attachments]" : "")}";

IReadOnlyCollection<Attachment> IMessage.Attachments => Attachments;
IReadOnlyCollection<IEmbed> IMessage.Embeds => Embeds;
IReadOnlyCollection<ulong> IMessage.MentionedChannelIds => MentionedChannelIds;
IReadOnlyCollection<ulong> IMessage.MentionedRoleIds => MentionedRoleIds;
IReadOnlyCollection<IUser> IMessage.MentionedUsers => MentionedUsers;
private string DebuggerDisplay => $"{Author}: {Text}{(Attachments.Count > 0 ? $" [{Attachments.Count} Attachments]" : "")}";
} }
} }

+ 38
- 24
src/Discord.Net/Utilities/MentionUtils.cs View File

@@ -4,6 +4,7 @@ using System.Collections.Immutable;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;


namespace Discord namespace Discord
{ {
@@ -107,7 +108,7 @@ namespace Discord
return builder; return builder;
} }


internal static string CleanUserMentions(string text, ImmutableArray<User> mentions)
/*internal static string CleanUserMentions(string text, ImmutableArray<User> mentions)
{ {
return _userRegex.Replace(text, new MatchEvaluator(e => return _userRegex.Replace(text, new MatchEvaluator(e =>
{ {
@@ -123,58 +124,71 @@ namespace Discord
} }
return e.Value; return e.Value;
})); }));
}
internal static string CleanUserMentions<T>(string text, IReadOnlyDictionary<ulong, T> users, ImmutableArray<T>.Builder mentions = null)
where T : IGuildUser
}*/
internal static string CleanUserMentions(string text, IMessageChannel channel, IReadOnlyCollection<IUser> fallbackUsers, ImmutableArray<IUser>.Builder mentions = null)
{ {
return _channelRegex.Replace(text, new MatchEvaluator(e =>
return _userRegex.Replace(text, new MatchEvaluator(e =>
{ {
ulong id; ulong id;
if (ulong.TryParse(e.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture, out id)) if (ulong.TryParse(e.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture, out id))
{ {
T user;
if (users.TryGetValue(id, out user))
IUser user = null;
if (channel != null)
user = channel.GetUserAsync(id).GetAwaiter().GetResult() as IUser;
if (user == null)
{
foreach (var fallbackUser in fallbackUsers)
{
if (fallbackUser.Id == id)
{
user = fallbackUser;
break;
}
}
}
if (user != null)
{ {
if (users != null)
mentions.Add(user);
if (e.Value[2] == '!' && user.Nickname != null)
return '@' + user.Nickname;
else
return '@' + user.Username;
mentions.Add(user);

if (e.Value[2] == '!')
{
var guildUser = user as IGuildUser;
if (guildUser != null && guildUser.Nickname != null)
return '@' + guildUser.Nickname;
}
return '@' + user.Username;
} }
} }
return e.Value; return e.Value;
})); }));
} }
internal static string CleanChannelMentions<T>(string text, IReadOnlyDictionary<ulong, T> channels, ImmutableArray<T>.Builder mentions = null)
where T : IGuildChannel
internal static string CleanChannelMentions(string text, IGuild guild, ImmutableArray<ulong>.Builder mentions = null)
{ {
return _channelRegex.Replace(text, new MatchEvaluator(e => return _channelRegex.Replace(text, new MatchEvaluator(e =>
{ {
ulong id; ulong id;
if (ulong.TryParse(e.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture, out id)) if (ulong.TryParse(e.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture, out id))
{ {
T channel;
if (channels.TryGetValue(id, out channel))
var channel = guild.GetChannelAsync(id).GetAwaiter().GetResult() as IGuildChannel;
if (channel != null)
{ {
if (channels != null)
mentions.Add(channel);
if (mentions != null)
mentions.Add(channel.Id);
return '#' + channel.Name; return '#' + channel.Name;
} }
} }
return e.Value; return e.Value;
})); }));
} }
internal static string CleanRoleMentions<T>(string text, IReadOnlyDictionary<ulong, T> roles, ImmutableArray<T>.Builder mentions = null)
where T : IRole
internal static string CleanRoleMentions(string text, IGuild guild, ImmutableArray<IRole>.Builder mentions = null)
{ {
return _channelRegex.Replace(text, new MatchEvaluator(e =>
return _roleRegex.Replace(text, new MatchEvaluator(e =>
{ {
ulong id; ulong id;
if (ulong.TryParse(e.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture, out id)) if (ulong.TryParse(e.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture, out id))
{ {
T role;
if (roles.TryGetValue(id, out role))
var role = guild.GetRole(id);
if (role != null)
{ {
if (mentions != null) if (mentions != null)
mentions.Add(role); mentions.Add(role);


Loading…
Cancel
Save