mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-09-26 23:52:05 +00:00
fix(rate-limit): charge plain messages and chat actions to the global bucket
send_media_group, send_animation and copy_messages paced themselves against both buckets; send_message and send_chat_action paced against neither. A dead-letter storm — or one error reply per failed item, plus the action refresh loop's repeated typing requests — could therefore burst past Telegram's per-bot30/s ceiling with only429s left to absorb it, exactly what the bot-wide bucket exists to prevent. Both now acquire one global token like their siblings (per-chat pacing for messages already happens at their call sites; chat actions are cheap and frequent, so only the global bucket applies to them).
This commit is contained in:
@@ -185,6 +185,10 @@ impl MediaSender for Bot {
|
|||||||
reply_markup: Option<InlineKeyboardMarkup>,
|
reply_markup: Option<InlineKeyboardMarkup>,
|
||||||
) -> BoxFuture<'_, Result<i64, RequestError>> {
|
) -> BoxFuture<'_, Result<i64, RequestError>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
|
// Plain messages never met a bucket: a dead-letter storm (or one
|
||||||
|
// error reply per failed item) could burst past Telegram's
|
||||||
|
// per-bot ceiling with only 429s left to absorb it.
|
||||||
|
crate::rate_limit::acquire_global(1.0).await;
|
||||||
let mut request = <Bot as Requester>::send_message(self, chat_id, text);
|
let mut request = <Bot as Requester>::send_message(self, chat_id, text);
|
||||||
if let Some(reply_to) = reply_to {
|
if let Some(reply_to) = reply_to {
|
||||||
request = request
|
request = request
|
||||||
@@ -272,6 +276,10 @@ impl MediaSender for Bot {
|
|||||||
action: ChatAction,
|
action: ChatAction,
|
||||||
) -> BoxFuture<'_, Result<(), RequestError>> {
|
) -> BoxFuture<'_, Result<(), RequestError>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
|
// Same gap as send_message: actions count against the bot-wide
|
||||||
|
// budget too (see there); the refresh loop behind
|
||||||
|
// `run_with_chat_action` makes them frequent enough to matter.
|
||||||
|
crate::rate_limit::acquire_global(1.0).await;
|
||||||
// teloxide's `send_chat_action` returns `Result<True, _>` (its
|
// teloxide's `send_chat_action` returns `Result<True, _>` (its
|
||||||
// unit marker type); map the success to `()`.
|
// unit marker type); map the success to `()`.
|
||||||
<Bot as Requester>::send_chat_action(self, chat_id, action)
|
<Bot as Requester>::send_chat_action(self, chat_id, action)
|
||||||
|
|||||||
Reference in New Issue
Block a user