From 4f3105f4a404ff69a0533f2b42b604dd611054a3 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 29 Jun 2022 18:51:24 +0300 Subject: [PATCH 01/15] Rely on TDLib checks for downloaded file existence. --- telegram-bot-api/Client.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index ca5db6a..d0c8121 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -8474,16 +8474,6 @@ void Client::do_get_file(object_ptr file, PromisedQueryPtr query) auto file_id = file->id_; file_download_listeners_[file_id].push_back(std::move(query)); - if (file->local_->is_downloading_completed_) { - Slice relative_path = td::PathView::relative(file->local_->path_, dir_, true); - if (!relative_path.empty()) { - auto r_stat = td::stat(file->local_->path_); - if (r_stat.is_ok() && r_stat.ok().is_reg_ && r_stat.ok().size_ == file->size_) { - return on_file_download(file_id, std::move(file)); - } - } - } - send_request(make_object(file_id, 1, 0, 0, false), td::make_unique(this, file_id)); } From 3de310c9512881be52366cc0e119db85e955e300 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 30 Jun 2022 19:59:30 +0300 Subject: [PATCH 02/15] Use LambdaPromise instead of PromiseActor. --- td | 2 +- telegram-bot-api/ClientManager.cpp | 4 +- telegram-bot-api/ClientManager.h | 2 +- telegram-bot-api/HttpConnection.cpp | 17 +++--- telegram-bot-api/HttpConnection.h | 5 +- telegram-bot-api/HttpStatConnection.cpp | 18 +++---- telegram-bot-api/HttpStatConnection.h | 8 +-- telegram-bot-api/Query.h | 8 +-- telegram-bot-api/WebhookActor.cpp | 72 ++++++++++++------------- telegram-bot-api/WebhookActor.h | 3 +- 10 files changed, 65 insertions(+), 74 deletions(-) diff --git a/td b/td index b393215..9a061c3 160000 --- a/td +++ b/td @@ -1 +1 @@ -Subproject commit b393215d6671863b6baf2a589d343cff9474f6ba +Subproject commit 9a061c30c1f1928f12bdb3feb2108a8052b102be diff --git a/telegram-bot-api/ClientManager.cpp b/telegram-bot-api/ClientManager.cpp index 13bf98a..12074c0 100644 --- a/telegram-bot-api/ClientManager.cpp +++ b/telegram-bot-api/ClientManager.cpp @@ -145,7 +145,7 @@ void ClientManager::send(PromisedQueryPtr query) { std::move(query)); // will send 429 if the client is already closed } -void ClientManager::get_stats(td::PromiseActor promise, +void ClientManager::get_stats(td::Promise promise, td::vector> args) { if (close_flag_) { promise.set_value(td::BufferSlice("Closing")); @@ -394,7 +394,7 @@ PromisedQueryPtr ClientManager::get_webhook_restore_query(td::Slice token, td::S auto query = td::make_unique(std::move(containers), token, is_test_dc, method, std::move(args), td::vector>(), td::vector(), std::move(shared_data), td::IPAddress(), true); - return PromisedQueryPtr(query.release(), PromiseDeleter(td::PromiseActor>())); + return PromisedQueryPtr(query.release(), PromiseDeleter(td::Promise>())); } void ClientManager::raw_event(const td::Event::Raw &event) { diff --git a/telegram-bot-api/ClientManager.h b/telegram-bot-api/ClientManager.h index 1dcc093..9bf30c4 100644 --- a/telegram-bot-api/ClientManager.h +++ b/telegram-bot-api/ClientManager.h @@ -43,7 +43,7 @@ class ClientManager final : public td::Actor { void send(PromisedQueryPtr query); - void get_stats(td::PromiseActor promise, td::vector> args); + void get_stats(td::Promise promise, td::vector> args); void close(td::Promise &&promise); diff --git a/telegram-bot-api/HttpConnection.cpp b/telegram-bot-api/HttpConnection.cpp index 68dcdec..5d718f3 100644 --- a/telegram-bot-api/HttpConnection.cpp +++ b/telegram-bot-api/HttpConnection.cpp @@ -48,22 +48,17 @@ void HttpConnection::handle(td::unique_ptr http_query, std::move(http_query->args_), std::move(http_query->headers_), std::move(http_query->files_), shared_data_, http_query->peer_address_, false); - td::PromiseActor> promise; - td::FutureActor> future; - td::init_promise_future(&promise, &future); - future.set_event(td::EventCreator::yield(actor_id())); + auto promise = td::PromiseCreator::lambda([actor_id = actor_id(this)](td::Result> r_query) { + send_closure(actor_id, &HttpConnection::on_query_finished, std::move(r_query)); + }); auto promised_query = PromisedQueryPtr(query.release(), PromiseDeleter(std::move(promise))); send_closure(client_manager_, &ClientManager::send, std::move(promised_query)); - result_ = std::move(future); } -void HttpConnection::wakeup() { - if (result_.empty()) { - return; - } - LOG_CHECK(result_.is_ok()) << result_.move_as_error(); +void HttpConnection::on_query_finished(td::Result> r_query) { + LOG_CHECK(r_query.is_ok()) << r_query.error(); - auto query = result_.move_as_ok(); + auto query = r_query.move_as_ok(); send_response(query->http_status_code(), std::move(query->answer()), query->retry_after()); } diff --git a/telegram-bot-api/HttpConnection.h b/telegram-bot-api/HttpConnection.h index d631244..c2e1148 100644 --- a/telegram-bot-api/HttpConnection.h +++ b/telegram-bot-api/HttpConnection.h @@ -32,10 +32,7 @@ class HttpConnection final : public td::HttpInboundConnection::Callback { void handle(td::unique_ptr http_query, td::ActorOwn connection) final; - void wakeup() final; - private: - td::FutureActor> result_; td::ActorId client_manager_; td::ActorOwn connection_; std::shared_ptr shared_data_; @@ -45,6 +42,8 @@ class HttpConnection final : public td::HttpInboundConnection::Callback { stop(); } + void on_query_finished(td::Result> r_query); + void send_response(int http_status_code, td::BufferSlice &&content, int retry_after); void send_http_error(int http_status_code, td::Slice description); diff --git a/telegram-bot-api/HttpStatConnection.cpp b/telegram-bot-api/HttpStatConnection.cpp index 9d66aba..21ac451 100644 --- a/telegram-bot-api/HttpStatConnection.cpp +++ b/telegram-bot-api/HttpStatConnection.cpp @@ -18,22 +18,20 @@ void HttpStatConnection::handle(td::unique_ptr http_query, CHECK(connection_->empty()); connection_ = std::move(connection); - td::PromiseActor promise; - td::FutureActor future; - init_promise_future(&promise, &future); - future.set_event(td::EventCreator::yield(actor_id())); - LOG(DEBUG) << "SEND"; + auto promise = td::PromiseCreator::lambda([actor_id = actor_id(this)](td::Result result) { + send_closure(actor_id, &HttpStatConnection::on_result, std::move(result)); + }); send_closure(client_manager_, &ClientManager::get_stats, std::move(promise), http_query->get_args()); - result_ = std::move(future); } -void HttpStatConnection::wakeup() { - if (result_.empty()) { +void HttpStatConnection::on_result(td::Result result) { + if (result.is_error()) { + send_closure(connection_.release(), &td::HttpInboundConnection::write_error, + td::Status::Error(500, "Internal Server Error: closing")); return; } - LOG_CHECK(result_.is_ok()) << result_.move_as_error(); - auto content = result_.move_as_ok(); + auto content = result.move_as_ok(); td::HttpHeaderCreator hc; hc.init_status_line(200); hc.set_keep_alive(); diff --git a/telegram-bot-api/HttpStatConnection.h b/telegram-bot-api/HttpStatConnection.h index 614f5ca..dc1fa63 100644 --- a/telegram-bot-api/HttpStatConnection.h +++ b/telegram-bot-api/HttpStatConnection.h @@ -12,9 +12,9 @@ #include "td/net/HttpQuery.h" #include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" #include "td/utils/buffer.h" +#include "td/utils/Status.h" namespace telegram_bot_api { @@ -22,15 +22,15 @@ class HttpStatConnection final : public td::HttpInboundConnection::Callback { public: explicit HttpStatConnection(td::ActorId client_manager) : client_manager_(client_manager) { } + void handle(td::unique_ptr http_query, td::ActorOwn connection) final; - void wakeup() final; - private: - td::FutureActor result_; td::ActorId client_manager_; td::ActorOwn connection_; + void on_result(td::Result result); + void hangup() final { connection_.release(); stop(); diff --git a/telegram-bot-api/Query.h b/telegram-bot-api/Query.h index 96bd056..c1df8b5 100644 --- a/telegram-bot-api/Query.h +++ b/telegram-bot-api/Query.h @@ -227,7 +227,7 @@ class JsonQueryError final : public td::Jsonable { class PromiseDeleter { public: - explicit PromiseDeleter(td::PromiseActor> &&promise) : promise_(std::move(promise)) { + explicit PromiseDeleter(td::Promise> &&promise) : promise_(std::move(promise)) { } PromiseDeleter() = default; PromiseDeleter(const PromiseDeleter &) = delete; @@ -236,7 +236,7 @@ class PromiseDeleter { PromiseDeleter &operator=(PromiseDeleter &&) = default; void operator()(Query *raw_ptr) { td::unique_ptr query(raw_ptr); // now I cannot forget to delete this pointer - if (!promise_.empty_promise()) { + if (promise_) { if (!query->is_ready()) { query->set_retry_after_error(5); } @@ -245,11 +245,11 @@ class PromiseDeleter { } } ~PromiseDeleter() { - CHECK(promise_.empty()); + CHECK(!promise_); } private: - td::PromiseActor> promise_; + td::Promise> promise_; }; using PromisedQueryPtr = std::unique_ptr; diff --git a/telegram-bot-api/WebhookActor.cpp b/telegram-bot-api/WebhookActor.cpp index 68b9ac9..095b5cf 100644 --- a/telegram-bot-api/WebhookActor.cpp +++ b/telegram-bot-api/WebhookActor.cpp @@ -82,7 +82,7 @@ void WebhookActor::relax_wakeup_at(double wakeup_at, const char *source) { } void WebhookActor::resolve_ip_address() { - if (fix_ip_address_) { + if (fix_ip_address_ || is_ip_address_being_resolved_) { return; } if (td::Time::now() < next_ip_address_resolve_time_) { @@ -90,43 +90,42 @@ void WebhookActor::resolve_ip_address() { return; } - bool future_created = false; - if (future_ip_address_.empty()) { - td::PromiseActor promise; - init_promise_future(&promise, &future_ip_address_); - future_created = true; - send_closure(parameters_->get_host_by_name_actor_id_, &td::GetHostByNameActor::run, url_.host_, url_.port_, false, - td::PromiseCreator::from_promise_actor(std::move(promise))); + is_ip_address_being_resolved_ = true; + auto promise = td::PromiseCreator::lambda([actor_id = actor_id(this)](td::Result r_ip_address) { + send_closure(actor_id, &WebhookActor::on_resolved_ip_address, std::move(r_ip_address)); + }); + send_closure(parameters_->get_host_by_name_actor_id_, &td::GetHostByNameActor::run, url_.host_, url_.port_, false, + std::move(promise)); +} + +void WebhookActor::on_resolved_ip_address(td::Result r_ip_address) { + CHECK(is_ip_address_being_resolved_); + is_ip_address_being_resolved_ = false; + + next_ip_address_resolve_time_ = + td::Time::now() + IP_ADDRESS_CACHE_TIME + td::Random::fast(0, IP_ADDRESS_CACHE_TIME / 10); + relax_wakeup_at(next_ip_address_resolve_time_, "on_resolved_ip_address"); + + SCOPE_EXIT { + loop(); + }; + + if (r_ip_address.is_error()) { + return on_error(r_ip_address.move_as_error()); } - - if (future_ip_address_.is_ready()) { - next_ip_address_resolve_time_ = - td::Time::now() + IP_ADDRESS_CACHE_TIME + td::Random::fast(0, IP_ADDRESS_CACHE_TIME / 10); - relax_wakeup_at(next_ip_address_resolve_time_, "resolve_ip_address"); - - auto r_ip_address = future_ip_address_.move_as_result(); - if (r_ip_address.is_error()) { - CHECK(!(r_ip_address.error() == td::Status::Error::HANGUP_ERROR_CODE>())); - return on_error(r_ip_address.move_as_error()); - } - auto new_ip_address = r_ip_address.move_as_ok(); - if (!check_ip_address(new_ip_address)) { - return on_error(td::Status::Error(PSLICE() << "IP address " << new_ip_address.get_ip_str() << " is reserved")); - } - if (!(ip_address_ == new_ip_address)) { - VLOG(webhook) << "IP address has changed: " << ip_address_ << " --> " << new_ip_address; - ip_address_ = new_ip_address; - ip_generation_++; - if (was_checked_) { - on_webhook_verified(); - } - } - VLOG(webhook) << "IP address was verified"; - } else { - if (future_created) { - future_ip_address_.set_event(td::EventCreator::yield(actor_id())); + auto new_ip_address = r_ip_address.move_as_ok(); + if (!check_ip_address(new_ip_address)) { + return on_error(td::Status::Error(PSLICE() << "IP address " << new_ip_address.get_ip_str() << " is reserved")); + } + if (!(ip_address_ == new_ip_address)) { + VLOG(webhook) << "IP address has changed: " << ip_address_ << " --> " << new_ip_address; + ip_address_ = new_ip_address; + ip_generation_++; + if (was_checked_) { + on_webhook_verified(); } } + VLOG(webhook) << "IP address was verified"; } td::Status WebhookActor::create_connection() { @@ -605,8 +604,7 @@ void WebhookActor::handle(td::unique_ptr response) { td::MutableSlice(), std::move(response->args_), std::move(response->headers_), std::move(response->files_), parameters_->shared_data_, response->peer_address_, false); - auto promised_query = - PromisedQueryPtr(query.release(), PromiseDeleter(td::PromiseActor>())); + auto promised_query = PromisedQueryPtr(query.release(), PromiseDeleter(td::Promise>())); send_closure(callback_, &Callback::send, std::move(promised_query)); } first_error_410_time_ = 0; diff --git a/telegram-bot-api/WebhookActor.h b/telegram-bot-api/WebhookActor.h index d5e2499..4ca2c34 100644 --- a/telegram-bot-api/WebhookActor.h +++ b/telegram-bot-api/WebhookActor.h @@ -137,7 +137,7 @@ class WebhookActor final : public td::HttpOutboundConnection::Callback { td::IPAddress ip_address_; td::int32 ip_generation_ = 0; double next_ip_address_resolve_time_ = 0; - td::FutureActor future_ip_address_; + bool is_ip_address_being_resolved_ = false; class Connection final : public td::ListNode { public: @@ -175,6 +175,7 @@ class WebhookActor final : public td::HttpOutboundConnection::Callback { void relax_wakeup_at(double wakeup_at, const char *source); void resolve_ip_address(); + void on_resolved_ip_address(td::Result r_ip_address); td::Result create_ssl_stream(); td::Status create_connection() TD_WARN_UNUSED_RESULT; From 95131fe3766310bf90dc3d7496e1da20a409a41f Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 30 Jun 2022 20:27:08 +0300 Subject: [PATCH 03/15] Update TDLib. --- build.html | 4 ++-- telegram-bot-api/Client.cpp | 2 -- telegram-bot-api/Client.h | 2 +- telegram-bot-api/ClientManager.cpp | 2 +- telegram-bot-api/ClientManager.h | 2 +- telegram-bot-api/HttpConnection.cpp | 1 + telegram-bot-api/HttpConnection.h | 2 +- telegram-bot-api/HttpStatConnection.cpp | 2 +- telegram-bot-api/Query.h | 2 +- telegram-bot-api/WebhookActor.cpp | 2 +- telegram-bot-api/WebhookActor.h | 1 - telegram-bot-api/telegram-bot-api.cpp | 2 +- 12 files changed, 11 insertions(+), 13 deletions(-) diff --git a/build.html b/build.html index 409fb28..d43e23a 100644 --- a/build.html +++ b/build.html @@ -181,7 +181,7 @@
-

Choose an operating system, on which you want to use the Telegram Bot API server:

+

Choose an operating system on which you want to use the Telegram Bot API server:

diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index d0c8121..abd776c 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -10,7 +10,6 @@ #include "td/db/TQueue.h" -#include "td/actor/PromiseFuture.h" #include "td/actor/SleepActor.h" #include "td/utils/algorithm.h" @@ -22,7 +21,6 @@ #include "td/utils/misc.h" #include "td/utils/PathView.h" #include "td/utils/port/path.h" -#include "td/utils/port/Stat.h" #include "td/utils/Slice.h" #include "td/utils/SliceBuilder.h" #include "td/utils/Span.h" diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index 852c309..2a47017 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -16,7 +16,6 @@ #include "td/net/HttpFile.h" #include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" #include "td/actor/SignalSlot.h" #include "td/utils/common.h" @@ -24,6 +23,7 @@ #include "td/utils/FlatHashMap.h" #include "td/utils/FlatHashSet.h" #include "td/utils/JsonBuilder.h" +#include "td/utils/Promise.h" #include "td/utils/Slice.h" #include "td/utils/Status.h" diff --git a/telegram-bot-api/ClientManager.cpp b/telegram-bot-api/ClientManager.cpp index 12074c0..8a58b22 100644 --- a/telegram-bot-api/ClientManager.cpp +++ b/telegram-bot-api/ClientManager.cpp @@ -118,7 +118,7 @@ void ClientManager::send(PromisedQueryPtr query) { flood_control.add_event(static_cast(now)); } auto tqueue_id = get_tqueue_id(user_id, query->is_test_dc()); - if (active_client_count_.find(tqueue_id) != active_client_count_.end()) { + if (active_client_count_.count(tqueue_id) != 0) { // return query->set_retry_after_error(1); } diff --git a/telegram-bot-api/ClientManager.h b/telegram-bot-api/ClientManager.h index 9bf30c4..921aaf0 100644 --- a/telegram-bot-api/ClientManager.h +++ b/telegram-bot-api/ClientManager.h @@ -11,13 +11,13 @@ #include "telegram-bot-api/Stats.h" #include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" #include "td/utils/buffer.h" #include "td/utils/common.h" #include "td/utils/Container.h" #include "td/utils/FlatHashMap.h" #include "td/utils/FloodControlFast.h" +#include "td/utils/Promise.h" #include "td/utils/Slice.h" #include diff --git a/telegram-bot-api/HttpConnection.cpp b/telegram-bot-api/HttpConnection.cpp index 5d718f3..b3fd1cf 100644 --- a/telegram-bot-api/HttpConnection.cpp +++ b/telegram-bot-api/HttpConnection.cpp @@ -14,6 +14,7 @@ #include "td/utils/JsonBuilder.h" #include "td/utils/logging.h" #include "td/utils/Parser.h" +#include "td/utils/Promise.h" #include "td/utils/SliceBuilder.h" namespace telegram_bot_api { diff --git a/telegram-bot-api/HttpConnection.h b/telegram-bot-api/HttpConnection.h index c2e1148..d0d245c 100644 --- a/telegram-bot-api/HttpConnection.h +++ b/telegram-bot-api/HttpConnection.h @@ -13,10 +13,10 @@ #include "td/net/HttpQuery.h" #include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" #include "td/utils/buffer.h" #include "td/utils/Slice.h" +#include "td/utils/Status.h" #include diff --git a/telegram-bot-api/HttpStatConnection.cpp b/telegram-bot-api/HttpStatConnection.cpp index 21ac451..9314a64 100644 --- a/telegram-bot-api/HttpStatConnection.cpp +++ b/telegram-bot-api/HttpStatConnection.cpp @@ -9,7 +9,7 @@ #include "td/net/HttpHeaderCreator.h" #include "td/utils/common.h" -#include "td/utils/logging.h" +#include "td/utils/Promise.h" namespace telegram_bot_api { diff --git a/telegram-bot-api/Query.h b/telegram-bot-api/Query.h index c1df8b5..c315fd5 100644 --- a/telegram-bot-api/Query.h +++ b/telegram-bot-api/Query.h @@ -11,7 +11,6 @@ #include "td/net/HttpFile.h" #include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" #include "td/utils/buffer.h" #include "td/utils/common.h" @@ -19,6 +18,7 @@ #include "td/utils/JsonBuilder.h" #include "td/utils/List.h" #include "td/utils/port/IPAddress.h" +#include "td/utils/Promise.h" #include "td/utils/Slice.h" #include "td/utils/StringBuilder.h" diff --git a/telegram-bot-api/WebhookActor.cpp b/telegram-bot-api/WebhookActor.cpp index 095b5cf..f63cd55 100644 --- a/telegram-bot-api/WebhookActor.cpp +++ b/telegram-bot-api/WebhookActor.cpp @@ -15,7 +15,6 @@ #include "td/net/TransparentProxy.h" #include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" #include "td/utils/base64.h" #include "td/utils/buffer.h" @@ -26,6 +25,7 @@ #include "td/utils/misc.h" #include "td/utils/port/IPAddress.h" #include "td/utils/port/SocketFd.h" +#include "td/utils/Promise.h" #include "td/utils/Random.h" #include "td/utils/ScopeGuard.h" #include "td/utils/SliceBuilder.h" diff --git a/telegram-bot-api/WebhookActor.h b/telegram-bot-api/WebhookActor.h index 4ca2c34..28f5989 100644 --- a/telegram-bot-api/WebhookActor.h +++ b/telegram-bot-api/WebhookActor.h @@ -15,7 +15,6 @@ #include "td/net/SslStream.h" #include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" #include "td/utils/BufferedFd.h" #include "td/utils/common.h" diff --git a/telegram-bot-api/telegram-bot-api.cpp b/telegram-bot-api/telegram-bot-api.cpp index bdce424..97a220a 100644 --- a/telegram-bot-api/telegram-bot-api.cpp +++ b/telegram-bot-api/telegram-bot-api.cpp @@ -22,7 +22,6 @@ #include "td/actor/actor.h" #include "td/actor/ConcurrentScheduler.h" -#include "td/actor/PromiseFuture.h" #include "td/utils/buffer.h" #include "td/utils/CombinedLog.h" @@ -45,6 +44,7 @@ #include "td/utils/port/stacktrace.h" #include "td/utils/port/Stat.h" #include "td/utils/port/user.h" +#include "td/utils/Promise.h" #include "td/utils/Slice.h" #include "td/utils/SliceBuilder.h" #include "td/utils/Status.h" From 0749acb7e647cabdf6c173df4c36cb90cb49351d Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 30 Jun 2022 21:30:14 +0300 Subject: [PATCH 04/15] Use Scheduler::run_on_scheduler. --- telegram-bot-api/Client.cpp | 38 ++++++++++++++----------------------- telegram-bot-api/Client.h | 2 ++ 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index abd776c..70132b0 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -4856,30 +4856,13 @@ void Client::on_closed() { if (logging_out_) { parameters_->shared_data_->webhook_db_->erase(bot_token_with_dc_); - class RmWorker final : public td::Actor { - public: - RmWorker(td::string dir, td::ActorId parent) : dir_(std::move(dir)), parent_(std::move(parent)) { - } - - private: - td::string dir_; - td::ActorId parent_; - - void start_up() final { - CHECK(dir_.size() >= 24); - CHECK(dir_.back() == TD_DIR_SLASH); - td::rmrf(dir_).ignore(); - stop(); - } - void tear_down() final { - send_closure(parent_, &Client::finish_closing); - } - }; - // NB: the same scheduler as for database in Td - auto current_scheduler_id = td::Scheduler::instance()->sched_id(); - auto scheduler_count = td::Scheduler::instance()->sched_count(); - auto scheduler_id = td::min(current_scheduler_id + 1, scheduler_count - 1); - td::create_actor_on_scheduler("RmWorker", scheduler_id, dir_, actor_id(this)).release(); + td::Scheduler::instance()->run_on_scheduler(get_database_scheduler_id(), + [actor_id = actor_id(this), dir = dir_](td::Unit) { + CHECK(dir.size() >= 24); + CHECK(dir.back() == TD_DIR_SLASH); + td::rmrf(dir).ignore(); + send_closure(actor_id, &Client::finish_closing); + }); return; } @@ -4899,6 +4882,13 @@ void Client::timeout_expired() { stop(); } +td::int32 Client::get_database_scheduler_id() { + // NB: the same scheduler as for database in Td + auto current_scheduler_id = td::Scheduler::instance()->sched_id(); + auto scheduler_count = td::Scheduler::instance()->sched_count(); + return td::min(current_scheduler_id + 1, scheduler_count - 1); +} + void Client::clear_tqueue() { CHECK(webhook_id_.empty()); auto &tqueue = parameters_->shared_data_->tqueue_; diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index 2a47017..3bf7265 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -302,6 +302,8 @@ class Client final : public WebhookActor::Callback { void on_closed(); void finish_closing(); + static int32 get_database_scheduler_id(); + void clear_tqueue(); bool allow_update_before_authorization(const td_api::Object *update) const; From ca2bb3cec6e0d657f6b5fca46c7af3bfa3661820 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 1 Jul 2022 13:58:28 +0300 Subject: [PATCH 05/15] Unlink webhook certificate in another thread. --- telegram-bot-api/Client.cpp | 19 +++++++++++++++---- telegram-bot-api/Client.h | 2 ++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 70132b0..ca9e24b 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -8550,14 +8550,25 @@ void Client::webhook_error(Status status) { } void Client::webhook_closed(Status status) { + if (has_webhook_certificate_) { + td::Scheduler::instance()->run_on_scheduler(get_database_scheduler_id(), + [actor_id = actor_id(this), path = get_webhook_certificate_path(), + status = std::move(status)](td::Unit) mutable { + LOG(INFO) << "Unlink certificate " << path; + td::unlink(path).ignore(); + send_closure(actor_id, &Client::on_webhook_closed, std::move(status)); + }); + return; + } + on_webhook_closed(std::move(status)); +} + +void Client::on_webhook_closed(Status status) { LOG(WARNING) << "Webhook closed: " << status << ", webhook_query_type = " << (webhook_query_type_ == WebhookQueryType::Verify ? "verify" : "change"); webhook_id_.release(); webhook_url_ = td::string(); - if (has_webhook_certificate_) { - td::unlink(get_webhook_certificate_path()).ignore(); - has_webhook_certificate_ = false; - } + has_webhook_certificate_ = false; webhook_max_connections_ = 0; webhook_ip_address_ = td::string(); webhook_fix_ip_address_ = false; diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index 3bf7265..af10157 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -563,6 +563,8 @@ class Client final : public WebhookActor::Callback { void save_webhook() const; td::string get_webhook_certificate_path() const; + void on_webhook_closed(Status status); + void do_send_message(object_ptr input_message_content, PromisedQueryPtr query); int64 get_send_message_query_id(PromisedQueryPtr query, bool is_multisend); From c23763484739772649f164a21c5a58cfee65663d Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 9 Jul 2022 14:08:08 +0300 Subject: [PATCH 06/15] Improve warnings about size of update queue. --- telegram-bot-api/Client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index ca9e24b..70e7c78 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -8853,7 +8853,7 @@ void Client::do_get_updates(int32 offset, int32 limit, int32 timeout, PromisedQu CHECK(total_size >= updates.size()); total_size -= updates.size(); - bool need_warning = false; + bool need_warning = total_size > 0 && (query->start_timestamp() - previous_get_updates_finish_time_ > 10.0); if (total_size <= MIN_PENDING_UPDATES_WARNING / 2) { if (last_pending_update_count_ > MIN_PENDING_UPDATES_WARNING) { need_warning = true; @@ -8865,7 +8865,7 @@ void Client::do_get_updates(int32 offset, int32 limit, int32 timeout, PromisedQu last_pending_update_count_ *= 2; } } - if (need_warning) { + if (need_warning && previous_get_updates_finish_time_ > 0) { LOG(WARNING) << "Found " << updates.size() << " updates out of " << (total_size + updates.size()) << " after last getUpdates call " << (query->start_timestamp() - previous_get_updates_finish_time_) << " seconds ago in " << (td::Time::now() - query->start_timestamp()) << " seconds"; From 0bf71e15dbc714da1c177b24814324aecaf68b72 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 12 Jul 2022 20:26:44 +0300 Subject: [PATCH 07/15] Add Ubuntu 22 to the list of Linux distros. --- build.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build.html b/build.html index d43e23a..035a176 100644 --- a/build.html +++ b/build.html @@ -207,6 +207,7 @@ +

@@ -493,6 +494,8 @@ function onOptionsChanged() { return '-6.0'; case 'Ubuntu 20': return '-10'; + case 'Ubuntu 22': + return '-14'; default: return ''; // use default version } @@ -534,6 +537,7 @@ function onOptionsChanged() { case 'Ubuntu 16': case 'Ubuntu 18': case 'Ubuntu 20': + case 'Ubuntu 22': if (linux_distro.includes('Debian') && !use_root) { commands.push('su -'); } @@ -550,7 +554,7 @@ function onOptionsChanged() { } if (use_clang) { packages += ' clang' + getClangVersionSuffix() + ' libc++-dev'; - if (linux_distro === 'Debian 10+' || linux_distro === 'Ubuntu 18' || linux_distro === 'Ubuntu 20') { + if (linux_distro === 'Debian 10+' || linux_distro === 'Ubuntu 18' || linux_distro === 'Ubuntu 20' || linux_distro === 'Ubuntu 22') { packages += ' libc++abi-dev'; } } else { From 2633de8b53d7ec57b1e4fdd3033024342b510271 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 20 Jul 2022 14:48:12 +0300 Subject: [PATCH 08/15] Update TDLib and destroy some big data storages asynchronously. --- telegram-bot-api/Client.cpp | 17 +++++++++++++++-- telegram-bot-api/Client.h | 7 +++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 70e7c78..f045df5 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -185,6 +185,12 @@ Client::Client(td::ActorShared<> parent, const td::string &bot_token, bool is_te CHECK(is_inited); } +Client::~Client() { + td::Scheduler::instance()->destroy_on_scheduler(get_file_gc_scheduler_id(), messages_, users_, groups_, supergroups_, + chats_, reply_message_ids_, yet_unsent_reply_message_ids_, + sticker_set_names_); +} + bool Client::init_methods() { methods_.emplace("getme", &Client::process_get_me_query); methods_.emplace("getmycommands", &Client::process_get_my_commands_query); @@ -4856,7 +4862,7 @@ void Client::on_closed() { if (logging_out_) { parameters_->shared_data_->webhook_db_->erase(bot_token_with_dc_); - td::Scheduler::instance()->run_on_scheduler(get_database_scheduler_id(), + td::Scheduler::instance()->run_on_scheduler(get_file_gc_scheduler_id(), [actor_id = actor_id(this), dir = dir_](td::Unit) { CHECK(dir.size() >= 24); CHECK(dir.back() == TD_DIR_SLASH); @@ -4883,12 +4889,19 @@ void Client::timeout_expired() { } td::int32 Client::get_database_scheduler_id() { - // NB: the same scheduler as for database in Td + // the same scheduler as for database in Td auto current_scheduler_id = td::Scheduler::instance()->sched_id(); auto scheduler_count = td::Scheduler::instance()->sched_count(); return td::min(current_scheduler_id + 1, scheduler_count - 1); } +td::int32 Client::get_file_gc_scheduler_id() { + // the same scheduler as for file GC in Td + auto current_scheduler_id = td::Scheduler::instance()->sched_id(); + auto scheduler_count = td::Scheduler::instance()->sched_count(); + return td::min(current_scheduler_id + 2, scheduler_count - 1); +} + void Client::clear_tqueue() { CHECK(webhook_id_.empty()); auto &tqueue = parameters_->shared_data_->tqueue_; diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index af10157..f7d8573 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -42,6 +42,11 @@ class Client final : public WebhookActor::Callback { public: Client(td::ActorShared<> parent, const td::string &bot_token, bool is_test_dc, td::int64 tqueue_id, std::shared_ptr parameters, td::ActorId stat_actor); + Client(const Client &) = delete; + Client &operator=(const Client &) = delete; + Client(Client &&) = delete; + Client &operator=(Client &&) = delete; + ~Client(); void send(PromisedQueryPtr query) final; @@ -304,6 +309,8 @@ class Client final : public WebhookActor::Callback { static int32 get_database_scheduler_id(); + static int32 get_file_gc_scheduler_id(); + void clear_tqueue(); bool allow_update_before_authorization(const td_api::Object *update) const; From 4be79ff78cae7c3ec649f8fb28b8d4dbea9d3f26 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 20 Jul 2022 22:54:07 +0300 Subject: [PATCH 09/15] Update TDLib to 1.8.5. --- td | 2 +- telegram-bot-api/Client.cpp | 83 ++++++++++++++++++++----------------- telegram-bot-api/Client.h | 2 +- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/td b/td index 9a061c3..d9cfcf8 160000 --- a/td +++ b/td @@ -1 +1 @@ -Subproject commit 9a061c30c1f1928f12bdb3feb2108a8052b102be +Subproject commit d9cfcf88fe4ad06dae1716ce8f66bbeb7f9491d9 diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index f045df5..02a6feb 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -481,7 +481,8 @@ class Client::JsonVectorEntities final : public Jsonable { for (auto &entity : entities_) { auto entity_type = entity->type_->get_id(); if (entity_type != td_api::textEntityTypeBankCardNumber::ID && - entity_type != td_api::textEntityTypeMediaTimestamp::ID) { + entity_type != td_api::textEntityTypeMediaTimestamp::ID && + entity_type != td_api::textEntityTypeCustomEmoji::ID) { array << JsonEntity(entity.get(), client_); } } @@ -1018,14 +1019,12 @@ class Client::JsonSticker final : public Jsonable { if (!set_name.empty()) { object("set_name", set_name); } - auto type = sticker_->type_->get_id(); - object("is_animated", td::JsonBool(type == td_api::stickerTypeAnimated::ID)); - object("is_video", td::JsonBool(type == td_api::stickerTypeVideo::ID)); - if (type == td_api::stickerTypeMask::ID) { - const auto &mask_position = static_cast(sticker_->type_.get())->mask_position_; - if (mask_position != nullptr) { - object("mask_position", JsonMaskPosition(mask_position.get())); - } + auto format = sticker_->format_->get_id(); + object("is_animated", td::JsonBool(format == td_api::stickerFormatTgs::ID)); + object("is_video", td::JsonBool(format == td_api::stickerFormatWebm::ID)); + const auto &mask_position = sticker_->mask_position_; + if (mask_position != nullptr) { + object("mask_position", JsonMaskPosition(mask_position.get())); } if (sticker_->premium_animation_ != nullptr) { object("premium_animation", JsonFile(sticker_->premium_animation_.get(), client_, false)); @@ -2018,6 +2017,8 @@ void Client::JsonMessage::store(JsonValueScope *scope) const { object("web_app_data", JsonWebAppData(content)); break; } + case td_api::messageGiftedPremium::ID: + break; default: UNREACHABLE(); } @@ -2612,9 +2613,10 @@ class Client::JsonStickerSet final : public Jsonable { if (sticker_set_->thumbnail_ != nullptr) { client_->json_store_thumbnail(object, sticker_set_->thumbnail_.get()); } + auto format = sticker_set_->sticker_format_->get_id(); + object("is_animated", td::JsonBool(format == td_api::stickerFormatTgs::ID)); + object("is_video", td::JsonBool(format == td_api::stickerFormatWebm::ID)); auto type = sticker_set_->sticker_type_->get_id(); - object("is_animated", td::JsonBool(type == td_api::stickerTypeAnimated::ID)); - object("is_video", td::JsonBool(type == td_api::stickerTypeVideo::ID)); object("contains_masks", td::JsonBool(type == td_api::stickerTypeMask::ID)); object("stickers", JsonStickers(sticker_set_->stickers_, client_)); } @@ -6144,27 +6146,23 @@ td::Result> Client::get_mask_position(c return r_mask_position.move_as_ok(); } -td::Result>> Client::get_input_stickers(const Query *query, - bool is_masks) const { +td::Result>> Client::get_input_stickers(const Query *query) const { auto emojis = query->arg("emojis"); auto sticker = get_input_file(query, "png_sticker"); - object_ptr sticker_type; + object_ptr sticker_format; + object_ptr mask_position; if (sticker != nullptr) { - if (is_masks) { - TRY_RESULT(mask_position, get_mask_position(query, "mask_position")); - sticker_type = make_object(std::move(mask_position)); - } else { - sticker_type = make_object(); - } + sticker_format = make_object(); + TRY_RESULT_ASSIGN(mask_position, get_mask_position(query, "mask_position")); } else { sticker = get_input_file(query, "tgs_sticker", true); if (sticker != nullptr) { - sticker_type = make_object(); + sticker_format = make_object(); } else { sticker = get_input_file(query, "webm_sticker", true); if (sticker != nullptr) { - sticker_type = make_object(); + sticker_format = make_object(); } else { if (!query->arg("tgs_sticker").empty()) { return Status::Error(400, "Bad Request: animated sticker must be uploaded as an InputFile"); @@ -6178,7 +6176,8 @@ td::Result>> Client::get_inp } td::vector> stickers; - stickers.push_back(make_object(std::move(sticker), emojis.str(), std::move(sticker_type))); + stickers.push_back(make_object(std::move(sticker), emojis.str(), std::move(sticker_format), + std::move(mask_position))); return std::move(stickers); } @@ -8256,13 +8255,13 @@ td::Status Client::process_upload_sticker_file_query(PromisedQueryPtr &query) { TRY_RESULT(user_id, get_user_id(query.get())); auto png_sticker = get_input_file(query.get(), "png_sticker"); - check_user(user_id, std::move(query), - [this, user_id, png_sticker = std::move(png_sticker)](PromisedQueryPtr query) mutable { - send_request(make_object( - user_id, make_object(std::move(png_sticker), "", - make_object())), - td::make_unique(this, std::move(query))); - }); + check_user( + user_id, std::move(query), [this, user_id, png_sticker = std::move(png_sticker)](PromisedQueryPtr query) mutable { + send_request(make_object( + user_id, make_object(std::move(png_sticker), "", + make_object(), nullptr)), + td::make_unique(this, std::move(query))); + }); return Status::OK(); } @@ -8270,14 +8269,22 @@ td::Status Client::process_create_new_sticker_set_query(PromisedQueryPtr &query) TRY_RESULT(user_id, get_user_id(query.get())); auto name = query->arg("name"); auto title = query->arg("title"); - auto is_masks = to_bool(query->arg("contains_masks")); - TRY_RESULT(stickers, get_input_stickers(query.get(), is_masks)); + TRY_RESULT(stickers, get_input_stickers(query.get())); + + object_ptr sticker_type; + if (to_bool(query->arg("contains_masks"))) { + sticker_type = make_object(); + } else { + sticker_type = make_object(); + } check_user(user_id, std::move(query), - [this, user_id, title, name, stickers = std::move(stickers)](PromisedQueryPtr query) mutable { - send_request(make_object(user_id, title.str(), name.str(), - std::move(stickers), PSTRING() << "bot" << my_id_), - td::make_unique(this, false, std::move(query))); + [this, user_id, title, name, sticker_type = std::move(sticker_type), + stickers = std::move(stickers)](PromisedQueryPtr query) mutable { + send_request( + make_object(user_id, title.str(), name.str(), std::move(sticker_type), + std::move(stickers), PSTRING() << "bot" << my_id_), + td::make_unique(this, false, std::move(query))); }); return Status::OK(); } @@ -8285,7 +8292,7 @@ td::Status Client::process_create_new_sticker_set_query(PromisedQueryPtr &query) td::Status Client::process_add_sticker_to_set_query(PromisedQueryPtr &query) { TRY_RESULT(user_id, get_user_id(query.get())); auto name = query->arg("name"); - TRY_RESULT(stickers, get_input_stickers(query.get(), true)); + TRY_RESULT(stickers, get_input_stickers(query.get())); CHECK(!stickers.empty()); check_user(user_id, std::move(query), @@ -9723,6 +9730,8 @@ bool Client::need_skip_update_message(int64 chat_id, const object_ptr mask_index_to_point(int32 index); - td::Result>> get_input_stickers(const Query *query, bool is_masks) const; + td::Result>> get_input_stickers(const Query *query) const; static td::Result get_passport_element_hash(Slice encoded_hash); From 4a7d515d947b77ef16f2ebfce7672b11a274724b Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 20 Jul 2022 23:28:56 +0300 Subject: [PATCH 10/15] Support custom_emoji entities. --- telegram-bot-api/Client.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 02a6feb..5952e50 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -461,6 +461,12 @@ class Client::JsonEntity final : public Jsonable { object("user", JsonUser(entity->user_id_, client_)); break; } + case td_api::textEntityTypeCustomEmoji::ID: { + auto entity = static_cast(entity_->type_.get()); + object("type", "custom_emoji"); + object("custom_emoji_id", td::to_string(entity->custom_emoji_id_)); + break; + } default: UNREACHABLE(); } @@ -481,8 +487,7 @@ class Client::JsonVectorEntities final : public Jsonable { for (auto &entity : entities_) { auto entity_type = entity->type_->get_id(); if (entity_type != td_api::textEntityTypeBankCardNumber::ID && - entity_type != td_api::textEntityTypeMediaTimestamp::ID && - entity_type != td_api::textEntityTypeCustomEmoji::ID) { + entity_type != td_api::textEntityTypeMediaTimestamp::ID) { array << JsonEntity(entity.get(), client_); } } @@ -6353,6 +6358,10 @@ td::Result> Client::get_text_entity_t TRY_RESULT(user_id, get_json_object_long_field(user.get_object(), "id", false)); return make_object(user_id); } + if (type == "custom_emoji") { + TRY_RESULT(custom_emoji_id, get_json_object_long_field(object, "custom_emoji_id", false)); + return make_object(custom_emoji_id); + } if (type == "mention" || type == "hashtag" || type == "cashtag" || type == "bot_command" || type == "url" || type == "email" || type == "phone_number" || type == "bank_card_number") { return nullptr; From eed4773a4ff14df0b457d3bb7970220fe13cec68 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 21 Jul 2022 18:17:23 +0300 Subject: [PATCH 11/15] Add sticker_type fields and parameter. --- telegram-bot-api/Client.cpp | 44 ++++++++++++++++++++++++++++++++----- telegram-bot-api/Client.h | 4 ++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 5952e50..474586f 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -1024,9 +1024,13 @@ class Client::JsonSticker final : public Jsonable { if (!set_name.empty()) { object("set_name", set_name); } + auto format = sticker_->format_->get_id(); object("is_animated", td::JsonBool(format == td_api::stickerFormatTgs::ID)); object("is_video", td::JsonBool(format == td_api::stickerFormatWebm::ID)); + + object("type", Client::get_sticker_type(sticker_->type_)); + const auto &mask_position = sticker_->mask_position_; if (mask_position != nullptr) { object("mask_position", JsonMaskPosition(mask_position.get())); @@ -2618,11 +2622,15 @@ class Client::JsonStickerSet final : public Jsonable { if (sticker_set_->thumbnail_ != nullptr) { client_->json_store_thumbnail(object, sticker_set_->thumbnail_.get()); } + auto format = sticker_set_->sticker_format_->get_id(); object("is_animated", td::JsonBool(format == td_api::stickerFormatTgs::ID)); object("is_video", td::JsonBool(format == td_api::stickerFormatWebm::ID)); - auto type = sticker_set_->sticker_type_->get_id(); - object("contains_masks", td::JsonBool(type == td_api::stickerTypeMask::ID)); + + auto type = Client::get_sticker_type(sticker_set_->sticker_type_); + object("sticker_type", type); + object("contains_masks", td::JsonBool(type == "mask")); + object("stickers", JsonStickers(sticker_set_->stickers_, client_)); } @@ -8280,11 +8288,9 @@ td::Status Client::process_create_new_sticker_set_query(PromisedQueryPtr &query) auto title = query->arg("title"); TRY_RESULT(stickers, get_input_stickers(query.get())); - object_ptr sticker_type; + TRY_RESULT(sticker_type, get_sticker_type(query->arg("sticker_type"))); if (to_bool(query->arg("contains_masks"))) { sticker_type = make_object(); - } else { - sticker_type = make_object(); } check_user(user_id, std::move(query), @@ -9793,6 +9799,34 @@ void Client::set_message_reply_to_message_id(MessageInfo *message_info, int64 re message_info->reply_to_message_id = reply_to_message_id; } +td::Slice Client::get_sticker_type(const object_ptr &type) { + CHECK(type != nullptr); + switch (type->get_id()) { + case td_api::stickerTypeRegular::ID: + return Slice("regular"); + case td_api::stickerTypeMask::ID: + return Slice("mask"); + case td_api::stickerTypeCustomEmoji::ID: + return Slice("custom_emoji"); + default: + UNREACHABLE(); + return Slice(); + } +} + +td::Result> Client::get_sticker_type(Slice type) { + if (type.empty() || type == "regular") { + return make_object(); + } + if (type == "mask") { + return make_object(); + } + if (type == "custom_emoji") { + return make_object(); + } + return Status::Error(400, "Unsupported sticker type specified"); +} + td::CSlice Client::get_callback_data(const object_ptr &type) { CHECK(type != nullptr); switch (type->get_id()) { diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index c236a78..2ebd3e6 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -739,6 +739,10 @@ class Client final : public WebhookActor::Callback { void set_message_reply_to_message_id(MessageInfo *message_info, int64 reply_to_message_id); + static Slice get_sticker_type(const object_ptr &type); + + static td::Result> get_sticker_type(Slice type); + static td::CSlice get_callback_data(const object_ptr &type); static bool are_equal_inline_keyboard_buttons(const td_api::inlineKeyboardButton *lhs, From 7cfdea20537223d560d27914b2339cf8b8ac2571 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 21 Jul 2022 19:00:58 +0300 Subject: [PATCH 12/15] Add getCustomEmojiStickers. --- telegram-bot-api/Client.cpp | 98 +++++++++++++++++++++++++++++++++++++ telegram-bot-api/Client.h | 5 ++ 2 files changed, 103 insertions(+) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 474586f..170e877 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -10,6 +10,7 @@ #include "td/db/TQueue.h" +#include "td/actor/MultiPromise.h" #include "td/actor/SleepActor.h" #include "td/utils/algorithm.h" @@ -268,6 +269,7 @@ bool Client::init_methods() { methods_.emplace("approvechatjoinrequest", &Client::process_approve_chat_join_request_query); methods_.emplace("declinechatjoinrequest", &Client::process_decline_chat_join_request_query); methods_.emplace("getstickerset", &Client::process_get_sticker_set_query); + methods_.emplace("getcustomemojistickers", &Client::process_get_custom_emoji_stickers_query); methods_.emplace("uploadstickerfile", &Client::process_upload_sticker_file_query); methods_.emplace("createnewstickerset", &Client::process_create_new_sticker_set_query); methods_.emplace("addstickertoset", &Client::process_add_sticker_to_set_query); @@ -3684,6 +3686,68 @@ class Client::TdOnReturnStickerSetCallback final : public TdQueryCallback { PromisedQueryPtr query_; }; +class Client::TdOnGetStickerSetPromiseCallback final : public TdQueryCallback { + public: + TdOnGetStickerSetPromiseCallback(Client *client, td::Promise &&promise) + : client_(client), promise_(std::move(promise)) { + } + + void on_result(object_ptr result) final { + if (result->get_id() == td_api::error::ID) { + auto error = move_object_as(result); + return promise_.set_error(Status::Error(error->code_, error->message_)); + } + + CHECK(result->get_id() == td_api::stickerSet::ID); + auto sticker_set = move_object_as(result); + client_->on_get_sticker_set_name(sticker_set->id_, sticker_set->name_); + promise_.set_value(td::Unit()); + } + + private: + Client *client_; + td::Promise promise_; +}; + +class Client::TdOnGetStickersCallback final : public TdQueryCallback { + public: + TdOnGetStickersCallback(Client *client, PromisedQueryPtr query) : client_(client), query_(std::move(query)) { + } + + void on_result(object_ptr result) final { + if (result->get_id() == td_api::error::ID) { + return fail_query_with_error(std::move(query_), move_object_as(result)); + } + + CHECK(result->get_id() == td_api::stickers::ID); + auto stickers = move_object_as(result); + td::FlatHashSet sticker_set_ids; + for (const auto &sticker : stickers->stickers_) { + if (sticker->set_id_ != 0 && client_->get_sticker_set_name(sticker->set_id_).empty()) { + sticker_set_ids.insert(sticker->set_id_); + } + } + + td::MultiPromiseActorSafe mpas("GetStickerSetsMultiPromiseActor"); + mpas.add_promise(td::PromiseCreator::lambda([actor_id = client_->actor_id(client_), stickers = std::move(stickers), + query = std::move(query_)](td::Unit) mutable { + send_closure(actor_id, &Client::return_stickers, std::move(stickers), std::move(query)); + })); + mpas.set_ignore_errors(true); + + auto lock = mpas.get_promise(); + for (auto sticker_set_id : sticker_set_ids) { + client_->send_request(make_object(sticker_set_id), + td::make_unique(client_, mpas.get_promise())); + } + lock.set_value(td::Unit()); + } + + private: + Client *client_; + PromisedQueryPtr query_; +}; + class Client::TdOnSendCustomRequestCallback final : public TdQueryCallback { public: explicit TdOnSendCustomRequestCallback(PromisedQueryPtr query) : query_(std::move(query)) { @@ -8268,6 +8332,36 @@ td::Status Client::process_get_sticker_set_query(PromisedQueryPtr &query) { return Status::OK(); } +td::Status Client::process_get_custom_emoji_stickers_query(PromisedQueryPtr &query) { + TRY_RESULT(custom_emoji_ids_json, get_required_string_arg(query.get(), "custom_emoji_ids")); + + LOG(INFO) << "Parsing JSON object: " << custom_emoji_ids_json; + auto r_value = json_decode(custom_emoji_ids_json); + if (r_value.is_error()) { + return Status::Error(400, "Can't parse custom emoji identifiers JSON object"); + } + auto value = r_value.move_as_ok(); + if (value.type() != JsonValue::Type::Array) { + return Status::Error(400, "Expected an Array of custom emoji identifiers"); + } + + td::vector custom_emoji_ids; + for (auto &custom_emoji_id : value.get_array()) { + if (custom_emoji_id.type() != JsonValue::Type::String) { + return Status::Error(400, "Custom emoji identifier must be of type String"); + } + auto parsed_id = td::to_integer_safe(custom_emoji_id.get_string()); + if (parsed_id.is_error()) { + return Status::Error(400, "Invalid custom emoji identifier specified"); + } + custom_emoji_ids.push_back(parsed_id.ok()); + } + + send_request(make_object(std::move(custom_emoji_ids)), + td::make_unique(this, std::move(query))); + return Status::OK(); +} + td::Status Client::process_upload_sticker_file_query(PromisedQueryPtr &query) { TRY_RESULT(user_id, get_user_id(query.get())); auto png_sticker = get_input_file(query.get(), "png_sticker"); @@ -8523,6 +8617,10 @@ void Client::on_file_download(int32 file_id, td::Result } } +void Client::return_stickers(object_ptr stickers, PromisedQueryPtr query) { + answer_query(JsonStickers(stickers->stickers_, this), std::move(query)); +} + void Client::webhook_verified(td::string cached_ip_address) { if (get_link_token() != webhook_generation_) { return; diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index 2ebd3e6..bdaa9b8 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -200,6 +200,8 @@ class Client final : public WebhookActor::Callback { class TdOnAnswerWebAppQueryCallback; class TdOnReturnFileCallback; class TdOnReturnStickerSetCallback; + class TdOnGetStickerSetPromiseCallback; + class TdOnGetStickersCallback; class TdOnDownloadFileCallback; class TdOnCancelDownloadFileCallback; class TdOnSendCustomRequestCallback; @@ -544,6 +546,7 @@ class Client final : public WebhookActor::Callback { Status process_approve_chat_join_request_query(PromisedQueryPtr &query); Status process_decline_chat_join_request_query(PromisedQueryPtr &query); Status process_get_sticker_set_query(PromisedQueryPtr &query); + Status process_get_custom_emoji_stickers_query(PromisedQueryPtr &query); Status process_upload_sticker_file_query(PromisedQueryPtr &query); Status process_create_new_sticker_set_query(PromisedQueryPtr &query); Status process_add_sticker_to_set_query(PromisedQueryPtr &query); @@ -583,6 +586,8 @@ class Client final : public WebhookActor::Callback { bool is_file_being_downloaded(int32 file_id) const; void on_file_download(int32 file_id, td::Result> r_file); + void return_stickers(object_ptr stickers, PromisedQueryPtr query); + void fix_reply_markup_bot_user_ids(object_ptr &reply_markup) const; void fix_inline_query_results_bot_user_ids(td::vector> &results) const; From e66c5fa67d1269792f5b375ef66fea8228be0060 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 21 Jul 2022 19:06:37 +0300 Subject: [PATCH 13/15] Add custom_emoji_id field to the class Sticker. --- telegram-bot-api/Client.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 170e877..859adf0 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -1033,6 +1033,10 @@ class Client::JsonSticker final : public Jsonable { object("type", Client::get_sticker_type(sticker_->type_)); + if (sticker_->custom_emoji_id_ != 0) { + object("custom_emoji_id", td::to_string(sticker_->custom_emoji_id_)); + } + const auto &mask_position = sticker_->mask_position_; if (mask_position != nullptr) { object("mask_position", JsonMaskPosition(mask_position.get())); From 9f3f32391cc0ddf33483ec386013c0e7f2aa1a09 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 21 Jul 2022 19:12:28 +0300 Subject: [PATCH 14/15] Add Chat.has_restricted_voice_and_video_messages. --- telegram-bot-api/Client.cpp | 10 ++++++++++ telegram-bot-api/Client.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 859adf0..752e92f 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -665,6 +665,9 @@ class Client::JsonChat final : public Jsonable { if (user_info->has_private_forwards) { object("has_private_forwards", td::JsonTrue()); } + if (user_info->has_restricted_voice_and_video_messages) { + object("has_restricted_voice_and_video_messages", td::JsonTrue()); + } } photo = user_info->photo.get(); break; @@ -4728,6 +4731,8 @@ void Client::on_update(object_ptr result) { set_user_bio(user_id, std::move(full_info->bio_->text_)); } set_user_has_private_forwards(user_id, full_info->has_private_forwards_); + set_user_has_restricted_voice_and_video_messages(user_id, + full_info->has_restricted_voice_and_video_note_messages_); break; } case td_api::updateBasicGroup::ID: { @@ -9119,6 +9124,11 @@ void Client::set_user_has_private_forwards(int64 user_id, bool has_private_forwa add_user_info(user_id)->has_private_forwards = has_private_forwards; } +void Client::set_user_has_restricted_voice_and_video_messages(int64 user_id, + bool has_restricted_voice_and_video_messages) { + add_user_info(user_id)->has_restricted_voice_and_video_messages = has_restricted_voice_and_video_messages; +} + void Client::add_group(GroupInfo *group_info, object_ptr &&group) { group_info->member_count = group->member_count_; group_info->left = group->status_->get_id() == td_api::chatMemberStatusLeft::ID; diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index bdaa9b8..f1f96a3 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -634,6 +634,7 @@ class Client final : public WebhookActor::Callback { bool can_read_all_group_messages = false; bool is_inline_bot = false; bool has_private_forwards = false; + bool has_restricted_voice_and_video_messages = false; bool is_premium = false; bool added_to_attachment_menu = false; }; @@ -641,6 +642,7 @@ class Client final : public WebhookActor::Callback { void set_user_photo(int64 user_id, object_ptr &&photo); void set_user_bio(int64 user_id, td::string &&bio); void set_user_has_private_forwards(int64 user_id, bool has_private_forwards); + void set_user_has_restricted_voice_and_video_messages(int64 user_id, bool has_restricted_voice_and_video_messages); UserInfo *add_user_info(int64 user_id); const UserInfo *get_user_info(int64 user_id) const; From f59097ab16232995ed5bdc3feff4f3ca82c9b127 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 31 Jul 2022 03:26:25 +0300 Subject: [PATCH 15/15] Update version to 6.2. --- CMakeLists.txt | 2 +- telegram-bot-api/telegram-bot-api.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 76ef36a..45d5df6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ if (POLICY CMP0065) cmake_policy(SET CMP0065 NEW) endif() -project(TelegramBotApi VERSION 6.1 LANGUAGES CXX) +project(TelegramBotApi VERSION 6.2 LANGUAGES CXX) if (POLICY CMP0069) option(TELEGRAM_BOT_API_ENABLE_LTO "Use \"ON\" to enable Link Time Optimization.") diff --git a/telegram-bot-api/telegram-bot-api.cpp b/telegram-bot-api/telegram-bot-api.cpp index 97a220a..1777beb 100644 --- a/telegram-bot-api/telegram-bot-api.cpp +++ b/telegram-bot-api/telegram-bot-api.cpp @@ -200,7 +200,7 @@ int main(int argc, char *argv[]) { auto start_time = td::Time::now(); auto shared_data = std::make_shared(); auto parameters = std::make_unique(); - parameters->version_ = "6.1"; + parameters->version_ = "6.2"; parameters->shared_data_ = shared_data; parameters->start_time_ = start_time; auto net_query_stats = td::create_net_query_stats();