diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index ec880ff03..ed9be41dc 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1720,6 +1720,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_open_link" = "Open"; "lng_allow_bot_pass" = "Allow {bot_name} to pass your Telegram name and ID to the web pages you open via this bot?"; "lng_allow_bot" = "Allow"; +"lng_allow_bot_webview" = "{bot_name} would like to open its web app to proceed.\n\nIt will be able to access your **IP address** and basic device info."; "lng_url_auth_open_confirm" = "Do you want to open {link}?"; "lng_url_auth_login_option" = "Log in to {domain} as {user}"; "lng_url_auth_allow_messages" = "Allow {bot} to send me messages"; diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 4bf757553..1409b6deb 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -224,18 +224,24 @@ void activateBotCommand( case ButtonType::WebView: { if (const auto bot = msg->getMessageBot()) { - bot->session().attachWebView().request( - bot, - bot, - { .text = button->text, .url = button->data }); + if (sessionController) { + bot->session().attachWebView().request( + sessionController, + bot, + bot, + { .text = button->text, .url = button->data }); + } } } break; case ButtonType::SimpleWebView: { if (const auto bot = msg->getMessageBot()) { - bot->session().attachWebView().requestSimple( - bot, - { .text = button->text, .url = button->data }); + if (sessionController) { + bot->session().attachWebView().requestSimple( + sessionController, + bot, + { .text = button->text, .url = button->data }); + } } } break; } diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 47295de39..daf1fc739 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/dropdown_menu.h" #include "ui/widgets/popup_menu.h" #include "ui/widgets/menu/menu_item_base.h" +#include "ui/text/text_utilities.h" #include "ui/effects/ripple_animation.h" #include "window/themes/window_theme.h" #include "window/window_controller.h" @@ -31,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/basic_click_handlers.h" #include "history/history.h" #include "history/history_item.h" +#include "storage/storage_account.h" #include "lang/lang_keys.h" #include "base/random.h" #include "base/timer_rpl.h" @@ -325,6 +327,7 @@ void AttachWebView::request( } void AttachWebView::request( + Window::SessionController *controller, not_null peer, not_null bot, const WebViewButton &button) { @@ -339,7 +342,13 @@ void AttachWebView::request( _bot = bot; _peer = peer; - request(button); + if (controller) { + confirmOpen(controller, [=] { + request(button); + }); + } else { + request(button); + } } void AttachWebView::request(const WebViewButton &button) { @@ -444,7 +453,11 @@ void AttachWebView::requestAddToMenu( if (!contextPeer) { return false; } - request(contextPeer, bot, { .startCommand = startCommand }); + request( + nullptr, + contextPeer, + bot, + { .startCommand = startCommand }); return true; }; result.match([&](const MTPDattachMenuBotsBot &data) { @@ -529,15 +542,22 @@ void AttachWebView::resolveUsername( } void AttachWebView::requestSimple( + not_null controller, not_null bot, const WebViewButton &button) { cancel(); _bot = bot; _peer = bot; + confirmOpen(controller, [=] { + requestSimple(button); + }); +} + +void AttachWebView::requestSimple(const WebViewButton &button) { using Flag = MTPmessages_RequestSimpleWebView::Flag; _requestId = _session->api().request(MTPmessages_RequestSimpleWebView( MTP_flags(Flag::f_theme_params), - bot->inputUser, + _bot->inputUser, MTP_bytes(button.url), MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams())) )).done([=](const MTPSimpleWebViewResult &result) { @@ -552,6 +572,32 @@ void AttachWebView::requestSimple( }).send(); } +void AttachWebView::confirmOpen( + not_null controller, + Fn done) { + if (!_bot) { + return; + } else if (_bot->isVerified() + || _bot->session().local().isBotTrustedOpenWebView(_bot->id)) { + done(); + return; + } + const auto callback = [=] { + _bot->session().local().markBotTrustedOpenWebView(_bot->id); + controller->hideLayer(); + done(); + }; + controller->show(Ui::MakeConfirmBox({ + .text = tr::lng_allow_bot_webview( + tr::now, + lt_bot_name, + Ui::Text::Bold(_bot->name), + Ui::Text::RichLangValue), + .confirmed = callback, + .confirmText = tr::lng_box_ok(), + })); +} + void AttachWebView::ClearAll() { while (!ActiveWebViews().empty()) { ActiveWebViews().front()->cancel(); @@ -706,7 +752,7 @@ std::unique_ptr MakeAttachBotsMenu( const auto callback = [=] { const auto active = controller->activeChatCurrent(); if (const auto history = active.history()) { - bots->request(history->peer, bot.user, {}); + bots->request(nullptr, history->peer, bot.user, {}); } }; auto action = base::make_unique_q( diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h index c68a33928..564ae6698 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h @@ -56,10 +56,12 @@ public: const QString &botUsername, const QString &startCommand); void request( + Window::SessionController *controller, not_null peer, not_null bot, const WebViewButton &button); void requestSimple( + not_null controller, not_null bot, const WebViewButton &button); @@ -84,10 +86,15 @@ public: private: void resolve(); void request(const WebViewButton &button); + void requestSimple(const WebViewButton &button); void resolveUsername( const QString &username, Fn)> done); + void confirmOpen( + not_null controller, + Fn done); + void toggleInMenu( not_null bot, bool enabled, diff --git a/Telegram/SourceFiles/storage/storage_account.cpp b/Telegram/SourceFiles/storage/storage_account.cpp index 73d52decb..0fccde674 100644 --- a/Telegram/SourceFiles/storage/storage_account.cpp +++ b/Telegram/SourceFiles/storage/storage_account.cpp @@ -2797,6 +2797,31 @@ bool Account::isBotTrustedPayment(PeerId botId) { && ((i->second & BotTrustFlag::Payment) != 0); } +void Account::markBotTrustedOpenWebView(PeerId botId) { + if (isBotTrustedOpenWebView(botId)) { + return; + } + const auto i = _trustedBots.find(botId); + if (i == end(_trustedBots)) { + _trustedBots.emplace( + botId, + BotTrustFlag::NoOpenGame | BotTrustFlag::OpenWebView); + } else { + i->second |= BotTrustFlag::OpenWebView; + } + writeTrustedBots(); +} + +bool Account::isBotTrustedOpenWebView(PeerId botId) { + if (!_trustedBotsRead) { + readTrustedBots(); + _trustedBotsRead = true; + } + const auto i = _trustedBots.find(botId); + return (i != end(_trustedBots)) + && ((i->second & BotTrustFlag::OpenWebView) != 0); +} + bool Account::encrypt( const void *src, void *dst, diff --git a/Telegram/SourceFiles/storage/storage_account.h b/Telegram/SourceFiles/storage/storage_account.h index c2d0f6104..a99beda6b 100644 --- a/Telegram/SourceFiles/storage/storage_account.h +++ b/Telegram/SourceFiles/storage/storage_account.h @@ -157,6 +157,8 @@ public: [[nodiscard]] bool isBotTrustedOpenGame(PeerId botId); void markBotTrustedPayment(PeerId botId); [[nodiscard]] bool isBotTrustedPayment(PeerId botId); + void markBotTrustedOpenWebView(PeerId botId); + [[nodiscard]] bool isBotTrustedOpenWebView(PeerId botId); [[nodiscard]] bool encrypt( const void *src, @@ -178,8 +180,9 @@ private: Failed, }; enum class BotTrustFlag : uchar { - NoOpenGame = (1 << 0), - Payment = (1 << 1), + NoOpenGame = (1 << 0), + Payment = (1 << 1), + OpenWebView = (1 << 2), }; friend inline constexpr bool is_flag_type(BotTrustFlag) { return true; };