screeps_rust_api/
rate_limit.rs

1use std::collections::HashMap;
2
3use reqwest::header::HeaderMap;
4
5use crate::http_client::Method;
6
7/// 接口速度限制
8#[derive(Debug, Clone)]
9pub struct RateLimit {
10    /// 限制次数
11    pub limit: i32,
12    /// 限制时期
13    pub period: Period,
14    /// 剩余次数
15    pub remaining: i32,
16    /// 重置时间,单位 s
17    pub reset: u128,
18}
19
20impl RateLimit {
21    /// 创建一个接口限制
22    pub fn new(limit: i32, period: Period, remaining: i32, reset: u128) -> Self {
23        Self {
24            limit,
25            period,
26            remaining,
27            reset,
28        }
29    }
30
31    /// 构造默认的速度限制
32    pub fn default(limit: i32, period: Period) -> Self {
33        Self::new(limit, period, limit, 0)
34    }
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
38pub enum Period {
39    Minute,
40    Hour,
41    Day,
42}
43
44/// 接口速度限制集合
45pub struct RateLimits {
46    /// 全局限制
47    pub global_limit: RateLimit,
48    /// GET 请求限制
49    pub get_limits: HashMap<String, RateLimit>,
50    /// POST 请求限制
51    pub post_limits: HashMap<String, RateLimit>,
52}
53
54impl RateLimits {
55    /// 获取指定请求方法和请求路径的限速信息,找不到返回 global 的限速信息
56    /// 参数:
57    /// - method: 请求方法,GET or POST
58    /// - path: 请求路径
59    pub fn get_limit(&self, method: &Method, path: &str) -> RateLimit {
60        match method {
61            Method::Get => self.get_limits.get(path).cloned().unwrap_or(self.global_limit.clone()),
62            Method::Post => self.post_limits.get(path).cloned().unwrap_or(self.global_limit.clone()),
63        }
64    }
65
66    /// 获取指定请求方法和请求路径的限速信息,找不到返回 global 的限速信息
67    /// 参数:
68    /// - method: 请求方法,GET or POST
69    /// - path: 请求路径
70    pub fn get_limit_mut(&mut self, method: &Method, path: &str) -> &mut RateLimit {
71        match method {
72            Method::Get => self
73                .get_limits
74                .get_mut(path)
75                .unwrap_or(&mut self.global_limit),
76            Method::Post => self
77                .post_limits
78                .get_mut(path)
79                .unwrap_or(&mut self.global_limit),
80        }
81    }
82
83    /// 更新限速信息
84    /// 参数:
85    /// - method: 请求方法,GET or POST
86    /// - path: 请求路径
87    /// - limit: 限速信息
88    pub fn update_limit(&mut self, method: &Method, path: &str, rate_limit: RateLimit) {
89        let now_rate_limit = self.get_limit_mut(method, path);
90        *now_rate_limit = rate_limit;
91    }
92
93    /// 根据响应头更新限速信息
94    pub fn update_from_headers(&mut self, method: &Method, path: &str, headers: &HeaderMap) {
95        let limit = headers
96            .get("x-ratelimit-limit")
97            .and_then(|s| s.to_str().unwrap_or("0").parse::<i32>().ok())
98            .unwrap_or(0);
99        if limit <= 0 {
100            return;
101        }
102        let remaining = headers
103            .get("x-ratelimit-remaining")
104            .and_then(|s| s.to_str().unwrap_or("0").parse::<i32>().ok())
105            .unwrap_or(0);
106        let reset = headers
107            .get("x-ratelimit-reset")
108            .and_then(|s| s.to_str().unwrap_or("0").parse::<u128>().ok())
109            .unwrap_or(0);
110        let rate_limit = self.get_limit_mut(method, path);
111        rate_limit.limit = limit;
112        rate_limit.remaining = remaining;
113        rate_limit.reset = reset;
114    }
115}
116
117impl Default for RateLimits {
118    fn default() -> Self {
119        let global_limit = RateLimit::default(120, Period::Minute);
120        let mut get_limits = HashMap::new();
121        let mut post_limits = HashMap::new();
122
123        // GET 请求限制
124        get_limits.insert(
125            "/game/room-terrain".to_string(),
126            RateLimit::default(360, Period::Hour),
127        );
128        get_limits.insert(
129            "/user/code".to_string(),
130            RateLimit::default(60, Period::Hour),
131        );
132        get_limits.insert(
133            "/user/memory".to_string(),
134            RateLimit::default(1440, Period::Day),
135        );
136        get_limits.insert(
137            "/user/memory-segment".to_string(),
138            RateLimit::default(360, Period::Hour),
139        );
140        get_limits.insert(
141            "/game/market/orders-index".to_string(),
142            RateLimit::default(60, Period::Hour),
143        );
144        get_limits.insert(
145            "/game/market/orders".to_string(),
146            RateLimit::default(60, Period::Hour),
147        );
148        get_limits.insert(
149            "/game/market/my-orders".to_string(),
150            RateLimit::default(60, Period::Hour),
151        );
152        get_limits.insert(
153            "/game/market/stats".to_string(),
154            RateLimit::default(60, Period::Hour),
155        );
156        get_limits.insert(
157            "/game/user/money-history".to_string(),
158            RateLimit::default(60, Period::Hour),
159        );
160
161        // POST 请求限制
162        post_limits.insert(
163            "/user/console".to_string(),
164            RateLimit::default(360, Period::Hour),
165        );
166        post_limits.insert(
167            "/game/map-stats".to_string(),
168            RateLimit::default(60, Period::Hour),
169        );
170        post_limits.insert(
171            "/user/code".to_string(),
172            RateLimit::default(240, Period::Day),
173        );
174        post_limits.insert(
175            "/user/set-active-branch".to_string(),
176            RateLimit::default(240, Period::Day),
177        );
178        post_limits.insert(
179            "/user/memory".to_string(),
180            RateLimit::default(240, Period::Day),
181        );
182        post_limits.insert(
183            "/user/memory-segment".to_string(),
184            RateLimit::default(60, Period::Hour),
185        );
186
187        Self {
188            global_limit,
189            get_limits,
190            post_limits,
191        }
192    }
193}