Expanded mention resolving optionspull/204/head
@@ -14,11 +14,11 @@ namespace Discord.Commands | |||||
private readonly Func<IMessage, IReadOnlyList<object>, Task> _action; | private readonly Func<IMessage, IReadOnlyList<object>, Task> _action; | ||||
public MethodInfo Source { get; } | public MethodInfo Source { get; } | ||||
public Module Module { get; } | |||||
public string Name { get; } | public string Name { get; } | ||||
public string Description { get; } | public string Description { get; } | ||||
public string Summary { get; } | public string Summary { get; } | ||||
public string Text { get; } | public string Text { get; } | ||||
public Module Module { get; } | |||||
public IReadOnlyList<CommandParameter> Parameters { get; } | public IReadOnlyList<CommandParameter> Parameters { get; } | ||||
public IReadOnlyList<PreconditionAttribute> Preconditions { get; } | public IReadOnlyList<PreconditionAttribute> Preconditions { get; } | ||||
@@ -2,7 +2,6 @@ | |||||
using System.Text; | using System.Text; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Linq; | |||||
using System; | using System; | ||||
namespace Discord.Commands | namespace Discord.Commands | ||||
@@ -0,0 +1,9 @@ | |||||
namespace Discord | |||||
{ | |||||
public enum ChannelMentionHandling | |||||
{ | |||||
Ignore = 0, | |||||
Remove, | |||||
Name | |||||
} | |||||
} |
@@ -0,0 +1,9 @@ | |||||
namespace Discord | |||||
{ | |||||
public enum EveryoneMentionHandling | |||||
{ | |||||
Ignore = 0, | |||||
Remove, | |||||
Sanitize | |||||
} | |||||
} |
@@ -43,8 +43,16 @@ namespace Discord | |||||
Task UnpinAsync(); | Task UnpinAsync(); | ||||
/// <summary> Transforms this message's text into a human readable form, resolving things like mentions to that object's name. </summary> | /// <summary> Transforms this message's text into a human readable form, resolving things like mentions to that object's name. </summary> | ||||
string Resolve(int startIndex, int length, UserResolveMode userMode = UserResolveMode.NameOnly); | |||||
string Resolve(int startIndex, int length, | |||||
UserMentionHandling userHandling = UserMentionHandling.Name, | |||||
ChannelMentionHandling channelHandling = ChannelMentionHandling.Name, | |||||
RoleMentionHandling roleHandling = RoleMentionHandling.Name, | |||||
EveryoneMentionHandling everyoneHandling = EveryoneMentionHandling.Ignore); | |||||
/// <summary> Transforms this message's text into a human readable form, resolving things like mentions to that object's name. </summary> | /// <summary> Transforms this message's text into a human readable form, resolving things like mentions to that object's name. </summary> | ||||
string Resolve(UserResolveMode userMode = UserResolveMode.NameOnly); | |||||
string Resolve( | |||||
UserMentionHandling userHandling = UserMentionHandling.Name, | |||||
ChannelMentionHandling channelHandling = ChannelMentionHandling.Name, | |||||
RoleMentionHandling roleHandling = RoleMentionHandling.Name, | |||||
EveryoneMentionHandling everyoneHandling = EveryoneMentionHandling.Ignore); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,9 @@ | |||||
namespace Discord | |||||
{ | |||||
public enum RoleMentionHandling | |||||
{ | |||||
Ignore = 0, | |||||
Remove, | |||||
Name | |||||
} | |||||
} |
@@ -0,0 +1,10 @@ | |||||
namespace Discord | |||||
{ | |||||
public enum UserMentionHandling | |||||
{ | |||||
Ignore = 0, | |||||
Remove, | |||||
Name, | |||||
NameAndDiscriminator | |||||
} | |||||
} |
@@ -1,8 +0,0 @@ | |||||
namespace Discord | |||||
{ | |||||
public enum UserResolveMode | |||||
{ | |||||
NameOnly = 0, | |||||
NameAndDiscriminator | |||||
} | |||||
} |
@@ -161,20 +161,20 @@ namespace Discord | |||||
await Discord.ApiClient.RemovePinAsync(Channel.Id, Id).ConfigureAwait(false); | await Discord.ApiClient.RemovePinAsync(Channel.Id, Id).ConfigureAwait(false); | ||||
} | } | ||||
public string Resolve(int startIndex, int length, UserResolveMode userMode = UserResolveMode.NameOnly) | |||||
=> Resolve(Content.Substring(startIndex, length), userMode); | |||||
public string Resolve(UserResolveMode userMode = UserResolveMode.NameOnly) | |||||
=> Resolve(Content, userMode); | |||||
public string Resolve(int startIndex, int length, UserMentionHandling userHandling, ChannelMentionHandling channelHandling, | |||||
RoleMentionHandling roleHandling, EveryoneMentionHandling everyoneHandling) | |||||
=> Resolve(Content.Substring(startIndex, length), userHandling, channelHandling, roleHandling, everyoneHandling); | |||||
public string Resolve(UserMentionHandling userHandling, ChannelMentionHandling channelHandling, | |||||
RoleMentionHandling roleHandling, EveryoneMentionHandling everyoneHandling) | |||||
=> Resolve(Content, userHandling, channelHandling, roleHandling, everyoneHandling); | |||||
private string Resolve(string text, UserResolveMode userMode = UserResolveMode.NameOnly) | |||||
private string Resolve(string text, UserMentionHandling userHandling, ChannelMentionHandling channelHandling, | |||||
RoleMentionHandling roleHandling, EveryoneMentionHandling everyoneHandling) | |||||
{ | { | ||||
var guild = (Channel as IGuildChannel)?.Guild; | |||||
text = MentionUtils.ResolveUserMentions(text, Channel, MentionedUsers, userMode); | |||||
if (guild != null) | |||||
{ | |||||
text = MentionUtils.ResolveChannelMentions(text, guild); | |||||
text = MentionUtils.ResolveRoleMentions(text, guild, MentionedRoles); | |||||
} | |||||
text = MentionUtils.ResolveUserMentions(text, Channel, MentionedUsers, userHandling); | |||||
text = MentionUtils.ResolveChannelMentions(text, (Channel as IGuildChannel)?.Guild, channelHandling); | |||||
text = MentionUtils.ResolveRoleMentions(text, MentionedRoles, roleHandling); | |||||
text = MentionUtils.ResolveEveryoneMentions(text, everyoneHandling); | |||||
return text; | return text; | ||||
} | } | ||||
@@ -1,4 +1,5 @@ | |||||
using System; | |||||
using Discord.WebSocket; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
using System.Globalization; | using System.Globalization; | ||||
@@ -154,8 +155,10 @@ namespace Discord | |||||
return builder.ToImmutable(); | return builder.ToImmutable(); | ||||
} | } | ||||
internal static string ResolveUserMentions(string text, IMessageChannel channel, IReadOnlyCollection<IUser> mentions, UserResolveMode mode) | |||||
internal static string ResolveUserMentions(string text, IMessageChannel channel, IReadOnlyCollection<IUser> mentions, UserMentionHandling mode) | |||||
{ | { | ||||
if (mode == UserMentionHandling.Ignore) return text; | |||||
return _userRegex.Replace(text, new MatchEvaluator(e => | return _userRegex.Replace(text, new MatchEvaluator(e => | ||||
{ | { | ||||
ulong id; | ulong id; | ||||
@@ -183,10 +186,12 @@ namespace Discord | |||||
switch (mode) | switch (mode) | ||||
{ | { | ||||
case UserResolveMode.NameOnly: | |||||
case UserMentionHandling.Remove: | |||||
default: | default: | ||||
return ""; | |||||
case UserMentionHandling.Name: | |||||
return $"@{name}"; | return $"@{name}"; | ||||
case UserResolveMode.NameAndDiscriminator: | |||||
case UserMentionHandling.NameAndDiscriminator: | |||||
return $"@{name}#{user.Discriminator}"; | return $"@{name}#{user.Discriminator}"; | ||||
} | } | ||||
} | } | ||||
@@ -194,8 +199,10 @@ namespace Discord | |||||
return e.Value; | return e.Value; | ||||
})); | })); | ||||
} | } | ||||
internal static string ResolveChannelMentions(string text, IGuild guild) | |||||
internal static string ResolveChannelMentions(string text, IGuild guild, ChannelMentionHandling mode) | |||||
{ | { | ||||
if (mode == ChannelMentionHandling.Ignore) return text; | |||||
if (guild.IsAttached) //It's too expensive to do a channel lookup in REST mode | if (guild.IsAttached) //It's too expensive to do a channel lookup in REST mode | ||||
{ | { | ||||
return _channelRegex.Replace(text, new MatchEvaluator(e => | return _channelRegex.Replace(text, new MatchEvaluator(e => | ||||
@@ -203,37 +210,68 @@ namespace Discord | |||||
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)) | ||||
{ | { | ||||
IGuildChannel channel = null; | |||||
channel = guild.GetChannelAsync(id).GetAwaiter().GetResult(); | |||||
if (channel != null) | |||||
return '#' + channel.Name; | |||||
switch (mode) | |||||
{ | |||||
case ChannelMentionHandling.Remove: | |||||
return ""; | |||||
case ChannelMentionHandling.Name: | |||||
IGuildChannel channel = null; | |||||
channel = guild?.GetChannel(id); | |||||
if (channel != null) | |||||
return $"#{channel.Name}"; | |||||
else | |||||
return $"#deleted-channel"; | |||||
} | |||||
} | } | ||||
return e.Value; | return e.Value; | ||||
})); | })); | ||||
} | } | ||||
return text; | return text; | ||||
} | } | ||||
internal static string ResolveRoleMentions(string text, IGuild guild, IReadOnlyCollection<IRole> mentions) | |||||
internal static string ResolveRoleMentions(string text, IReadOnlyCollection<IRole> mentions, RoleMentionHandling mode) | |||||
{ | { | ||||
if (mode == RoleMentionHandling.Ignore) return text; | |||||
return _roleRegex.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)) | ||||
{ | { | ||||
IRole role = null; | |||||
foreach (var mention in mentions) | |||||
switch (mode) | |||||
{ | { | ||||
if (mention.Id == id) | |||||
{ | |||||
role = mention; | |||||
break; | |||||
} | |||||
case RoleMentionHandling.Remove: | |||||
return ""; | |||||
case RoleMentionHandling.Name: | |||||
IRole role = null; | |||||
foreach (var mention in mentions) | |||||
{ | |||||
if (mention.Id == id) | |||||
{ | |||||
role = mention; | |||||
break; | |||||
} | |||||
} | |||||
if (role != null) | |||||
return $"@{role.Name}"; | |||||
else | |||||
return $"@deleted-role"; | |||||
} | } | ||||
if (role != null) | |||||
return '@' + role.Name; | |||||
} | } | ||||
return e.Value; | return e.Value; | ||||
})); | })); | ||||
} | } | ||||
internal static string ResolveEveryoneMentions(string text, EveryoneMentionHandling mode) | |||||
{ | |||||
if (mode == EveryoneMentionHandling.Ignore) return text; | |||||
switch (mode) | |||||
{ | |||||
case EveryoneMentionHandling.Sanitize: | |||||
return text.Replace("@everyone", "@\x200beveryone").Replace("@here", "@\x200bhere"); | |||||
case EveryoneMentionHandling.Remove: | |||||
default: | |||||
return text.Replace("@everyone", "").Replace("@here", ""); | |||||
} | |||||
} | |||||
} | } | ||||
} | } |