Reworked the mention system
This commit is contained in:
@@ -93,7 +93,6 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
||||||
if (text == null) throw new ArgumentNullException(nameof(text));
|
if (text == null) throw new ArgumentNullException(nameof(text));
|
||||||
if (text.Length > MaxMessageSize) throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less.");
|
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return SendMessage(channel, text, false);
|
return SendMessage(channel, text, false);
|
||||||
@@ -103,7 +102,6 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
||||||
if (text == null) throw new ArgumentNullException(nameof(text));
|
if (text == null) throw new ArgumentNullException(nameof(text));
|
||||||
if (text.Length > MaxMessageSize) throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less.");
|
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return SendMessage(channel, text, false);
|
return SendMessage(channel, text, false);
|
||||||
@@ -113,7 +111,6 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||||
if (text == null) throw new ArgumentNullException(nameof(text));
|
if (text == null) throw new ArgumentNullException(nameof(text));
|
||||||
if (text.Length > MaxMessageSize) throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less.");
|
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
var channel = await CreatePMChannel(user).ConfigureAwait(false);
|
var channel = await CreatePMChannel(user).ConfigureAwait(false);
|
||||||
@@ -122,10 +119,10 @@ namespace Discord
|
|||||||
private async Task<Message> SendMessage(Channel channel, string text, bool isTextToSpeech)
|
private async Task<Message> SendMessage(Channel channel, string text, bool isTextToSpeech)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
var userIds = !channel.IsPrivate ? Mention.GetUserIds(text).Distinct() : new string[0];
|
var server = channel.Server;
|
||||||
|
|
||||||
if (Config.UseMessageQueue)
|
if (Config.UseMessageQueue)
|
||||||
{
|
{
|
||||||
var channelIds = !channel.IsPrivate ? Mention.GetChannelIds(text).Distinct() : new string[0];
|
|
||||||
var nonce = GenerateNonce();
|
var nonce = GenerateNonce();
|
||||||
msg = _messages.GetOrAdd("nonce_" + nonce, channel.Id, _userId);
|
msg = _messages.GetOrAdd("nonce_" + nonce, channel.Id, _userId);
|
||||||
var currentUser = msg.User;
|
var currentUser = msg.User;
|
||||||
@@ -140,21 +137,21 @@ namespace Discord
|
|||||||
msg.Nonce = nonce;
|
msg.Nonce = nonce;
|
||||||
msg.IsQueued = true;
|
msg.IsQueued = true;
|
||||||
|
|
||||||
//IsPrivate check is already done earlier
|
if (text.Length > MaxMessageSize)
|
||||||
msg.MentionedUsers = userIds
|
throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less.");
|
||||||
.Select(x => _users[x, channel.Server.Id])
|
|
||||||
.Where(x => x != null)
|
|
||||||
.ToArray();
|
|
||||||
msg.MentionedChannels = channelIds
|
|
||||||
.Select(x => _channels[x])
|
|
||||||
.Where(x => x != null && x.Server == channel.Server)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
_pendingMessages.Enqueue(msg);
|
_pendingMessages.Enqueue(msg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var model = await _api.SendMessage(channel.Id, text, userIds, null, isTextToSpeech).ConfigureAwait(false);
|
var mentionedUsers = new List<User>();
|
||||||
|
if (!channel.IsPrivate)
|
||||||
|
text = Mention.CleanUserMentions(this, server, text, mentionedUsers);
|
||||||
|
|
||||||
|
if (text.Length > MaxMessageSize)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less.");
|
||||||
|
|
||||||
|
var model = await _api.SendMessage(channel.Id, text, mentionedUsers.Select(x => x.Id), null, isTextToSpeech).ConfigureAwait(false);
|
||||||
msg = _messages.GetOrAdd(model.Id, channel.Id, model.Author.Id);
|
msg = _messages.GetOrAdd(model.Id, channel.Id, model.Author.Id);
|
||||||
msg.Update(model);
|
msg.Update(model);
|
||||||
RaiseMessageSent(msg);
|
RaiseMessageSent(msg);
|
||||||
@@ -179,13 +176,17 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
if (message == null) throw new ArgumentNullException(nameof(message));
|
if (message == null) throw new ArgumentNullException(nameof(message));
|
||||||
if (text == null) throw new ArgumentNullException(nameof(text));
|
if (text == null) throw new ArgumentNullException(nameof(text));
|
||||||
if (text.Length > MaxMessageSize) throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less.");
|
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
if (text != null && text.Length > MaxMessageSize)
|
var channel = message.Channel;
|
||||||
text = text.Substring(0, MaxMessageSize);
|
var mentionedUsers = new List<User>();
|
||||||
|
if (!channel.IsPrivate)
|
||||||
|
text = Mention.CleanUserMentions(this, channel.Server, text, mentionedUsers);
|
||||||
|
|
||||||
return _api.EditMessage(message.Id, message.Channel.Id, text, Mention.GetUserIds(text));
|
if (text.Length > MaxMessageSize)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less.");
|
||||||
|
|
||||||
|
return _api.EditMessage(message.Id, message.Channel.Id, text, mentionedUsers.Select(x => x.Id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Deletes the provided message. </summary>
|
/// <summary> Deletes the provided message. </summary>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
private static readonly Regex _userRegex = new Regex(@"<@([0-9]+?)>", RegexOptions.Compiled);
|
private static readonly Regex _userRegex = new Regex(@"<@([0-9]+?)>", RegexOptions.Compiled);
|
||||||
private static readonly Regex _channelRegex = new Regex(@"<#([0-9]+?)>", RegexOptions.Compiled);
|
private static readonly Regex _channelRegex = new Regex(@"<#([0-9]+?)>", RegexOptions.Compiled);
|
||||||
|
private static readonly Regex _roleRegex = new Regex(@"@everyone", RegexOptions.Compiled);
|
||||||
|
|
||||||
/// <summary> Returns the string used to create a user mention. </summary>
|
/// <summary> Returns the string used to create a user mention. </summary>
|
||||||
public static string User(User user)
|
public static string User(User user)
|
||||||
@@ -19,45 +20,45 @@ namespace Discord
|
|||||||
public static string Everyone()
|
public static string Everyone()
|
||||||
=> $"@everyone";
|
=> $"@everyone";
|
||||||
|
|
||||||
internal static string ConvertToNames(DiscordClient client, Server server, string text)
|
internal static string CleanUserMentions(DiscordClient client, Server server, string text, List<User> users = null)
|
||||||
{
|
{
|
||||||
text = _userRegex.Replace(text, new MatchEvaluator(e =>
|
return _userRegex.Replace(text, new MatchEvaluator(e =>
|
||||||
{
|
{
|
||||||
string id = e.Value.Substring(2, e.Value.Length - 3);
|
string id = e.Value.Substring(2, e.Value.Length - 3);
|
||||||
var user = client.Users[id, server?.Id];
|
var user = client.Users[id, server?.Id];
|
||||||
if (user != null)
|
if (user != null)
|
||||||
|
{
|
||||||
|
if (users != null)
|
||||||
|
users.Add(user);
|
||||||
return '@' + user.Name;
|
return '@' + user.Name;
|
||||||
|
}
|
||||||
else //User not found
|
else //User not found
|
||||||
return '@' + e.Value;
|
return '@' + e.Value;
|
||||||
}));
|
}));
|
||||||
if (server != null)
|
}
|
||||||
|
internal static string CleanChannelMentions(DiscordClient client, Server server, string text, List<Channel> channels = null)
|
||||||
|
{
|
||||||
|
return _channelRegex.Replace(text, new MatchEvaluator(e =>
|
||||||
{
|
{
|
||||||
text = _channelRegex.Replace(text, new MatchEvaluator(e =>
|
string id = e.Value.Substring(2, e.Value.Length - 3);
|
||||||
|
var channel = client.Channels[id];
|
||||||
|
if (channel != null && channel.Server.Id == server.Id)
|
||||||
{
|
{
|
||||||
string id = e.Value.Substring(2, e.Value.Length - 3);
|
if (channels != null)
|
||||||
var channel = client.Channels[id];
|
channels.Add(channel);
|
||||||
if (channel != null && channel.Server.Id == server.Id)
|
return '#' + channel.Name;
|
||||||
return '#' + channel.Name;
|
}
|
||||||
else //Channel not found
|
else //Channel not found
|
||||||
return '#' + e.Value;
|
return '#' + e.Value;
|
||||||
}));
|
}));
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
internal static string CleanRoleMentions(DiscordClient client, Server server, string text, List<Role> roles = null)
|
||||||
internal static IEnumerable<string> GetUserIds(string text)
|
|
||||||
{
|
{
|
||||||
return _userRegex.Matches(text)
|
return _roleRegex.Replace(text, new MatchEvaluator(e =>
|
||||||
.OfType<Match>()
|
{
|
||||||
.Select(x => x.Groups[1].Value)
|
roles.Add(server.EveryoneRole);
|
||||||
.Where(x => x != null);
|
return e.Value;
|
||||||
}
|
}));
|
||||||
internal static IEnumerable<string> GetChannelIds(string text)
|
|
||||||
{
|
|
||||||
return _channelRegex.Matches(text)
|
|
||||||
.OfType<Match>()
|
|
||||||
.Select(x => x.Groups[1].Value)
|
|
||||||
.Where(x => x != null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,9 +90,7 @@ namespace Discord
|
|||||||
Height = height;
|
Height = height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _cleanText;
|
|
||||||
|
|
||||||
/// <summary> Returns the local unique identifier for this message. </summary>
|
/// <summary> Returns the local unique identifier for this message. </summary>
|
||||||
public string Nonce { get; internal set; }
|
public string Nonce { get; internal set; }
|
||||||
|
|
||||||
@@ -110,8 +108,7 @@ namespace Discord
|
|||||||
/// <summary> Returns the raw content of this message as it was received from the server.. </summary>
|
/// <summary> Returns the raw content of this message as it was received from the server.. </summary>
|
||||||
public string RawText { get; private set; }
|
public string RawText { get; private set; }
|
||||||
/// <summary> Returns the content of this message with any special references such as mentions converted. </summary>
|
/// <summary> Returns the content of this message with any special references such as mentions converted. </summary>
|
||||||
/// <remarks> This value is lazy loaded and only processed on first request. Each subsequent request will pull from cache. </remarks>
|
public string Text { get; private set; }
|
||||||
public string Text => _cleanText != null ? _cleanText : (_cleanText = Mention.ConvertToNames(_client, Server, RawText));
|
|
||||||
/// <summary> Returns the timestamp for when this message was sent. </summary>
|
/// <summary> Returns the timestamp for when this message was sent. </summary>
|
||||||
public DateTime Timestamp { get; private set; }
|
public DateTime Timestamp { get; private set; }
|
||||||
/// <summary> Returns the timestamp for when this message was last edited. </summary>
|
/// <summary> Returns the timestamp for when this message was last edited. </summary>
|
||||||
@@ -131,6 +128,10 @@ namespace Discord
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Channel> MentionedChannels { get; internal set; }
|
public IEnumerable<Channel> MentionedChannels { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary> Returns a collection of all roles mentioned in this message. </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public IEnumerable<Role> MentionedRoles { get; internal set; }
|
||||||
|
|
||||||
/// <summary> Returns the server containing the channel this message was sent to. </summary>
|
/// <summary> Returns the server containing the channel this message was sent to. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Server Server => _channel.Value.Server;
|
public Server Server => _channel.Value.Server;
|
||||||
@@ -220,18 +221,23 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
if (model.Content != null)
|
if (model.Content != null)
|
||||||
{
|
{
|
||||||
RawText = model.Content;
|
var server = Server;
|
||||||
_cleanText = null;
|
string text = model.Content;
|
||||||
|
RawText = text;
|
||||||
if (!Channel.IsPrivate)
|
|
||||||
|
//var mentionedUsers = new List<User>();
|
||||||
|
var mentionedChannels = new List<Channel>();
|
||||||
|
var mentionedRoles = new List<Role>();
|
||||||
|
text = Mention.CleanUserMentions(_client, server, text/*, mentionedUsers*/);
|
||||||
|
if (server != null)
|
||||||
{
|
{
|
||||||
MentionedChannels = Mention.GetChannelIds(model.Content)
|
text = Mention.CleanChannelMentions(_client, server, text, mentionedChannels);
|
||||||
.Select(x => _client.Channels[x])
|
text = Mention.CleanRoleMentions(_client, server, text, mentionedRoles);
|
||||||
.Where(x => x.Server == Channel.Server)
|
|
||||||
.ToArray();
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
MentionedChannels = new Channel[0];
|
//MentionedUsers = mentionedUsers;
|
||||||
|
MentionedChannels = mentionedChannels;
|
||||||
|
MentionedRoles = mentionedRoles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user