diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 0225b831d..17ec7fd33 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -473,8 +473,8 @@ venue location:location title:string address:string provider:string id:string ty //@animation Game animation; may be null game id:int64 short_name:string title:string text:formattedText description:string photo:photo animation:animation = Game; -//@description Describes a web app -//@short_name Web app short name. To share a web app use the URL https://t.me/{bot_username}/{app_short_name}?startapp={start_parameter} +//@description Describes a Web App +//@short_name Web App short name. To share a Web App use the URL https://t.me/{bot_username}/{app_short_name}?startapp={start_parameter} //@title Web App title //@param_description Web App description //@photo Web App photo @@ -1553,10 +1553,16 @@ loginUrlInfoOpen url:string skip_confirmation:Bool = LoginUrlInfo; //@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 +//@request_write_access True, if the user must be asked for the permission to the bot to send them messages loginUrlInfoRequestConfirmation url:string domain:string bot_user_id:int53 request_write_access:Bool = LoginUrlInfo; +//@description Contains information about a Web App found by its short name +//@web_app The Web App +//@request_write_access True, if the user must be asked for the permission to the bot to send them messages +//@skip_confirmation True, if there is no need to show an ordinary open URL confirmation before opening the Web App. The field must be ignored and confirmation must be shown anyway if the Web App link was hidden +foundWebApp web_app:webApp request_write_access:Bool skip_confirmation:Bool = FoundWebApp; + //@description Contains information about a Web App @launch_id Unique identifier for the Web App launch @url A Web App URL to open in a web view webAppInfo launch_id:int64 url:string = WebAppInfo; @@ -3317,7 +3323,7 @@ attachmentMenuBotColor light_color:int32 dark_color:int32 = AttachmentMenuBotCol //@supports_group_chats True, if the bot supports opening from attachment menu in basic group and supergroup chats //@supports_channel_chats True, if the bot supports opening from attachment menu in channel chats //@supports_settings True, if the bot supports "settings_button_pressed" event -//@request_write_access True, if the user needs to be requested to give the permission to the bot to send them messages +//@request_write_access True, if the user must be asked for the permission to the bot to send them messages //@name Name for the bot in attachment menu //@name_color Color to highlight selected name of the bot if appropriate; may be null //@default_icon Default attachment menu icon for the bot in SVG format; may be null @@ -4714,8 +4720,8 @@ internalLinkTypeUserToken token:string = InternalLinkType; //@is_live_stream True, if the video chat is expected to be a live stream in a channel or a broadcast group internalLinkTypeVideoChat chat_username:string invite_hash:string is_live_stream:Bool = InternalLinkType; -//@description The link is a link to a web app. Call searchPublicChat with the given bot username, check that the user is a bot, then call searchWebApp with the received bot and the given web_app_short_name. -//-Process received webAppInfo by showing a confirmation dialog if needed, calling getWebAppLinkUrl and opening returned URL +//@description The link is a link to a Web App. Call searchPublicChat with the given bot username, check that the user is a bot, then call searchWebApp with the received bot and the given web_app_short_name. +//-Process received foundWebApp by showing a confirmation dialog if needed, calling getWebAppLinkUrl and opening returned URL //@bot_username Username of the bot that owns the Web App //@web_app_short_name Short name of the Web App //@start_parameter Start parameter to be passed to getWebAppLinkUrl @@ -6538,6 +6544,11 @@ getInlineQueryResults bot_user_id:int53 chat_id:int53 user_location:location que answerInlineQuery inline_query_id:int64 is_personal:Bool button:inlineQueryResultsButton results:vector cache_time:int32 next_offset:string = Ok; +//@description Returns information about a Web App by its short name. Returns a 404 error if the Web App is not found +//@bot_user_id Identifier of the target bot +//@web_app_short_name Short name of the Web App +searchWebApp bot_user_id:int53 web_app_short_name:string = FoundWebApp; + //@description Returns an HTTPS URL of a Web App to open after keyboardButtonTypeWebApp or inlineQueryResultsButtonTypeWebApp button is pressed //@bot_user_id Identifier of the target bot //@url The URL from the keyboardButtonTypeWebApp or inlineQueryResultsButtonTypeWebApp button diff --git a/td/telegram/AttachMenuManager.cpp b/td/telegram/AttachMenuManager.cpp index f12353c67..063cb3030 100644 --- a/td/telegram/AttachMenuManager.cpp +++ b/td/telegram/AttachMenuManager.cpp @@ -23,6 +23,7 @@ #include "td/telegram/TdDb.h" #include "td/telegram/TdParameters.h" #include "td/telegram/ThemeManager.h" +#include "td/telegram/WebApp.h" #include "td/utils/algorithm.h" #include "td/utils/buffer.h" @@ -35,6 +36,36 @@ namespace td { +class GetBotAppQuery final : public Td::ResultHandler { + Promise> promise_; + + public: + explicit GetBotAppQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(telegram_api::object_ptr &&input_user, const string &short_name) { + auto input_bot_app = + telegram_api::make_object(std::move(input_user), short_name); + send_query(G()->net_query_creator().create(telegram_api::messages_getBotApp(std::move(input_bot_app), 0))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for GetBotAppQuery: " << to_string(ptr); + promise_.set_value(std::move(ptr)); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + class RequestWebViewQuery final : public Td::ResultHandler { Promise> promise_; DialogId dialog_id_; @@ -213,7 +244,6 @@ class GetAttachMenuBotsQuery final : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for GetAttachMenuBotsQuery: " << to_string(ptr); - promise_.set_value(std::move(ptr)); } @@ -615,6 +645,37 @@ void AttachMenuManager::schedule_ping_web_view() { ping_web_view_timeout_.set_timeout_in(PING_WEB_VIEW_TIMEOUT); } +void AttachMenuManager::get_web_app(UserId bot_user_id, string &&web_app_short_name, + Promise> &&promise) { + TRY_RESULT_PROMISE(promise, input_user, td_->contacts_manager_->get_input_user(bot_user_id)); + auto query_promise = + PromiseCreator::lambda([actor_id = actor_id(this), bot_user_id, web_app_short_name, promise = std::move(promise)]( + Result> result) mutable { + send_closure(actor_id, &AttachMenuManager::on_get_web_app, bot_user_id, std::move(web_app_short_name), + std::move(result), std::move(promise)); + }); + td_->create_handler(std::move(query_promise))->send(std::move(input_user), web_app_short_name); +} + +void AttachMenuManager::on_get_web_app(UserId bot_user_id, string web_app_short_name, + Result> result, + Promise> promise) { + G()->ignore_result_if_closing(result); + if (result.is_error() && result.error().message() == "BOT_APP_INVALID") { + return promise.set_value(nullptr); + } + TRY_RESULT_PROMISE(promise, bot_app, std::move(result)); + if (bot_app->app_->get_id() != telegram_api::botApp::ID) { + CHECK(bot_app->app_->get_id() != telegram_api::botAppNotModified::ID); + LOG(ERROR) << "Receive " << to_string(bot_app); + return promise.set_error(Status::Error(500, "Receive invalid response")); + } + + WebApp web_app(td_, telegram_api::move_object_as(bot_app->app_), DialogId(bot_user_id)); + promise.set_value(td_api::make_object(web_app.get_web_app_object(td_), + bot_app->request_write_access_, !bot_app->inactive_)); +} + void AttachMenuManager::request_web_view(DialogId dialog_id, UserId bot_user_id, MessageId top_thread_message_id, MessageId reply_to_message_id, string &&url, td_api::object_ptr &&theme, string &&platform, diff --git a/td/telegram/AttachMenuManager.h b/td/telegram/AttachMenuManager.h index b7e38dd2f..8ebc44f18 100644 --- a/td/telegram/AttachMenuManager.h +++ b/td/telegram/AttachMenuManager.h @@ -32,6 +32,9 @@ class AttachMenuManager final : public Actor { void init(); + void get_web_app(UserId bot_user_id, string &&web_app_short_name, + Promise> &&promise); + void request_web_view(DialogId dialog_id, UserId bot_user_id, MessageId top_thread_message_id, MessageId reply_to_message_id, string &&url, td_api::object_ptr &&theme, string &&platform, @@ -127,6 +130,10 @@ class AttachMenuManager final : public Actor { void schedule_ping_web_view(); + void on_get_web_app(UserId bot_user_id, string web_app_short_name, + Result> result, + Promise> promise); + Result get_attach_menu_bot(tl_object_ptr &&bot); td_api::object_ptr get_attachment_menu_bot_object(const AttachMenuBot &bot) const; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index a0b519ac1..bb83efcd3 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -7770,6 +7770,14 @@ void Td::on_request(uint64 id, td_api::answerInlineQuery &request) { request.cache_time_, request.next_offset_, std::move(promise)); } +void Td::on_request(uint64 id, td_api::searchWebApp &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.web_app_short_name_); + CREATE_REQUEST_PROMISE(); + attach_menu_manager_->get_web_app(UserId(request.bot_user_id_), std::move(request.web_app_short_name_), + std::move(promise)); +} + void Td::on_request(uint64 id, td_api::getWebAppUrl &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.url_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 787070f35..de79d05da 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1330,6 +1330,8 @@ class Td final : public Actor { void on_request(uint64 id, td_api::answerInlineQuery &request); + void on_request(uint64 id, td_api::searchWebApp &request); + void on_request(uint64 id, td_api::getWebAppUrl &request); void on_request(uint64 id, td_api::sendWebAppData &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 4d0b24f48..ae1513541 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3741,17 +3741,22 @@ class CliClient final : public Actor { get_args(args, user_id, is_added, allow_write_access); send_request( td_api::make_object(user_id, is_added, allow_write_access)); + } else if (op == "swa") { + UserId bot_user_id; + string short_name; + get_args(args, bot_user_id, short_name); + send_request(td_api::make_object(bot_user_id, short_name)); } else if (op == "gwau") { - UserId user_id; + UserId bot_user_id; string url; - get_args(args, user_id, url); - send_request(td_api::make_object(user_id, url, as_theme_parameters(), "android")); + get_args(args, bot_user_id, url); + send_request(td_api::make_object(bot_user_id, url, as_theme_parameters(), "android")); } else if (op == "swad") { - UserId user_id; + UserId bot_user_id; string button_text; string data; - get_args(args, user_id, button_text, data); - send_request(td_api::make_object(user_id, button_text, data)); + get_args(args, bot_user_id, button_text, data); + send_request(td_api::make_object(bot_user_id, button_text, data)); } else if (op == "owa") { ChatId chat_id; UserId bot_user_id;