mirror of
https://github.com/teloxide/teloxide.git
synced 2025-01-09 03:43:22 +01:00
Merge pull request #121 from teloxide/throttle_fix
Fix `Throttle` adaptor
This commit is contained in:
commit
156cff7ce5
3 changed files with 63 additions and 4 deletions
|
@ -11,9 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
- `EditedMessageIsTooLong` error [#109][pr109]
|
||||
- `UntilDate` enum and use it for `{Restricted, Banned}::until_date` ([#116][pr116])
|
||||
- `Limits::messages_per_min_channel` ([#121][pr121])
|
||||
|
||||
[pr109]: https://github.com/teloxide/teloxide-core/pull/109
|
||||
[pr116]: https://github.com/teloxide/teloxide-core/pull/116
|
||||
[pr121]: https://github.com/teloxide/teloxide-core/pull/121
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -26,8 +28,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Type of `BanChatMember::until_date`: `u64` -> `chrono::DateTime<Utc>` ([#116][pr116])
|
||||
- Type of `Poll::correct_option_id`: `i32` -> `u8` ([#119][pr119])
|
||||
- Type of `Poll::open_period`: `i32` -> `u16` ([#119][pr119])
|
||||
- `Throttle` adaptor not honouring chat/min limits ([#121][pr121])
|
||||
|
||||
[pr119]: https://github.com/teloxide/teloxide-core/pull/119
|
||||
|
||||
## 0.3.3 - 2021-08-03
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -203,11 +203,15 @@ pub struct Limits {
|
|||
/// Allowed messages in one chat per minute.
|
||||
pub messages_per_min_chat: u32,
|
||||
|
||||
/// Allowed messages in one channel per minute.
|
||||
pub messages_per_min_channel: u32,
|
||||
|
||||
/// Allowed messages per second.
|
||||
pub messages_per_sec_overall: u32,
|
||||
}
|
||||
|
||||
/// Defaults are taken from [telegram documentation][tgdoc].
|
||||
/// Defaults are taken from [telegram documentation][tgdoc] (except for
|
||||
/// `messages_per_min_channel`).
|
||||
///
|
||||
/// [tgdoc]: https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this
|
||||
impl Default for Limits {
|
||||
|
@ -216,6 +220,7 @@ impl Default for Limits {
|
|||
messages_per_sec_chat: 1,
|
||||
messages_per_sec_overall: 30,
|
||||
messages_per_min_chat: 20,
|
||||
messages_per_min_channel: 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -465,9 +470,17 @@ async fn worker(
|
|||
|
||||
while let Some(entry) = queue_removing.next() {
|
||||
let chat = &entry.value().0;
|
||||
let requests_sent_count = requests_sent.per_sec.get(chat).copied().unwrap_or(0);
|
||||
let limits_not_exceeded = requests_sent_count < limits.messages_per_sec_chat
|
||||
&& requests_sent_count < limits.messages_per_min_chat;
|
||||
let requests_sent_per_sec_count = requests_sent.per_sec.get(chat).copied().unwrap_or(0);
|
||||
let requests_sent_per_min_count = requests_sent.per_min.get(chat).copied().unwrap_or(0);
|
||||
|
||||
let messages_per_min_limit = if chat.is_channel() {
|
||||
limits.messages_per_min_channel
|
||||
} else {
|
||||
limits.messages_per_min_chat
|
||||
};
|
||||
|
||||
let limits_not_exceeded = requests_sent_per_sec_count < limits.messages_per_sec_chat
|
||||
&& requests_sent_per_min_count < messages_per_min_limit;
|
||||
|
||||
if limits_not_exceeded {
|
||||
*requests_sent.per_sec.entry(*chat).or_insert(0) += 1;
|
||||
|
@ -627,6 +640,15 @@ enum ChatIdHash {
|
|||
ChannelUsernameHash(u64),
|
||||
}
|
||||
|
||||
impl ChatIdHash {
|
||||
fn is_channel(&self) -> bool {
|
||||
match self {
|
||||
&Self::Id(id) => ChatId::Id(id).is_channel(),
|
||||
Self::ChannelUsernameHash(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ChatId> for ChatIdHash {
|
||||
fn from(value: &ChatId) -> Self {
|
||||
match value {
|
||||
|
|
|
@ -15,6 +15,39 @@ pub enum ChatId {
|
|||
ChannelUsername(String),
|
||||
}
|
||||
|
||||
impl ChatId {
|
||||
pub(crate) fn is_channel(&self) -> bool {
|
||||
matches!(self.unmark(), None | Some(UnmarkedChatId::Channel(_)))
|
||||
}
|
||||
|
||||
pub(crate) fn unmark(&self) -> Option<UnmarkedChatId> {
|
||||
use UnmarkedChatId::*;
|
||||
|
||||
const MAX_CHANNEL_ID: i64 = -(10i64.pow(12));
|
||||
const MIN_CHANNEL_ID: i64 = MAX_CHANNEL_ID - (i32::MAX as i64);
|
||||
const MAX_USER_ID: i64 = i32::MAX as _;
|
||||
const MIN_CHAT_ID: i64 = -MAX_USER_ID;
|
||||
|
||||
let res = match self {
|
||||
&Self::Id(id @ MIN_CHAT_ID..=-1) => Chat(-id as _),
|
||||
&Self::Id(id @ MIN_CHANNEL_ID..=MAX_CHANNEL_ID) => Channel((MAX_CHANNEL_ID - id) as _),
|
||||
&Self::Id(id) => {
|
||||
debug_assert!(0 < id && id < MAX_USER_ID, "malformed chat id");
|
||||
User(id as _)
|
||||
}
|
||||
Self::ChannelUsername(_) => return None,
|
||||
};
|
||||
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum UnmarkedChatId {
|
||||
User(u32),
|
||||
Chat(u32),
|
||||
Channel(u32),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
Loading…
Reference in a new issue