Initial support for min-user-from-message request.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -137,100 +137,6 @@ bool HasForceLogoutNotification(const MTPUpdates &updates) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ForwardedInfoDataLoaded(
|
||||
not_null<Main::Session*> 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<Main::Session*> session,
|
||||
const MTPVector<MTPMessageEntity> &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<Main::Session*> 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<Main::Session*> 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."));
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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<MegagroupInfo> mgInfo;
|
||||
|
||||
@@ -588,6 +586,8 @@ private:
|
||||
std::vector<UserId> _recentRequesters;
|
||||
MsgId _availableMinId = 0;
|
||||
|
||||
uint64 _accessHash = 0;
|
||||
|
||||
RestrictionFlags _defaultRestrictions;
|
||||
AdminRightFlags _adminRights;
|
||||
RestrictionFlags _restrictions;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -584,8 +584,9 @@ public:
|
||||
|
||||
[[nodiscard]] int peerGiftsCount() const;
|
||||
|
||||
[[nodiscard]] MTPInputPeer input() const;
|
||||
|
||||
const PeerId id;
|
||||
MTPinputPeer input = MTP_inputPeerEmpty();
|
||||
|
||||
protected:
|
||||
void updateNameDelayed(
|
||||
|
||||
@@ -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<MTPMessageEntity> &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
|
||||
|
||||
@@ -918,6 +918,9 @@ public:
|
||||
|
||||
void clearLocalStorage();
|
||||
|
||||
void fillMessagePeers(const MTPMessage &message);
|
||||
[[nodiscard]] HistoryItem *messageWithPeer(PeerId id) const;
|
||||
|
||||
private:
|
||||
using Messages = std::unordered_map<MsgId, not_null<HistoryItem*>>;
|
||||
|
||||
@@ -1259,6 +1262,8 @@ private:
|
||||
not_null<ChannelData*>,
|
||||
mtpRequestId> _viewAsMessagesRequests;
|
||||
|
||||
mutable base::flat_map<PeerId, std::vector<FullMsgId>> _messagesWithPeer;
|
||||
|
||||
Groups _groups;
|
||||
const std::unique_ptr<ChatFilters> _chatsFilters;
|
||||
const std::unique_ptr<CloudThemes> _cloudThemes;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user