diff options
Diffstat (limited to 'src/framework/standard/buckets.rs')
| -rw-r--r-- | src/framework/standard/buckets.rs | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/framework/standard/buckets.rs b/src/framework/standard/buckets.rs new file mode 100644 index 0000000..f2c4486 --- /dev/null +++ b/src/framework/standard/buckets.rs @@ -0,0 +1,58 @@ +use chrono::Utc; +use std::collections::HashMap; +use std::default::Default; +use client::Context; +use model::{ChannelId, GuildId, UserId}; + +#[cfg(feature = "cache")] +type Check = Fn(&mut Context, Option<GuildId>, ChannelId, UserId) -> bool + 'static; + +#[cfg(not(feature = "cache"))] +type Check = Fn(&mut Context, ChannelId, UserId) -> bool + 'static; + +pub(crate) struct Ratelimit { + pub delay: i64, + pub limit: Option<(i64, i32)>, +} + +#[derive(Default)] +pub(crate) struct MemberRatelimit { + pub last_time: i64, + pub set_time: i64, + pub tickets: i32, +} + +pub(crate) struct Bucket { + pub ratelimit: Ratelimit, + pub users: HashMap<u64, MemberRatelimit>, + pub check: Option<Box<Check>>, +} + +impl Bucket { + pub fn take(&mut self, user_id: u64) -> i64 { + let time = Utc::now().timestamp(); + let user = self.users.entry(user_id).or_insert_with( + MemberRatelimit::default, + ); + + if let Some((timespan, limit)) = self.ratelimit.limit { + if (user.tickets + 1) > limit { + if time < (user.set_time + timespan) { + return (user.set_time + timespan) - time; + } else { + user.tickets = 0; + user.set_time = time; + } + } + } + + if time < user.last_time + self.ratelimit.delay { + (user.last_time + self.ratelimit.delay) - time + } else { + user.tickets += 1; + user.last_time = time; + + 0 + } + } +} |