Added new parameter scoring, support multiple matches
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -9,40 +11,37 @@ namespace Discord.Commands
|
||||
{
|
||||
public override async Task<TypeReaderResult> Read(IMessage context, string input)
|
||||
{
|
||||
IGuildChannel guildChannel = context.Channel as IGuildChannel;
|
||||
IChannel result = null;
|
||||
var guild = (context.Channel as IGuildChannel)?.Guild;
|
||||
|
||||
if (guildChannel != null)
|
||||
if (guild != null)
|
||||
{
|
||||
//By Id
|
||||
var results = new Dictionary<ulong, TypeReaderValue>();
|
||||
var channels = await guild.GetChannelsAsync().ConfigureAwait(false);
|
||||
ulong id;
|
||||
if (MentionUtils.TryParseChannel(input, out id) || ulong.TryParse(input, out id))
|
||||
{
|
||||
var channel = await guildChannel.Guild.GetChannelAsync(id).ConfigureAwait(false);
|
||||
if (channel != null)
|
||||
result = channel;
|
||||
}
|
||||
|
||||
//By Name
|
||||
if (result == null)
|
||||
{
|
||||
var channels = await guildChannel.Guild.GetChannelsAsync().ConfigureAwait(false);
|
||||
var filteredChannels = channels.Where(x => string.Equals(input, x.Name, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
if (filteredChannels.Length > 1)
|
||||
return TypeReaderResult.FromError(CommandError.MultipleMatches, "Multiple channels found.");
|
||||
else if (filteredChannels.Length == 1)
|
||||
result = filteredChannels[0];
|
||||
}
|
||||
//By Mention (1.0)
|
||||
if (MentionUtils.TryParseChannel(input, out id))
|
||||
AddResult(results, await guild.GetUserAsync(id).ConfigureAwait(false) as T, 1.00f);
|
||||
|
||||
//By Id (0.9)
|
||||
if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id))
|
||||
AddResult(results, await guild.GetChannelAsync(id).ConfigureAwait(false) as T, 0.90f);
|
||||
|
||||
//By Name (0.7-0.8)
|
||||
foreach (var channel in channels.Where(x => string.Equals(input, x.Name, StringComparison.OrdinalIgnoreCase)))
|
||||
AddResult(results, channel as T, channel.Name == input ? 0.80f : 0.70f);
|
||||
|
||||
if (results.Count > 0)
|
||||
return TypeReaderResult.FromSuccess(results.Values);
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
return TypeReaderResult.FromError(CommandError.ObjectNotFound, "Channel not found.");
|
||||
return TypeReaderResult.FromError(CommandError.ObjectNotFound, "Channel not found.");
|
||||
}
|
||||
|
||||
T castResult = result as T;
|
||||
if (castResult == null)
|
||||
return TypeReaderResult.FromError(CommandError.CastFailed, $"Channel is not a {typeof(T).Name}.");
|
||||
else
|
||||
return TypeReaderResult.FromSuccess(castResult);
|
||||
private void AddResult(Dictionary<ulong, TypeReaderValue> results, T channel, float score)
|
||||
{
|
||||
if (channel != null && !results.ContainsKey(channel.Id))
|
||||
results.Add(channel.Id, new TypeReaderValue(channel, score));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,14 +52,14 @@ namespace Discord.Commands
|
||||
if (_enumsByValue.TryGetValue(baseValue, out enumValue))
|
||||
return Task.FromResult(TypeReaderResult.FromSuccess(enumValue));
|
||||
else
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.CastFailed, $"Value is not a {_enumType.Name}"));
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Value is not a {_enumType.Name}"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_enumsByName.TryGetValue(input.ToLower(), out enumValue))
|
||||
return Task.FromResult(TypeReaderResult.FromSuccess(enumValue));
|
||||
else
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.CastFailed, $"Value is not a {_enumType.Name}"));
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Value is not a {_enumType.Name}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,18 +7,17 @@ namespace Discord.Commands
|
||||
{
|
||||
public override Task<TypeReaderResult> Read(IMessage context, string input)
|
||||
{
|
||||
//By Id
|
||||
ulong id;
|
||||
|
||||
//By Id (1.0)
|
||||
if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id))
|
||||
{
|
||||
var msg = context.Channel.GetCachedMessage(id);
|
||||
if (msg == null)
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ObjectNotFound, "Message not found."));
|
||||
else
|
||||
if (msg != null)
|
||||
return Task.FromResult(TypeReaderResult.FromSuccess(msg));
|
||||
}
|
||||
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse Message Id."));
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ObjectNotFound, "Message not found."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Commands
|
||||
{
|
||||
internal class RoleTypeReader : TypeReader
|
||||
internal class RoleTypeReader<T> : TypeReader
|
||||
where T : class, IRole
|
||||
{
|
||||
public override Task<TypeReaderResult> Read(IMessage context, string input)
|
||||
{
|
||||
IGuildChannel guildChannel = context.Channel as IGuildChannel;
|
||||
var guild = (context.Channel as IGuildChannel)?.Guild;
|
||||
ulong id;
|
||||
|
||||
if (guildChannel != null)
|
||||
if (guild != null)
|
||||
{
|
||||
//By Id
|
||||
ulong id;
|
||||
if (MentionUtils.TryParseRole(input, out id) || ulong.TryParse(input, out id))
|
||||
{
|
||||
var channel = guildChannel.Guild.GetRole(id);
|
||||
if (channel != null)
|
||||
return Task.FromResult(TypeReaderResult.FromSuccess(channel));
|
||||
}
|
||||
var results = new Dictionary<ulong, TypeReaderValue>();
|
||||
var roles = guild.Roles;
|
||||
|
||||
//By Name
|
||||
var roles = guildChannel.Guild.Roles;
|
||||
var filteredRoles = roles.Where(x => string.Equals(input, x.Name, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
if (filteredRoles.Length > 1)
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.MultipleMatches, "Multiple roles found."));
|
||||
else if (filteredRoles.Length == 1)
|
||||
return Task.FromResult(TypeReaderResult.FromSuccess(filteredRoles[0]));
|
||||
//By Mention (1.0)
|
||||
if (MentionUtils.TryParseRole(input, out id))
|
||||
AddResult(results, guild.GetRole(id) as T, 1.00f);
|
||||
|
||||
//By Id (0.9)
|
||||
if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id))
|
||||
AddResult(results, guild.GetRole(id) as T, 0.90f);
|
||||
|
||||
//By Name (0.7-0.8)
|
||||
foreach (var role in roles.Where(x => string.Equals(input, x.Name, StringComparison.OrdinalIgnoreCase)))
|
||||
AddResult(results, role as T, role.Name == input ? 0.80f : 0.70f);
|
||||
|
||||
if (results.Count > 0)
|
||||
return Task.FromResult(TypeReaderResult.FromSuccess(results));
|
||||
}
|
||||
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ObjectNotFound, "Role not found."));
|
||||
}
|
||||
|
||||
private void AddResult(Dictionary<ulong, TypeReaderValue> results, T role, float score)
|
||||
{
|
||||
if (role != null && !results.ContainsKey(role.Id))
|
||||
results.Add(role.Id, new TypeReaderValue(role, score));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace Discord.Commands
|
||||
T value;
|
||||
if (_tryParse(input, out value))
|
||||
return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
||||
else
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Failed to parse {typeof(T).Name}"));
|
||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Failed to parse {typeof(T).Name}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -9,54 +11,78 @@ namespace Discord.Commands
|
||||
{
|
||||
public override async Task<TypeReaderResult> Read(IMessage context, string input)
|
||||
{
|
||||
IUser result = null;
|
||||
|
||||
//By Id
|
||||
var results = new Dictionary<ulong, TypeReaderValue>();
|
||||
var guild = (context.Channel as IGuildChannel)?.Guild;
|
||||
IReadOnlyCollection<IUser> channelUsers = await context.Channel.GetUsersAsync().ConfigureAwait(false);
|
||||
IReadOnlyCollection<IGuildUser> guildUsers = null;
|
||||
ulong id;
|
||||
if (MentionUtils.TryParseUser(input, out id) || ulong.TryParse(input, out id))
|
||||
|
||||
if (guild != null)
|
||||
guildUsers = await guild.GetUsersAsync().ConfigureAwait(false);
|
||||
|
||||
//By Mention (1.0)
|
||||
if (MentionUtils.TryParseUser(input, out id))
|
||||
{
|
||||
var user = await context.Channel.GetUserAsync(id).ConfigureAwait(false);
|
||||
if (user != null)
|
||||
result = user;
|
||||
if (guild != null)
|
||||
AddResult(results, await guild.GetUserAsync(id).ConfigureAwait(false) as T, 1.00f);
|
||||
else
|
||||
AddResult(results, await context.Channel.GetUserAsync(id).ConfigureAwait(false) as T, 1.00f);
|
||||
}
|
||||
|
||||
//By Username + Discriminator
|
||||
if (result == null)
|
||||
//By Id (0.9)
|
||||
if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id))
|
||||
{
|
||||
int index = input.LastIndexOf('#');
|
||||
if (index >= 0)
|
||||
if (guild != null)
|
||||
AddResult(results, await guild.GetUserAsync(id).ConfigureAwait(false) as T, 0.90f);
|
||||
else
|
||||
AddResult(results, await context.Channel.GetUserAsync(id).ConfigureAwait(false) as T, 0.90f);
|
||||
}
|
||||
|
||||
//By Username + Discriminator (0.7-0.85)
|
||||
int index = input.LastIndexOf('#');
|
||||
if (index >= 0)
|
||||
{
|
||||
string username = input.Substring(0, index);
|
||||
ushort discriminator;
|
||||
if (ushort.TryParse(input.Substring(index + 1), out discriminator))
|
||||
{
|
||||
string username = input.Substring(0, index);
|
||||
ushort discriminator;
|
||||
if (ushort.TryParse(input.Substring(index + 1), out discriminator))
|
||||
{
|
||||
var users = await context.Channel.GetUsersAsync().ConfigureAwait(false);
|
||||
result = users.Where(x =>
|
||||
x.DiscriminatorValue == discriminator &&
|
||||
string.Equals(username, x.Username, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
|
||||
}
|
||||
var channelUser = channelUsers.Where(x => x.DiscriminatorValue == discriminator &&
|
||||
string.Equals(username, x.Username, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
|
||||
AddResult(results, channelUser as T, channelUser.Username == username ? 0.85f : 0.75f);
|
||||
|
||||
var guildUser = channelUsers.Where(x => x.DiscriminatorValue == discriminator &&
|
||||
string.Equals(username, x.Username, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
|
||||
AddResult(results, guildUser as T, guildUser.Username == username ? 0.80f : 0.70f);
|
||||
}
|
||||
}
|
||||
|
||||
//By Username
|
||||
if (result == null)
|
||||
//By Username (0.5-0.6)
|
||||
{
|
||||
var users = await context.Channel.GetUsersAsync().ConfigureAwait(false);
|
||||
var filteredUsers = users.Where(x => string.Equals(input, x.Username, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
if (filteredUsers.Length > 1)
|
||||
return TypeReaderResult.FromError(CommandError.MultipleMatches, "Multiple users found.");
|
||||
else if (filteredUsers.Length == 1)
|
||||
result = filteredUsers[0];
|
||||
foreach (var channelUser in channelUsers.Where(x => string.Equals(input, x.Username, StringComparison.OrdinalIgnoreCase)))
|
||||
AddResult(results, channelUser as T, channelUser.Username == input ? 0.65f : 0.55f);
|
||||
|
||||
foreach (var guildUser in guildUsers.Where(x => string.Equals(input, x.Username, StringComparison.OrdinalIgnoreCase)))
|
||||
AddResult(results, guildUser as T, guildUser.Username == input ? 0.60f : 0.50f);
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
return TypeReaderResult.FromError(CommandError.ObjectNotFound, "User not found.");
|
||||
//By Nickname (0.5-0.6)
|
||||
{
|
||||
foreach (var channelUser in channelUsers.Where(x => string.Equals(input, (x as IGuildUser).Nickname, StringComparison.OrdinalIgnoreCase)))
|
||||
AddResult(results, channelUser as T, (channelUser as IGuildUser).Nickname == input ? 0.65f : 0.55f);
|
||||
|
||||
T castResult = result as T;
|
||||
if (castResult == null)
|
||||
return TypeReaderResult.FromError(CommandError.CastFailed, $"User is not a {typeof(T).Name}.");
|
||||
else
|
||||
return TypeReaderResult.FromSuccess(castResult);
|
||||
foreach (var guildUser in guildUsers.Where(x => string.Equals(input, (x as IGuildUser).Nickname, StringComparison.OrdinalIgnoreCase)))
|
||||
AddResult(results, guildUser as T, (guildUser as IGuildUser).Nickname == input ? 0.60f : 0.50f);
|
||||
}
|
||||
|
||||
if (results.Count > 0)
|
||||
return TypeReaderResult.FromSuccess(results.Values.ToArray());
|
||||
return TypeReaderResult.FromError(CommandError.ObjectNotFound, "User not found.");
|
||||
}
|
||||
|
||||
private void AddResult(Dictionary<ulong, TypeReaderValue> results, T user, float score)
|
||||
{
|
||||
if (user != null && !results.ContainsKey(user.Id))
|
||||
results.Add(user.Id, new TypeReaderValue(user, score));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user