From ae987f2211f154b91f62be516d392dbb971136e8 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 10 Nov 2021 17:14:00 +0300 Subject: [PATCH] Add inlineKeyboardButtonTypeUser. --- td/generate/scheme/td_api.tl | 3 ++ td/telegram/MessagesManager.cpp | 1 + td/telegram/ReplyMarkup.cpp | 87 +++++++++++++++++++++++++-------- td/telegram/ReplyMarkup.h | 11 ++++- td/telegram/ReplyMarkup.hpp | 73 ++++++++++++++++++++++----- td/telegram/UpdatesManager.cpp | 18 +++++++ td/telegram/UpdatesManager.h | 2 + td/telegram/Version.h | 1 + 8 files changed, 162 insertions(+), 34 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 6157eee8b..d79c4b1d1 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1070,6 +1070,9 @@ inlineKeyboardButtonTypeSwitchInline query:string in_current_chat:Bool = InlineK //@description A button to buy something. This button must be in the first column and row of the keyboard and can be attached only to a message with content of the type messageInvoice inlineKeyboardButtonTypeBuy = InlineKeyboardButtonType; +//@description A button to open a chat with a user @user_id User identifier +inlineKeyboardButtonTypeUser user_id:int53 = InlineKeyboardButtonType; + //@description Represents a single button in an inline keyboard @text Text of the button @type Type of the button inlineKeyboardButton text:string type:InlineKeyboardButtonType = InlineKeyboardButton; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index e9ceee88c..d19f4b326 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -23833,6 +23833,7 @@ void MessagesManager::add_message_dependencies(Dependencies &dependencies, const add_message_sender_dependencies(dependencies, recent_replier_dialog_id); } add_message_content_dependencies(dependencies, m->content.get()); + add_reply_markup_dependencies(dependencies, m->reply_markup.get()); } class MessagesManager::SendMessageLogEvent { diff --git a/td/telegram/ReplyMarkup.cpp b/td/telegram/ReplyMarkup.cpp index 2223ee01d..cd1f22ce6 100644 --- a/td/telegram/ReplyMarkup.cpp +++ b/td/telegram/ReplyMarkup.cpp @@ -7,6 +7,7 @@ #include "td/telegram/ReplyMarkup.h" #include "td/telegram/ContactsManager.h" +#include "td/telegram/Dependencies.h" #include "td/telegram/Global.h" #include "td/telegram/LinkManager.h" #include "td/telegram/misc.h" @@ -90,6 +91,9 @@ static StringBuilder &operator<<(StringBuilder &string_builder, const InlineKeyb case InlineKeyboardButton::Type::CallbackWithPassword: string_builder << "CallbackWithPassword"; break; + case InlineKeyboardButton::Type::User: + string_builder << "User " << keyboard_button.user_id.get(); + break; default: UNREACHABLE(); } @@ -264,9 +268,14 @@ static InlineKeyboardButton get_inline_keyboard_button( button.id = keyboard_button->button_id_; button.text = std::move(keyboard_button->text_); button.data = std::move(keyboard_button->url_); - if ((keyboard_button->flags_ & telegram_api::keyboardButtonUrlAuth::FWD_TEXT_MASK) != 0) { - button.forward_text = std::move(keyboard_button->fwd_text_); - } + button.forward_text = std::move(keyboard_button->fwd_text_); + break; + } + case telegram_api::keyboardButtonUserProfile::ID: { + auto keyboard_button = move_tl_object_as(keyboard_button_ptr); + button.type = InlineKeyboardButton::Type::User; + button.text = std::move(keyboard_button->text_); + button.user_id = UserId(keyboard_button->user_id_); break; } default: @@ -434,42 +443,42 @@ static Result get_inline_keyboard_button(tl_object_ptrtype_->get_id(); switch (button_type_id) { case td_api::inlineKeyboardButtonTypeUrl::ID: { - current_button.type = InlineKeyboardButton::Type::Url; - auto r_url = - LinkManager::check_link(static_cast(button->type_.get())->url_); + auto button_type = move_tl_object_as(button->type_); + auto r_url = LinkManager::check_link(button_type->url_); if (r_url.is_error()) { return Status::Error(400, "Inline keyboard button URL is invalid"); } + current_button.type = InlineKeyboardButton::Type::Url; current_button.data = r_url.move_as_ok(); if (!clean_input_string(current_button.data)) { return Status::Error(400, "Inline keyboard button URL must be encoded in UTF-8"); } break; } - case td_api::inlineKeyboardButtonTypeCallback::ID: + case td_api::inlineKeyboardButtonTypeCallback::ID: { + auto button_type = move_tl_object_as(button->type_); current_button.type = InlineKeyboardButton::Type::Callback; - current_button.data = - std::move(static_cast(button->type_.get())->data_); + current_button.data = std::move(button_type->data_); break; + } case td_api::inlineKeyboardButtonTypeCallbackGame::ID: current_button.type = InlineKeyboardButton::Type::CallbackGame; break; case td_api::inlineKeyboardButtonTypeCallbackWithPassword::ID: return Status::Error(400, "Can't use CallbackWithPassword inline button"); case td_api::inlineKeyboardButtonTypeSwitchInline::ID: { - auto switch_inline_button = move_tl_object_as(button->type_); + auto button_type = move_tl_object_as(button->type_); if (!switch_inline_buttons_allowed) { const char *button_name = - switch_inline_button->in_current_chat_ ? "switch_inline_query_current_chat" : "switch_inline_query"; + button_type->in_current_chat_ ? "switch_inline_query_current_chat" : "switch_inline_query"; return Status::Error(400, PSLICE() << "Can't use " << button_name << " in a channel chat, because a user will not be able to use the button " "without knowing bot's username"); } - current_button.type = switch_inline_button->in_current_chat_ - ? InlineKeyboardButton::Type::SwitchInlineCurrentDialog - : InlineKeyboardButton::Type::SwitchInline; - current_button.data = std::move(switch_inline_button->query_); + current_button.type = button_type->in_current_chat_ ? InlineKeyboardButton::Type::SwitchInlineCurrentDialog + : InlineKeyboardButton::Type::SwitchInline; + current_button.data = std::move(button_type->query_); if (!clean_input_string(current_button.data)) { return Status::Error(400, "Inline keyboard button switch inline query must be encoded in UTF-8"); } @@ -479,26 +488,36 @@ static Result get_inline_keyboard_button(tl_object_ptr(button->type_); - auto r_url = LinkManager::check_link(login_url->url_); + auto button_type = td_api::move_object_as(button->type_); + auto r_url = LinkManager::check_link(button_type->url_); if (r_url.is_error()) { return Status::Error(400, "Inline keyboard button login URL is invalid"); } + current_button.type = InlineKeyboardButton::Type::UrlAuth; current_button.data = r_url.move_as_ok(); - current_button.forward_text = std::move(login_url->forward_text_); + current_button.forward_text = std::move(button_type->forward_text_); if (!clean_input_string(current_button.data)) { return Status::Error(400, "Inline keyboard button login URL must be encoded in UTF-8"); } if (!clean_input_string(current_button.forward_text)) { return Status::Error(400, "Inline keyboard button forward text must be encoded in UTF-8"); } - current_button.id = login_url->id_; - if (current_button.id == 0 || current_button.id == std::numeric_limits::min()) { + current_button.id = button_type->id_; + if (current_button.id == std::numeric_limits::min() || + !UserId(current_button.id >= 0 ? current_button.id : -current_button.id).is_valid()) { return Status::Error(400, "Invalid bot_user_id specified"); } break; } + case td_api::inlineKeyboardButtonTypeUser::ID: { + auto button_type = td_api::move_object_as(button->type_); + current_button.type = InlineKeyboardButton::Type::User; + current_button.user_id = UserId(button_type->user_id_); + if (!current_button.user_id.is_valid()) { + return Status::Error(400, "Invalid user_id specified"); + } + break; + } default: UNREACHABLE(); } @@ -683,6 +702,14 @@ static tl_object_ptr get_inline_keyboard_button( case InlineKeyboardButton::Type::CallbackWithPassword: UNREACHABLE(); break; + case InlineKeyboardButton::Type::User: { + auto input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(keyboard_button.user_id); + if (input_user == nullptr) { + LOG(ERROR) << "Failed to get InputUser for " << keyboard_button.user_id; + input_user = make_tl_object(); + } + return make_tl_object(keyboard_button.text, std::move(input_user)); + } default: UNREACHABLE(); return nullptr; @@ -796,6 +823,11 @@ static tl_object_ptr get_inline_keyboard_button_ob case InlineKeyboardButton::Type::CallbackWithPassword: type = make_tl_object(keyboard_button.data); break; + case InlineKeyboardButton::Type::User: + type = make_tl_object( + G()->td().get_actor_unsafe()->contacts_manager_->get_user_id_object(keyboard_button.user_id, + "get_inline_keyboard_button_object")); + break; default: UNREACHABLE(); return nullptr; @@ -860,4 +892,17 @@ tl_object_ptr get_reply_markup_object(const unique_ptrget_reply_markup_object(); } +void add_reply_markup_dependencies(Dependencies &dependencies, const ReplyMarkup *reply_markup) { + if (reply_markup == nullptr) { + return; + } + for (auto &row : reply_markup->inline_keyboard) { + for (auto &button : row) { + if (button.user_id.is_valid()) { + dependencies.user_ids.insert(button.user_id); + } + } + } +} + } // namespace td diff --git a/td/telegram/ReplyMarkup.h b/td/telegram/ReplyMarkup.h index 6ba401141..eabbeedbe 100644 --- a/td/telegram/ReplyMarkup.h +++ b/td/telegram/ReplyMarkup.h @@ -8,6 +8,7 @@ #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" +#include "td/telegram/UserId.h" #include "td/utils/common.h" #include "td/utils/Status.h" @@ -15,6 +16,8 @@ namespace td { +struct Dependencies; + struct KeyboardButton { // append only enum class Type : int32 { @@ -39,10 +42,12 @@ struct InlineKeyboardButton { SwitchInlineCurrentDialog, Buy, UrlAuth, - CallbackWithPassword + CallbackWithPassword, + User }; Type type; - int64 id = 0; // UrlAuth only, button_id or (2 * request_write_access - 1) * bot_user_id + int64 id = 0; // UrlAuth only, button_id or (2 * request_write_access - 1) * bot_user_id + UserId user_id; // User only string text; string forward_text; // UrlAuth only string data; @@ -85,4 +90,6 @@ tl_object_ptr get_input_reply_markup(const unique_ptr tl_object_ptr get_reply_markup_object(const unique_ptr &reply_markup); +void add_reply_markup_dependencies(Dependencies &dependencies, const ReplyMarkup *reply_markup); + } // namespace td diff --git a/td/telegram/ReplyMarkup.hpp b/td/telegram/ReplyMarkup.hpp index ceae194a0..994102b2c 100644 --- a/td/telegram/ReplyMarkup.hpp +++ b/td/telegram/ReplyMarkup.hpp @@ -15,40 +15,91 @@ namespace td { template void store(KeyboardButton button, StorerT &storer) { + BEGIN_STORE_FLAGS(); + END_STORE_FLAGS(); store(button.type, storer); store(button.text, storer); } template void parse(KeyboardButton &button, ParserT &parser) { + if (parser.version() >= static_cast(Version::AddKeyboardButtonFlags)) { + BEGIN_PARSE_FLAGS(); + END_PARSE_FLAGS(); + } parse(button.type, parser); parse(button.text, parser); } template void store(InlineKeyboardButton button, StorerT &storer) { + bool has_id = button.id != 0; + bool has_user_id = button.user_id.is_valid(); + bool has_forward_text = !button.forward_text.empty(); + bool has_data = !button.data.empty(); + BEGIN_STORE_FLAGS(); + STORE_FLAG(has_id); + STORE_FLAG(has_user_id); + STORE_FLAG(has_forward_text); + STORE_FLAG(has_data); + END_STORE_FLAGS(); store(button.type, storer); - if (button.type == InlineKeyboardButton::Type::UrlAuth) { + if (has_id) { store(button.id, storer); } + if (has_user_id) { + store(button.user_id, storer); + } store(button.text, storer); - store(button.data, storer); + if (has_forward_text) { + store(button.forward_text, storer); + } + if (has_data) { + store(button.data, storer); + } } template void parse(InlineKeyboardButton &button, ParserT &parser) { - parse(button.type, parser); - if (button.type == InlineKeyboardButton::Type::UrlAuth) { - if (parser.version() >= static_cast(Version::Support64BitIds)) { + if (parser.version() >= static_cast(Version::AddKeyboardButtonFlags)) { + bool has_id; + bool has_user_id; + bool has_forward_text; + bool has_data; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_id); + PARSE_FLAG(has_user_id); + PARSE_FLAG(has_forward_text); + PARSE_FLAG(has_data); + END_PARSE_FLAGS(); + parse(button.type, parser); + if (has_id) { parse(button.id, parser); - } else { - int32 old_id; - parse(old_id, parser); - button.id = old_id; } + if (has_user_id) { + parse(button.user_id, parser); + } + parse(button.text, parser); + if (has_forward_text) { + parse(button.forward_text, parser); + } + if (has_data) { + parse(button.data, parser); + } + } else { + parse(button.type, parser); + if (button.type == InlineKeyboardButton::Type::UrlAuth) { + if (parser.version() >= static_cast(Version::Support64BitIds)) { + parse(button.id, parser); + } else { + int32 old_id; + parse(old_id, parser); + button.id = old_id; + } + } + parse(button.text, parser); + parse(button.data, parser); } - parse(button.text, parser); - parse(button.data, parser); } template diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 425660ae9..05911bbc5 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -536,6 +536,24 @@ bool UpdatesManager::is_acceptable_message_entities( return true; } +bool UpdatesManager::is_acceptable_reply_markup(const tl_object_ptr &reply_markup) const { + if (reply_markup == nullptr || reply_markup->get_id() != telegram_api::replyInlineMarkup::ID) { + return true; + } + for (const auto &row : static_cast(reply_markup.get())->rows_) { + for (const auto &button : row->buttons_) { + if (button->get_id() == telegram_api::keyboardButtonUserProfile::ID) { + auto user_profile_button = static_cast(button.get()); + UserId user_id(user_profile_button->user_id_); + if (!is_acceptable_user(user_id) || !td_->contacts_manager_->have_input_user(user_id)) { + return false; + } + } + } + } + return true; +} + bool UpdatesManager::is_acceptable_message_reply_header( const telegram_api::object_ptr &header) const { if (header == nullptr) { diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index 44413f860..5e7b7ee20 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -356,6 +356,8 @@ class UpdatesManager final : public Actor { bool is_acceptable_message_entities(const vector> &message_entities) const; + bool is_acceptable_reply_markup(const tl_object_ptr &reply_markup) const; + bool is_acceptable_message_reply_header( const telegram_api::object_ptr &header) const; diff --git a/td/telegram/Version.h b/td/telegram/Version.h index 3ba32c72d..545040dc8 100644 --- a/td/telegram/Version.h +++ b/td/telegram/Version.h @@ -48,6 +48,7 @@ enum class Version : int32 { RemovePhotoVolumeAndLocalId, Support64BitIds, AddInviteLinksRequiringApproval, + AddKeyboardButtonFlags, // 35 Next };