diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a1928a..fadd00d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ if (POLICY CMP0065) cmake_policy(SET CMP0065 NEW) endif() -project(TelegramBotApi VERSION 6.6 LANGUAGES CXX) +project(TelegramBotApi VERSION 6.7.1 LANGUAGES CXX) if (POLICY CMP0069) option(TELEGRAM_BOT_API_ENABLE_LTO "Use \"ON\" to enable Link Time Optimization.") @@ -73,6 +73,9 @@ if (CLANG OR GCC) elseif (APPLE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-no_pie") endif() + include(AddCXXCompilerFlag) + add_cxx_compiler_flag("-static-libstdc++") + add_cxx_compiler_flag("-static-libgcc") endif() endif() diff --git a/td b/td index 70bee08..328b864 160000 --- a/td +++ b/td @@ -1 +1 @@ -Subproject commit 70bee089d492437ce931aa78446d89af3da182fc +Subproject commit 328b8649d859c5ed4088a875cbb059db6029dc0d diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index ab657b8..92541b6 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -57,7 +57,7 @@ using td_api::move_object_as; int Client::get_retry_after_time(td::Slice error_message) { td::Slice prefix = "Too Many Requests: retry after "; - if (begins_with(error_message, prefix)) { + if (td::begins_with(error_message, prefix)) { auto r_retry_after = td::to_integer_safe(error_message.substr(prefix.size())); if (r_retry_after.is_ok() && r_retry_after.ok() > 0) { return r_retry_after.ok(); @@ -173,7 +173,7 @@ void Client::fail_query_with_error(PromisedQueryPtr query, int32 error_code, td: return fail_query(400, PSLICE() << "Bad Request: " << error_message, std::move(query)); } - if (begins_with(error_message, prefix)) { + if (td::begins_with(error_message, prefix)) { return fail_query(error_code, error_message, std::move(query)); } else { td::string error_str = prefix.str(); @@ -225,6 +225,8 @@ bool Client::init_methods() { methods_.emplace("deletemycommands", &Client::process_delete_my_commands_query); methods_.emplace("getmydefaultadministratorrights", &Client::process_get_my_default_administrator_rights_query); methods_.emplace("setmydefaultadministratorrights", &Client::process_set_my_default_administrator_rights_query); + methods_.emplace("getmyname", &Client::process_get_my_name_query); + methods_.emplace("setmyname", &Client::process_set_my_name_query); methods_.emplace("getmydescription", &Client::process_get_my_description_query); methods_.emplace("setmydescription", &Client::process_set_my_description_query); methods_.emplace("getmyshortdescription", &Client::process_get_my_short_description_query); @@ -1928,10 +1930,28 @@ class Client::JsonInlineKeyboardButton final : public td::Jsonable { break; case td_api::inlineKeyboardButtonTypeSwitchInline::ID: { auto type = static_cast(button_->type_.get()); - if (type->in_current_chat_) { - object("switch_inline_query_current_chat", type->query_); - } else { - object("switch_inline_query", type->query_); + switch (type->target_chat_->get_id()) { + case td_api::targetChatCurrent::ID: + object("switch_inline_query_current_chat", type->query_); + break; + case td_api::targetChatChosen::ID: { + auto target_chat = static_cast(type->target_chat_.get()); + if (target_chat->allow_user_chats_ && target_chat->allow_bot_chats_ && target_chat->allow_group_chats_ && + target_chat->allow_channel_chats_) { + object("switch_inline_query", type->query_); + } else { + object("switch_inline_query_chosen_chat", td::json_object([&](auto &o) { + o("query", type->query_); + o("allow_user_chats", td::JsonBool(target_chat->allow_user_chats_)); + o("allow_bot_chats", td::JsonBool(target_chat->allow_bot_chats_)); + o("allow_group_chats", td::JsonBool(target_chat->allow_group_chats_)); + o("allow_channel_chats", td::JsonBool(target_chat->allow_channel_chats_)); + })); + } + break; + } + default: + UNREACHABLE(); } break; } @@ -2384,6 +2404,8 @@ void Client::JsonMessage::store(td::JsonValueScope *scope) const { object("chat_shared", JsonChatShared(content)); break; } + case td_api::messageChatSetBackground::ID: + break; default: UNREACHABLE(); } @@ -2702,6 +2724,19 @@ class Client::JsonBotMenuButton final : public td::Jsonable { const td_api::botMenuButton *menu_button_; }; +class Client::JsonBotName final : public td::Jsonable { + public: + explicit JsonBotName(const td_api::text *text) : text_(text) { + } + void store(td::JsonValueScope *scope) const { + auto object = scope->enter_object(); + object("name", text_->text_); + } + + private: + const td_api::text *text_; +}; + class Client::JsonBotInfoDescription final : public td::Jsonable { public: explicit JsonBotInfoDescription(const td_api::text *text) : text_(text) { @@ -2904,6 +2939,9 @@ class Client::JsonChatMemberUpdated final : public td::Jsonable { if (update_->invite_link_ != nullptr) { object("invite_link", JsonChatInviteLink(update_->invite_link_.get(), client_)); } + if (update_->via_chat_folder_invite_link_) { + object("via_chat_folder_invite_link", td::JsonTrue()); + } } private: @@ -4172,6 +4210,25 @@ class Client::TdOnGetMyDefaultAdministratorRightsCallback final : public TdQuery PromisedQueryPtr query_; }; +class Client::TdOnGetMyNameCallback final : public TdQueryCallback { + public: + explicit TdOnGetMyNameCallback(PromisedQueryPtr query) : 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::text::ID); + auto text = move_object_as(result); + answer_query(JsonBotName(text.get()), std::move(query_)); + } + + private: + PromisedQueryPtr query_; +}; + class Client::TdOnGetMyDescriptionCallback final : public TdQueryCallback { public: explicit TdOnGetMyDescriptionCallback(PromisedQueryPtr query) : query_(std::move(query)) { @@ -5547,9 +5604,9 @@ void Client::on_update_authorization_state() { send_request(make_object("reuse_uploaded_photos_by_hash", make_object(true)), td::make_unique()); - send_request(make_object("disable_persistent_network_statistics", - make_object(true)), - td::make_unique()); + send_request( + make_object("disable_network_statistics", make_object(true)), + td::make_unique()); send_request(make_object("disable_time_adjustment_protection", make_object(true)), td::make_unique()); @@ -6271,13 +6328,31 @@ td::Result> Client::get_inline_ if (has_json_object_field(object, "switch_inline_query")) { TRY_RESULT(switch_inline_query, get_json_object_string_field(object, "switch_inline_query", false)); return make_object( - text, make_object(switch_inline_query, false)); + text, make_object( + switch_inline_query, td_api::make_object(true, true, true, true))); + } + + if (has_json_object_field(object, "switch_inline_query_chosen_chat")) { + TRY_RESULT(switch_inline_query, + get_json_object_field(object, "switch_inline_query_chosen_chat", td::JsonValue::Type::Object, false)); + CHECK(switch_inline_query.type() == td::JsonValue::Type::Object); + auto &switch_inline_query_object = switch_inline_query.get_object(); + TRY_RESULT(query, get_json_object_string_field(switch_inline_query_object, "query")); + TRY_RESULT(allow_user_chats, get_json_object_bool_field(switch_inline_query_object, "allow_user_chats")); + TRY_RESULT(allow_bot_chats, get_json_object_bool_field(switch_inline_query_object, "allow_bot_chats")); + TRY_RESULT(allow_group_chats, get_json_object_bool_field(switch_inline_query_object, "allow_group_chats")); + TRY_RESULT(allow_channel_chats, get_json_object_bool_field(switch_inline_query_object, "allow_channel_chats")); + return make_object( + text, make_object( + query, td_api::make_object(allow_user_chats, allow_bot_chats, + allow_group_chats, allow_channel_chats))); } if (has_json_object_field(object, "switch_inline_query_current_chat")) { TRY_RESULT(switch_inline_query, get_json_object_string_field(object, "switch_inline_query_current_chat", false)); return make_object( - text, make_object(switch_inline_query, true)); + text, make_object( + switch_inline_query, td_api::make_object())); } if (has_json_object_field(object, "login_url")) { @@ -8710,9 +8785,24 @@ td::Status Client::process_set_my_default_administrator_rights_query(PromisedQue return td::Status::OK(); } +td::Status Client::process_get_my_name_query(PromisedQueryPtr &query) { + auto language_code = query->arg("language_code"); + send_request(make_object(my_id_, language_code.str()), + td::make_unique(std::move(query))); + return td::Status::OK(); +} + +td::Status Client::process_set_my_name_query(PromisedQueryPtr &query) { + auto language_code = query->arg("language_code"); + auto name = query->arg("name"); + send_request(make_object(my_id_, language_code.str(), name.str()), + td::make_unique(std::move(query))); + return td::Status::OK(); +} + td::Status Client::process_get_my_description_query(PromisedQueryPtr &query) { auto language_code = query->arg("language_code"); - send_request(make_object(language_code.str()), + send_request(make_object(my_id_, language_code.str()), td::make_unique(std::move(query))); return td::Status::OK(); } @@ -8720,14 +8810,14 @@ td::Status Client::process_get_my_description_query(PromisedQueryPtr &query) { td::Status Client::process_set_my_description_query(PromisedQueryPtr &query) { auto language_code = query->arg("language_code"); auto description = query->arg("description"); - send_request(make_object(language_code.str(), description.str()), + send_request(make_object(my_id_, language_code.str(), description.str()), td::make_unique(std::move(query))); return td::Status::OK(); } td::Status Client::process_get_my_short_description_query(PromisedQueryPtr &query) { auto language_code = query->arg("language_code"); - send_request(make_object(language_code.str()), + send_request(make_object(my_id_, language_code.str()), td::make_unique(std::move(query))); return td::Status::OK(); } @@ -8735,7 +8825,7 @@ td::Status Client::process_get_my_short_description_query(PromisedQueryPtr &quer td::Status Client::process_set_my_short_description_query(PromisedQueryPtr &query) { auto language_code = query->arg("language_code"); auto short_description = query->arg("short_description"); - send_request(make_object(language_code.str(), short_description.str()), + send_request(make_object(my_id_, language_code.str(), short_description.str()), td::make_unique(std::move(query))); return td::Status::OK(); } @@ -11525,7 +11615,8 @@ void Client::do_get_updates(int32 offset, int32 limit, int32 timeout, PromisedQu 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"; + << " seconds ago in " << (td::Time::now() - query->start_timestamp()) << " seconds from " + << query->get_peer_ip_address(); } else { LOG(DEBUG) << "Found " << updates.size() << " updates out of " << total_size << " from " << from; } @@ -12442,6 +12533,8 @@ bool Client::need_skip_update_message(int64 chat_id, const object_ptr(lhs->type_.get()); auto rhs_type = static_cast(rhs->type_.get()); - return lhs_type->query_ == rhs_type->query_ && lhs_type->in_current_chat_ == rhs_type->in_current_chat_; + return lhs_type->query_ == rhs_type->query_ && + to_string(lhs_type->target_chat_) == to_string(rhs_type->target_chat_); } case td_api::inlineKeyboardButtonTypeBuy::ID: return true; diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index 14c993a..f059a0a 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -150,6 +150,7 @@ class Client final : public WebhookActor::Callback { class JsonPreCheckoutQuery; class JsonBotCommand; class JsonBotMenuButton; + class JsonBotName; class JsonBotInfoDescription; class JsonBotInfoShortDescription; class JsonChatAdministratorRights; @@ -214,6 +215,7 @@ class Client final : public WebhookActor::Callback { class TdOnGetMenuButtonCallback; class TdOnGetMyCommandsCallback; class TdOnGetMyDefaultAdministratorRightsCallback; + class TdOnGetMyNameCallback; class TdOnGetMyDescriptionCallback; class TdOnGetMyShortDescriptionCallback; class TdOnGetChatFullInfoCallback; @@ -573,6 +575,8 @@ class Client final : public WebhookActor::Callback { td::Status process_delete_my_commands_query(PromisedQueryPtr &query); td::Status process_get_my_default_administrator_rights_query(PromisedQueryPtr &query); td::Status process_set_my_default_administrator_rights_query(PromisedQueryPtr &query); + td::Status process_get_my_name_query(PromisedQueryPtr &query); + td::Status process_set_my_name_query(PromisedQueryPtr &query); td::Status process_get_my_description_query(PromisedQueryPtr &query); td::Status process_set_my_description_query(PromisedQueryPtr &query); td::Status process_get_my_short_description_query(PromisedQueryPtr &query); diff --git a/telegram-bot-api/ClientManager.cpp b/telegram-bot-api/ClientManager.cpp index 6815302..5f351c2 100644 --- a/telegram-bot-api/ClientManager.cpp +++ b/telegram-bot-api/ClientManager.cpp @@ -177,13 +177,7 @@ void ClientManager::user_login(PromisedQueryPtr query) { } bool ClientManager::check_flood_limits(PromisedQueryPtr &query, bool is_user_login) { - td::string ip_address; - if (query->peer_address().is_valid() && !query->peer_address().is_reserved()) { // external connection - ip_address = query->peer_address().get_ip_str().str(); - } else { - // invalid peer address or connection from the local network - ip_address = query->get_header("x-real-ip").str(); - } + td::string ip_address = query->get_peer_ip_address(); if (!ip_address.empty()) { td::IPAddress tmp; tmp.init_host_port(ip_address, 0).ignore(); @@ -192,7 +186,7 @@ bool ClientManager::check_flood_limits(PromisedQueryPtr &query, bool is_user_log ip_address = tmp.get_ip_str().str(); } } - LOG(DEBUG) << "Receive incoming query for new bot " << query->token() << " from " << query->peer_address(); + LOG(DEBUG) << "Receive incoming query for new bot " << query->token() << " from " << ip_address; if (!ip_address.empty()) { LOG(DEBUG) << "Check Client creation flood control for IP address " << ip_address; if (is_user_login) { diff --git a/telegram-bot-api/Query.cpp b/telegram-bot-api/Query.cpp index 9429564..6ef2ae1 100644 --- a/telegram-bot-api/Query.cpp +++ b/telegram-bot-api/Query.cpp @@ -26,10 +26,10 @@ td::FlatHashMap> empty_paramet Query::Query(td::vector &&container, td::Slice token, bool is_user, bool is_test_dc, td::MutableSlice method, td::vector> &&args, td::vector> &&headers, td::vector &&files, - std::shared_ptr shared_data, const td::IPAddress &peer_address, bool is_internal) + std::shared_ptr shared_data, const td::IPAddress &peer_ip_address, bool is_internal) : state_(State::Query) , shared_data_(shared_data) - , peer_address_(peer_address) + , peer_ip_address_(peer_ip_address) , container_(std::move(container)) , token_(token) , is_user_(is_user) @@ -54,6 +54,15 @@ Query::Query(td::vector &&container, td::Slice token, bool is_u } } +td::string Query::get_peer_ip_address() const { + if (peer_ip_address_.is_valid() && !peer_ip_address_.is_reserved()) { // external connection + return peer_ip_address_.get_ip_str().str(); + } else { + // invalid peer IP address or connection from the local network + return get_header("x-real-ip").str(); + } +} + td::int64 Query::query_size() const { return std::accumulate( container_.begin(), container_.end(), td::int64{0}, diff --git a/telegram-bot-api/Query.h b/telegram-bot-api/Query.h index 18cf010..b956e14 100644 --- a/telegram-bot-api/Query.h +++ b/telegram-bot-api/Query.h @@ -73,9 +73,7 @@ class Query final : public td::ListNode { return files_; } - const td::IPAddress &peer_address() const { - return peer_address_; - } + td::string get_peer_ip_address() const; td::BufferSlice &answer() { return answer_; @@ -106,7 +104,7 @@ class Query final : public td::ListNode { Query(td::vector &&container, td::Slice token, bool is_user, bool is_test_dc, td::MutableSlice method, td::vector> &&args, td::vector> &&headers, td::vector &&files, - std::shared_ptr shared_data, const td::IPAddress &peer_address, bool is_internal); + std::shared_ptr shared_data, const td::IPAddress &peer_ip_address, bool is_internal); Query(const Query &) = delete; Query &operator=(const Query &) = delete; Query(Query &&) = delete; @@ -132,7 +130,7 @@ class Query final : public td::ListNode { State state_; std::shared_ptr shared_data_; double start_timestamp_; - td::IPAddress peer_address_; + td::IPAddress peer_ip_address_; td::ActorId stat_actor_; // request diff --git a/telegram-bot-api/Watchdog.cpp b/telegram-bot-api/Watchdog.cpp index 1bb15e6..9b5c88d 100644 --- a/telegram-bot-api/Watchdog.cpp +++ b/telegram-bot-api/Watchdog.cpp @@ -13,7 +13,7 @@ namespace telegram_bot_api { void Watchdog::kick() { auto now = td::Time::now(); - if (now >= last_kick_time_ + timeout_ && last_kick_time_ > 0) { + if (now >= last_kick_time_ + timeout_ && last_kick_time_ > 0 && GET_VERBOSITY_LEVEL() >= VERBOSITY_NAME(ERROR)) { LOG(ERROR) << get_name() << " timeout expired after " << now - last_kick_time_ << " seconds"; td::thread::send_real_time_signal(main_thread_id_, 2); } diff --git a/telegram-bot-api/WebhookActor.cpp b/telegram-bot-api/WebhookActor.cpp index 630cb83..548398d 100644 --- a/telegram-bot-api/WebhookActor.cpp +++ b/telegram-bot-api/WebhookActor.cpp @@ -207,7 +207,7 @@ td::Status WebhookActor::create_webhook_error(td::Slice error_message, td::Statu on_webhook_error(error_message); } on_error(std::move(result)); - return std::move(error); + return error; } td::Result WebhookActor::create_ssl_stream() { diff --git a/telegram-bot-api/telegram-bot-api.cpp b/telegram-bot-api/telegram-bot-api.cpp index 6b3ef31..cd4b3b6 100644 --- a/telegram-bot-api/telegram-bot-api.cpp +++ b/telegram-bot-api/telegram-bot-api.cpp @@ -165,7 +165,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.6"; + parameters->version_ = "6.7.1"; parameters->shared_data_ = shared_data; parameters->start_time_ = start_time; auto net_query_stats = td::create_net_query_stats();