diff --git a/Feature/AutoRespond/RateLimitCache.cs b/Feature/AutoRespond/RateLimitCache.cs
new file mode 100644
index 0000000..19e3514
--- /dev/null
+++ b/Feature/AutoRespond/RateLimitCache.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+
+namespace Noikoio.RegexBot.Feature.AutoRespond
+{
+ ///
+ /// Stores rate limit settings and caches.
+ ///
+ class RateLimitCache
+ {
+ public const ushort DefaultTimeout = 30; // TODO make configurable
+
+ private readonly ushort _timeout;
+ private Dictionary _cache;
+
+ public ushort Timeout => _timeout;
+
+ ///
+ /// Sets up a new instance of .
+ ///
+ public RateLimitCache(ushort timeout)
+ {
+ _timeout = timeout;
+ _cache = new Dictionary();
+ }
+
+ ///
+ /// Adds a cache item corersponding to the given ID.
+ /// Items added to cache will be removed after the number of seconds specified in .
+ ///
+ /// The ID to add to the cache.
+ /// True on success. False if the given ID already exists.
+ 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();
+ 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;
+ }
+ }
+}
diff --git a/Feature/AutoRespond/ResponseConfigItem.cs b/Feature/AutoRespond/ResponseDefinition.cs
similarity index 75%
rename from Feature/AutoRespond/ResponseConfigItem.cs
rename to Feature/AutoRespond/ResponseDefinition.cs
index cdd400f..168cbe0 100644
--- a/Feature/AutoRespond/ResponseConfigItem.cs
+++ b/Feature/AutoRespond/ResponseDefinition.cs
@@ -8,7 +8,7 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
///
/// Represents a single autoresponse definition.
///
- 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();
@@ -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();
+ 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);
+ }
+ }
}
}
}