/// <summary> /// </summary> /// <param name="type"> /// </param> /// <param name="names"> /// </param> /// <param name="limits"> /// </param> /// <param name="methods"> /// </param> /// <returns> /// </returns> public RateLimitBuilder AddRateLimitFor(LolUrlType type, List <LolApiName> names, List <ApiLimit> limits, params LolApiMethodName[] methods) { var rla = new RLolApiName(); var rlan = new RLolApiMethodName(); rlan.Add(names, methods.Distinct().ToArray()); rlan.AddLimit(limits.ToArray()); rla.Add(rlan); if (!Limits.ContainsKey(type)) { Limits.TryAdd(type, rla); } else { Limits[type].Add(rlan); } return(this); }
/// <summary> /// rate-limit main function /// </summary> /// <param name="prop"> /// </param> private void Wait(RateLimitProperties prop) { TimeSpan currentDelay = TimeSpan.Zero; RLolApiMethodName regionLimit = Rates.Find(prop.Platform, prop.UrlType, prop.ApiName, prop.ApiMethod); if (regionLimit == null) { var snc = ApiSettings.ApiOptions.RateLimitOptions.All[prop.UrlType].DeepClone(); //special rate-limiting for leagues var methodRateLeague = ApiSettings.ApiOptions.RateLimitOptions.FindLeagueApiLimit(prop.Platform); if (methodRateLeague != null) { var app_rates = snc.Names.First().Limits.Where(p => p.LimitType == RateLimitType.AppRate); List <ApiLimit> lmts = new List <ApiLimit>(); lmts.Add(methodRateLeague); lmts.AddRange(app_rates); snc.Add(new RLolApiMethodName(LolApiName.League, new List <LolApiMethodName>() { LolApiMethodName.ChallengerLeagues, LolApiMethodName.Leagues, LolApiMethodName.MasterLeagues, LolApiMethodName.Positions }, lmts.ToArray())); } //special rate-limiting for summoner var methodRateSummoner = ApiSettings.ApiOptions.RateLimitOptions.FindSummonerApiLimit(prop.Platform); if (methodRateSummoner != null) { var app_rates = snc.Names.First().Limits.Where(p => p.LimitType == RateLimitType.AppRate); List <ApiLimit> lmts = new List <ApiLimit>(); lmts.Add(methodRateSummoner); lmts.AddRange(app_rates); snc.Add(new RLolApiMethodName(LolApiName.Summoner, new List <LolApiMethodName>() { LolApiMethodName.Summoners }, lmts.ToArray())); } // Add(prop.Platform, prop.UrlType, snc); regionLimit = Rates.Find(prop.Platform, prop.UrlType, prop.ApiName, prop.ApiMethod); } //lock (_lock) { if (regionLimit.IsRetryActive) { currentDelay = (regionLimit.RetryAfter - DateTime.Now); Debug.WriteLine($"Limit Exceeded Retry-After:{currentDelay}, Region:{prop.Platform}, ApiType:{prop.UrlType}, ApiName:{prop.ApiName}, ApiMethod:{prop.ApiMethod} Forced-Limit:{regionLimit.UsedRateLimitType}"); } //special condition to check '/lol/summoner/v3/summoners/by-account/{accountId}' int limitForByAccount = -1; if (prop.ApiMethod == LolApiMethodName.Summoners && prop.ApiName == LolApiName.Summoner) { if (prop.ApiPaths[0] == LolApiPath.ByAccount) { var limit = ApiSettings.ApiOptions.RateLimitOptions.SummonerAccountNameLimits; limitForByAccount = limit["All"].Limit; } } foreach (var limit in regionLimit.Limits) { int bypassedLimit = limit.Limit; if (limitForByAccount != -1) { if (limit.LimitType == RateLimitType.MethodRate) { bypassedLimit = limitForByAccount; } } if (limit.Counter < bypassedLimit) { continue; } var largestDelay = limit.ChainStartTime.Add(limit.Time) - DateTime.Now; Debug.WriteLine( $"[{DateTime.Now:MM/dd/yyyy HH:mm:ss.fff}] limit:{bypassedLimit}\tregion:{prop.Platform}\ttype:{prop.UrlType}\tapiName:{prop.ApiName}\tmultipler:{limit.Time}\tcount:{limit.Counter}\t\tDelay:{largestDelay}"); if (largestDelay > currentDelay) { currentDelay = largestDelay; } break; } regionLimit.Limits.ForEach((limit) => { if (limit.ChainStartTime <= DateTime.Now.Add(currentDelay) - limit.Time) { limit.Counter = 0; } limit.ChainStartTime = DateTime.Now.Add(currentDelay); limit.Counter++; }); } Task.Delay(currentDelay).Wait(); }