Add support for LoginUrl buttons handling.
GitOrigin-RevId: 3b53d50a6619743830e065f34946869e56f94bcb
This commit is contained in:
parent
e70d12c751
commit
1f22f9e0b7
@ -349,7 +349,7 @@ chatMemberStatusCreator is_member:Bool = ChatMemberStatus;
|
||||
//@can_invite_users True, if the administrator can invite new users to the chat
|
||||
//@can_restrict_members True, if the administrator can restrict, ban, or unban chat members
|
||||
//@can_pin_messages True, if the administrator can pin messages; applicable to groups only
|
||||
//@can_promote_members True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that were directly or indirectly promoted by him
|
||||
//@can_promote_members True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that were directly or indirectly promoted by them
|
||||
chatMemberStatusAdministrator can_be_edited:Bool can_change_info:Bool can_post_messages:Bool can_edit_messages:Bool can_delete_messages:Bool can_invite_users:Bool can_restrict_members:Bool can_pin_messages:Bool can_promote_members:Bool = ChatMemberStatus;
|
||||
|
||||
//@description The user is a member of a chat, without any additional privileges or restrictions
|
||||
@ -679,7 +679,7 @@ 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 @forward_text If non-empty, new text of the button in forwarded messages
|
||||
//@description A button that opens a specified URL and automatically logs in in current user if they allowed to do that @url An HTTP URL to open @id Unique button identifier @forward_text If non-empty, new text of the button in forwarded messages
|
||||
inlineKeyboardButtonTypeLoginUrl url:string id:int32 forward_text:string = 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
|
||||
@ -721,6 +721,16 @@ replyMarkupShowKeyboard rows:vector<vector<keyboardButton>> resize_keyboard:Bool
|
||||
replyMarkupInlineKeyboard rows:vector<vector<inlineKeyboardButton>> = ReplyMarkup;
|
||||
|
||||
|
||||
//@class LoginUrlInfo @description Contains information about an inline button of type inlineKeyboardButtonTypeLoginUrl returned by the method getLoginUrlInfo
|
||||
|
||||
//@description An HTTP url needs to be open @url The URL to open @skip_confirm True, if there is no need to show an ordinary open URL confirm
|
||||
loginUrlInfoOpen url:string skip_confirm:Bool = LoginUrlInfo;
|
||||
|
||||
//@description An authorization confirmation dialog needs to be shown to the user @url An HTTP URL to be opened @domain A domain of the URL
|
||||
//@bot_user_id User identifier of a bot linked with the website @request_write_access True, if the user needs to be requested to give the permission to the bot to send them messages
|
||||
loginUrlInfoRequestConfirmation url:string domain:string bot_user_id:int32 request_write_access:Bool = LoginUrlInfo;
|
||||
|
||||
|
||||
//@class RichText @description Describes a text object inside an instant-view web page
|
||||
|
||||
//@description A plain text @text Text
|
||||
@ -2122,7 +2132,7 @@ pushMessageContentVoiceNote voice_note:voiceNote is_pinned:Bool = PushMessageCon
|
||||
pushMessageContentBasicGroupChatCreate = PushMessageContent;
|
||||
|
||||
//@description New chat members were invited to a group @member_name Name of the added member @is_current_user True, if the current user was added to the group
|
||||
//@is_returned True, if the user has returned to the group himself
|
||||
//@is_returned True, if the user has returned to the group themself
|
||||
pushMessageContentChatAddMembers member_name:string is_current_user:Bool is_returned:Bool = PushMessageContent;
|
||||
|
||||
//@description A chat photo was edited
|
||||
@ -2132,7 +2142,7 @@ pushMessageContentChatChangePhoto = PushMessageContent;
|
||||
pushMessageContentChatChangeTitle title:string = PushMessageContent;
|
||||
|
||||
//@description A chat member was deleted @member_name Name of the deleted member @is_current_user True, if the current user was deleted from the group
|
||||
//@is_left True, if the user has left the group himself
|
||||
//@is_left True, if the user has left the group themself
|
||||
pushMessageContentChatDeleteMember member_name:string is_current_user:Bool is_left:Bool = PushMessageContent;
|
||||
|
||||
//@description A new member joined the chat by invite link
|
||||
@ -3248,6 +3258,17 @@ setPollAnswer chat_id:int53 message_id:int53 option_ids:vector<int32> = Ok;
|
||||
stopPoll chat_id:int53 message_id:int53 reply_markup:ReplyMarkup = Ok;
|
||||
|
||||
|
||||
//@description Returns information about a button of type inlineKeyboardButtonTypeLoginUrl. The method needs to be called when the user presses the button
|
||||
//@chat_id Chat identifier of the message with the button @message_id Message identifier of the message with the button @button_id Button identifier
|
||||
getLoginUrlInfo chat_id:int53 message_id:int53 button_id:int32 = LoginUrlInfo;
|
||||
|
||||
//@description Returns an HTTP URL which can be used to automatically authorize the user on a website after clicking an inline button of type inlineKeyboardButtonTypeLoginUrl.
|
||||
//-Use the method getLoginUrlInfo to find whether a prior user confirmation is needed. If an error is returned, then the button must be handled as an ordinary URL button
|
||||
//@chat_id Chat identifier of the message with the button @message_id Message identifier of the message with the button @button_id Button identifier
|
||||
//@allow_write_access True, if the user allowed the bot to send them messages
|
||||
getLoginUrl chat_id:int53 message_id:int53 button_id:int32 allow_write_access:Bool = HttpUrl;
|
||||
|
||||
|
||||
//@description Sends an inline query to a bot and returns its results. Returns an error with code 502 if the bot fails to answer the query before the query timeout expires @bot_user_id The identifier of the target bot
|
||||
//@chat_id Identifier of the chat, where the query was sent @user_location Location of the user, only if needed @query Text of the query @offset Offset of the first entry to return
|
||||
getInlineQueryResults bot_user_id:int32 chat_id:int53 user_location:location query:string offset:string = InlineQueryResults;
|
||||
|
Binary file not shown.
@ -3394,7 +3394,6 @@ class GetStatsUrlQuery : public Td::ResultHandler {
|
||||
}
|
||||
|
||||
void send(DialogId dialog_id, const string ¶meters, bool is_dark) {
|
||||
// TODO use parameters and is_dark
|
||||
dialog_id_ = dialog_id;
|
||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||
CHECK(input_peer != nullptr);
|
||||
@ -3422,6 +3421,120 @@ class GetStatsUrlQuery : public Td::ResultHandler {
|
||||
}
|
||||
};
|
||||
|
||||
class RequestUrlAuthQuery : public Td::ResultHandler {
|
||||
Promise<td_api::object_ptr<td_api::LoginUrlInfo>> promise_;
|
||||
string url_;
|
||||
DialogId dialog_id_;
|
||||
|
||||
public:
|
||||
explicit RequestUrlAuthQuery(Promise<td_api::object_ptr<td_api::LoginUrlInfo>> &&promise)
|
||||
: promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(string url, DialogId dialog_id, MessageId message_id, int32 button_id) {
|
||||
url_ = std::move(url);
|
||||
dialog_id_ = dialog_id;
|
||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||
CHECK(input_peer != nullptr);
|
||||
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_requestUrlAuth(
|
||||
std::move(input_peer), message_id.get_server_message_id().get(), button_id))));
|
||||
}
|
||||
|
||||
void on_result(uint64 id, BufferSlice packet) override {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_requestUrlAuth>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(id, result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto result = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive " << to_string(result);
|
||||
switch (result->get_id()) {
|
||||
case telegram_api::urlAuthResultRequest::ID: {
|
||||
auto request = telegram_api::move_object_as<telegram_api::urlAuthResultRequest>(result);
|
||||
UserId bot_user_id = ContactsManager::get_user_id(request->bot_);
|
||||
if (!bot_user_id.is_valid()) {
|
||||
return on_error(id, Status::Error(500, "Receive invalid bot_user_id"));
|
||||
}
|
||||
td->contacts_manager_->on_get_user(std::move(request->bot_), "RequestUrlAuthQuery");
|
||||
bool request_write_access =
|
||||
(request->flags_ & telegram_api::urlAuthResultRequest::REQUEST_WRITE_ACCESS_MASK) != 0;
|
||||
promise_.set_value(td_api::make_object<td_api::loginUrlInfoRequestConfirmation>(
|
||||
url_, request->domain_, td->contacts_manager_->get_user_id_object(bot_user_id, "RequestUrlAuthQuery"),
|
||||
request_write_access));
|
||||
break;
|
||||
}
|
||||
case telegram_api::urlAuthResultAccepted::ID: {
|
||||
auto accepted = telegram_api::move_object_as<telegram_api::urlAuthResultAccepted>(result);
|
||||
promise_.set_value(td_api::make_object<td_api::loginUrlInfoOpen>(accepted->url_, true));
|
||||
break;
|
||||
}
|
||||
case telegram_api::urlAuthResultDefault::ID:
|
||||
promise_.set_value(td_api::make_object<td_api::loginUrlInfoOpen>(url_, false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void on_error(uint64 id, Status status) override {
|
||||
if (!td->messages_manager_->on_get_dialog_error(dialog_id_, status, "RequestUrlAuthQuery")) {
|
||||
LOG(INFO) << "RequestUrlAuthQuery returned " << status;
|
||||
}
|
||||
promise_.set_value(td_api::make_object<td_api::loginUrlInfoOpen>(url_, false));
|
||||
}
|
||||
};
|
||||
|
||||
class AcceptUrlAuthQuery : public Td::ResultHandler {
|
||||
Promise<td_api::object_ptr<td_api::httpUrl>> promise_;
|
||||
string url_;
|
||||
DialogId dialog_id_;
|
||||
|
||||
public:
|
||||
explicit AcceptUrlAuthQuery(Promise<td_api::object_ptr<td_api::httpUrl>> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(string url, DialogId dialog_id, MessageId message_id, int32 button_id, bool allow_write_access) {
|
||||
url_ = std::move(url);
|
||||
dialog_id_ = dialog_id;
|
||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||
CHECK(input_peer != nullptr);
|
||||
int32 flags = 0;
|
||||
if (allow_write_access) {
|
||||
flags |= telegram_api::messages_acceptUrlAuth::WRITE_ALLOWED_MASK;
|
||||
}
|
||||
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_acceptUrlAuth(
|
||||
flags, false /*ignored*/, std::move(input_peer), message_id.get_server_message_id().get(), button_id))));
|
||||
}
|
||||
|
||||
void on_result(uint64 id, BufferSlice packet) override {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_acceptUrlAuth>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(id, result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto result = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive " << to_string(result);
|
||||
switch (result->get_id()) {
|
||||
case telegram_api::urlAuthResultRequest::ID:
|
||||
LOG(ERROR) << "Receive unexpected " << to_string(result);
|
||||
return on_error(id, Status::Error(500, "Receive unexpected urlAuthResultRequest"));
|
||||
case telegram_api::urlAuthResultAccepted::ID: {
|
||||
auto accepted = telegram_api::move_object_as<telegram_api::urlAuthResultAccepted>(result);
|
||||
promise_.set_value(td_api::make_object<td_api::httpUrl>(accepted->url_));
|
||||
break;
|
||||
}
|
||||
case telegram_api::urlAuthResultDefault::ID:
|
||||
promise_.set_value(td_api::make_object<td_api::httpUrl>(url_));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void on_error(uint64 id, Status status) override {
|
||||
if (!td->messages_manager_->on_get_dialog_error(dialog_id_, status, "AcceptUrlAuthQuery")) {
|
||||
LOG(INFO) << "AcceptUrlAuthQuery returned " << status;
|
||||
}
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class GetChannelDifferenceQuery : public Td::ResultHandler {
|
||||
DialogId dialog_id_;
|
||||
int32 pts_;
|
||||
@ -6523,6 +6636,64 @@ void MessagesManager::get_dialog_statistics_url(DialogId dialog_id, const string
|
||||
td_->create_handler<GetStatsUrlQuery>(std::move(promise))->send(dialog_id, parameters, is_dark);
|
||||
}
|
||||
|
||||
Result<string> MessagesManager::get_login_button_url(DialogId dialog_id, MessageId message_id, int32 button_id) {
|
||||
Dialog *d = get_dialog_force(dialog_id);
|
||||
if (d == nullptr) {
|
||||
return Status::Error(3, "Chat not found");
|
||||
}
|
||||
if (!have_input_peer(dialog_id, AccessRights::Read)) {
|
||||
return Status::Error(3, "Can't access the chat");
|
||||
}
|
||||
|
||||
auto m = get_message_force(d, message_id, "get_login_button_url");
|
||||
if (m == nullptr) {
|
||||
return Status::Error(5, "Message not found");
|
||||
}
|
||||
if (m->reply_markup == nullptr || m->reply_markup->type != ReplyMarkup::Type::InlineKeyboard) {
|
||||
return Status::Error(5, "Message has no inline keyboard");
|
||||
}
|
||||
if (!message_id.is_server()) {
|
||||
// it shouldn't have UrlAuth buttons anyway
|
||||
return Status::Error(5, "Message is not server");
|
||||
}
|
||||
if (dialog_id.get_type() == DialogType::SecretChat) {
|
||||
// secret chat messages can't have reply markup, so this shouldn't happen now
|
||||
return Status::Error(5, "Message is in a secret chat");
|
||||
}
|
||||
|
||||
for (auto &row : m->reply_markup->inline_keyboard) {
|
||||
for (auto &button : row) {
|
||||
if (button.type == InlineKeyboardButton::Type::UrlAuth && button.id == button_id) {
|
||||
return button.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status::Error(5, "Button not found");
|
||||
}
|
||||
|
||||
void MessagesManager::get_login_url_info(DialogId dialog_id, MessageId message_id, int32 button_id,
|
||||
Promise<td_api::object_ptr<td_api::LoginUrlInfo>> &&promise) {
|
||||
auto r_url = get_login_button_url(dialog_id, message_id, button_id);
|
||||
if (r_url.is_error()) {
|
||||
return promise.set_error(r_url.move_as_error());
|
||||
}
|
||||
|
||||
td_->create_handler<RequestUrlAuthQuery>(std::move(promise))
|
||||
->send(r_url.move_as_ok(), dialog_id, message_id, button_id);
|
||||
}
|
||||
|
||||
void MessagesManager::get_login_url(DialogId dialog_id, MessageId message_id, int32 button_id, bool allow_write_access,
|
||||
Promise<td_api::object_ptr<td_api::httpUrl>> &&promise) {
|
||||
auto r_url = get_login_button_url(dialog_id, message_id, button_id);
|
||||
if (r_url.is_error()) {
|
||||
return promise.set_error(r_url.move_as_error());
|
||||
}
|
||||
|
||||
td_->create_handler<AcceptUrlAuthQuery>(std::move(promise))
|
||||
->send(r_url.move_as_ok(), dialog_id, message_id, button_id, allow_write_access);
|
||||
}
|
||||
|
||||
void MessagesManager::load_secret_thumbnail(FileId thumbnail_file_id) {
|
||||
class Callback : public FileManager::DownloadCallback {
|
||||
public:
|
||||
|
@ -665,10 +665,16 @@ class MessagesManager : public Actor {
|
||||
void report_dialog(DialogId dialog_id, const tl_object_ptr<td_api::ChatReportReason> &reason,
|
||||
const vector<MessageId> &message_ids, Promise<Unit> &&promise);
|
||||
|
||||
void on_get_peer_settings(DialogId dialog_id, tl_object_ptr<telegram_api::peerSettings> &&peer_settings);
|
||||
|
||||
void get_dialog_statistics_url(DialogId dialog_id, const string ¶meters, bool is_dark,
|
||||
Promise<td_api::object_ptr<td_api::httpUrl>> &&promise);
|
||||
|
||||
void on_get_peer_settings(DialogId dialog_id, tl_object_ptr<telegram_api::peerSettings> &&peer_settings);
|
||||
void get_login_url_info(DialogId dialog_id, MessageId message_id, int32 button_id,
|
||||
Promise<td_api::object_ptr<td_api::LoginUrlInfo>> &&promise);
|
||||
|
||||
void get_login_url(DialogId dialog_id, MessageId message_id, int32 button_id, bool allow_write_access,
|
||||
Promise<td_api::object_ptr<td_api::httpUrl>> &&promise);
|
||||
|
||||
void before_get_difference();
|
||||
|
||||
@ -2263,6 +2269,8 @@ class MessagesManager : public Actor {
|
||||
void suffix_load_till_date(Dialog *d, int32 date, Promise<> promise);
|
||||
void suffix_load_till_message_id(Dialog *d, MessageId message_id, Promise<> promise);
|
||||
|
||||
Result<string> get_login_button_url(DialogId dialog_id, MessageId message_id, int32 button_id);
|
||||
|
||||
Result<ServerMessageId> get_invoice_message_id(FullMessageId full_message_id);
|
||||
|
||||
bool is_broadcast_channel(DialogId dialog_id) const;
|
||||
|
@ -7054,6 +7054,20 @@ void Td::on_request(uint64 id, td_api::stopPoll &request) {
|
||||
std::move(request.reply_markup_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::getLoginUrlInfo &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_REQUEST_PROMISE();
|
||||
messages_manager_->get_login_url_info(DialogId(request.chat_id_), MessageId(request.message_id_), request.button_id_,
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::getLoginUrl &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_REQUEST_PROMISE();
|
||||
messages_manager_->get_login_url(DialogId(request.chat_id_), MessageId(request.message_id_), request.button_id_,
|
||||
request.allow_write_access_, std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getInlineQueryResults &request) {
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.query_);
|
||||
|
@ -874,6 +874,10 @@ class Td final : public NetQueryCallback {
|
||||
|
||||
void on_request(uint64 id, td_api::stopPoll &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::getLoginUrlInfo &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::getLoginUrl &request);
|
||||
|
||||
void on_request(uint64 id, td_api::getInlineQueryResults &request);
|
||||
|
||||
void on_request(uint64 id, td_api::answerInlineQuery &request);
|
||||
|
@ -475,6 +475,10 @@ class CliClient final : public Actor {
|
||||
return transform(full_split(trim(message_ids), delimiter), as_message_id);
|
||||
}
|
||||
|
||||
static int32 as_button_id(Slice str) {
|
||||
return to_integer<int32>(trim(str));
|
||||
}
|
||||
|
||||
int32 as_user_id(Slice str) const {
|
||||
str = trim(str);
|
||||
if (str[0] == '@') {
|
||||
@ -3637,6 +3641,20 @@ class CliClient final : public Actor {
|
||||
std::tie(parameters, is_dark) = split(args);
|
||||
|
||||
send_request(td_api::make_object<td_api::getChatStatisticsUrl>(as_chat_id(args), parameters, as_bool(is_dark)));
|
||||
} else if (op == "glui" || op == "glu" || op == "glua") {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
string button_id;
|
||||
std::tie(chat_id, args) = split(args);
|
||||
std::tie(message_id, button_id) = split(args);
|
||||
|
||||
if (op == "glui") {
|
||||
send_request(td_api::make_object<td_api::getLoginUrlInfo>(as_chat_id(chat_id), as_message_id(message_id),
|
||||
as_button_id(button_id)));
|
||||
} else {
|
||||
send_request(td_api::make_object<td_api::getLoginUrl>(as_chat_id(chat_id), as_message_id(message_id),
|
||||
as_button_id(button_id), op == "glua"));
|
||||
}
|
||||
} else if (op == "rsgs" || op == "rchs") {
|
||||
string supergroup_id;
|
||||
string user_id;
|
||||
|
Loading…
Reference in New Issue
Block a user