Support LoginUrl buttons.
GitOrigin-RevId: ca630cc32bf17df6dcedcff4ffa8507fb82ae9cc
This commit is contained in:
parent
bf3e0b8457
commit
93dd076d8a
@ -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;
|
||||
|
||||
|
Binary file not shown.
@ -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<KeyboardButton> = KeyboardButtonRow;
|
||||
|
||||
|
Binary file not shown.
@ -23513,7 +23513,9 @@ bool MessagesManager::update_message(Dialog *d, unique_ptr<Message> &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<Message> &old_message
|
||||
}
|
||||
} else {
|
||||
if (new_message->reply_markup != nullptr) {
|
||||
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
|
||||
|
@ -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 <limits>
|
||||
|
||||
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<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:
|
||||
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:
|
||||
current_button.type = InlineKeyboardButton::Type::Buy;
|
||||
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:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -552,6 +581,22 @@ static tl_object_ptr<telegram_api::KeyboardButton> get_inline_keyboard_button(
|
||||
}
|
||||
case InlineKeyboardButton::Type::Buy:
|
||||
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:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
@ -648,6 +693,9 @@ static tl_object_ptr<td_api::inlineKeyboardButton> get_inline_keyboard_button_ob
|
||||
case InlineKeyboardButton::Type::Buy:
|
||||
type = make_tl_object<td_api::inlineKeyboardButtonTypeBuy>();
|
||||
break;
|
||||
case InlineKeyboardButton::Type::UrlAuth:
|
||||
type = make_tl_object<td_api::inlineKeyboardButtonTypeLoginUrl>(keyboard_button.data, keyboard_button.id);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -27,6 +27,9 @@ void parse(KeyboardButton &button, ParserT &parser) {
|
||||
template <class StorerT>
|
||||
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 <class ParserT>
|
||||
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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user