Implementing rate limiting for discord bot interactions with absolute expiration of items
I’m trying to create a simple and customizable
RateLimitAttribute
for interactions in Discord.Net using their preconditions.
I'm too confused about all the possibilities. So, how would you implement this? What decisions would you make and what data structures would you use?
Expected usage
Expected behavior
/ping
— Pong! (count is now 1)
/ping
— Pong! (count is now 2)
/ping
— Wait 60 seconds for limit to expire!
/ping (30 seconds later)
— Wait 30 seconds for limit to expire!
… (30 seconds later)
— Remove rate limit from store in background.
/ping (any time later)
— Pong! (count is now 1)
Wanted features:
- Users can define custom ignore policies: for instance, if you have a database with different roles like admins and regular users, you might want to apply rate limiting to all users but exclude admins.
- Users can access the store of rate limits: for example, EPIC RPG’s /cd
command shows the cooldowns for each command per user.
Problems I’ve met
- Attributes require constant values: TimeSpan
cannot be used directly. Instead, people use parameters specifying periods in seconds. Alternatively, a converter could be used with double period
and enum TimeMeasure
.
- Caching with absolute expiration: IMemoryCache
's AbsoluteExpiration
simplifies caching implementation because it removes the rate limits right when they expire, but the keys there are strings and not generic types. Using System.Threading.RateLimiting
, it’s hard to display the exact remaining time until the limit expires.4 Replies
Implementations from other people:
- https://gist.github.com/PassiveModding/91b5756c1ba5f060fbc71f51e57a42f7
- https://github.com/jalaljaleh/Template.Discord.Bot/blob/7e22f9765c62d6b1f0928e85833a43db62e3a822/Template/Interactions/Precondinations/RateLimit.cs
- https://github.com/SylveonDeko/BoostBotV2/blob/d7d52de7a55dc4ddac792951b6df319bc34337d8/BoostBotV2/Common/Attributes/Interactions/Ratelimit.cs
- https://github.com/zobweyt/Discord.Net.Template/blob/1aa377e85b18bd1ae456f54677fd2b7caa895123/Template/Common/Preconditions/RateLimitAttribute.cs
So here I tried to implement this using
System.Threading.RateLimiting
And here is implementation using
MemoryCache
Also, I thought about using polymorphism instead of
IgnoreTargets
, but I couldn’t get to a good and working implementation