diff --git a/Telegram/Resources/tl/api.tl b/Telegram/Resources/tl/api.tl index 2ebe8fd72..7401aa08b 100644 --- a/Telegram/Resources/tl/api.tl +++ b/Telegram/Resources/tl/api.tl @@ -562,6 +562,7 @@ auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery; receivedNotifyMessage#a384b779 id:int flags:int = ReceivedNotifyMessage; chatInviteExported#ab4a819 flags:# revoked:flags.0?true permanent:flags.5?true request_needed:flags.6?true link:string admin_id:long date:int start_date:flags.4?int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int requested:flags.7?int title:flags.8?string = ExportedChatInvite; +chatInvitePublicJoinRequests#ed107ab7 = ExportedChatInvite; chatInviteAlready#5a686d7c chat:Chat = ChatInvite; chatInvite#300c44c1 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true request_needed:flags.6?true title:string about:flags.5?string photo:Photo participants_count:int participants:flags.4?Vector = ChatInvite; @@ -581,7 +582,7 @@ messages.stickerSetNotModified#d3f924eb = messages.StickerSet; botCommand#c27ac8c7 command:string description:string = BotCommand; -botInfo#e4169b5d user_id:long description:string commands:Vector menu_button:BotMenuButton = BotInfo; +botInfo#cc8ba4d7 flags:# user_id:flags.0?long description:flags.1?string description_photo:flags.4?Photo commands:flags.2?Vector menu_button:flags.3?BotMenuButton = BotInfo; keyboardButton#a2fa4880 text:string = KeyboardButton; keyboardButtonUrl#258aff05 text:string url:string = KeyboardButton; @@ -1750,6 +1751,8 @@ channels.viewSponsoredMessage#beaedb94 channel:InputChannel random_id:bytes = Bo channels.getSponsoredMessages#ec210fbf channel:InputChannel = messages.SponsoredMessages; channels.getSendAs#dc770ee peer:InputPeer = channels.SendAsPeers; channels.deleteParticipantHistory#367544db channel:InputChannel participant:InputPeer = messages.AffectedHistory; +channels.toggleJoinToSend#e4cb9580 channel:InputChannel enabled:Bool = Updates; +channels.toggleJoinRequest#4c2985b6 channel:InputChannel enabled:Bool = Updates; bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON; bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool; diff --git a/Telegram/SourceFiles/api/api_invite_links.cpp b/Telegram/SourceFiles/api/api_invite_links.cpp index 3aad8c14e..e6d8182f3 100644 --- a/Telegram/SourceFiles/api/api_invite_links.cpp +++ b/Telegram/SourceFiles/api/api_invite_links.cpp @@ -123,9 +123,9 @@ void InviteLinks::performCreate( )).done([=](const MTPExportedChatInvite &result) { const auto callbacks = _createCallbacks.take(peer); const auto link = prepend(peer, peer->session().user(), result); - if (callbacks) { + if (link && callbacks) { for (const auto &callback : *callbacks) { - callback(link); + callback(*link); } } }).fail([=] { @@ -155,15 +155,18 @@ auto InviteLinks::lookupMyPermanent(const Links &links) const -> const Link* { auto InviteLinks::prepend( not_null peer, not_null admin, - const MTPExportedChatInvite &invite) -> Link { + const MTPExportedChatInvite &invite) -> std::optional { const auto link = parse(peer, invite); + if (!link) { + return link; + } if (admin->isSelf()) { - prependMyToFirstSlice(peer, admin, link); + prependMyToFirstSlice(peer, admin, *link); } _updates.fire(Update{ .peer = peer, .admin = admin, - .now = link + .now = *link }); return link; } @@ -281,6 +284,9 @@ void InviteLinks::performEdit( result.match([&](const auto &data) { _api->session().data().processUsers(data.vusers()); const auto link = parse(peer, data.vinvite()); + if (!link) { + return; + } auto i = _firstSlices.find(peer); if (i != end(_firstSlices)) { const auto j = ranges::find( @@ -288,18 +294,18 @@ void InviteLinks::performEdit( key.link, &Link::link); if (j != end(i->second.links)) { - if (link.revoked && !j->revoked) { + if (link->revoked && !j->revoked) { i->second.links.erase(j); if (i->second.count > 0) { --i->second.count; } } else { - *j = link; + *j = *link; } } } for (const auto &callback : *callbacks) { - callback(link); + callback(*link); } _updates.fire(Update{ .peer = peer, @@ -617,7 +623,11 @@ void InviteLinks::setMyPermanent( not_null peer, const MTPExportedChatInvite &invite) { auto link = parse(peer, invite); - if (!link.permanent) { + if (!link) { + LOG(("API Error: " + "InviteLinks::setPermanent called with non-link.")); + return; + } else if (!link->permanent) { LOG(("API Error: " "InviteLinks::setPermanent called with non-permanent link.")); return; @@ -632,13 +642,13 @@ void InviteLinks::setMyPermanent( .admin = peer->session().user(), }; if (const auto permanent = lookupMyPermanent(links)) { - if (permanent->link == link.link) { - if (permanent->usage != link.usage) { - permanent->usage = link.usage; + if (permanent->link == link->link) { + if (permanent->usage != link->usage) { + permanent->usage = link->usage; _updates.fire(Update{ .peer = peer, .admin = peer->session().user(), - .was = link.link, + .was = link->link, .now = *permanent }); } @@ -652,9 +662,9 @@ void InviteLinks::setMyPermanent( --links.count; } } - links.links.insert(begin(links.links), link); + links.links.insert(begin(links.links), *link); - editPermanentLink(peer, link.link); + editPermanentLink(peer, link->link); notify(peer); if (updateOldPermanent.now) { @@ -722,9 +732,10 @@ auto InviteLinks::parseSlice( peer->session().data().processUsers(data.vusers()); result.count = data.vcount().v; for (const auto &invite : data.vinvites().v) { - const auto link = parse(peer, invite); - if (!permanent || link.link != permanent->link) { - result.links.push_back(link); + if (const auto link = parse(peer, invite)) { + if (!permanent || link->link != permanent->link) { + result.links.push_back(*link); + } } } }); @@ -733,9 +744,9 @@ auto InviteLinks::parseSlice( auto InviteLinks::parse( not_null peer, - const MTPExportedChatInvite &invite) const -> Link { + const MTPExportedChatInvite &invite) const -> std::optional { return invite.match([&](const MTPDchatInviteExported &data) { - return Link{ + return std::optional(Link{ .link = qs(data.vlink()), .label = qs(data.vtitle().value_or_empty()), .admin = peer->session().data().user(data.vadmin_id()), @@ -748,7 +759,9 @@ auto InviteLinks::parse( .requestApproval = data.is_request_needed(), .permanent = data.is_permanent(), .revoked = data.is_revoked(), - }; + }); + }, [&](const MTPDchatInvitePublicJoinRequests &data) { + return std::optional(); }); } diff --git a/Telegram/SourceFiles/api/api_invite_links.h b/Telegram/SourceFiles/api/api_invite_links.h index 586a38a1e..14f510796 100644 --- a/Telegram/SourceFiles/api/api_invite_links.h +++ b/Telegram/SourceFiles/api/api_invite_links.h @@ -157,13 +157,13 @@ private: [[nodiscard]] Links parseSlice( not_null peer, const MTPmessages_ExportedChatInvites &slice) const; - [[nodiscard]] Link parse( + [[nodiscard]] std::optional parse( not_null peer, const MTPExportedChatInvite &invite) const; [[nodiscard]] Link *lookupMyPermanent(not_null peer); [[nodiscard]] Link *lookupMyPermanent(Links &links); [[nodiscard]] const Link *lookupMyPermanent(const Links &links) const; - Link prepend( + std::optional prepend( not_null peer, not_null admin, const MTPExportedChatInvite &invite); diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index 804c38311..6d73fbc3f 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -1988,7 +1988,7 @@ void Updates::feedUpdate(const MTPUpdate &update) { const auto botId = UserId(d.vbot_id().v); if (const auto user = peer->asUser()) { if (user->isBot() && user->id == peerFromUser(botId)) { - if (Data::UpdateBotCommands(user->botInfo->commands, d.vcommands())) { + if (Data::UpdateBotCommands(user->botInfo->commands, &d.vcommands())) { session().data().botCommandsChanged(user); } } @@ -2015,7 +2015,7 @@ void Updates::feedUpdate(const MTPUpdate &update) { const auto &d = update.c_updateBotMenuButton(); if (const auto bot = session().data().userLoaded(d.vbot_id())) { if (const auto info = bot->botInfo.get(); info && info->inited) { - if (Data::ApplyBotMenuButton(info, d.vbutton())) { + if (Data::ApplyBotMenuButton(info, &d.vbutton())) { session().data().botCommandsChanged(bot); } } diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index c74ffde88..df48daf29 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -56,7 +56,7 @@ bool MegagroupInfo::updateBotCommands(const MTPVector &data) { bool MegagroupInfo::updateBotCommands( UserId botId, const MTPVector &data) { - return Data::UpdateBotCommands(_botCommands, botId, data); + return Data::UpdateBotCommands(_botCommands, botId, &data); } ChannelData::ChannelData(not_null owner, PeerId id) diff --git a/Telegram/SourceFiles/data/data_chat.cpp b/Telegram/SourceFiles/data/data_chat.cpp index 090dda7de..9ad2968bd 100644 --- a/Telegram/SourceFiles/data/data_chat.cpp +++ b/Telegram/SourceFiles/data/data_chat.cpp @@ -263,7 +263,7 @@ void ChatData::setBotCommands(const MTPVector &data) { void ChatData::setBotCommands( UserId botId, const MTPVector &data) { - if (Data::UpdateBotCommands(_botCommands, botId, data)) { + if (Data::UpdateBotCommands(_botCommands, botId, &data)) { owner().botCommandsChanged(this); } } diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index ac7ec6518..ea3d7ea2b 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -90,8 +90,13 @@ PeerId FakePeerIdForJustName(const QString &name) { bool UpdateBotCommands( std::vector &commands, - const MTPVector &data) { - const auto &v = data.v; + const MTPVector *data) { + if (!data) { + const auto changed = !commands.empty(); + commands.clear(); + return changed; + } + const auto &v = data->v; commands.reserve(v.size()); auto result = false; auto index = 0; @@ -127,8 +132,8 @@ bool UpdateBotCommands( bool UpdateBotCommands( base::flat_map> &commands, UserId botId, - const MTPVector &data) { - return data.v.isEmpty() + const MTPVector *data) { + return (!data || data->v.isEmpty()) ? commands.remove(botId) : UpdateBotCommands(commands[botId], data); } @@ -141,7 +146,11 @@ bool UpdateBotCommands( filled.reserve(data.v.size()); for (const auto &item : data.v) { item.match([&](const MTPDbotInfo &data) { - const auto id = UserId(data.vuser_id().v); + if (!data.vuser_id()) { + LOG(("API Error: BotInfo without UserId for commands map.")); + return; + } + const auto id = UserId(*data.vuser_id()); if (!filled.emplace(id).second) { LOG(("API Error: Two BotInfo for a single bot.")); return; @@ -163,14 +172,16 @@ bool UpdateBotCommands( bool ApplyBotMenuButton( not_null info, - const MTPBotMenuButton &button) { + const MTPBotMenuButton *button) { auto text = QString(); auto url = QString(); - button.match([&](const MTPDbotMenuButton &data) { - text = qs(data.vtext()); - url = qs(data.vurl()); - }, [&](const auto &) { - }); + if (button) { + button->match([&](const MTPDbotMenuButton &data) { + text = qs(data.vtext()); + url = qs(data.vurl()); + }, [&](const auto &) { + }); + } const auto changed = (info->botMenuButtonText != text) || (info->botMenuButtonUrl != url); diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 02d186834..d42dfc1b1 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -102,17 +102,17 @@ struct UnavailableReason { bool UpdateBotCommands( std::vector &commands, - const MTPVector &data); + const MTPVector *data); bool UpdateBotCommands( base::flat_map> &commands, UserId botId, - const MTPVector &data); + const MTPVector *data); bool UpdateBotCommands( base::flat_map> &commands, const MTPVector &data); bool ApplyBotMenuButton( not_null info, - const MTPBotMenuButton &button); + const MTPBotMenuButton *button); } // namespace Data diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index 86afabe94..e52c66cd2 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -121,11 +121,13 @@ void UserData::setBotInfo(const MTPBotInfo &info) { switch (info.type()) { case mtpc_botInfo: { const auto &d = info.c_botInfo(); - if (peerFromUser(d.vuser_id().v) != id || !isBot()) { + if (!isBot()) { + return; + } else if (d.vuser_id() && peerFromUser(*d.vuser_id()) != id) { return; } - QString desc = qs(d.vdescription()); + QString desc = qs(d.vdescription().value_or_empty()); if (botInfo->description != desc) { botInfo->description = desc; botInfo->text = Ui::Text::String(st::msgMinWidth); diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp index 5a5c9492a..efe1ab41c 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp @@ -302,15 +302,23 @@ TextWithEntities GeneratePermissionsChangeText( return result; } +QString PublicJoinLink() { + return u"(public_join_link)"_q; +} + QString ExtractInviteLink(const MTPExportedChatInvite &data) { return data.match([&](const MTPDchatInviteExported &data) { return qs(data.vlink()); + }, [&](const MTPDchatInvitePublicJoinRequests &data) { + return PublicJoinLink(); }); } QString ExtractInviteLinkLabel(const MTPExportedChatInvite &data) { return data.match([&](const MTPDchatInviteExported &data) { return qs(data.vtitle().value_or_empty()); + }, [&](const MTPDchatInvitePublicJoinRequests &data) { + return PublicJoinLink(); }); } @@ -361,21 +369,29 @@ TextWithEntities GenerateInviteLinkChangeText( const auto label = [](const MTPExportedChatInvite &link) { return link.match([](const MTPDchatInviteExported &data) { return qs(data.vtitle().value_or_empty()); + }, [&](const MTPDchatInvitePublicJoinRequests &data) { + return PublicJoinLink(); }); }; const auto expireDate = [](const MTPExportedChatInvite &link) { return link.match([](const MTPDchatInviteExported &data) { return data.vexpire_date().value_or_empty(); + }, [&](const MTPDchatInvitePublicJoinRequests &data) { + return TimeId(); }); }; const auto usageLimit = [](const MTPExportedChatInvite &link) { return link.match([](const MTPDchatInviteExported &data) { return data.vusage_limit().value_or_empty(); + }, [&](const MTPDchatInvitePublicJoinRequests &data) { + return 0; }); }; const auto requestApproval = [](const MTPExportedChatInvite &link) { return link.match([](const MTPDchatInviteExported &data) { return data.is_request_needed(); + }, [&](const MTPDchatInvitePublicJoinRequests &data) { + return true; }); }; const auto wrapDate = [](TimeId date) {