diff --git a/Telegram/Resources/tl/api.tl b/Telegram/Resources/tl/api.tl index ba6b4fea1..21bfa0489 100644 --- a/Telegram/Resources/tl/api.tl +++ b/Telegram/Resources/tl/api.tl @@ -110,7 +110,7 @@ storage.fileMp4#b3cea0e4 = storage.FileType; storage.fileWebp#1081464c = storage.FileType; userEmpty#d3bc4b7a id:long = User; -user#3ff6ecb0 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User; +user#3ff6ecb0 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User; userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto; userProfilePhoto#82d1f706 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto; @@ -384,6 +384,7 @@ updateBotCommands#4d712f2e peer:Peer bot_id:long commands:Vector = U updatePendingJoinRequests#7063c3db peer:Peer requests_pending:int recent_requesters:Vector = Update; updateBotChatInviteRequester#11dfa986 peer:Peer date:int user_id:long about:string invite:ExportedChatInvite qts:int = Update; updateMessageReactions#154798c3 peer:Peer msg_id:int reactions:MessageReactions = Update; +updateAttachMenuBots#17b7a20b = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -590,6 +591,7 @@ inputKeyboardButtonUrlAuth#d02e7fd4 flags:# request_write_access:flags.0?true te keyboardButtonRequestPoll#bbc7515d flags:# quiz:flags.0?Bool text:string = KeyboardButton; inputKeyboardButtonUserProfile#e988037b text:string user_id:InputUser = KeyboardButton; keyboardButtonUserProfile#308660c1 text:string user_id:long = KeyboardButton; +keyboardButtonWebView#13767230 text:string url:string = KeyboardButton; keyboardButtonRow#77608b83 buttons:Vector = KeyboardButtonRow; @@ -1329,6 +1331,16 @@ phone.groupCallStreamChannels#d0e482b2 channels:Vector = phone.groupCallStreamRtmpUrl#2dbf3432 url:string key:string = phone.GroupCallStreamRtmpUrl; +attachMenuBot#d47e3658 bot_id:long attach_menu_icon:Document = AttachMenuBot; + +attachMenuBotsNotModified#f1d88a5c = AttachMenuBots; +attachMenuBots#3c4301c0 hash:long bots:Vector users:Vector = AttachMenuBots; + +webViewResultUrl#c14557c query_id:long url:string = WebViewResult; +webViewResultConfirmationRequired#b1cad385 bot:AttachMenuBot users:Vector = WebViewResult; + +messages.webViewResult#aadf159b result:BotInlineResult users:Vector = messages.WebViewResult; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -1618,6 +1630,11 @@ messages.translateText#24ce6dee flags:# peer:flags.0?InputPeer msg_id:flags.0?in messages.getUnreadReactions#e85bae1a peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages; messages.readReactions#82e251d7 peer:InputPeer = messages.AffectedHistory; messages.searchSentMedia#107e31a0 q:string filter:MessagesFilter limit:int = messages.Messages; +messages.getAttachMenuBots#16fcc2cb hash:long = AttachMenuBots; +messages.addBotToAttachMenu#f319bd48 bot:InputUser = Bool; +messages.requestWebView#a17c10db flags:# peer:InputPeer bot:InputUser url:flags.0?string theme_params:flags.1?DataJSON = WebViewResult; +messages.setWebViewResult#e41cd11d query_id:long result:InputBotInlineResult = Bool; +messages.getWebViewResult#22b6c214 peer:InputPeer bot:InputUser query_id:long = messages.WebViewResult; updates.getState#edd4882a = updates.State; updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference; diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 86f3a98ee..9b0590909 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -361,6 +361,7 @@ bool ResolveUsernameOrPhone( .startType = startType, .startToken = startToken, .startAdminRights = adminRights, + .attachBotUsername = params.value(u"attach"_q), .voicechatHash = (params.contains(u"livestream"_q) ? std::make_optional(params.value(u"livestream"_q)) : params.contains(u"videochat"_q) diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 72d9573d1..ded68526a 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -541,6 +541,7 @@ not_null Session::processUser(const MTPUser &data) { } else { result->botInfo->inlinePlaceholder = QString(); } + result->botInfo->supportsAttachMenu = data.is_bot_attach_menu(); } else { result->setBotInfoVersion(-1); } diff --git a/Telegram/SourceFiles/data/data_user.h b/Telegram/SourceFiles/data/data_user.h index 04fe28760..df37d7891 100644 --- a/Telegram/SourceFiles/data/data_user.h +++ b/Telegram/SourceFiles/data/data_user.h @@ -15,6 +15,7 @@ struct BotInfo { bool inited = false; bool readsAllHistory = false; bool cantJoinGroups = false; + bool supportsAttachMenu = false; int version = 0; QString description, inlinePlaceholder; std::vector commands; diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 9045bab17..8de3ae5f9 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -220,6 +220,10 @@ void activateBotCommand( } } } break; + + case ButtonType::WebView: { + + } break; } } diff --git a/Telegram/SourceFiles/history/history_item_reply_markup.cpp b/Telegram/SourceFiles/history/history_item_reply_markup.cpp index 230538d92..325eb980e 100644 --- a/Telegram/SourceFiles/history/history_item_reply_markup.cpp +++ b/Telegram/SourceFiles/history/history_item_reply_markup.cpp @@ -121,6 +121,11 @@ void HistoryMessageMarkupData::fillRows( }, [&](const MTPDinputKeyboardButtonUserProfile &data) { LOG(("API Error: inputKeyboardButtonUserProfile.")); // Should not get those for the users. + }, [&](const MTPDkeyboardButtonWebView &data) { + row.emplace_back( + Type::WebView, + qs(data.vtext()), + data.vurl().v); }); } if (!row.empty()) { diff --git a/Telegram/SourceFiles/history/history_item_reply_markup.h b/Telegram/SourceFiles/history/history_item_reply_markup.h index c857b5953..cecb9da65 100644 --- a/Telegram/SourceFiles/history/history_item_reply_markup.h +++ b/Telegram/SourceFiles/history/history_item_reply_markup.h @@ -41,6 +41,7 @@ struct HistoryMessageMarkupButton { Buy, Auth, UserProfile, + WebView, }; HistoryMessageMarkupButton( diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 6f16eb04f..33c7223b9 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -382,6 +382,7 @@ void SessionNavigation::showPeerByLinkResolved( // Show specific posts only in channels / supergroups. msgId = ShowAtUnreadMsgId; } + const auto attachBotUsername = info.attachBotUsername; if (user && user->isBot()) { user->botInfo->startToken = info.startToken; user->session().changes().peerUpdated( @@ -390,10 +391,47 @@ void SessionNavigation::showPeerByLinkResolved( } crl::on_main(this, [=] { showPeerHistory(peer->id, params, msgId); + showAttachWebview(peer, attachBotUsername); }); } } +void SessionNavigation::showAttachWebview( + not_null peer, + const QString &botUsername) { + if (!peer->isUser() || botUsername.isEmpty()) { + return; + } + resolveUsername(botUsername, [=](not_null bot) { + const auto user = bot->asUser(); + if (!user || !user->isBot() || !user->botInfo->supportsAttachMenu) { + Ui::ShowMultilineToast({ + // #TODO webview lang + .text = { u"This bot isn't supported in the attach menu."_q } + }); + return; + } + + // #TODO webview cancel request in destructor + session().api().request(MTPmessages_RequestWebView( + MTP_flags(0), + peer->input, + user->inputUser, + MTPstring(), // start_param + MTPDataJSON() // theme_params + )).done([=](const MTPWebViewResult &result) { + result.match([&](const MTPDwebViewResultUrl &data) { + int b = 0; + }, [&](const MTPDwebViewResultConfirmationRequired &data) { + session().data().processUsers(data.vusers()); + int a = 0; + }); + }).fail([=](const MTP::Error &error) { + int a = error.code(); + }).send(); + }); +} + void SessionNavigation::showRepliesForMessage( not_null history, MsgId rootId, diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index f610eae85..d83953ad6 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -190,10 +190,14 @@ public: BotStartType startType = BotStartType::None; QString startToken; ChatAdminRights startAdminRights; + QString attachBotUsername; std::optional voicechatHash; FullMsgId clickFromMessageId; }; void showPeerByLink(const PeerByLinkInfo &info); + void showAttachWebview( + not_null peer, + const QString &botUsername); void showRepliesForMessage( not_null history,