Files
Operation-Blue-Laminate-v2/BlueLaminate/BlueLaminate.Scraper/CsFloat/CsFloatRateLimit.cs
2026-05-29 22:08:32 -05:00

34 lines
1.6 KiB
C#

namespace BlueLaminate.Scraper.CsFloat;
/// <summary>
/// Rate-limit state parsed from a CSFloat API response's headers. The official
/// docs don't pin down the exact header names, so this is populated generically
/// (any header whose name contains "ratelimit"/"rate-limit", plus "retry-after")
/// and keeps the <see cref="Raw"/> map so the real names surface during the
/// spike. A future catalog sweep uses <see cref="Remaining"/>/<see cref="Reset"/>
/// to pace requests and avoid 429s.
/// </summary>
/// <param name="Limit">Max requests allowed in the current window, if reported.</param>
/// <param name="Remaining">Requests left in the current window, if reported.</param>
/// <param name="Reset">Raw reset value as sent (epoch seconds or seconds-until — unverified).</param>
/// <param name="RetryAfter">Seconds to wait, from a Retry-After header (typically on 429).</param>
/// <param name="Raw">Every rate-limit-related header, verbatim, for inspection.</param>
public sealed record CsFloatRateLimit(
int? Limit,
int? Remaining,
string? Reset,
int? RetryAfter,
IReadOnlyDictionary<string, string> Raw)
{
public static readonly CsFloatRateLimit None =
new(null, null, null, null, new Dictionary<string, string>());
/// <summary>True when the API reports zero requests remaining.</summary>
public bool IsExhausted => Remaining is <= 0;
public override string ToString() =>
Raw.Count == 0
? "rate-limit: (no headers)"
: "rate-limit: " + string.Join(", ", Raw.Select(kv => $"{kv.Key}={kv.Value}"));
}