1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
use crate::shard::error::{Error, Result}; use tokio::time::delay_until; use std::time::Duration; use tokio::{sync::Mutex, time::Instant}; use tracing::warn; #[derive(Debug)] pub(crate) struct DayLimiter(pub(crate) Mutex<DayLimiterInner>); #[derive(Debug)] pub(crate) struct DayLimiterInner { pub http: twilight_http::Client, pub last_check: Instant, pub next_reset: Duration, pub total: u64, pub current: u64, } impl DayLimiter { pub async fn new(http: &twilight_http::Client) -> Result<Self> { let info = http .gateway() .authed() .await .map_err(|e| Error::GettingGatewayUrl { source: e })?; let last_check = Instant::now(); let next_reset = Duration::from_millis(info.session_start_limit.reset_after); let total = info.session_start_limit.total; let remaining = info.session_start_limit.remaining; debug_assert!(total >= remaining); let current = total - remaining; Ok(DayLimiter(Mutex::new(DayLimiterInner { http: http.clone(), last_check, next_reset, total: info.session_start_limit.total, current, }))) } pub async fn get(&self) { let mut lock = self.0.lock().await; if lock.current < lock.total { lock.current += 1; } else { let wait = lock.last_check + lock.next_reset; delay_until(wait).await; if let Ok(info) = lock.http.gateway().authed().await { let last_check = Instant::now(); let next_reset = Duration::from_millis(info.session_start_limit.remaining); tracing::info!("Next session start limit reset in: {:.2?}", next_reset); let total = info.session_start_limit.total; let remaining = info.session_start_limit.remaining; assert!(total >= remaining); let current = total - remaining; lock.last_check = last_check; lock.next_reset = next_reset; lock.total = total; lock.current = current + 1; } else { warn!("Unable to get new session limits, skipping it. (This may cause bad things)") } } } }