From a9a0140476fae8edd4741f2a85dc3148b15ec679 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 6 Jul 2023 14:47:31 +0300 Subject: [PATCH] Keep last time when a file was uploaded. --- telegram-bot-api/Client.cpp | 59 ++++++++++++++++++++++++++++++++++++- telegram-bot-api/Client.h | 7 ++++- telegram-bot-api/Query.h | 12 ++++++-- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index bcb1bd3..ca01e24 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -10028,7 +10028,64 @@ void Client::finish_set_webhook(PromisedQueryPtr query) { webhook_set_query_ = std::move(query); } -void Client::do_send_message(object_ptr input_message_content, PromisedQueryPtr query) { +void Client::delete_last_send_message_time(td::int64 file_size, double max_delay) { + auto last_send_message_time = last_send_message_time_.get(file_size); + if (last_send_message_time == 0.0) { + return; + } + if (last_send_message_time < td::Time::now() - max_delay) { + LOG(DEBUG) << "Clear last send message time for size " << file_size; + last_send_message_time_.erase(file_size); + } +} + +void Client::do_send_message(object_ptr input_message_content, PromisedQueryPtr query, + bool force) { + if (!parameters_->local_mode_) { + if (!force) { + auto file_size = query->files_size(); + if (file_size > 100000) { + auto &last_send_message_time = last_send_message_time_[file_size]; + auto now = td::Time::now(); + auto min_delay = td::clamp(static_cast(file_size) * 1e-7, 0.1, 0.5); + auto max_bucket_volume = 1.0; + if (last_send_message_time > now + 5.0) { + return fail_query_flood_limit_exceeded(std::move(query)); + } + + last_send_message_time = td::max(last_send_message_time + min_delay, now - max_bucket_volume); + LOG(DEBUG) << "Query with files of size " << file_size << " can be processed in " + << last_send_message_time - now << " seconds"; + + td::create_actor( + "DeleteLastSendMessageTimeSleepActor", last_send_message_time + min_delay - (now - max_bucket_volume), + td::PromiseCreator::lambda([actor_id = actor_id(this), file_size, + max_delay = max_bucket_volume + min_delay](td::Result) mutable { + send_closure(actor_id, &Client::delete_last_send_message_time, file_size, max_delay); + })) + .release(); + + if (last_send_message_time > now) { + td::create_actor( + "DoSendMessageSleepActor", last_send_message_time - now, + td::PromiseCreator::lambda([actor_id = actor_id(this), + input_message_content = std::move(input_message_content), + query = std::move(query)](td::Result) mutable { + send_closure(actor_id, &Client::do_send_message, std::move(input_message_content), std::move(query), + true); + })) + .release(); + return; + } + } + } else { + if (logging_out_ || closing_) { + return fail_query_closing(std::move(query)); + } + CHECK(was_authorized_); + } + } + auto chat_id = query->arg("chat_id"); auto message_thread_id = get_message_id(query.get(), "message_thread_id"); auto reply_to_message_id = get_message_id(query.get(), "reply_to_message_id"); diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index 07e01c1..e31c45a 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -639,7 +639,10 @@ class Client final : public WebhookActor::Callback { void on_webhook_closed(td::Status status); - void do_send_message(object_ptr input_message_content, PromisedQueryPtr query); + void delete_last_send_message_time(td::int64 file_size, double max_delay); + + void do_send_message(object_ptr input_message_content, PromisedQueryPtr query, + bool force = false); int64 get_send_message_query_id(PromisedQueryPtr query, bool is_multisend); @@ -1082,6 +1085,8 @@ class Client final : public WebhookActor::Callback { td::WaitFreeHashMap sticker_set_names_; + td::WaitFreeHashMap last_send_message_time_; + struct BotUserIds { int64 default_bot_user_id_ = 0; int64 cur_temp_bot_user_id_ = 1; diff --git a/telegram-bot-api/Query.h b/telegram-bot-api/Query.h index 0b7b51e..5044ce0 100644 --- a/telegram-bot-api/Query.h +++ b/telegram-bot-api/Query.h @@ -38,38 +38,48 @@ class Query final : public td::ListNode { td::Slice token() const { return token_; } + bool is_test_dc() const { return is_test_dc_; } + td::Slice method() const { return method_; } + bool has_arg(td::Slice key) const { auto it = std::find_if(args_.begin(), args_.end(), [&key](const std::pair &s) { return s.first == key; }); return it != args_.end(); } + td::MutableSlice arg(td::Slice key) const { auto it = std::find_if(args_.begin(), args_.end(), [&key](const std::pair &s) { return s.first == key; }); return it == args_.end() ? td::MutableSlice() : it->second; } + const td::vector> &args() const { return args_; } + td::Slice get_header(td::Slice key) const { auto it = std::find_if(headers_.begin(), headers_.end(), [&key](const std::pair &s) { return s.first == key; }); return it == headers_.end() ? td::Slice() : it->second; } + const td::HttpFile *file(td::Slice key) const { auto it = std::find_if(files_.begin(), files_.end(), [&key](const td::HttpFile &f) { return f.field_name == key; }); return it == files_.end() ? nullptr : &*it; } + const td::vector &files() const { return files_; } + td::int64 files_size() const; + td::string get_peer_ip_address() const; td::BufferSlice &answer() { @@ -152,8 +162,6 @@ class Query final : public td::ListNode { td::int64 query_size() const; - td::int64 files_size() const; - td::int64 files_max_size() const; void send_request_stat() const;