From d98b9c961a66e6180c6474904f126ade5aa28796 Mon Sep 17 00:00:00 2001 From: Khionu Terabite Date: Tue, 6 Sep 2016 16:50:30 -0400 Subject: [PATCH] Added case insensitivity option to CommandService.Search() --- src/Discord.Net.Commands/CommandService.cs | 14 ++-- .../Extensions/FindEntityExtensions.cs | 69 +++++++++++++++++++ 2 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 src/Discord.Net/Extensions/FindEntityExtensions.cs diff --git a/src/Discord.Net.Commands/CommandService.cs b/src/Discord.Net.Commands/CommandService.cs index 814277b04..03e2d2648 100644 --- a/src/Discord.Net.Commands/CommandService.cs +++ b/src/Discord.Net.Commands/CommandService.cs @@ -176,12 +176,16 @@ namespace Discord.Commands return false; } - public SearchResult Search(IUserMessage message, int argPos) => Search(message, message.Content.Substring(argPos)); - public SearchResult Search(IUserMessage message, string input) + public SearchResult Search(IUserMessage message, int argPos, bool caseInsensitive = true) => Search(message, message.Content.Substring(argPos), caseInsensitive); + public SearchResult Search(IUserMessage message, string input, bool caseInsensitive = true) { - string lowerInput = input.ToLowerInvariant(); - var matches = _map.GetCommands(input).ToImmutableArray(); - + ImmutableArray matches; + + if (caseInsensitive) + matches = _map.GetCommands(input.ToLowerInvariant()).ToImmutableArray(); + else + matches = _map.GetCommands(input).ToImmutableArray(); + if (matches.Length > 0) return SearchResult.FromSuccess(input, matches); else diff --git a/src/Discord.Net/Extensions/FindEntityExtensions.cs b/src/Discord.Net/Extensions/FindEntityExtensions.cs new file mode 100644 index 000000000..9a2c276b3 --- /dev/null +++ b/src/Discord.Net/Extensions/FindEntityExtensions.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Discord.Extensions +{ + public static class FindEntityExtensions + { + // Guilds + + public static async Task> FindUsersAsync(this IGuild guild, string name) + => (await guild.GetUsersAsync()).Where(x => distance(name, x.Username) < 5); + + public static IEnumerable FindRoles(this IGuild guild, string name) + => guild.Roles.Where(x => distance(name, x.Name) < 5); + + public static async Task> FindChannels(this IGuild guild, string name) + => (await guild.GetChannelsAsync()).Where(x => distance(name, x.Name) < 5); + + public static async Task> FindTextChannels(this IGuild guild, string name) + => (await guild.GetChannelsAsync()).Select(x => x as ITextChannel) + .Where(x => x != null).Where(x => distance(name, x.Name) < 5); + + public static async Task> FindVoiceChannels(this IGuild guild, string name) + => (await guild.GetChannelsAsync()).Select(x => x as IVoiceChannel) + .Where(x => x != null).Where(x => distance(name, x.Name) < 5); + + // Channels + + public static async Task> FindUsersAsync(this IChannel channel, string name) + => (await channel.GetUsersAsync()).Where(x => distance(name, x.Username) < 5); + + /// + /// Compute the distance between two strings. + /// Copied from DotNetPerls + /// + private static int distance(string s, string t) + { + int n = s.Length; + int m = t.Length; + int[,] d = new int[n + 1, m + 1]; + + if (n == 0) + return m; + + if (m == 0) + return n; + + for (int i = 0; i <= n; d[i, 0] = i++) { } + + for (int j = 0; j <= m; d[0, j] = j++) { } + + for (int i = 1; i <= n; i++) + { + for (int j = 1; j <= m; j++) + { + int cost = (t[j - 1] == s[i - 1]) ? 0 : 1; + + d[i, j] = Math.Min( + Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), + d[i - 1, j - 1] + cost); + } + } + + return d[n, m]; + } + } +}