From 93dd076d8a355879104f41df1718e0c2d29d14c9 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 23 May 2019 23:35:26 +0300 Subject: [PATCH] Support LoginUrl buttons. GitOrigin-RevId: ca630cc32bf17df6dcedcff4ffa8507fb82ae9cc --- td/generate/scheme/td_api.tl | 3 ++ td/generate/scheme/td_api.tlo | Bin 151724 -> 151856 bytes td/generate/scheme/telegram_api.tl | 2 ++ td/generate/scheme/telegram_api.tlo | Bin 174584 -> 174992 bytes td/telegram/MessagesManager.cpp | 19 +++++++--- td/telegram/ReplyMarkup.cpp | 54 ++++++++++++++++++++++++++-- td/telegram/ReplyMarkup.h | 3 +- td/telegram/ReplyMarkup.hpp | 6 ++++ 8 files changed, 79 insertions(+), 8 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index c758b8ef..2ee2ffc8 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -643,6 +643,9 @@ keyboardButton text:string type:KeyboardButtonType = KeyboardButton; //@description A button that opens a specified URL @url HTTP or tg:// URL to open inlineKeyboardButtonTypeUrl url:string = InlineKeyboardButtonType; +//@description A button that opens a specified URL and automatically logs in in current user if they allowed to do that @url HTTP URL to open @id Unique button identifier +inlineKeyboardButtonTypeLoginUrl url:string id:int32 = InlineKeyboardButtonType; + //@description A button that sends a special callback query to a bot @data Data to be sent to the bot via a callback query inlineKeyboardButtonTypeCallback data:bytes = InlineKeyboardButtonType; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index a5d7b06916ee5fe4f3b8c9a88336b73b259d827f..704927d43a7b9889a0f06b8a8f80e9fb59018bf8 100644 GIT binary patch delta 226 zcmZ3pkaNQ#&J8gLOx8B6DKN9e(^?P@&h9dh#4() zCJ=^!tpSAbq0T}ArU7Jdku#ePhi%(Iu(KTMEx@X#FOXrpH;+YW-wK2mQ1RyC<10-`#mK?kSm<^>Jg K7c?+VxBvi*{XT&J diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index 078a86c8..0fee71dd 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -512,6 +512,8 @@ keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton; keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton; keyboardButtonGame#50f41ccf text:string = KeyboardButton; keyboardButtonBuy#afd93fbb text:string = KeyboardButton; +keyboardButtonUrlAuth#77a34975 text:string url:string button_id:int = KeyboardButton; +inputKeyboardButtonUrlAuth#af24bb74 flags:# request_write_access:flags.0?true text:string url:string bot:InputUser = KeyboardButton; keyboardButtonRow#77608b83 buttons:Vector = KeyboardButtonRow; diff --git a/td/generate/scheme/telegram_api.tlo b/td/generate/scheme/telegram_api.tlo index df7ab647dee4791d5131bf5facff32ebb096f5ff..7b75f9b7f4a2e0663133c7f141a96572c38b1e73 100644 GIT binary patch delta 396 zcmexynQOvzt_>jqqAzC5Zs7AytxU>KEJ|@IEh)**W8j+X$SA(KL7+jF@!Doay~7Jx zK&mEBxM%=j{5h`zVJx_yGdbXb0)$g?K?5cl0AYN&paWsRbw*q?K@&N05vu0EB*V$7 zm+~RfGcG}Gfb0B%Bw_$^4g(ZimE(#j^;}#onvLR#(4rj2(vl1Y29Vn60rreClN~N- zOtNQXO9Fdxa=eY?bb}ZsPGdB)N_MNPm&(j5C@nz^6_|lw^Acnj4MatXQVUB{i%a6m zi!w`6;}esUQ;UnI2WBv-OpiUpC=U!7iOB&5EYnZ)Gf7Nt*vA3!TEOK9Fr#_RjqqA#;#BKW*hE0gjQi&C6QOG@(d7&s<7GKz0*5NMEPyt0{5@9;tv zkgCZOE*d}>f6l8w7z-}wOb)o90O6Ee(13{sKp0;x=s*~7oe>vJ&_s@0gsM3($#Amj grF@9=j7v}(;5xrxh`hKG0ao1Xa&^1QRYsp{0DsL~kN^Mx diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 45ce7385..99ee5dc6 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -23513,7 +23513,9 @@ bool MessagesManager::update_message(Dialog *d, unique_ptr &old_message if (new_message->reply_markup != nullptr) { auto content_type = old_message->content->get_type(); // MessageGame and MessageInvoice reply markup can be generated server side - if (content_type != MessageContentType::Game && content_type != MessageContentType::Invoice) { + // some forwards retain their reply markup + if (content_type != MessageContentType::Game && content_type != MessageContentType::Invoice && + old_message->forward_info == nullptr) { LOG(ERROR) << message_id << " in " << dialog_id << " has received reply markup " << *new_message->reply_markup << ", message content type is " << old_message->content->get_type() << '/' << new_message->content->get_type(); @@ -23527,9 +23529,18 @@ bool MessagesManager::update_message(Dialog *d, unique_ptr &old_message } } else { if (new_message->reply_markup != nullptr) { - LOG_IF(WARNING, *old_message->reply_markup != *new_message->reply_markup) - << message_id << " in " << dialog_id << " has changed reply_markup from " << *old_message->reply_markup - << " to " << *new_message->reply_markup; + if (message_id.is_yet_unsent() && old_message->reply_markup->type == ReplyMarkup::Type::InlineKeyboard && + new_message->reply_markup->type == ReplyMarkup::Type::InlineKeyboard) { + // allow the server to update inline keyboard for sent messages + // this is needed to get correct button_id for UrlAuth buttons + old_message->had_reply_markup = false; + old_message->reply_markup = std::move(new_message->reply_markup); + is_changed = true; + } else { + LOG_IF(WARNING, *old_message->reply_markup != *new_message->reply_markup) + << message_id << " in " << dialog_id << " has changed reply_markup from " << *old_message->reply_markup + << " to " << *new_message->reply_markup; + } } else if (is_new_available) { // if the message is not accessible anymore, then we don't need a warning LOG(ERROR) << message_id << " in " << dialog_id << " sent by " << old_message->sender_user_id << " has lost reply markup " << *old_message->reply_markup diff --git a/td/telegram/ReplyMarkup.cpp b/td/telegram/ReplyMarkup.cpp index 65ed10e4..bbda2e99 100644 --- a/td/telegram/ReplyMarkup.cpp +++ b/td/telegram/ReplyMarkup.cpp @@ -6,15 +6,19 @@ // #include "td/telegram/ReplyMarkup.h" +#include "td/telegram/ContactsManager.h" +#include "td/telegram/Global.h" +#include "td/telegram/misc.h" +#include "td/telegram/Td.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" -#include "td/telegram/misc.h" - #include "td/utils/buffer.h" #include "td/utils/format.h" #include "td/utils/logging.h" +#include + namespace td { static constexpr int32 REPLY_MARKUP_FLAG_NEED_RESIZE_KEYBOARD = 1 << 0; @@ -44,7 +48,7 @@ static StringBuilder &operator<<(StringBuilder &string_builder, const KeyboardBu } static bool operator==(const InlineKeyboardButton &lhs, const InlineKeyboardButton &rhs) { - return lhs.type == rhs.type && lhs.text == rhs.text && lhs.data == rhs.data; + return lhs.type == rhs.type && lhs.text == rhs.text && lhs.data == rhs.data && lhs.id == rhs.id; } static StringBuilder &operator<<(StringBuilder &string_builder, const InlineKeyboardButton &keyboard_button) { @@ -68,6 +72,9 @@ static StringBuilder &operator<<(StringBuilder &string_builder, const InlineKeyb case InlineKeyboardButton::Type::Buy: string_builder << "Buy"; break; + case InlineKeyboardButton::Type::UrlAuth: + string_builder << "UrlAuth, id = " << keyboard_button.id; + break; default: UNREACHABLE(); } @@ -215,6 +222,14 @@ static InlineKeyboardButton get_inline_keyboard_button( button.text = std::move(keyboard_button->text_); break; } + case telegram_api::keyboardButtonUrlAuth::ID: { + auto keyboard_button = move_tl_object_as(keyboard_button_ptr); + button.type = InlineKeyboardButton::Type::UrlAuth; + button.id = keyboard_button->button_id_; + button.text = std::move(keyboard_button->text_); + button.data = std::move(keyboard_button->url_); + break; + } default: LOG(ERROR) << "Unsupported inline keyboard button: " << to_string(keyboard_button_ptr); } @@ -399,6 +414,20 @@ static Result get_inline_keyboard_button(tl_object_ptr(button->type_); + TRY_RESULT(url, check_url(login_url->url_)); + current_button.data = std::move(url); + if (!clean_input_string(current_button.data)) { + return Status::Error(400, "Inline keyboard button url must be encoded in UTF-8"); + } + current_button.id = login_url->id_; + if (current_button.id == 0 || current_button.id == std::numeric_limits::min()) { + return Status::Error(400, "Invalid bot_user_id specified"); + } + break; + } default: UNREACHABLE(); } @@ -552,6 +581,22 @@ static tl_object_ptr get_inline_keyboard_button( } case InlineKeyboardButton::Type::Buy: return make_tl_object(keyboard_button.text); + case InlineKeyboardButton::Type::UrlAuth: { + int32 flags = 0; + int32 bot_user_id = keyboard_button.id; + if (bot_user_id > 0) { + flags |= telegram_api::inputKeyboardButtonUrlAuth::REQUEST_WRITE_ACCESS_MASK; + } else { + bot_user_id = -bot_user_id; + } + auto input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(UserId(bot_user_id)); + if (input_user == nullptr) { + LOG(ERROR) << "Failed to get InputUser for " << bot_user_id; + return make_tl_object(keyboard_button.text, keyboard_button.data); + } + return make_tl_object(flags, false /*ignored*/, keyboard_button.text, + keyboard_button.data, std::move(input_user)); + } default: UNREACHABLE(); return nullptr; @@ -648,6 +693,9 @@ static tl_object_ptr get_inline_keyboard_button_ob case InlineKeyboardButton::Type::Buy: type = make_tl_object(); break; + case InlineKeyboardButton::Type::UrlAuth: + type = make_tl_object(keyboard_button.data, keyboard_button.id); + break; default: UNREACHABLE(); return nullptr; diff --git a/td/telegram/ReplyMarkup.h b/td/telegram/ReplyMarkup.h index b3b3a448..99d4d996 100644 --- a/td/telegram/ReplyMarkup.h +++ b/td/telegram/ReplyMarkup.h @@ -24,8 +24,9 @@ struct KeyboardButton { struct InlineKeyboardButton { // append only - enum class Type : int32 { Url, Callback, CallbackGame, SwitchInline, SwitchInlineCurrentDialog, Buy }; + enum class Type : int32 { Url, Callback, CallbackGame, SwitchInline, SwitchInlineCurrentDialog, Buy, UrlAuth }; Type type; + int32 id = 0; // UrlAuth only, button_id or (2 * request_write_access - 1) * bot_user_id string text; string data; }; diff --git a/td/telegram/ReplyMarkup.hpp b/td/telegram/ReplyMarkup.hpp index b752f773..afa2bd8f 100644 --- a/td/telegram/ReplyMarkup.hpp +++ b/td/telegram/ReplyMarkup.hpp @@ -27,6 +27,9 @@ void parse(KeyboardButton &button, ParserT &parser) { template void store(InlineKeyboardButton button, StorerT &storer) { store(button.type, storer); + if (button.type == InlineKeyboardButton::Type::UrlAuth) { + store(button.id, storer); + } store(button.text, storer); store(button.data, storer); } @@ -34,6 +37,9 @@ void store(InlineKeyboardButton button, StorerT &storer) { template void parse(InlineKeyboardButton &button, ParserT &parser) { parse(button.type, parser); + if (button.type == InlineKeyboardButton::Type::UrlAuth) { + parse(button.id, parser); + } parse(button.text, parser); parse(button.data, parser); }