Implemented command type readers, parser and service.

This commit is contained in:
RogueException
2016-06-26 03:35:40 -03:00
parent d934a5a1eb
commit f59b6b9004
19 changed files with 775 additions and 42 deletions

View File

@@ -0,0 +1,48 @@
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Discord.Commands
{
internal class ChannelTypeReader<T> : TypeReader
where T : class, IChannel
{
public override async Task<TypeReaderResult> Read(IMessage context, string input)
{
IGuildChannel guildChannel = context.Channel as IGuildChannel;
IChannel result = null;
if (guildChannel != null)
{
//By Id
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];
}
}
if (result == null)
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);
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Threading.Tasks;
namespace Discord.Commands
{
internal class GenericTypeReader : TypeReader
{
private readonly Func<IMessage, string, Task<TypeReaderResult>> _action;
public GenericTypeReader(Func<IMessage, string, Task<TypeReaderResult>> action)
{
_action = action;
}
public override Task<TypeReaderResult> Read(IMessage context, string input) => _action(context, input);
}
}

View File

@@ -0,0 +1,24 @@
using System.Globalization;
using System.Threading.Tasks;
namespace Discord.Commands
{
internal class MessageTypeReader : TypeReader
{
public override Task<TypeReaderResult> Read(IMessage context, string input)
{
//By Id
ulong id;
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
return Task.FromResult(TypeReaderResult.FromSuccess(msg));
}
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse Message Id."));
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Discord.Commands
{
internal class RoleTypeReader : TypeReader
{
public override Task<TypeReaderResult> Read(IMessage context, string input)
{
IGuildChannel guildChannel = context.Channel as IGuildChannel;
if (guildChannel != 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));
}
//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]));
}
return Task.FromResult(TypeReaderResult.FromError(CommandError.ObjectNotFound, "Role not found."));
}
}
}

View File

@@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Discord.Commands
{
public abstract class TypeReader
{
public abstract Task<TypeReaderResult> Read(IMessage context, string input);
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Discord.Commands
{
internal class UserTypeReader<T> : TypeReader
where T : class, IUser
{
public override async Task<TypeReaderResult> Read(IMessage context, string input)
{
IGuildChannel guildChannel = context.Channel as IGuildChannel;
IUser result = null;
if (guildChannel != null)
{
//By Id
ulong id;
if (MentionUtils.TryParseUser(input, out id) || ulong.TryParse(input, out id))
{
var user = await guildChannel.Guild.GetUserAsync(id).ConfigureAwait(false);
if (user != null)
result = user;
}
//By Username + Discriminator
if (result == null)
{
int index = input.LastIndexOf('#');
if (index >= 0)
{
string username = input.Substring(0, index);
ushort discriminator;
if (ushort.TryParse(input.Substring(index + 1), out discriminator))
{
var users = await guildChannel.Guild.GetUsersAsync().ConfigureAwait(false);
result = users.Where(x =>
x.DiscriminatorValue == discriminator &&
string.Equals(username, x.Username, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
}
}
}
//By Username
if (result == null)
{
var users = await guildChannel.Guild.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];
}
}
if (result == null)
return TypeReaderResult.FromError(CommandError.ObjectNotFound, "User not found.");
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);
}
}
}