Re-organized providers and added a few
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::time::Instant;
|
||||
|
||||
/// A simple rate limiter that enforces a minimum interval between requests.
|
||||
pub struct RateLimiter {
|
||||
last_request: Mutex<Instant>,
|
||||
interval: Duration,
|
||||
}
|
||||
|
||||
impl RateLimiter {
|
||||
pub fn new(interval: Duration) -> Self {
|
||||
Self {
|
||||
last_request: Mutex::new(Instant::now() - interval),
|
||||
interval,
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait if needed so we don't exceed the rate limit.
|
||||
pub async fn wait(&self) {
|
||||
let mut last = self.last_request.lock().await;
|
||||
let elapsed = last.elapsed();
|
||||
if elapsed < self.interval {
|
||||
tokio::time::sleep(self.interval - elapsed).await;
|
||||
}
|
||||
*last = Instant::now();
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a reqwest client with a custom user agent and timeout.
|
||||
pub fn build_client(user_agent: &str, timeout_secs: u64) -> reqwest::Result<reqwest::Client> {
|
||||
reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(Duration::from_secs(timeout_secs))
|
||||
.build()
|
||||
}
|
||||
|
||||
/// Simple URL-encode for query parameters.
|
||||
pub fn urlencoded(s: &str) -> String {
|
||||
s.replace(' ', "+")
|
||||
.replace('&', "%26")
|
||||
.replace('=', "%3D")
|
||||
.replace('#', "%23")
|
||||
}
|
||||
|
||||
/// Escape special characters for MusicBrainz Lucene query syntax.
|
||||
pub fn escape_lucene(s: &str) -> String {
|
||||
let special = [
|
||||
'+', '-', '&', '|', '!', '(', ')', '{', '}', '[', ']', '^', '"', '~', '*', '?', ':', '\\',
|
||||
'/',
|
||||
];
|
||||
let mut result = String::with_capacity(s.len());
|
||||
for c in s.chars() {
|
||||
if special.contains(&c) {
|
||||
result.push('\\');
|
||||
}
|
||||
result.push(c);
|
||||
}
|
||||
result
|
||||
}
|
||||
Reference in New Issue
Block a user