using System; namespace SharpChat { public class RateLimiter { private readonly int Size; private readonly int MinimumDelay; private readonly int RiskyOffset; private readonly long[] TimePoints; public RateLimiter(int size, int minDelay, int riskyOffset = 0) { if(size < 2) throw new ArgumentException("Size is too small.", nameof(size)); if(minDelay < 1000) throw new ArgumentException("Minimum delay is inhuman.", nameof(minDelay)); if(riskyOffset != 0) { if(riskyOffset >= size) throw new ArgumentException("Risky offset may not be greater or equal to the size.", nameof(riskyOffset)); else if(riskyOffset < 0) throw new ArgumentException("Risky offset may not be negative.", nameof(riskyOffset)); } Size = size; MinimumDelay = minDelay; RiskyOffset = riskyOffset; TimePoints = new long[Size]; } public bool IsRisky => TimePoints[RiskyOffset] != 0 && TimePoints[RiskyOffset + 1] != 0 && TimePoints[RiskyOffset] + MinimumDelay >= TimePoints[Size - 1]; public bool IsExceeded => TimePoints[0] != 0 && TimePoints[1] != 0 && TimePoints[0] + MinimumDelay >= TimePoints[Size - 1]; public void Update() { for(int i = 1; i < Size; ++i) TimePoints[i - 1] = TimePoints[i]; TimePoints[Size - 1] = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } } }