Support LoginUrl buttons.

GitOrigin-RevId: ca630cc32bf17df6dcedcff4ffa8507fb82ae9cc
This commit is contained in:
levlam 2019-05-23 23:35:26 +03:00
parent bf3e0b8457
commit 93dd076d8a
8 changed files with 79 additions and 8 deletions

View File

@ -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 //@description A button that opens a specified URL @url HTTP or tg:// URL to open
inlineKeyboardButtonTypeUrl url:string = InlineKeyboardButtonType; 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 //@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; inlineKeyboardButtonTypeCallback data:bytes = InlineKeyboardButtonType;

Binary file not shown.

View File

@ -512,6 +512,8 @@ keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton;
keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton; keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton;
keyboardButtonGame#50f41ccf text:string = KeyboardButton; keyboardButtonGame#50f41ccf text:string = KeyboardButton;
keyboardButtonBuy#afd93fbb 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<KeyboardButton> = KeyboardButtonRow; keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;

Binary file not shown.

View File

@ -23513,7 +23513,9 @@ bool MessagesManager::update_message(Dialog *d, unique_ptr<Message> &old_message
if (new_message->reply_markup != nullptr) { if (new_message->reply_markup != nullptr) {
auto content_type = old_message->content->get_type(); auto content_type = old_message->content->get_type();
// MessageGame and MessageInvoice reply markup can be generated server side // 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 LOG(ERROR) << message_id << " in " << dialog_id << " has received reply markup " << *new_message->reply_markup
<< ", message content type is " << old_message->content->get_type() << '/' << ", message content type is " << old_message->content->get_type() << '/'
<< new_message->content->get_type(); << new_message->content->get_type();
@ -23527,9 +23529,18 @@ bool MessagesManager::update_message(Dialog *d, unique_ptr<Message> &old_message
} }
} else { } else {
if (new_message->reply_markup != nullptr) { if (new_message->reply_markup != nullptr) {
LOG_IF(WARNING, *old_message->reply_markup != *new_message->reply_markup) if (message_id.is_yet_unsent() && old_message->reply_markup->type == ReplyMarkup::Type::InlineKeyboard &&
<< message_id << " in " << dialog_id << " has changed reply_markup from " << *old_message->reply_markup new_message->reply_markup->type == ReplyMarkup::Type::InlineKeyboard) {
<< " to " << *new_message->reply_markup; // 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 } 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 LOG(ERROR) << message_id << " in " << dialog_id << " sent by " << old_message->sender_user_id
<< " has lost reply markup " << *old_message->reply_markup << " has lost reply markup " << *old_message->reply_markup

View File

@ -6,15 +6,19 @@
// //
#include "td/telegram/ReplyMarkup.h" #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/td_api.h"
#include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.h"
#include "td/telegram/misc.h"
#include "td/utils/buffer.h" #include "td/utils/buffer.h"
#include "td/utils/format.h" #include "td/utils/format.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include <limits>
namespace td { namespace td {
static constexpr int32 REPLY_MARKUP_FLAG_NEED_RESIZE_KEYBOARD = 1 << 0; 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) { 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) { 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: case InlineKeyboardButton::Type::Buy:
string_builder << "Buy"; string_builder << "Buy";
break; break;
case InlineKeyboardButton::Type::UrlAuth:
string_builder << "UrlAuth, id = " << keyboard_button.id;
break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
@ -215,6 +222,14 @@ static InlineKeyboardButton get_inline_keyboard_button(
button.text = std::move(keyboard_button->text_); button.text = std::move(keyboard_button->text_);
break; break;
} }
case telegram_api::keyboardButtonUrlAuth::ID: {
auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonUrlAuth>(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: default:
LOG(ERROR) << "Unsupported inline keyboard button: " << to_string(keyboard_button_ptr); LOG(ERROR) << "Unsupported inline keyboard button: " << to_string(keyboard_button_ptr);
} }
@ -399,6 +414,20 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
case td_api::inlineKeyboardButtonTypeBuy::ID: case td_api::inlineKeyboardButtonTypeBuy::ID:
current_button.type = InlineKeyboardButton::Type::Buy; current_button.type = InlineKeyboardButton::Type::Buy;
break; break;
case td_api::inlineKeyboardButtonTypeLoginUrl::ID: {
current_button.type = InlineKeyboardButton::Type::UrlAuth;
auto login_url = td_api::move_object_as<td_api::inlineKeyboardButtonTypeLoginUrl>(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<int32>::min()) {
return Status::Error(400, "Invalid bot_user_id specified");
}
break;
}
default: default:
UNREACHABLE(); UNREACHABLE();
} }
@ -552,6 +581,22 @@ static tl_object_ptr<telegram_api::KeyboardButton> get_inline_keyboard_button(
} }
case InlineKeyboardButton::Type::Buy: case InlineKeyboardButton::Type::Buy:
return make_tl_object<telegram_api::keyboardButtonBuy>(keyboard_button.text); return make_tl_object<telegram_api::keyboardButtonBuy>(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<telegram_api::keyboardButtonUrl>(keyboard_button.text, keyboard_button.data);
}
return make_tl_object<telegram_api::inputKeyboardButtonUrlAuth>(flags, false /*ignored*/, keyboard_button.text,
keyboard_button.data, std::move(input_user));
}
default: default:
UNREACHABLE(); UNREACHABLE();
return nullptr; return nullptr;
@ -648,6 +693,9 @@ static tl_object_ptr<td_api::inlineKeyboardButton> get_inline_keyboard_button_ob
case InlineKeyboardButton::Type::Buy: case InlineKeyboardButton::Type::Buy:
type = make_tl_object<td_api::inlineKeyboardButtonTypeBuy>(); type = make_tl_object<td_api::inlineKeyboardButtonTypeBuy>();
break; break;
case InlineKeyboardButton::Type::UrlAuth:
type = make_tl_object<td_api::inlineKeyboardButtonTypeLoginUrl>(keyboard_button.data, keyboard_button.id);
break;
default: default:
UNREACHABLE(); UNREACHABLE();
return nullptr; return nullptr;

View File

@ -24,8 +24,9 @@ struct KeyboardButton {
struct InlineKeyboardButton { struct InlineKeyboardButton {
// append only // 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; Type type;
int32 id = 0; // UrlAuth only, button_id or (2 * request_write_access - 1) * bot_user_id
string text; string text;
string data; string data;
}; };

View File

@ -27,6 +27,9 @@ void parse(KeyboardButton &button, ParserT &parser) {
template <class StorerT> template <class StorerT>
void store(InlineKeyboardButton button, StorerT &storer) { void store(InlineKeyboardButton button, StorerT &storer) {
store(button.type, storer); store(button.type, storer);
if (button.type == InlineKeyboardButton::Type::UrlAuth) {
store(button.id, storer);
}
store(button.text, storer); store(button.text, storer);
store(button.data, storer); store(button.data, storer);
} }
@ -34,6 +37,9 @@ void store(InlineKeyboardButton button, StorerT &storer) {
template <class ParserT> template <class ParserT>
void parse(InlineKeyboardButton &button, ParserT &parser) { void parse(InlineKeyboardButton &button, ParserT &parser) {
parse(button.type, parser); parse(button.type, parser);
if (button.type == InlineKeyboardButton::Type::UrlAuth) {
parse(button.id, parser);
}
parse(button.text, parser); parse(button.text, parser);
parse(button.data, parser); parse(button.data, parser);
} }