2023-02-17 21:47:44 +00:00
|
|
|
|
using System;
|
|
|
|
|
|
|
|
|
|
namespace SharpChat {
|
|
|
|
|
public class RateLimiter {
|
|
|
|
|
private readonly int Size;
|
|
|
|
|
private readonly int MinimumDelay;
|
|
|
|
|
private readonly int RiskyOffset;
|
|
|
|
|
private readonly long[] TimePoints;
|
|
|
|
|
|
2023-02-19 22:27:08 +00:00
|
|
|
|
public RateLimiter(int size, int minDelay, int riskyOffset = 0) {
|
2023-02-17 21:47:44 +00:00
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|