const TIME_THRESHOLD_S: u64 = 30; const TIME_MIN_S_F64: f64 = 1.0; const MSG_THRESHOLD: u32 = 20; use std::time::Instant; use crate::core::botlog; #[derive(Debug, Clone)] pub struct RateLimiter { timer: Instant, msgcounter: u32, lastmsgtimer : Instant, } #[derive(Debug)] pub enum LimiterResp { Allow, // when it's evaluated to be within limits Skip, // as outside of rate limits // Enqueue, // [FUTURE] Sleep(f64), // Sleep for x seconds } impl Default for RateLimiter { fn default() -> Self { Self::new() } } impl RateLimiter { pub fn new() -> Self { Self { timer: Instant::now(), msgcounter: 0, lastmsgtimer: Instant::now(), } } pub fn check_limiter(&mut self) -> LimiterResp { let logstr = format!( ">> RateLimiter > {:?}",self ); botlog::trace( logstr.as_str(), Some("Rate Limiter Inner".to_string()), None, ); let rsp = if self.timer.elapsed().as_secs() >= TIME_THRESHOLD_S { self.timer = Instant::now(); self.msgcounter = 0; LimiterResp::Allow } else if self.msgcounter < MSG_THRESHOLD && self.lastmsgtimer.elapsed().as_secs_f64() >= TIME_MIN_S_F64 { LimiterResp::Allow } else { // when elapsed() < TIME_THRESHOLD_S && msgcounter >= MSG_THRESHOLD // LimiterResp::Skip LimiterResp::Sleep(TIME_MIN_S_F64 - self.lastmsgtimer.elapsed().as_secs_f64() + 0.1) }; botlog::trace( &format!("Limiter Response : {:?} ; Elapsed (as_sec_f64) : {}", rsp, self.lastmsgtimer.elapsed().as_secs_f64()), Some("Rate Limiter Inner".to_string()), None, ); rsp } pub fn increment_counter(&mut self) { self.msgcounter += 1; self.lastmsgtimer = Instant::now(); } }