me when i write bad code
This commit is contained in:
parent
9795b8696c
commit
2d42423a1f
162
src/limit.rs
162
src/limit.rs
|
@ -45,168 +45,6 @@ impl LimitedRequester {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_limit(&self, bucket: &str) -> Option<&Limit> {
|
||||
for limit in self.limits.iter() {
|
||||
if limit.bucket == bucket {
|
||||
return Some(limit.to_owned());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// `last_match` returns the last match of a `Vec<&str>` in a `String`. It returns a `Option<(usize, String)>`
|
||||
/// that contains the index of the match and the match itself.
|
||||
/// If no match is found, it returns `None`.
|
||||
/// # Example
|
||||
/// ```rs
|
||||
/// let string = "https://discord.com/api/v8/channels/1234567890/messages";
|
||||
/// let matches = ["channels", "messages"];
|
||||
/// let index_match = last_match(string, matches.to_vec());
|
||||
/// assert_eq!(index_match, Some((43, String::from("messages"))));
|
||||
/// ```
|
||||
fn last_match(string: &str, search_for: Vec<&str>) -> Option<(usize, String)> {
|
||||
let mut index_match: (usize, &str) = (0, "");
|
||||
for _match in search_for.iter() {
|
||||
if !string.contains(_match) {
|
||||
continue;
|
||||
}
|
||||
// Get the index of the match
|
||||
let temp_index_match = string.match_indices(_match).next().unwrap();
|
||||
// As only the last match is relevant, we only update the index_match if the index is
|
||||
// higher than the previous one.
|
||||
if temp_index_match.0 > index_match.0 {
|
||||
index_match = temp_index_match;
|
||||
}
|
||||
}
|
||||
if index_match.0 == 0 {
|
||||
return None;
|
||||
} else {
|
||||
return Some((index_match.0, String::from(index_match.1)));
|
||||
}
|
||||
}
|
||||
|
||||
/// `can_send_request` checks if a request can be sent. It returns a `bool` that indicates if
|
||||
/// the request can be sent.
|
||||
fn can_send_request(&mut self, request: RequestBuilder) -> bool {
|
||||
// get the url from request
|
||||
let global_limit = self.get_limit("global").unwrap();
|
||||
let ip_limit = self.get_limit("ip").unwrap();
|
||||
|
||||
if ip_limit.remaining == 0 || global_limit.remaining == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let url_path = request
|
||||
.try_clone()
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap()
|
||||
.url()
|
||||
.path()
|
||||
.to_string();
|
||||
// Define the different rate limit buckets as they would appear in the URL
|
||||
let matches = [
|
||||
"login", "register", "webhooks", "channels", "messages", "guilds",
|
||||
];
|
||||
let index_match_string = LimitedRequester::last_match(&url_path, matches.to_vec())
|
||||
.unwrap_or_else(|| (0, String::from("")));
|
||||
if index_match_string.0 == 0 {
|
||||
return true;
|
||||
}
|
||||
let index_match = (index_match_string.0, index_match_string.1.as_str());
|
||||
match index_match.1 {
|
||||
"login" => {
|
||||
let auth_limit = self.get_limit("login").unwrap();
|
||||
if auth_limit.remaining != 0 {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
"register" => {
|
||||
let auth_limit = self.get_limit("auth.register").unwrap();
|
||||
let absolute_limit = self.get_limit("absoluteRate.register").unwrap();
|
||||
if auth_limit.remaining != 0 && absolute_limit.remaining != 0 {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
"messages" => {
|
||||
let absolute_limit = self.get_limit("absoluteRate.sendMessages").unwrap();
|
||||
let request_method = request
|
||||
.try_clone()
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap()
|
||||
.method()
|
||||
.as_str()
|
||||
.to_owned();
|
||||
if absolute_limit.remaining != 0
|
||||
|| request_method != "POST"
|
||||
|| request_method != "PUT"
|
||||
|| request_method != "PATCH"
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
"webhooks" => {
|
||||
let auth_limit = self.get_limit("webhooks").unwrap();
|
||||
if auth_limit.remaining != 0 {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
"channels" => {
|
||||
let auth_limit = self.get_limit("channels").unwrap();
|
||||
if auth_limit.remaining != 0 {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
"guilds" => {
|
||||
let auth_limit = self.get_limit("guilds").unwrap();
|
||||
if auth_limit.remaining != 0 {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
&_ => {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `update_limits` updates the `Limit`s of the `LimitedRequester` based on the response headers
|
||||
/// of the request that was just sent.
|
||||
fn update_limits(&mut self, response: &reqwest::Response) {
|
||||
let headers = response.headers();
|
||||
let mut reset_epoch = 0;
|
||||
for limit in self.limits.iter_mut() {
|
||||
if let Some(value) = headers.get(limit.bucket.clone()) {
|
||||
limit.remaining = value.to_str().unwrap().parse().unwrap();
|
||||
}
|
||||
if let Some(value) = headers.get("X-RateLimit-Reset".to_string()) {
|
||||
reset_epoch = value.to_str().unwrap().parse().unwrap();
|
||||
}
|
||||
}
|
||||
if reset_epoch != 0 {
|
||||
self.last_reset_epoch = reset_epoch;
|
||||
}
|
||||
}
|
||||
|
||||
/// `send_request` sends a request to the server, if `can_send_request()` is true.
|
||||
/// It will then update the `Limit`s by calling `update_limits()`.
|
||||
/// # Example
|
||||
pub async fn send_request(&mut self, request: RequestBuilder) -> reqwest::Response {
|
||||
if !self.can_send_request(request.try_clone().unwrap()) {
|
||||
panic!("429: Rate limited");
|
||||
}
|
||||
let response = request.send().await.unwrap();
|
||||
self.update_limits(&response);
|
||||
// TODO: This does not use the request queue at all. Implement! >:3
|
||||
response
|
||||
}
|
||||
|
||||
/// check_limits uses the API to get the current request limits of the instance.
|
||||
/// It returns a `Vec` of `Limit`s, which can be used to check if a request can be sent.
|
||||
pub async fn check_limits(api_url: String) -> Vec<Limit> {
|
||||
|
|
Loading…
Reference in New Issue