/// <summary>
 /// Returns true if the current module contains the <typeparamref name="T"/> typed attribute, otherwise false.
 /// </summary>
 /// <typeparam name="T">The attribute's type.</typeparam>
 /// <param name="module">The current module.</param>
 /// <returns>True if the module has the attribute, otherwise false.</returns>
 public static bool HasAttribute <T>(this Discord.Commands.ModuleInfo module) where T : Attribute
 {
     return(module.Attributes.Any(a => (a as T) != null));
 }
 /// <summary>
 /// Gets the attribute, if found, from the current module.
 /// </summary>
 /// <typeparam name="T">The attribute's type.</typeparam>
 /// <param name="module">The current module.</param>
 /// <returns>The attribute if found, otherwise null.</returns>
 public static T GetAttribute <T>(this Discord.Commands.ModuleInfo module) where T : Attribute
 {
     return(module.Attributes.Where(a => (a as T) != null).Select(a => a as T).FirstOrDefault());
 }
        public static async Task <IReadOnlyCollection <CommandInfo> > GetExecutableCommandsAsync(this ModuleInfo module, ICommandContext context, IServiceProvider provider)
        {
            var executableCommands = new List <CommandInfo>();

            executableCommands.AddRange(await module.Commands.ToArray().GetExecutableCommandsAsync(context, provider).ConfigureAwait(false));

            var tasks   = module.Submodules.Select(async s => await s.GetExecutableCommandsAsync(context, provider).ConfigureAwait(false));
            var results = await Task.WhenAll(tasks).ConfigureAwait(false);

            executableCommands.AddRange(results.SelectMany(c => c));

            return(executableCommands);
        }