/// <summary>
        /// Calculates bucket ID for given command context.
        /// </summary>
        /// <param name="ctx">Context for which to calculate bucket ID for.</param>
        /// <param name="userId">ID of the user with which this bucket is associated.</param>
        /// <param name="channelId">ID of the channel with which this bucket is associated.</param>
        /// <param name="guildId">ID of the guild with which this bucket is associated.</param>
        /// <returns>Calculated bucket ID.</returns>
        private string GetBucketId(CommandContext ctx, out ulong userId, out ulong channelId, out ulong guildId)
        {
            userId = 0ul;
            if ((this.BucketType & CooldownBucketType.User) != 0)
            {
                userId = ctx.User.Id;
            }

            channelId = 0ul;
            if ((this.BucketType & CooldownBucketType.Channel) != 0)
            {
                channelId = ctx.Channel.Id;
            }
            if ((this.BucketType & CooldownBucketType.Guild) != 0 && ctx.Guild == null)
            {
                channelId = ctx.Channel.Id;
            }

            guildId = 0ul;
            if (ctx.Guild != null && (this.BucketType & CooldownBucketType.Guild) != 0)
            {
                guildId = ctx.Guild.Id;
            }

            var bid = CommandCooldownBucket.MakeId(userId, channelId, guildId);

            return(bid);
        }
        public override async Task <bool> ExecuteCheckAsync(CommandContext ctx, bool help)
        {
            if (help)
            {
                return(true);
            }

            var bid = this.GetBucketId(ctx, out var usr, out var chn, out var gld);

            if (!this.Buckets.TryGetValue(bid, out var bucket))
            {
                bucket = new CommandCooldownBucket(this.MaxUses, this.Reset, usr, chn, gld);
                this.Buckets.AddOrUpdate(bid, bucket, (k, v) => bucket);
            }

            return(await bucket.DecrementUseAsync().ConfigureAwait(false));
        }