using Discord; namespace Ellie.Marmalade; /// /// The base class which will be loaded as a module into Ellie /// Any user-defined canary has to inherit from this class. /// Canaries get instantiated ONLY ONCE during the loading, /// and any canary commands will be executed on the same instance. /// public abstract class Canary : IAsyncDisposable { /// /// Name of the canary. Defaults to the lowercase class name /// public virtual string Name => GetType().Name.ToLowerInvariant(); /// /// The prefix required before the command name. For example /// if you set this to 'test' then a command called 'cmd' will have to be invoked by using /// '.test cmd' instead of `.cmd` /// public virtual string Prefix => string.Empty; /// /// Executed once this canary has been instantiated and before any command is executed. /// /// A representing completion public virtual ValueTask InitializeAsync() => default; /// /// Override to cleanup any resources or references which might hold this canary in memory /// /// public virtual ValueTask DisposeAsync() => default; /// /// This method is called right after the message was received by the bot. /// You can use this method to make the bot conditionally ignore some messages and prevent further processing. /// Execution order: /// /// ** → /// → /// → /// OR /// /// /// Guild in which the message was sent /// Message received by the bot /// A representing whether the message should be ignored and not processed further public virtual ValueTask ExecOnMessageAsync(IGuild? guild, IUserMessage msg) => default; /// /// Override this method to modify input before the bot searches for any commands matching the input /// Executed after /// This is useful if you want to reinterpret the message under some conditions /// Execution order: /// /// → /// ** → /// → /// OR /// /// /// Guild in which the message was sent /// Channel in which the message was sent /// User who sent the message /// Content of the message /// A representing new, potentially modified content public virtual ValueTask ExecInputTransformAsync( IGuild? guild, IMessageChannel channel, IUser user, string input ) => default; /// /// This method is called after the command was found but not executed, /// and can be used to prevent the command's execution. /// The command information doesn't have to be from this canary as this method /// will be called when *any* command from any module or canary was found. /// You can choose to prevent the execution of the command by returning "true" value. /// Execution order: /// /// → /// → /// ** → /// OR /// /// /// Command context /// Name of the canary or module from which the command originates /// Name of the command which is about to be executed /// A representing whether the execution should be blocked public virtual ValueTask ExecPreCommandAsync( AnyContext context, string moduleName, string commandName ) => default; /// /// This method is called after the command was succesfully executed. /// If this method was called, then will not be executed /// Execution order: /// /// → /// → /// → /// ** OR /// /// /// A representing completion public virtual ValueTask ExecPostCommandAsync(AnyContext ctx, string moduleName, string commandName) => default; /// /// This method is called if no command was found for the input. /// Useful if you want to have games or features which take arbitrary input /// but ignore any messages which were blocked or caused a command execution /// If this method was called, then will not be executed /// Execution order: /// /// → /// → /// → /// OR ** /// /// /// A representing completion public virtual ValueTask ExecOnNoCommandAsync(IGuild? guild, IUserMessage msg) => default; } public readonly struct ExecResponse { }