Added AutoRespond rate limiting
This commit is contained in:
parent
8d228a4d7c
commit
262f77d82d
2 changed files with 81 additions and 6 deletions
56
Feature/AutoRespond/RateLimitCache.cs
Normal file
56
Feature/AutoRespond/RateLimitCache.cs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Stores rate limit settings and caches.
|
||||||
|
/// </summary>
|
||||||
|
class RateLimitCache
|
||||||
|
{
|
||||||
|
public const ushort DefaultTimeout = 30; // TODO make configurable
|
||||||
|
|
||||||
|
private readonly ushort _timeout;
|
||||||
|
private Dictionary<ulong, DateTime> _cache;
|
||||||
|
|
||||||
|
public ushort Timeout => _timeout;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets up a new instance of <see cref="RateLimitCache"/>.
|
||||||
|
/// </summary>
|
||||||
|
public RateLimitCache(ushort timeout)
|
||||||
|
{
|
||||||
|
_timeout = timeout;
|
||||||
|
_cache = new Dictionary<ulong, DateTime>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a cache item corersponding to the given ID.
|
||||||
|
/// Items added to cache will be removed after the number of seconds specified in <see cref="Timeout"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The ID to add to the cache.</param>
|
||||||
|
/// <returns>True on success. False if the given ID already exists.</returns>
|
||||||
|
public bool AddUsage(ulong id)
|
||||||
|
{
|
||||||
|
Clean();
|
||||||
|
if (_cache.ContainsKey(id)) return false;
|
||||||
|
_cache.Add(id, DateTime.Now);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Clean()
|
||||||
|
{
|
||||||
|
var now = DateTime.Now;
|
||||||
|
var clean = new Dictionary<ulong, DateTime>();
|
||||||
|
foreach (var kp in _cache)
|
||||||
|
{
|
||||||
|
if (kp.Value.AddSeconds(Timeout) > now)
|
||||||
|
{
|
||||||
|
// Copy items that have not yet timed out to the new dictionary
|
||||||
|
clean.Add(kp.Key, kp.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_cache = clean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a single autoresponse definition.
|
/// Represents a single autoresponse definition.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
struct ResponseConfigItem
|
struct ResponseDefinition
|
||||||
{
|
{
|
||||||
public enum ResponseType { None, Exec, Reply }
|
public enum ResponseType { None, Exec, Reply }
|
||||||
|
|
||||||
|
@ -16,15 +16,16 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
Regex _trigger;
|
Regex _trigger;
|
||||||
ResponseType _rtype;
|
ResponseType _rtype;
|
||||||
string _rbody; // response body
|
string _rbody; // response body
|
||||||
private FilterType _filtermode;
|
private FilterList _filter;
|
||||||
private EntityList _filterlist;
|
private RateLimitCache _limit;
|
||||||
|
|
||||||
public string Label => _label;
|
public string Label => _label;
|
||||||
public Regex Trigger => _trigger;
|
public Regex Trigger => _trigger;
|
||||||
public (ResponseType, string) Response => (_rtype, _rbody);
|
public (ResponseType, string) Response => (_rtype, _rbody);
|
||||||
public (FilterType, EntityList) Filter => (_filtermode, _filterlist);
|
public FilterList Filter => _filter;
|
||||||
|
public RateLimitCache RateLimit => _limit;
|
||||||
|
|
||||||
public ResponseConfigItem(JObject definition)
|
public ResponseDefinition(JObject definition)
|
||||||
{
|
{
|
||||||
// label
|
// label
|
||||||
_label = definition["label"]?.Value<string>();
|
_label = definition["label"]?.Value<string>();
|
||||||
|
@ -77,7 +78,25 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
// whitelist/blacklist filtering
|
// whitelist/blacklist filtering
|
||||||
(_filtermode, _filterlist) = EntityList.GetFilterList(definition);
|
_filter = new FilterList(definition);
|
||||||
|
|
||||||
|
// rate limiting
|
||||||
|
string rlstr = definition["ratelimit"].Value<string>();
|
||||||
|
if (string.IsNullOrWhiteSpace(rlstr))
|
||||||
|
{
|
||||||
|
_limit = new RateLimitCache(RateLimitCache.DefaultTimeout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ushort.TryParse(rlstr, out var rlval))
|
||||||
|
{
|
||||||
|
_limit = new RateLimitCache(rlval);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RuleImportException("Rate limit value is invalid" + errorpfx);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue