RegexBot/RegexBot-Modules/RateLimit.cs

41 lines
1.6 KiB
C#
Raw Normal View History

2022-04-23 20:01:27 +00:00
namespace RegexBot.Modules;
/// <summary>
/// Helper class for managing rate limit data.
/// More accurately, this class holds entries, not allowing the same entry to be held more than once until a specified
/// amount of time has passed since the entry was originally tracked; useful for a rate limit system.
2022-04-23 20:01:27 +00:00
/// </summary>
class RateLimit<T> where T : notnull {
2022-04-23 20:01:27 +00:00
public const ushort DefaultTimeout = 20; // Skeeter's a cool guy and you can't convince me otherwise.
/// <summary>
/// Time until an entry within this instance expires, in seconds.
/// </summary>
2022-04-23 20:01:27 +00:00
public uint Timeout { get; }
private Dictionary<T, DateTime> Entries { get; } = new Dictionary<T, DateTime>();
public RateLimit() : this(DefaultTimeout) { }
public RateLimit(uint timeout) => Timeout = timeout;
/// <summary>
/// Checks if the given value is permitted through the rate limit.
/// Executing this method may create a rate limit entry for the given value.
/// </summary>
/// <returns>True if the given value is permitted by the rate limiter.</returns>
public bool IsPermitted(T value) {
if (Timeout == 0) return true;
// Take a moment to clean out expired entries
var now = DateTime.Now;
var expired = Entries.Where(x => x.Value.AddSeconds(Timeout) <= now).Select(x => x.Key).ToList();
foreach (var item in expired) Entries.Remove(item);
if (Entries.ContainsKey(value)) {
return false;
} else {
Entries.Add(value, DateTime.Now);
return true;
}
}
}