Added support for custom ModuleBase command contexts. Added SocketCommandContext/RpcCommandContext.
This commit is contained in:
@@ -6,6 +6,6 @@ namespace Discord.Commands
|
||||
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
|
||||
public abstract class ParameterPreconditionAttribute : Attribute
|
||||
{
|
||||
public abstract Task<PreconditionResult> CheckPermissions(CommandContext context, ParameterInfo parameter, object value, IDependencyMap map);
|
||||
public abstract Task<PreconditionResult> CheckPermissions(ICommandContext context, ParameterInfo parameter, object value, IDependencyMap map);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,6 @@ namespace Discord.Commands
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
|
||||
public abstract class PreconditionAttribute : Attribute
|
||||
{
|
||||
public abstract Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map);
|
||||
public abstract Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IDependencyMap map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Discord.Commands
|
||||
GuildPermission = null;
|
||||
}
|
||||
|
||||
public override async Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map)
|
||||
public override async Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IDependencyMap map)
|
||||
{
|
||||
var guildUser = await context.Guild.GetCurrentUserAsync();
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Discord.Commands
|
||||
Contexts = contexts;
|
||||
}
|
||||
|
||||
public override Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map)
|
||||
public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IDependencyMap map)
|
||||
{
|
||||
bool isValid = false;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Discord.Commands
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public class RequireOwnerAttribute : PreconditionAttribute
|
||||
{
|
||||
public override async Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map)
|
||||
public override async Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IDependencyMap map)
|
||||
{
|
||||
var application = await context.Client.GetApplicationInfoAsync();
|
||||
if (context.User.Id == application.Owner.Id) return PreconditionResult.FromSuccess();
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Discord.Commands
|
||||
GuildPermission = null;
|
||||
}
|
||||
|
||||
public override Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map)
|
||||
public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IDependencyMap map)
|
||||
{
|
||||
var guildUser = context.User as IGuildUser;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Discord.Commands.Builders
|
||||
private readonly List<string> _aliases;
|
||||
|
||||
public ModuleBuilder Module { get; }
|
||||
internal Func<CommandContext, object[], IDependencyMap, Task> Callback { get; set; }
|
||||
internal Func<ICommandContext, object[], IDependencyMap, Task> Callback { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Summary { get; set; }
|
||||
@@ -34,7 +34,7 @@ namespace Discord.Commands.Builders
|
||||
_aliases = new List<string>();
|
||||
}
|
||||
//User-defined
|
||||
internal CommandBuilder(ModuleBuilder module, string primaryAlias, Func<CommandContext, object[], IDependencyMap, Task> callback)
|
||||
internal CommandBuilder(ModuleBuilder module, string primaryAlias, Func<ICommandContext, object[], IDependencyMap, Task> callback)
|
||||
: this(module)
|
||||
{
|
||||
Discord.Preconditions.NotNull(primaryAlias, nameof(primaryAlias));
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Discord.Commands.Builders
|
||||
_preconditions.Add(precondition);
|
||||
return this;
|
||||
}
|
||||
public ModuleBuilder AddCommand(string primaryAlias, Func<CommandContext, object[], IDependencyMap, Task> callback, Action<CommandBuilder> createFunc)
|
||||
public ModuleBuilder AddCommand(string primaryAlias, Func<ICommandContext, object[], IDependencyMap, Task> callback, Action<CommandBuilder> createFunc)
|
||||
{
|
||||
var builder = new CommandBuilder(this, primaryAlias, callback);
|
||||
createFunc(builder);
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Discord.Commands
|
||||
{
|
||||
internal static class ModuleClassBuilder
|
||||
{
|
||||
private static readonly TypeInfo _moduleTypeInfo = typeof(ModuleBase).GetTypeInfo();
|
||||
private static readonly TypeInfo _moduleTypeInfo = typeof(IModuleBase).GetTypeInfo();
|
||||
|
||||
public static IEnumerable<TypeInfo> Search(Assembly assembly)
|
||||
{
|
||||
@@ -155,12 +155,12 @@ namespace Discord.Commands
|
||||
});
|
||||
}
|
||||
|
||||
var createInstance = ReflectionUtils.CreateBuilder<ModuleBase>(typeInfo, service);
|
||||
var createInstance = ReflectionUtils.CreateBuilder<IModuleBase>(typeInfo, service);
|
||||
|
||||
builder.Callback = (ctx, args, map) =>
|
||||
{
|
||||
var instance = createInstance(map);
|
||||
instance.Context = ctx;
|
||||
instance.SetContext(ctx);
|
||||
try
|
||||
{
|
||||
return method.Invoke(instance, args) as Task ?? Task.Delay(0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Discord.Commands
|
||||
{
|
||||
public struct CommandContext
|
||||
public class CommandContext : ICommandContext
|
||||
{
|
||||
public IDiscordClient Client { get; }
|
||||
public IGuild Guild { get; }
|
||||
@@ -9,15 +9,7 @@
|
||||
public IUserMessage Message { get; }
|
||||
|
||||
public bool IsPrivate => Channel is IPrivateChannel;
|
||||
|
||||
public CommandContext(IDiscordClient client, IGuild guild, IMessageChannel channel, IUser user, IUserMessage msg)
|
||||
{
|
||||
Client = client;
|
||||
Guild = guild;
|
||||
Channel = channel;
|
||||
User = user;
|
||||
Message = msg;
|
||||
}
|
||||
|
||||
public CommandContext(IDiscordClient client, IUserMessage msg)
|
||||
{
|
||||
Client = client;
|
||||
|
||||
@@ -14,13 +14,13 @@ namespace Discord.Commands
|
||||
Alias = alias;
|
||||
}
|
||||
|
||||
public Task<PreconditionResult> CheckPreconditionsAsync(CommandContext context, IDependencyMap map = null)
|
||||
public Task<PreconditionResult> CheckPreconditionsAsync(ICommandContext context, IDependencyMap map = null)
|
||||
=> Command.CheckPreconditionsAsync(context, map);
|
||||
public Task<ParseResult> ParseAsync(CommandContext context, SearchResult searchResult, PreconditionResult? preconditionResult = null)
|
||||
public Task<ParseResult> ParseAsync(ICommandContext context, SearchResult searchResult, PreconditionResult? preconditionResult = null)
|
||||
=> Command.ParseAsync(context, Alias.Length, searchResult, preconditionResult);
|
||||
public Task<ExecuteResult> ExecuteAsync(CommandContext context, IEnumerable<object> argList, IEnumerable<object> paramList, IDependencyMap map)
|
||||
public Task<ExecuteResult> ExecuteAsync(ICommandContext context, IEnumerable<object> argList, IEnumerable<object> paramList, IDependencyMap map)
|
||||
=> Command.ExecuteAsync(context, argList, paramList, map);
|
||||
public Task<ExecuteResult> ExecuteAsync(CommandContext context, ParseResult parseResult, IDependencyMap map)
|
||||
public Task<ExecuteResult> ExecuteAsync(ICommandContext context, ParseResult parseResult, IDependencyMap map)
|
||||
=> Command.ExecuteAsync(context, parseResult, map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Discord.Commands
|
||||
QuotedParameter
|
||||
}
|
||||
|
||||
public static async Task<ParseResult> ParseArgs(CommandInfo command, CommandContext context, string input, int startPos)
|
||||
public static async Task<ParseResult> ParseArgs(CommandInfo command, ICommandContext context, string input, int startPos)
|
||||
{
|
||||
ParameterInfo curParam = null;
|
||||
StringBuilder argBuilder = new StringBuilder(input.Length);
|
||||
|
||||
@@ -222,9 +222,9 @@ namespace Discord.Commands
|
||||
}
|
||||
|
||||
//Execution
|
||||
public SearchResult Search(CommandContext context, int argPos)
|
||||
public SearchResult Search(ICommandContext context, int argPos)
|
||||
=> Search(context, context.Message.Content.Substring(argPos));
|
||||
public SearchResult Search(CommandContext context, string input)
|
||||
public SearchResult Search(ICommandContext context, string input)
|
||||
{
|
||||
string searchInput = _caseSensitive ? input : input.ToLowerInvariant();
|
||||
var matches = _map.GetCommands(searchInput).OrderByDescending(x => x.Command.Priority).ToImmutableArray();
|
||||
@@ -235,9 +235,9 @@ namespace Discord.Commands
|
||||
return SearchResult.FromError(CommandError.UnknownCommand, "Unknown command.");
|
||||
}
|
||||
|
||||
public Task<IResult> ExecuteAsync(CommandContext context, int argPos, IDependencyMap dependencyMap = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
||||
public Task<IResult> ExecuteAsync(ICommandContext context, int argPos, IDependencyMap dependencyMap = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
||||
=> ExecuteAsync(context, context.Message.Content.Substring(argPos), dependencyMap, multiMatchHandling);
|
||||
public async Task<IResult> ExecuteAsync(CommandContext context, string input, IDependencyMap dependencyMap = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
||||
public async Task<IResult> ExecuteAsync(ICommandContext context, string input, IDependencyMap dependencyMap = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
||||
{
|
||||
dependencyMap = dependencyMap ?? DependencyMap.Empty;
|
||||
|
||||
|
||||
7
src/Discord.Net.Commands/IModuleBase.cs
Normal file
7
src/Discord.Net.Commands/IModuleBase.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Discord.Commands
|
||||
{
|
||||
internal interface IModuleBase
|
||||
{
|
||||
void SetContext(ICommandContext context);
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Discord.Commands
|
||||
private static readonly System.Reflection.MethodInfo _convertParamsMethod = typeof(CommandInfo).GetTypeInfo().GetDeclaredMethod(nameof(ConvertParamsList));
|
||||
private static readonly ConcurrentDictionary<Type, Func<IEnumerable<object>, object>> _arrayConverters = new ConcurrentDictionary<Type, Func<IEnumerable<object>, object>>();
|
||||
|
||||
private readonly Func<CommandContext, object[], IDependencyMap, Task> _action;
|
||||
private readonly Func<ICommandContext, object[], IDependencyMap, Task> _action;
|
||||
|
||||
public ModuleInfo Module { get; }
|
||||
public string Name { get; }
|
||||
@@ -63,7 +63,7 @@ namespace Discord.Commands
|
||||
_action = builder.Callback;
|
||||
}
|
||||
|
||||
public async Task<PreconditionResult> CheckPreconditionsAsync(CommandContext context, IDependencyMap map = null)
|
||||
public async Task<PreconditionResult> CheckPreconditionsAsync(ICommandContext context, IDependencyMap map = null)
|
||||
{
|
||||
if (map == null)
|
||||
map = DependencyMap.Empty;
|
||||
@@ -85,7 +85,7 @@ namespace Discord.Commands
|
||||
return PreconditionResult.FromSuccess();
|
||||
}
|
||||
|
||||
public async Task<ParseResult> ParseAsync(CommandContext context, int startIndex, SearchResult searchResult, PreconditionResult? preconditionResult = null)
|
||||
public async Task<ParseResult> ParseAsync(ICommandContext context, int startIndex, SearchResult searchResult, PreconditionResult? preconditionResult = null)
|
||||
{
|
||||
if (!searchResult.IsSuccess)
|
||||
return ParseResult.FromError(searchResult);
|
||||
@@ -96,7 +96,7 @@ namespace Discord.Commands
|
||||
return await CommandParser.ParseArgs(this, context, input, 0).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Task<ExecuteResult> ExecuteAsync(CommandContext context, ParseResult parseResult, IDependencyMap map)
|
||||
public Task<ExecuteResult> ExecuteAsync(ICommandContext context, ParseResult parseResult, IDependencyMap map)
|
||||
{
|
||||
if (!parseResult.IsSuccess)
|
||||
return Task.FromResult(ExecuteResult.FromError(parseResult));
|
||||
@@ -119,7 +119,7 @@ namespace Discord.Commands
|
||||
|
||||
return ExecuteAsync(context, argList, paramList, map);
|
||||
}
|
||||
public async Task<ExecuteResult> ExecuteAsync(CommandContext context, IEnumerable<object> argList, IEnumerable<object> paramList, IDependencyMap map)
|
||||
public async Task<ExecuteResult> ExecuteAsync(ICommandContext context, IEnumerable<object> argList, IEnumerable<object> paramList, IDependencyMap map)
|
||||
{
|
||||
if (map == null)
|
||||
map = DependencyMap.Empty;
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Discord.Commands
|
||||
_reader = builder.TypeReader;
|
||||
}
|
||||
|
||||
public async Task<PreconditionResult> CheckPreconditionsAsync(CommandContext context, object[] args, IDependencyMap map = null)
|
||||
public async Task<PreconditionResult> CheckPreconditionsAsync(ICommandContext context, object[] args, IDependencyMap map = null)
|
||||
{
|
||||
if (map == null)
|
||||
map = DependencyMap.Empty;
|
||||
@@ -61,7 +61,7 @@ namespace Discord.Commands
|
||||
return PreconditionResult.FromSuccess();
|
||||
}
|
||||
|
||||
public async Task<TypeReaderResult> Parse(CommandContext context, string input)
|
||||
public async Task<TypeReaderResult> Parse(ICommandContext context, string input)
|
||||
{
|
||||
return await _reader.Read(context, input).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Commands
|
||||
{
|
||||
public abstract class ModuleBase
|
||||
public abstract class ModuleBase : ModuleBase<CommandContext> { }
|
||||
|
||||
public abstract class ModuleBase<T> : IModuleBase
|
||||
where T : class, ICommandContext
|
||||
{
|
||||
public CommandContext Context { get; internal set; }
|
||||
public T Context { get; private set; }
|
||||
|
||||
protected virtual async Task<IUserMessage> ReplyAsync(string message, bool isTTS = false, EmbedBuilder embed = null, RequestOptions options = null)
|
||||
{
|
||||
return await Context.Channel.SendMessageAsync(message, isTTS, embed, options).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
//IModuleBase
|
||||
void IModuleBase.SetContext(ICommandContext context)
|
||||
{
|
||||
var newValue = context as T;
|
||||
if (newValue == null)
|
||||
throw new InvalidOperationException($"Invalid context type. Expected {typeof(T).Name}, got {context.GetType().Name}");
|
||||
Context = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Discord.Commands
|
||||
internal class ChannelTypeReader<T> : TypeReader
|
||||
where T : class, IChannel
|
||||
{
|
||||
public override async Task<TypeReaderResult> Read(CommandContext context, string input)
|
||||
public override async Task<TypeReaderResult> Read(ICommandContext context, string input)
|
||||
{
|
||||
if (context.Guild != null)
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Discord.Commands
|
||||
_enumsByValue = byValueBuilder.ToImmutable();
|
||||
}
|
||||
|
||||
public override Task<TypeReaderResult> Read(CommandContext context, string input)
|
||||
public override Task<TypeReaderResult> Read(ICommandContext context, string input)
|
||||
{
|
||||
T baseValue;
|
||||
object enumValue;
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Discord.Commands
|
||||
internal class MessageTypeReader<T> : TypeReader
|
||||
where T : class, IMessage
|
||||
{
|
||||
public override async Task<TypeReaderResult> Read(CommandContext context, string input)
|
||||
public override async Task<TypeReaderResult> Read(ICommandContext context, string input)
|
||||
{
|
||||
ulong id;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Discord.Commands
|
||||
_tryParse = PrimitiveParsers.Get<T>();
|
||||
}
|
||||
|
||||
public override Task<TypeReaderResult> Read(CommandContext context, string input)
|
||||
public override Task<TypeReaderResult> Read(ICommandContext context, string input)
|
||||
{
|
||||
T value;
|
||||
if (_tryParse(input, out value))
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Discord.Commands
|
||||
internal class RoleTypeReader<T> : TypeReader
|
||||
where T : class, IRole
|
||||
{
|
||||
public override Task<TypeReaderResult> Read(CommandContext context, string input)
|
||||
public override Task<TypeReaderResult> Read(ICommandContext context, string input)
|
||||
{
|
||||
ulong id;
|
||||
|
||||
|
||||
@@ -4,6 +4,6 @@ namespace Discord.Commands
|
||||
{
|
||||
public abstract class TypeReader
|
||||
{
|
||||
public abstract Task<TypeReaderResult> Read(CommandContext context, string input);
|
||||
public abstract Task<TypeReaderResult> Read(ICommandContext context, string input);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Discord.Commands
|
||||
internal class UserTypeReader<T> : TypeReader
|
||||
where T : class, IUser
|
||||
{
|
||||
public override async Task<TypeReaderResult> Read(CommandContext context, string input)
|
||||
public override async Task<TypeReaderResult> Read(ICommandContext context, string input)
|
||||
{
|
||||
var results = new Dictionary<ulong, TypeReaderValue>();
|
||||
IReadOnlyCollection<IUser> channelUsers = (await context.Channel.GetUsersAsync(CacheMode.CacheOnly).Flatten().ConfigureAwait(false)).ToArray(); //TODO: must be a better way?
|
||||
|
||||
Reference in New Issue
Block a user