Add inlineKeyboardButtonTypeSwitchInline.target_chat.

This commit is contained in:
levlam 2023-04-07 14:00:10 +03:00
parent 6fde8184af
commit 2a70fec0b0
3 changed files with 108 additions and 18 deletions

View File

@ -1545,8 +1545,8 @@ inlineKeyboardButtonTypeCallbackWithPassword data:bytes = InlineKeyboardButtonTy
//@description A button with a game that sends a callback query to a bot. 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 messageGame
inlineKeyboardButtonTypeCallbackGame = InlineKeyboardButtonType;
//@description A button that forces an inline query to the bot to be inserted in the input field @query Inline query to be sent to the bot @in_current_chat True, if the inline query must be sent from the current chat
inlineKeyboardButtonTypeSwitchInline query:string in_current_chat:Bool = InlineKeyboardButtonType;
//@description A button that forces an inline query to the bot to be inserted in the input field @query Inline query to be sent to the bot @target_chat Target chat from which to send the inline query
inlineKeyboardButtonTypeSwitchInline query:string target_chat:TargetChat = InlineKeyboardButtonType;
//@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;

View File

@ -84,7 +84,7 @@ static StringBuilder &operator<<(StringBuilder &string_builder, const InlineKeyb
string_builder << "CallbackGame";
break;
case InlineKeyboardButton::Type::SwitchInline:
string_builder << "SwitchInline";
string_builder << "SwitchInline, target chat mask = " << keyboard_button.id;
break;
case InlineKeyboardButton::Type::SwitchInlineCurrentDialog:
string_builder << "SwitchInlineCurrentChat";
@ -292,6 +292,30 @@ static InlineKeyboardButton get_inline_keyboard_button(
: InlineKeyboardButton::Type::SwitchInline;
button.text = std::move(keyboard_button->text_);
button.data = std::move(keyboard_button->query_);
if (!keyboard_button->same_peer_) {
for (auto &peer_type : keyboard_button->peer_types_) {
switch (peer_type->get_id()) {
case telegram_api::inlineQueryPeerTypePM::ID:
button.id |= InlineKeyboardButton::USERS_MASK;
break;
case telegram_api::inlineQueryPeerTypeBotPM::ID:
button.id |= InlineKeyboardButton::BOTS_MASK;
break;
case telegram_api::inlineQueryPeerTypeChat::ID:
case telegram_api::inlineQueryPeerTypeMegagroup::ID:
button.id |= InlineKeyboardButton::CHATS_MASK;
break;
case telegram_api::inlineQueryPeerTypeBroadcast::ID:
button.id |= InlineKeyboardButton::BROADCASTS_MASK;
break;
default:
LOG(ERROR) << "Receive " << to_string(peer_type);
}
}
}
if (button.id == InlineKeyboardButton::FULL_MASK) {
button.id = 0;
}
break;
}
case telegram_api::keyboardButtonBuy::ID: {
@ -576,16 +600,47 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
return Status::Error(400, "Can't use CallbackWithPassword inline button");
case td_api::inlineKeyboardButtonTypeSwitchInline::ID: {
auto button_type = move_tl_object_as<td_api::inlineKeyboardButtonTypeSwitchInline>(button->type_);
if (button_type->target_chat_ == nullptr) {
return Status::Error(400, "Target chat must be non-empty");
}
switch (button_type->target_chat_->get_id()) {
case td_api::targetChatChosen::ID: {
auto target = static_cast<const td_api::targetChatChosen *>(button_type->target_chat_.get());
if (target->allow_user_chats_) {
current_button.id |= InlineKeyboardButton::USERS_MASK;
}
if (target->allow_bot_chats_) {
current_button.id |= InlineKeyboardButton::BOTS_MASK;
}
if (target->allow_group_chats_) {
current_button.id |= InlineKeyboardButton::CHATS_MASK;
}
if (target->allow_channel_chats_) {
current_button.id |= InlineKeyboardButton::BROADCASTS_MASK;
}
if (current_button.id == InlineKeyboardButton::FULL_MASK) {
current_button.id = 0;
}
current_button.type = InlineKeyboardButton::Type::SwitchInline;
break;
}
case td_api::targetChatCurrent::ID:
current_button.type = InlineKeyboardButton::Type::SwitchInlineCurrentDialog;
break;
case td_api::targetChatInternalLink::ID:
return Status::Error(400, "Unsupported target chat specified");
default:
UNREACHABLE();
}
if (!switch_inline_buttons_allowed) {
const char *button_name =
button_type->in_current_chat_ ? "switch_inline_query_current_chat" : "switch_inline_query";
const char *button_name = current_button.type == InlineKeyboardButton::Type::SwitchInline
? "switch_inline_query"
: "switch_inline_query_current_chat";
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");
<< " button in a channel chat, because users will not be able to use the "
"button without knowing bot's username");
}
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");
@ -828,16 +883,33 @@ static tl_object_ptr<telegram_api::KeyboardButton> get_input_keyboard_button(
BufferSlice(keyboard_button.data));
case InlineKeyboardButton::Type::CallbackGame:
return make_tl_object<telegram_api::keyboardButtonGame>(keyboard_button.text);
case InlineKeyboardButton::Type::SwitchInline:
case InlineKeyboardButton::Type::SwitchInlineCurrentDialog: {
case InlineKeyboardButton::Type::SwitchInline: {
int32 flags = 0;
if (keyboard_button.type == InlineKeyboardButton::Type::SwitchInlineCurrentDialog) {
flags |= telegram_api::keyboardButtonSwitchInline::SAME_PEER_MASK;
}
vector<telegram_api::object_ptr<telegram_api::InlineQueryPeerType>> peer_types;
if (keyboard_button.id != 0) {
CHECK(keyboard_button.type == InlineKeyboardButton::Type::SwitchInline);
flags |= telegram_api::keyboardButtonSwitchInline::PEER_TYPES_MASK;
if ((keyboard_button.id & InlineKeyboardButton::USERS_MASK) != 0) {
peer_types.push_back(telegram_api::make_object<telegram_api::inlineQueryPeerTypePM>());
}
if ((keyboard_button.id & InlineKeyboardButton::BOTS_MASK) != 0) {
peer_types.push_back(telegram_api::make_object<telegram_api::inlineQueryPeerTypeBotPM>());
}
if ((keyboard_button.id & InlineKeyboardButton::CHATS_MASK) != 0) {
peer_types.push_back(telegram_api::make_object<telegram_api::inlineQueryPeerTypeChat>());
peer_types.push_back(telegram_api::make_object<telegram_api::inlineQueryPeerTypeMegagroup>());
}
if ((keyboard_button.id & InlineKeyboardButton::BROADCASTS_MASK) != 0) {
peer_types.push_back(telegram_api::make_object<telegram_api::inlineQueryPeerTypeBroadcast>());
}
}
return make_tl_object<telegram_api::keyboardButtonSwitchInline>(flags, false /*ignored*/, keyboard_button.text,
keyboard_button.data, std::move(peer_types));
}
case InlineKeyboardButton::Type::SwitchInlineCurrentDialog:
return make_tl_object<telegram_api::keyboardButtonSwitchInline>(
telegram_api::keyboardButtonSwitchInline::SAME_PEER_MASK, false /*ignored*/, keyboard_button.text,
keyboard_button.data, vector<telegram_api::object_ptr<telegram_api::InlineQueryPeerType>>());
case InlineKeyboardButton::Type::Buy:
return make_tl_object<telegram_api::keyboardButtonBuy>(keyboard_button.text);
case InlineKeyboardButton::Type::UrlAuth: {
@ -978,11 +1050,21 @@ static tl_object_ptr<td_api::inlineKeyboardButton> get_inline_keyboard_button_ob
case InlineKeyboardButton::Type::CallbackGame:
type = make_tl_object<td_api::inlineKeyboardButtonTypeCallbackGame>();
break;
case InlineKeyboardButton::Type::SwitchInline:
type = make_tl_object<td_api::inlineKeyboardButtonTypeSwitchInline>(keyboard_button.data, false);
case InlineKeyboardButton::Type::SwitchInline: {
auto mask = keyboard_button.id;
if (mask == 0) {
mask = InlineKeyboardButton::FULL_MASK;
}
type = make_tl_object<td_api::inlineKeyboardButtonTypeSwitchInline>(
keyboard_button.data,
td_api::make_object<td_api::targetChatChosen>(
(mask & InlineKeyboardButton::USERS_MASK) != 0, (mask & InlineKeyboardButton::BOTS_MASK) != 0,
(mask & InlineKeyboardButton::CHATS_MASK) != 0, (mask & InlineKeyboardButton::BROADCASTS_MASK) != 0));
break;
}
case InlineKeyboardButton::Type::SwitchInlineCurrentDialog:
type = make_tl_object<td_api::inlineKeyboardButtonTypeSwitchInline>(keyboard_button.data, true);
type = make_tl_object<td_api::inlineKeyboardButtonTypeSwitchInline>(
keyboard_button.data, td_api::make_object<td_api::targetChatCurrent>());
break;
case InlineKeyboardButton::Type::Buy:
type = make_tl_object<td_api::inlineKeyboardButtonTypeBuy>();

View File

@ -53,8 +53,16 @@ struct InlineKeyboardButton {
User,
WebView
};
static constexpr int64 USERS_MASK = 1;
static constexpr int64 BOTS_MASK = 2;
static constexpr int64 CHATS_MASK = 4;
static constexpr int64 BROADCASTS_MASK = 8;
static constexpr int64 FULL_MASK = USERS_MASK | BOTS_MASK | CHATS_MASK | BROADCASTS_MASK;
Type type;
int64 id = 0; // UrlAuth only, button_id or (2 * request_write_access - 1) * bot_user_id
int64 id = 0; // UrlAuth: button_id or (2 * request_write_access - 1) * bot_user_id
// SwitchInline: mask of allowed target chats; 0 if any
UserId user_id; // User only
string text;
string forward_text; // UrlAuth only