Added AutoRespond rate limiting

This commit is contained in:
Noikoio 2017-08-10 15:19:42 -07:00
parent 8d228a4d7c
commit 262f77d82d
2 changed files with 81 additions and 6 deletions

View 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;
}
}
}

View file

@ -8,7 +8,7 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
/// <summary>
/// Represents a single autoresponse definition.
/// </summary>
struct ResponseConfigItem
struct ResponseDefinition
{
public enum ResponseType { None, Exec, Reply }
@ -16,15 +16,16 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
Regex _trigger;
ResponseType _rtype;
string _rbody; // response body
private FilterType _filtermode;
private EntityList _filterlist;
private FilterList _filter;
private RateLimitCache _limit;
public string Label => _label;
public Regex Trigger => _trigger;
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 = definition["label"]?.Value<string>();
@ -77,7 +78,25 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
// ---
// 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);
}
}
}
}
}