public double LimitRequest(string url)
        {
            int             waitTime;
            RateLimitObject rlo;

            lock (historyLock)
            {
                if (history.ContainsKey(url))
                {
                    rlo = history[url];
                }
                else
                {
                    rlo = new RateLimitObject();
                    history.Add(url, rlo);
                }
            }

            var sw = Stopwatch.StartNew();

            lock (rlo.LockObject)
            {
                sw.Stop();
                waitTime = rlo.GetWaitTime(DateTime.UtcNow, limitPerEndpoint, perTimePeriod);
                if (waitTime != 0)
                {
                    Thread.Sleep(Convert.ToInt32(waitTime));
                    waitTime += (int)sw.ElapsedMilliseconds;
                }

                rlo.Add(DateTime.UtcNow);
            }

            return(waitTime);
        }
        /// <inheritdoc />
        public CallResult <double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour, int credits = 1)
        {
            if (client.authProvider?.Credentials?.Key == null)
            {
                return(new CallResult <double>(0, null));
            }

            var           keyBytes = encryptor.ComputeHash(Encoding.UTF8.GetBytes(client.authProvider.Credentials.Key.GetString()));
            StringBuilder builder  = new StringBuilder();

            for (int i = 0; i < keyBytes.Length; i++)
            {
                builder.Append(keyBytes[i].ToString("x2"));
            }

            var key = builder.ToString();

            int             waitTime;
            RateLimitObject rlo;

            lock (historyLock)
            {
                if (history.ContainsKey(key))
                {
                    rlo = history[key];
                }
                else
                {
                    rlo = new RateLimitObject();
                    history.Add(key, rlo);
                }
            }

            var sw = Stopwatch.StartNew();

            lock (rlo.LockObject)
            {
                sw.Stop();
                waitTime = rlo.GetWaitTime(DateTime.UtcNow, limitPerKey, perTimePeriod);
                if (waitTime != 0)
                {
                    if (limitBehaviour == RateLimitingBehaviour.Fail)
                    {
                        return(new CallResult <double>(waitTime, new RateLimitError($"endpoint limit of {limitPerKey} reached on api key " + key)));
                    }

                    Thread.Sleep(Convert.ToInt32(waitTime));
                    waitTime += (int)sw.ElapsedMilliseconds;
                }

                rlo.Add(DateTime.UtcNow);
            }

            return(new CallResult <double>(waitTime, null));
        }
        public CallResult <double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour)
        {
            if (client.authProvider?.Credentials == null)
            {
                return(new CallResult <double>(0, null));
            }

            string key = client.authProvider.Credentials.Key.GetString();

            int             waitTime;
            RateLimitObject rlo;

            lock (historyLock)
            {
                if (history.ContainsKey(key))
                {
                    rlo = history[key];
                }
                else
                {
                    rlo = new RateLimitObject();
                    history.Add(key, rlo);
                }
            }

            var sw = Stopwatch.StartNew();

            lock (rlo.LockObject)
            {
                sw.Stop();
                waitTime = rlo.GetWaitTime(DateTime.UtcNow, limitPerKey, perTimePeriod);
                if (waitTime != 0)
                {
                    if (limitBehaviour == RateLimitingBehaviour.Fail)
                    {
                        return(new CallResult <double>(waitTime, new RateLimitError($"endpoint limit of {limitPerKey} reached on api key " + key)));
                    }

                    Thread.Sleep(Convert.ToInt32(waitTime));
                    waitTime += (int)sw.ElapsedMilliseconds;
                }

                rlo.Add(DateTime.UtcNow);
            }

            return(new CallResult <double>(waitTime, null));
        }
        public CallResult <double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitingBehaviour)
        {
            int             waitTime;
            RateLimitObject rlo;

            lock (historyLock)
            {
                if (history.ContainsKey(url))
                {
                    rlo = history[url];
                }
                else
                {
                    rlo = new RateLimitObject();
                    history.Add(url, rlo);
                }
            }

            var sw = Stopwatch.StartNew();

            lock (rlo.LockObject)
            {
                sw.Stop();
                waitTime = rlo.GetWaitTime(DateTime.UtcNow, limitPerEndpoint, perTimePeriod);
                if (waitTime != 0)
                {
                    if (limitingBehaviour == RateLimitingBehaviour.Fail)
                    {
                        return(new CallResult <double>(waitTime, new RateLimitError($"endpoint limit of {limitPerEndpoint} reached on endpoint " + url)));
                    }

                    Thread.Sleep(Convert.ToInt32(waitTime));
                    waitTime += (int)sw.ElapsedMilliseconds;
                }

                rlo.Add(DateTime.UtcNow);
            }

            return(new CallResult <double>(waitTime, null));
        }