diff --git a/Telegram/SourceFiles/api/api_text_entities.cpp b/Telegram/SourceFiles/api/api_text_entities.cpp index 9f400d05cc..f3d6db8b40 100644 --- a/Telegram/SourceFiles/api/api_text_entities.cpp +++ b/Telegram/SourceFiles/api/api_text_entities.cpp @@ -12,6 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_stickers_set.h" +#include "history/history.h" +#include "history/history_item.h" #include "main/main_session.h" namespace Api { @@ -47,14 +49,23 @@ using namespace TextUtilities; if (!parsed.userId || parsed.selfId != session->userId().bare) { return {}; } - return MTP_inputMessageEntityMentionName( - offset, - length, - (parsed.userId == parsed.selfId - ? MTP_inputUserSelf() - : MTP_inputUser( - MTP_long(parsed.userId), - MTP_long(parsed.accessHash)))); + const auto user = session->data().user(UserId(parsed.userId)); + const auto item = user->isLoaded() + ? nullptr + : user->owner().messageWithPeer(user->id); + const auto input = item + ? MTP_inputUserFromMessage( + item->history()->peer->input(), + MTP_int(item->id.bare), + MTP_long(parsed.userId)) + : (parsed.userId == parsed.selfId) + ? MTP_inputUserSelf() + : user->isLoaded() + ? user->inputUser() + : MTP_inputUser( + MTP_long(parsed.userId), + MTP_long(parsed.accessHash)); + return MTP_inputMessageEntityMentionName(offset, length, input); } } // namespace diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index 352e80a355..ec26e117ce 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -137,100 +137,6 @@ bool HasForceLogoutNotification(const MTPUpdates &updates) { return false; } -bool ForwardedInfoDataLoaded( - not_null session, - const MTPMessageFwdHeader &header) { - return header.match([&](const MTPDmessageFwdHeader &data) { - if (const auto fromId = data.vfrom_id()) { - // Fully loaded is required in this case. - if (!session->data().peerLoaded(peerFromMTP(*fromId))) { - return false; - } - } - return true; - }); -} - -bool MentionUsersLoaded( - not_null session, - const MTPVector &entities) { - for (const auto &entity : entities.v) { - auto type = entity.type(); - if (type == mtpc_messageEntityMentionName) { - if (!session->data().userLoaded(entity.c_messageEntityMentionName().vuser_id())) { - return false; - } - } else if (type == mtpc_inputMessageEntityMentionName) { - auto &inputUser = entity.c_inputMessageEntityMentionName().vuser_id(); - if (inputUser.type() == mtpc_inputUser) { - if (!session->data().userLoaded(inputUser.c_inputUser().vuser_id())) { - return false; - } - } - } - } - return true; -} - -DataIsLoadedResult AllDataLoadedForMessage( - not_null session, - const MTPMessage &message) { - return message.match([&](const MTPDmessage &message) { - if (const auto fromId = message.vfrom_id()) { - if (!message.is_post() - && !session->data().peerLoaded(peerFromMTP(*fromId))) { - return DataIsLoadedResult::FromNotLoaded; - } - } - if (const auto viaBotId = message.vvia_bot_id()) { - if (!session->data().userLoaded(*viaBotId)) { - return DataIsLoadedResult::NotLoaded; - } - } - if (const auto fwd = message.vfwd_from()) { - if (!ForwardedInfoDataLoaded(session, *fwd)) { - return DataIsLoadedResult::NotLoaded; - } - } - if (const auto entities = message.ventities()) { - if (!MentionUsersLoaded(session, *entities)) { - return DataIsLoadedResult::MentionNotLoaded; - } - } - return DataIsLoadedResult::Ok; - }, [&](const MTPDmessageService &message) { - if (const auto fromId = message.vfrom_id()) { - if (!message.is_post() - && !session->data().peerLoaded(peerFromMTP(*fromId))) { - return DataIsLoadedResult::FromNotLoaded; - } - } - return message.vaction().match( - [&](const MTPDmessageActionChatAddUser &action) { - for (const auto &userId : action.vusers().v) { - if (!session->data().userLoaded(userId)) { - return DataIsLoadedResult::NotLoaded; - } - } - return DataIsLoadedResult::Ok; - }, [&](const MTPDmessageActionChatJoinedByLink &action) { - if (!session->data().userLoaded(action.vinviter_id())) { - return DataIsLoadedResult::NotLoaded; - } - return DataIsLoadedResult::Ok; - }, [&](const MTPDmessageActionChatDeleteUser &action) { - if (!session->data().userLoaded(action.vuser_id())) { - return DataIsLoadedResult::NotLoaded; - } - return DataIsLoadedResult::Ok; - }, [](const auto &) { - return DataIsLoadedResult::Ok; - }); - }, [](const MTPDmessageEmpty &message) { - return DataIsLoadedResult::Ok; - }); -} - } // namespace Updates::Updates(not_null session) @@ -1613,25 +1519,13 @@ void Updates::feedUpdate(const MTPUpdate &update) { // New messages. case mtpc_updateNewMessage: { auto &d = update.c_updateNewMessage(); - - const auto isDataLoaded = AllDataLoadedForMessage(&session(), d.vmessage()); - if (!requestingDifference() && isDataLoaded != DataIsLoadedResult::Ok) { - MTP_LOG(0, ("getDifference " - "{ good - after not all data loaded in updateNewMessage }%1" - ).arg(_session->mtp().isTestMode() ? " TESTMODE" : "")); - - // This can be if this update was created by grouping - // some short message update into an updates vector. - return getDifference(); - } - + _session->data().fillMessagePeers(d.vmessage()); updateAndApply(d.vpts().v, d.vpts_count().v, update); } break; case mtpc_updateNewChannelMessage: { auto &d = update.c_updateNewChannelMessage(); auto channel = session().data().channelLoaded(peerToChannel(PeerFromMessage(d.vmessage()))); - const auto isDataLoaded = AllDataLoadedForMessage(&session(), d.vmessage()); { // Todo delete. const auto messageId = IdFromMessage(d.vmessage()); @@ -1643,27 +1537,16 @@ void Updates::feedUpdate(const MTPUpdate &update) { } } } - if (!requestingDifference() && (!channel || isDataLoaded != DataIsLoadedResult::Ok)) { + if (!requestingDifference() && !channel) { MTP_LOG(0, ("getDifference " "{ good - after not all data loaded in updateNewChannelMessage }%1" ).arg(_session->mtp().isTestMode() ? " TESTMODE" : "")); - - // Request last active supergroup participants if the 'from' user was not loaded yet. - // This will optimize similar getDifference() calls for almost all next messages. - if (isDataLoaded == DataIsLoadedResult::FromNotLoaded && channel && channel->isMegagroup()) { - if (channel->canViewMembers() - && channel->mgInfo->lastParticipants.size() < _session->serverConfig().chatSizeMax - && (channel->mgInfo->lastParticipants.empty() - || channel->mgInfo->lastParticipants.size() < channel->membersCount())) { - session().api().chatParticipants().requestLast(channel); - } - } - if (!_byMinChannelTimer.isActive()) { // getDifference after timeout _byMinChannelTimer.callOnce(PtsWaiter::kWaitForSkippedTimeout); } return; } + _session->data().fillMessagePeers(d.vmessage()); if (channel && !_handlingChannelDifference) { if (channel->ptsRequesting()) { // skip global updates while getting channel difference MTP_LOG(0, ("Skipping new channel message because getting the difference.")); diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 1203db88b1..40ad9bff3b 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "core/application.h" #include "history/history.h" +#include "history/history_item.h" #include "api/api_chat_invite.h" #include "api/api_invite_links.h" #include "apiwrap.h" @@ -1210,6 +1211,19 @@ void ChannelData::updateSubscriptionUntilDate(TimeId subscriptionUntilDate) { _subscriptionUntilDate = subscriptionUntilDate; } +MTPInputChannel ChannelData::inputChannel() const { + const auto item = isLoaded() ? nullptr : owner().messageWithPeer(id); + if (item) { + return MTP_inputChannelFromMessage( + item->history()->peer->input(), + MTP_int(item->id.bare), + MTP_long(peerToChannel(id).bare)); + } + return MTP_inputChannel( + MTP_long(peerToChannel(id).bare), + MTP_long(_accessHash)); +} + namespace Data { void ApplyMigration( diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index 6efc41f4a7..2d6e21c88b 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -553,11 +553,9 @@ public: [[nodiscard]] TimeId subscriptionUntilDate() const; void updateSubscriptionUntilDate(TimeId subscriptionUntilDate); + [[nodiscard]] MTPInputChannel inputChannel() const; + // Still public data members. - uint64 access = 0; - - MTPinputChannel inputChannel = MTP_inputChannelEmpty(); - int32 date = 0; std::unique_ptr mgInfo; @@ -588,6 +586,8 @@ private: std::vector _recentRequesters; MsgId _availableMinId = 0; + uint64 _accessHash = 0; + RestrictionFlags _defaultRestrictions; AdminRightFlags _adminRights; RestrictionFlags _restrictions; diff --git a/Telegram/SourceFiles/data/data_chat.cpp b/Telegram/SourceFiles/data/data_chat.cpp index 774b0f57c9..05d4f8b1e6 100644 --- a/Telegram/SourceFiles/data/data_chat.cpp +++ b/Telegram/SourceFiles/data/data_chat.cpp @@ -313,6 +313,10 @@ const Data::AllowedReactions &ChatData::allowedReactions() const { return _allowedReactions; } +MTPlong ChatData::inputChat() const { + return MTP_long(peerToChat(id).bare); +} + namespace Data { void ApplyChatUpdate( diff --git a/Telegram/SourceFiles/data/data_chat.h b/Telegram/SourceFiles/data/data_chat.h index 5a285aeeb5..24b719c619 100644 --- a/Telegram/SourceFiles/data/data_chat.h +++ b/Telegram/SourceFiles/data/data_chat.h @@ -166,9 +166,9 @@ public: void setAllowedReactions(Data::AllowedReactions value); [[nodiscard]] const Data::AllowedReactions &allowedReactions() const; - // Still public data members. - const MTPlong inputChat; + [[nodiscard]] MTPlong inputChat() const; + // Still public data members. int count = 0; TimeId date = 0; UserId creator = 0; diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 636cf43a97..95f6741c66 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -2014,6 +2014,41 @@ int PeerData::peerGiftsCount() const { return 0; } +MTPInputPeer PeerData::input() const { + if (const auto user = asUser()) { + const auto specific = user->inputUser(); + return specific.match([](const MTPDinputUser &data) { + return MTP_inputPeerUser(data.vuser_id(), data.vaccess_hash()); + }, [](const MTPDinputUserFromMessage &data) { + return MTP_inputPeerUserFromMessage( + data.vpeer(), + data.vmsg_id(), + data.vuser_id()); + }, [](const MTPDinputUserEmpty &) { + return MTP_inputPeerEmpty(); + }, [](const MTPDinputUserSelf &) { + return MTP_inputPeerSelf(); + }); + } else if (const auto chat = asChat()) { + return MTP_inputPeerChat(chat->inputChat()); + } else if (const auto channel = asChannel()) { + const auto &specific = channel->inputChannel(); + return specific.match([](const MTPDinputChannel &data) { + return MTP_inputPeerChannel( + data.vchannel_id(), + data.vaccess_hash()); + }, [](const MTPDinputChannelFromMessage &data) { + return MTP_inputPeerChannelFromMessage( + data.vpeer(), + data.vmsg_id(), + data.vchannel_id()); + }, [](const MTPDinputChannelEmpty &) { + return MTP_inputPeerEmpty(); + }); + } + return MTP_inputPeerEmpty(); +} + void PeerData::setIsBlocked(bool is) { const auto status = is ? BlockStatus::Blocked diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index a70b036362..44880d4d44 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -584,8 +584,9 @@ public: [[nodiscard]] int peerGiftsCount() const; + [[nodiscard]] MTPInputPeer input() const; + const PeerId id; - MTPinputPeer input = MTP_inputPeerEmpty(); protected: void updateNameDelayed( diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 7c5a71a44b..f0329fb78b 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -5363,4 +5363,83 @@ void Session::clearLocalStorage() { _bigFileCache->clear(); } +void Session::fillMessagePeers(const MTPMessage &message) { + const auto id = IdFromMessage(message); + const auto peerId = PeerFromMessage(message); + if (!id || !peerId) { + return; + } + const auto fullId = FullMsgId(peerId, id); + const auto fill = [&](PeerId peerId) { + if (!peerLoaded(peerId)) { + _messagesWithPeer[peerId].push_back(fullId); + } + }; + const auto fillForwardedInfo = [&](const MTPMessageFwdHeader &header) { + return header.match([&](const MTPDmessageFwdHeader &data) { + if (const auto fromId = data.vfrom_id()) { + fill(peerFromMTP(*fromId)); + } + }); + }; + const auto fillMentionUsers = [&]( + const MTPVector &entities) { + for (const auto &entity : entities.v) { + entity.match([&](const MTPDmessageEntityMentionName &data) { + fill(peerFromUser(data.vuser_id())); + }, [&](const MTPDinputMessageEntityMentionName &data) { + data.vuser_id().match([&](const MTPDinputUser &data) { + fill(peerFromUser(data.vuser_id())); + }, [](const auto &) {}); + }, [](const auto &) {}); + } + }; + return message.match([&](const MTPDmessage &message) { + if (const auto fromId = message.vfrom_id()) { + fill(peerFromMTP(*fromId)); + } + if (const auto viaBotId = message.vvia_bot_id()) { + fill(peerFromUser(*viaBotId)); + } + if (const auto fwd = message.vfwd_from()) { + fillForwardedInfo(*fwd); + } + if (const auto entities = message.ventities()) { + fillMentionUsers(*entities); + } + }, [&](const MTPDmessageService &message) { + if (const auto fromId = message.vfrom_id()) { + fill(peerFromMTP(*fromId)); + } + return message.vaction().match( + [&](const MTPDmessageActionChatAddUser &action) { + for (const auto &userId : action.vusers().v) { + fill(peerFromUser(userId)); + } + }, [&](const MTPDmessageActionChatJoinedByLink &action) { + fill(peerFromUser(action.vinviter_id())); + }, [&](const MTPDmessageActionChatDeleteUser &action) { + fill(peerFromUser(action.vuser_id())); + }, [](const auto &) { + }); + }, [](const MTPDmessageEmpty &message) { + }); +} + +HistoryItem *Session::messageWithPeer(PeerId id) const { + const auto i = _messagesWithPeer.find(id); + if (i == end(_messagesWithPeer)) { + return nullptr; + } + auto &list = i->second; + for (auto j = begin(list); j != end(list);) { + if (const auto item = message(*j)) { + return item; + } + j = list.erase(j); + } + _messagesWithPeer.erase(i); + return nullptr; +} + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index c1d42df8a1..e464f6ceb1 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -918,6 +918,9 @@ public: void clearLocalStorage(); + void fillMessagePeers(const MTPMessage &message); + [[nodiscard]] HistoryItem *messageWithPeer(PeerId id) const; + private: using Messages = std::unordered_map>; @@ -1259,6 +1262,8 @@ private: not_null, mtpRequestId> _viewAsMessagesRequests; + mutable base::flat_map> _messagesWithPeer; + Groups _groups; const std::unique_ptr _chatsFilters; const std::unique_ptr _cloudThemes; diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index f1a52958a4..545d85c400 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_wall_paper.h" #include "data/notify/data_notify_settings.h" #include "history/history.h" +#include "history/history_item.h" #include "api/api_peer_photo.h" #include "apiwrap.h" #include "lang/lang_keys.h" @@ -317,6 +318,21 @@ void UserData::setPersonalChannel(ChannelId channelId, MsgId messageId) { } } +MTPInputUser UserData::inputUser() const { + const auto item = isLoaded() ? nullptr : owner().messageWithPeer(id); + if (item) { + return MTP_inputUserFromMessage( + item->history()->peer->input(), + MTP_int(item->id.bare), + MTP_long(peerToUser(id).bare)); + } else if (isSelf()) { + return MTP_inputUserSelf(); + } + return MTP_inputUser( + MTP_long(peerToUser(id).bare), + MTP_long(_accessHash)); +} + void UserData::setName( const QString &newFirstName, const QString &newLastName, diff --git a/Telegram/SourceFiles/data/data_user.h b/Telegram/SourceFiles/data/data_user.h index 2ff22ab67b..c20166fd8f 100644 --- a/Telegram/SourceFiles/data/data_user.h +++ b/Telegram/SourceFiles/data/data_user.h @@ -286,7 +286,7 @@ public: [[nodiscard]] MsgId personalChannelMessageId() const; void setPersonalChannel(ChannelId channelId, MsgId messageId); - MTPInputUser inputUser = MTP_inputUserEmpty(); + [[nodiscard]] MTPInputUser inputUser() const; QString firstName; QString lastName;