From ef23b96c94adf0e82ffce9927574190ca5642fde Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Apr 2021 16:49:00 +0300 Subject: [PATCH 1/7] Improve log message. --- telegram-bot-api/Client.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 22ae961..a4ffeb3 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -7897,9 +7897,9 @@ void Client::do_get_updates(int32 offset, int32 limit, int32 timeout, PromisedQu } } if (need_warning) { - LOG(WARNING) << "Found " << updates.size() << " updates out of " << total_size << " + " << updates.size() - << " after last getUpdates call " << (td::Time::now() - previous_get_updates_finish_time_) - << " seconds ago"; + 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"; } else { LOG(DEBUG) << "Found " << updates.size() << " updates out of " << total_size << " from " << from; } From 39f96f93a9d1872ad0fb8a62a7da6ebac3f3e1e4 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Apr 2021 17:17:05 +0300 Subject: [PATCH 2/7] Update TDLib to 1.7.4. --- td | 2 +- telegram-bot-api/Client.cpp | 73 ++++++++++++++++++++++++++----------- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/td b/td index fbc7e5a..5bd0c2c 160000 --- a/td +++ b/td @@ -1 +1 @@ -Subproject commit fbc7e5a7f845d6c8df12b11f5b9a5c9ffc6eea0e +Subproject commit 5bd0c2c46ded5c75a641829cfe84c0b5fead5bfc diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index a4ffeb3..2b5f39c 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -2166,7 +2166,18 @@ class Client::JsonChatMember : public Jsonable { void store(JsonValueScope *scope) const { auto object = scope->enter_object(); - object("user", JsonUser(member_->user_id_, client_)); + CHECK(member_->member_id_ != nullptr); + switch (member_->member_id_->get_id()) { + case td_api::messageSenderUser::ID: { + auto user_id = static_cast(member_->member_id_.get())->user_id_; + object("user", JsonUser(user_id, client_)); + break; + } + case td_api::messageSenderChat::ID: + break; + default: + UNREACHABLE(); + } object("status", Client::get_chat_member_status(member_->status_)); switch (member_->status_->get_id()) { case td_api::chatMemberStatusCreator::ID: { @@ -2239,15 +2250,20 @@ class Client::JsonChatMembers : public Jsonable { auto array = scope->enter_array(); for (auto &member : members_) { CHECK(member != nullptr); + CHECK(member->member_id_ != nullptr); + if (member->member_id_->get_id() != td_api::messageSenderUser::ID) { + continue; + } + auto user_id = static_cast(member->member_id_.get())->user_id_; bool is_member_bot = member->bot_info_ != nullptr; if (!is_member_bot) { // bot info may be unknown - auto user_info = client_->get_user_info(member->user_id_); + auto user_info = client_->get_user_info(user_id); if (user_info != nullptr && user_info->type == UserInfo::Type::Bot) { is_member_bot = true; } } - if (is_member_bot && member->user_id_ != client_->my_id_) { + if (is_member_bot && user_id != client_->my_id_) { continue; } if (administrators_only_) { @@ -3912,8 +3928,9 @@ void Client::get_chat_member(int64 chat_id, int32 user_id, PromisedQueryPtr quer check_user_no_fail( user_id, std::move(query), [this, chat_id, user_id, on_success = std::move(on_success)](PromisedQueryPtr query) mutable { - send_request(make_object(chat_id, user_id), - std::make_unique>(std::move(query), std::move(on_success))); + send_request( + make_object(chat_id, td_api::make_object(user_id)), + std::make_unique>(std::move(query), std::move(on_success))); }); } @@ -6327,9 +6344,9 @@ td::Status Client::process_send_invoice_query(PromisedQueryPtr &query) { do_send_message( make_object( - make_object(currency.str(), std::move(prices), false, need_name, need_phone_number, - need_email_address, need_shipping_address, send_phone_number_to_provider, - send_email_address_to_provider, is_flexible), + make_object(currency.str(), std::move(prices), 0, td::vector(), false, need_name, + need_phone_number, need_email_address, need_shipping_address, + send_phone_number_to_provider, send_email_address_to_provider, is_flexible), title.str(), description.str(), photo_url.str(), photo_size, photo_width, photo_height, payload.str(), provider_token.str(), provider_data.str(), start_parameter.str()), std::move(query)); @@ -7172,8 +7189,10 @@ td::Status Client::process_promote_chat_member_query(PromisedQueryPtr &query) { status->custom_title_ = std::move(administrator->custom_title_); } - send_request(make_object(chat_id, user_id, std::move(status)), - std::make_unique(std::move(query))); + send_request( + make_object( + chat_id, td_api::make_object(user_id), std::move(status)), + std::make_unique(std::move(query))); }); }); return Status::OK(); @@ -7204,7 +7223,8 @@ td::Status Client::process_set_chat_administrator_custom_title_query(PromisedQue } administrator->custom_title_ = query->arg("custom_title").str(); - send_request(make_object(chat_id, user_id, std::move(administrator)), + send_request(make_object( + chat_id, td_api::make_object(user_id), std::move(administrator)), std::make_unique(std::move(query))); }); }); @@ -7219,12 +7239,13 @@ td::Status Client::process_ban_chat_member_query(PromisedQueryPtr &query) { check_chat(chat_id, AccessRights::Write, std::move(query), [this, user_id, until_date, revoke_messages](int64 chat_id, PromisedQueryPtr query) { - check_user_no_fail( - user_id, std::move(query), - [this, chat_id, user_id, until_date, revoke_messages](PromisedQueryPtr query) { - send_request(make_object(chat_id, user_id, until_date, revoke_messages), - std::make_unique(std::move(query))); - }); + check_user_no_fail(user_id, std::move(query), + [this, chat_id, user_id, until_date, revoke_messages](PromisedQueryPtr query) { + send_request(make_object( + chat_id, td_api::make_object(user_id), + until_date, revoke_messages), + std::make_unique(std::move(query))); + }); }); return Status::OK(); } @@ -7258,7 +7279,7 @@ td::Status Client::process_restrict_chat_member_query(PromisedQueryPtr &query) { } send_request(make_object( - chat_id, user_id, + chat_id, td_api::make_object(user_id), make_object( is_chat_member(chat_member->status_), until_date, std::move(permissions))), std::make_unique(std::move(query))); @@ -7290,13 +7311,15 @@ td::Status Client::process_unban_chat_member_query(PromisedQueryPtr &query) { } send_request(make_object( - chat_id, user_id, make_object()), + chat_id, td_api::make_object(user_id), + make_object()), std::make_unique(std::move(query))); }); } else { check_user_no_fail(user_id, std::move(query), [this, chat_id, user_id](PromisedQueryPtr query) { - send_request(make_object(chat_id, user_id, - make_object()), + send_request(make_object( + chat_id, td_api::make_object(user_id), + make_object()), std::make_unique(std::move(query))); }); } @@ -8529,7 +8552,13 @@ void Client::add_update_chat_member(object_ptr &&updat CHECK(update != nullptr); auto left_time = update->date_ + 86400 - get_unix_time(); if (left_time > 0) { - bool is_my = (update->old_chat_member_->user_id_ == my_id_); + CHECK(update->old_chat_member_->member_id_ != nullptr); + if (update->old_chat_member_->member_id_->get_id() != td_api::messageSenderUser::ID || + update->new_chat_member_->member_id_->get_id() != td_api::messageSenderUser::ID) { + return; + } + auto user_id = static_cast(update->old_chat_member_->member_id_.get())->user_id_; + bool is_my = (user_id == my_id_); auto webhook_queue_id = update->chat_id_ + (static_cast(is_my ? 5 : 6) << 33); auto update_type = is_my ? UpdateType::MyChatMember : UpdateType::ChatMember; add_update(update_type, JsonChatMemberUpdated(update.get(), this), left_time, webhook_queue_id); From b71e66003e1ede22349ca5098629bdc807fd1adf Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Apr 2021 17:42:21 +0300 Subject: [PATCH 3/7] Support new invoice fields. --- telegram-bot-api/Client.cpp | 71 ++++++++++++++++++++++++++++++------- telegram-bot-api/Client.h | 2 ++ 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 2b5f39c..706ce3c 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -4789,6 +4789,30 @@ td::Result>> Client::get return std::move(prices); } +td::Result> Client::get_suggested_tip_amounts(JsonValue &value) { + if (value.type() != JsonValue::Type::Array) { + return Status::Error(400, "Expected an Array of suggested tip amounts"); + } + + td::vector suggested_tip_amounts; + for (auto &amount : value.get_array()) { + Slice number; + if (amount.type() == JsonValue::Type::Number) { + number = amount.get_number(); + } else if (amount.type() == JsonValue::Type::String) { + number = amount.get_string(); + } else { + return Status::Error(400, "Suggested tip amount must be of type Number or String"); + } + auto parsed_amount = td::to_integer_safe(number); + if (parsed_amount.is_error()) { + return Status::Error(400, "Can't parse suggested tip amount as Number"); + } + suggested_tip_amounts.push_back(parsed_amount.ok()); + } + return std::move(suggested_tip_amounts); +} + td::Result> Client::get_shipping_option(JsonValue &option) { if (option.type() != JsonValue::Type::Object) { return Status::Error(400, "ShippingOption must be an Object"); @@ -6318,16 +6342,39 @@ td::Status Client::process_send_invoice_query(PromisedQueryPtr &query) { } TRY_RESULT(provider_token, get_required_string_arg(query.get(), "provider_token")); auto provider_data = query->arg("provider_data"); - TRY_RESULT(start_parameter, get_required_string_arg(query.get(), "start_parameter")); + auto start_parameter = query->arg("start_parameter"); TRY_RESULT(currency, get_required_string_arg(query.get(), "currency")); TRY_RESULT(labeled_price_parts, get_required_string_arg(query.get(), "prices")); - auto r_value = json_decode(labeled_price_parts); - if (r_value.is_error()) { + auto r_labeled_price_parts_value = json_decode(labeled_price_parts); + if (r_labeled_price_parts_value.is_error()) { return Status::Error(400, "Can't parse prices JSON object"); } - TRY_RESULT(prices, get_labeled_price_parts(r_value.ok_ref())); + TRY_RESULT(prices, get_labeled_price_parts(r_labeled_price_parts_value.ok_ref())); + + int64 max_tip_amount = 0; + td::vector suggested_tip_amounts; + { + auto max_tip_amount_str = query->arg("max_tip_amount"); + if (!max_tip_amount_str.empty()) { + auto r_max_tip_amount = td::to_integer_safe(max_tip_amount_str); + if (r_max_tip_amount.is_error()) { + return Status::Error(400, "Can't parse \"max_tip_amount\" as Number"); + } + max_tip_amount = r_max_tip_amount.ok(); + } + + auto suggested_tip_amounts_str = query->arg("suggested_tip_amounts"); + if (!suggested_tip_amounts_str.empty()) { + auto r_suggested_tip_amounts_value = json_decode(suggested_tip_amounts_str); + if (r_suggested_tip_amounts_value.is_error()) { + return Status::Error(400, "Can't parse suggested_tip_amounts JSON object"); + } + + TRY_RESULT_ASSIGN(suggested_tip_amounts, get_suggested_tip_amounts(r_suggested_tip_amounts_value.ok_ref())); + } + } auto photo_url = query->arg("photo_url"); int32 photo_size = get_integer_arg(query.get(), "photo_size", 0, 0, 1000000000); @@ -6342,14 +6389,14 @@ td::Status Client::process_send_invoice_query(PromisedQueryPtr &query) { auto send_email_address_to_provider = to_bool(query->arg("send_email_to_provider")); auto is_flexible = to_bool(query->arg("is_flexible")); - do_send_message( - make_object( - make_object(currency.str(), std::move(prices), 0, td::vector(), false, need_name, - need_phone_number, need_email_address, need_shipping_address, - send_phone_number_to_provider, send_email_address_to_provider, is_flexible), - title.str(), description.str(), photo_url.str(), photo_size, photo_width, photo_height, payload.str(), - provider_token.str(), provider_data.str(), start_parameter.str()), - std::move(query)); + do_send_message(make_object( + make_object( + currency.str(), std::move(prices), max_tip_amount, std::move(suggested_tip_amounts), false, + need_name, need_phone_number, need_email_address, need_shipping_address, + send_phone_number_to_provider, send_email_address_to_provider, is_flexible), + title.str(), description.str(), photo_url.str(), photo_size, photo_width, photo_height, + payload.str(), provider_token.str(), provider_data.str(), start_parameter.str()), + std::move(query)); return Status::OK(); } diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index 2ad425d..eeaa8af 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -301,6 +301,8 @@ class Client : public WebhookActor::Callback { static td::Result>> get_labeled_price_parts(td::JsonValue &value); + static td::Result> get_suggested_tip_amounts(td::JsonValue &value); + static td::Result> get_shipping_option(td::JsonValue &option); static td::Result>> get_shipping_options(const Query *query); From efaf601e8552574f9f12ae97d668381f5a916b22 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Apr 2021 17:44:55 +0300 Subject: [PATCH 4/7] Don't store empty chat_type. --- telegram-bot-api/Client.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 706ce3c..d3b4c39 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -1941,7 +1941,9 @@ class Client::JsonInlineQuery : public Jsonable { return ""; } }(); - object("chat_type", chat_type); + if (chat_type[0] != '\0') { + object("chat_type", chat_type); + } } object("query", query_); object("offset", offset_); From aa737b3dcff87fbe69a0b72d2738a13c04fa825f Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Apr 2021 17:49:53 +0300 Subject: [PATCH 5/7] Support messageVoiceChatScheduled. --- telegram-bot-api/Client.cpp | 20 ++++++++++++++++++++ telegram-bot-api/Client.h | 1 + 2 files changed, 21 insertions(+) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index d3b4c39..04109e6 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -1400,6 +1400,20 @@ class Client::JsonProximityAlertTriggered : public Jsonable { const Client *client_; }; +class Client::JsonVoiceChatScheduled : public Jsonable { + public: + explicit JsonVoiceChatScheduled(const td_api::messageVoiceChatScheduled *voice_chat_scheduled) + : voice_chat_scheduled_(voice_chat_scheduled) { + } + void store(JsonValueScope *scope) const { + auto object = scope->enter_object(); + object("start_date", voice_chat_scheduled_->start_date_); + } + + private: + const td_api::messageVoiceChatScheduled *voice_chat_scheduled_; +}; + class Client::JsonVoiceChatStarted : public Jsonable { public: explicit JsonVoiceChatStarted(const td_api::messageVoiceChatStarted *voice_chat_started) @@ -1836,6 +1850,11 @@ void Client::JsonMessage::store(JsonValueScope *scope) const { object("proximity_alert_triggered", JsonProximityAlertTriggered(content, client_)); break; } + case td_api::messageVoiceChatScheduled::ID: { + auto content = static_cast(message_->content.get()); + object("voice_chat_scheduled", JsonVoiceChatScheduled(content)); + break; + } case td_api::messageVoiceChatStarted::ID: { auto content = static_cast(message_->content.get()); object("voice_chat_started", JsonVoiceChatStarted(content)); @@ -8638,6 +8657,7 @@ bool Client::need_skip_update_message(int64 chat_id, const object_ptr Date: Thu, 8 Apr 2021 18:38:05 +0300 Subject: [PATCH 6/7] Add InputInvoiceMessageContent. --- telegram-bot-api/Client.cpp | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 04109e6..ae8f08e 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -5051,6 +5051,45 @@ td::Result> Client::get_input_me make_object(phone_number, first_name, last_name, vcard, 0)); } + if (has_json_object_field(object, "payload")) { + TRY_RESULT(title, get_json_object_string_field(object, "title", false)); + TRY_RESULT(description, get_json_object_string_field(object, "description", false)); + TRY_RESULT(payload, get_json_object_string_field(object, "payload", false)); + if (!td::check_utf8(payload)) { + return Status::Error(400, "InputInvoiceMessageContent payload must be encoded in UTF-8"); + } + TRY_RESULT(provider_token, get_json_object_string_field(object, "provider_token", false)); + TRY_RESULT(currency, get_json_object_string_field(object, "currency", false)); + TRY_RESULT(prices_object, get_json_object_field(object, "prices", JsonValue::Type::Array, false)); + TRY_RESULT(prices, get_labeled_price_parts(prices_object)); + TRY_RESULT(provider_data, get_json_object_string_field(object, "provider_data")); + TRY_RESULT(max_tip_amount, get_json_object_long_field(object, "max_tip_amount")); + td::vector suggested_tip_amounts; + TRY_RESULT(suggested_tip_amounts_array, + get_json_object_field(object, "suggested_tip_amounts", JsonValue::Type::Array)); + if (suggested_tip_amounts_array.type() == JsonValue::Type::Array) { + TRY_RESULT_ASSIGN(suggested_tip_amounts, get_suggested_tip_amounts(suggested_tip_amounts_array)); + } + TRY_RESULT(photo_url, get_json_object_string_field(object, "photo_url")); + TRY_RESULT(photo_size, get_json_object_int_field(object, "photo_size")); + TRY_RESULT(photo_width, get_json_object_int_field(object, "photo_width")); + TRY_RESULT(photo_height, get_json_object_int_field(object, "photo_height")); + TRY_RESULT(need_name, get_json_object_bool_field(object, "need_name")); + TRY_RESULT(need_phone_number, get_json_object_bool_field(object, "need_phone_number")); + TRY_RESULT(need_email_address, get_json_object_bool_field(object, "need_email")); + TRY_RESULT(need_shipping_address, get_json_object_bool_field(object, "need_shipping_address")); + TRY_RESULT(send_phone_number_to_provider, get_json_object_bool_field(object, "send_phone_number_to_provider")); + TRY_RESULT(send_email_address_to_provider, get_json_object_bool_field(object, "send_email_to_provider")); + TRY_RESULT(is_flexible, get_json_object_bool_field(object, "is_flexible")); + + return make_object( + make_object(currency, std::move(prices), max_tip_amount, std::move(suggested_tip_amounts), + false, need_name, need_phone_number, need_email_address, need_shipping_address, + send_phone_number_to_provider, send_email_address_to_provider, is_flexible), + title, description, photo_url, photo_size, photo_width, photo_height, payload, provider_token, provider_data, + td::string()); + } + if (is_input_message_content_required) { return Status::Error(400, "Input message content is not specified"); } From 90fed9b9a7c3598ccb1538b29f7a276a62ff179c Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 13 Apr 2021 19:33:50 +0300 Subject: [PATCH 7/7] Update version to 5.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 56b275e..45de0b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) -project(TelegramBotApi VERSION 5.1 LANGUAGES CXX) +project(TelegramBotApi VERSION 5.2 LANGUAGES CXX) add_subdirectory(td EXCLUDE_FROM_ALL) diff --git a/telegram-bot-api/telegram-bot-api.cpp b/telegram-bot-api/telegram-bot-api.cpp index 973f0bf..3e1b02b 100644 --- a/telegram-bot-api/telegram-bot-api.cpp +++ b/telegram-bot-api/telegram-bot-api.cpp @@ -134,7 +134,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_ = "5.1"; + parameters->version_ = "5.2"; parameters->shared_data_ = shared_data; parameters->start_time_ = start_time; auto net_query_stats = td::create_net_query_stats();