Skip to main content

seher/claude/
types.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Deserialize, Serialize)]
5pub struct UsageWindow {
6    pub utilization: Option<f64>,
7    pub resets_at: Option<DateTime<Utc>>,
8}
9
10impl UsageWindow {
11    #[must_use]
12    pub fn is_limited(&self) -> bool {
13        self.utilization.unwrap_or(0.0) >= 100.0
14    }
15}
16
17#[derive(Debug, Deserialize, Serialize)]
18pub struct UsageResponse {
19    pub five_hour: Option<UsageWindow>,
20    pub seven_day: Option<UsageWindow>,
21    pub seven_day_sonnet: Option<UsageWindow>,
22    pub seven_day_oauth_apps: Option<UsageWindow>,
23    pub seven_day_opus: Option<UsageWindow>,
24    pub seven_day_cowork: Option<UsageWindow>,
25    pub iguana_necktie: Option<UsageWindow>,
26    pub extra_usage: Option<UsageWindow>,
27}
28
29impl UsageResponse {
30    /// Returns all present windows as `(name, &UsageWindow)` pairs.
31    #[must_use]
32    pub fn all_windows(&self) -> Vec<(&str, &UsageWindow)> {
33        [
34            ("five_hour", self.five_hour.as_ref()),
35            ("seven_day", self.seven_day.as_ref()),
36            ("seven_day_sonnet", self.seven_day_sonnet.as_ref()),
37            ("seven_day_oauth_apps", self.seven_day_oauth_apps.as_ref()),
38            ("seven_day_opus", self.seven_day_opus.as_ref()),
39            ("seven_day_cowork", self.seven_day_cowork.as_ref()),
40            ("iguana_necktie", self.iguana_necktie.as_ref()),
41            ("extra_usage", self.extra_usage.as_ref()),
42        ]
43        .into_iter()
44        .filter_map(|(name, w)| w.map(|w| (name, w)))
45        .collect()
46    }
47
48    #[must_use]
49    pub fn next_reset_time(&self) -> Option<chrono::DateTime<Utc>> {
50        self.all_windows()
51            .into_iter()
52            .filter(|(_, w)| w.is_limited())
53            .filter_map(|(_, w)| w.resets_at)
54            .max()
55    }
56}