aboutsummaryrefslogtreecommitdiff
path: root/src/framework/standard/buckets.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/framework/standard/buckets.rs')
-rw-r--r--src/framework/standard/buckets.rs58
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
+ }
+ }
+}