Skip to content

Commit

Permalink
[Telegram] Wait then retry if rate limited
Browse files Browse the repository at this point in the history
  • Loading branch information
SpriteOvO committed Nov 14, 2024
1 parent 0aff506 commit c33ac7b
Showing 1 changed file with 39 additions and 4 deletions.
43 changes: 39 additions & 4 deletions src/notify/platform/telegram/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,36 @@ impl<'a> Request<'a> {
method: &str,
body: &json::Value,
) -> anyhow::Result<Response<T>> {
Self::send_request_with_files(self, method, body, None as Option<[FileUrl; 0]>).await
self.send_request_inner(method, body, None as Option<[FileUrl; 0]>, true)
.await
}

async fn send_request_with_files<T: DeserializeOwned>(
&self,
method: &str,
body: &json::Value,
file_urls: impl IntoIterator<Item = FileUrl<'_>>,
) -> anyhow::Result<Response<T>> {
self.send_request_inner(method, body, Some(file_urls), true)
.await
}

async fn send_request_inner<T: DeserializeOwned>(
&self,
method: &str,
body: &json::Value,
// If `file_urls` specified, the media fields in body should be replaced with
// "attach://{index}"
file_urls: Option<impl IntoIterator<Item = FileUrl<'_>>>,
retry: bool,
) -> anyhow::Result<Response<T>> {
let file_urls = file_urls.map(|f| f.into_iter().collect::<Vec<_>>());

let url = format!("https://api.telegram.org/bot{}/{}", self.token, method);

let mut client = helper::reqwest_client()?.post(url);

if let Some(file_urls) = file_urls {
if let Some(file_urls) = file_urls.as_ref().map(|f| f.clone()) {
let form = form_append_json(Form::new(), body.as_object().unwrap());
let form = futures::stream::iter(file_urls)
.enumerate()
Expand Down Expand Up @@ -103,6 +117,27 @@ impl<'a> Request<'a> {
let resp: Response<T> = json::from_str(&text).map_err(|err| {
anyhow!("failed to deserialize response: {err}, status: {status}, text: '{text}', request '{body}'")
})?;

if retry {
if !resp.ok && resp.description.is_some() {
if let Some(after) = resp
.description
.as_deref()
.unwrap()
.strip_prefix("Too Many Requests: retry after ")
{
warn!("Telegram rate limited, retry after '{}' + 1 seconds", after);

let after = after
.parse::<u64>()
.map_err(|err| anyhow!("failed to parse rate limit duration: {err}"))?;
tokio::time::sleep(tokio::time::Duration::from_secs(after + 1)).await;

return Box::pin(self.send_request_inner(method, body, file_urls, false)).await;
}
}
}

Ok(resp)
}

Expand Down Expand Up @@ -504,7 +539,7 @@ impl<'a> SendMedia<'a> {
};
resp = self
.base
.send_request_with_files(method, &body, Some([file_url]))
.send_request_with_files(method, &body, [file_url])
.await?;
}
Ok(resp)
Expand Down Expand Up @@ -623,7 +658,7 @@ impl<'a> SendMediaGroup<'a> {

resp = self
.base
.send_request_with_files("sendMediaGroup", &body, Some(file_urls))
.send_request_with_files("sendMediaGroup", &body, file_urls)
.await?;
}
Ok(resp)
Expand Down

0 comments on commit c33ac7b

Please sign in to comment.