From b28e9a6167a563fbf5bac90f0589b4dba222dd45 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 9 May 2016 13:07:25 +0300 Subject: [PATCH] Requesting difference or messages when users from mentions not loaded. --- Telegram/SourceFiles/apiwrap.cpp | 32 ++-- Telegram/SourceFiles/apiwrap.h | 2 +- Telegram/SourceFiles/history.cpp | 4 +- Telegram/SourceFiles/historywidget.cpp | 4 +- Telegram/SourceFiles/mainwidget.cpp | 204 ++++++++++++++----------- 5 files changed, 135 insertions(+), 111 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index eb3210be17..d49c68cc45 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -37,17 +37,19 @@ ApiWrap::ApiWrap(QObject *parent) : QObject(parent) void ApiWrap::init() { } -void ApiWrap::requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback *callback) { - MessageDataRequest::CallbackPtr pcallback(callback); +void ApiWrap::requestMessageData(ChannelData *channel, MsgId msgId, std_::unique_ptr callback) { MessageDataRequest &req(channel ? _channelMessageDataRequests[channel][msgId] : _messageDataRequests[msgId]); - req.callbacks.append(pcallback); + if (callback) { + MessageDataRequest::CallbackPtr pcallback(callback.release()); + req.callbacks.append(pcallback); + } if (!req.req) _messageDataResolveDelayed->call(); } ApiWrap::MessageIds ApiWrap::collectMessageIds(const MessageDataRequests &requests) { MessageIds result; result.reserve(requests.size()); - for (MessageDataRequests::const_iterator i = requests.cbegin(), e = requests.cend(); i != e; ++i) { + for (auto i = requests.cbegin(), e = requests.cend(); i != e; ++i) { if (i.value().req > 0) continue; result.push_back(MTP_int(i.key())); } @@ -56,7 +58,7 @@ ApiWrap::MessageIds ApiWrap::collectMessageIds(const MessageDataRequests &reques ApiWrap::MessageDataRequests *ApiWrap::messageDataRequests(ChannelData *channel, bool onlyExisting) { if (channel) { - ChannelMessageDataRequests::iterator i = _channelMessageDataRequests.find(channel); + auto i = _channelMessageDataRequests.find(channel); if (i == _channelMessageDataRequests.cend()) { if (onlyExisting) return 0; i = _channelMessageDataRequests.insert(channel, MessageDataRequests()); @@ -72,12 +74,12 @@ void ApiWrap::resolveMessageDatas() { MessageIds ids = collectMessageIds(_messageDataRequests); if (!ids.isEmpty()) { mtpRequestId req = MTP::send(MTPmessages_GetMessages(MTP_vector(ids)), rpcDone(&ApiWrap::gotMessageDatas, (ChannelData*)nullptr), RPCFailHandlerPtr(), 0, 5); - for (MessageDataRequests::iterator i = _messageDataRequests.begin(); i != _messageDataRequests.cend(); ++i) { - if (i.value().req > 0) continue; - i.value().req = req; + for (auto &request : _messageDataRequests) { + if (request.req > 0) continue; + request.req = req; } } - for (ChannelMessageDataRequests::iterator j = _channelMessageDataRequests.begin(); j != _channelMessageDataRequests.cend();) { + for (auto j = _channelMessageDataRequests.begin(); j != _channelMessageDataRequests.cend();) { if (j->isEmpty()) { j = _channelMessageDataRequests.erase(j); continue; @@ -85,9 +87,9 @@ void ApiWrap::resolveMessageDatas() { MessageIds ids = collectMessageIds(j.value()); if (!ids.isEmpty()) { mtpRequestId req = MTP::send(MTPchannels_GetMessages(j.key()->inputChannel, MTP_vector(ids)), rpcDone(&ApiWrap::gotMessageDatas, j.key()), RPCFailHandlerPtr(), 0, 5); - for (MessageDataRequests::iterator i = j->begin(); i != j->cend(); ++i) { - if (i.value().req > 0) continue; - i.value().req = req; + for (auto &request : *j) { + if (request.req > 0) continue; + request.req = req; } } ++j; @@ -128,10 +130,10 @@ void ApiWrap::gotMessageDatas(ChannelData *channel, const MTPmessages_Messages & } MessageDataRequests *requests(messageDataRequests(channel, true)); if (requests) { - for (MessageDataRequests::iterator i = requests->begin(); i != requests->cend();) { + for (auto i = requests->begin(); i != requests->cend();) { if (i.value().req == req) { - for (MessageDataRequest::Callbacks::const_iterator j = i.value().callbacks.cbegin(), e = i.value().callbacks.cend(); j != e; ++j) { - (*j)->call(channel, i.key()); + for_const (auto &callback, i.value().callbacks) { + callback->call(channel, i.key()); } i = requests->erase(i); } else { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 8845d90bd0..606ef7f14f 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -29,7 +29,7 @@ public: void init(); typedef SharedCallback RequestMessageDataCallback; - void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback *callback); + void requestMessageData(ChannelData *channel, MsgId msgId, std_::unique_ptr callback); void requestFullPeer(PeerData *peer); void requestPeer(PeerData *peer); diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 60d53120aa..4c130f4a81 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -6843,7 +6843,7 @@ void HistoryMessage::createComponents(const CreateConfig &config) { if (auto reply = Get()) { reply->replyToMsgId = config.replyTo; if (!reply->updateData(this) && App::api()) { - App::api()->requestMessageData(history()->peer->asChannel(), reply->replyToMsgId, new HistoryDependentItemCallback(fullId())); + App::api()->requestMessageData(history()->peer->asChannel(), reply->replyToMsgId, std_::make_unique(fullId())); } } if (auto via = Get()) { @@ -8192,7 +8192,7 @@ HistoryService::HistoryService(History *history, const MTPDmessageService &msg) UpdateComponents(HistoryServicePinned::Bit()); MsgId pinnedMsgId = Get()->msgId = msg.vreply_to_msg_id.v; if (!updatePinned() && App::api()) { - App::api()->requestMessageData(history->peer->asChannel(), pinnedMsgId, new HistoryDependentItemCallback(fullId())); + App::api()->requestMessageData(history->peer->asChannel(), pinnedMsgId, std_::make_unique(fullId())); } } setMessageByAction(msg.vaction); diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 44d58b0ef8..1242148f57 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -3703,7 +3703,7 @@ void HistoryWidget::applyDraft(bool parseLinks) { if (_editMsgId || _replyToId) { updateReplyEditTexts(); if (!_replyEditMsg && App::api()) { - App::api()->requestMessageData(_peer->asChannel(), _editMsgId ? _editMsgId : _replyToId, new ReplyEditMessageDataCallback()); + App::api()->requestMessageData(_peer->asChannel(), _editMsgId ? _editMsgId : _replyToId, std_::make_unique()); } } } @@ -7249,7 +7249,7 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() { update(); } if (!_pinnedBar->msg && App::api()) { - App::api()->requestMessageData(_peer->asChannel(), _pinnedBar->msgId, new ReplyEditMessageDataCallback()); + App::api()->requestMessageData(_peer->asChannel(), _pinnedBar->msgId, std_::make_unique()); } } else if (_pinnedBar) { destroyPinnedBar(); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 53cf80b790..22e24d2d94 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -3826,6 +3826,107 @@ void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) { update(); } +namespace { + +bool fwdInfoDataLoaded(const MTPMessageFwdHeader &header) { + if (header.type() != mtpc_messageFwdHeader) { + return true; + } + auto &info = header.c_messageFwdHeader(); + if (info.has_channel_id()) { + if (!App::channelLoaded(peerFromChannel(info.vchannel_id))) { + return false; + } + if (info.has_from_id() && !App::user(peerFromUser(info.vfrom_id), PeerData::MinimalLoaded)) { + return false; + } + } else { + if (info.has_from_id() && !App::userLoaded(peerFromUser(info.vfrom_id))) { + return false; + } + } + return true; +} + +bool mentionUsersLoaded(const MTPVector &entities) { + for_const (auto &entity, entities.c_vector().v) { + auto type = entity.type(); + if (type == mtpc_messageEntityMentionName) { + if (!App::userLoaded(peerFromUser(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 (!App::userLoaded(peerFromUser(inputUser.c_inputUser().vuser_id))) { + return false; + } + } + } + } + return true; +} + +enum class DataIsLoadedResult { + NotLoaded = 0, + FromNotLoaded = 1, + MentionNotLoaded = 2, + Ok = 3, +}; +DataIsLoadedResult allDataLoadedForMessage(const MTPMessage &msg) { + switch (msg.type()) { + case mtpc_message: { + const MTPDmessage &d(msg.c_message()); + if (!d.is_post() && d.has_from_id()) { + if (!App::userLoaded(peerFromUser(d.vfrom_id))) { + return DataIsLoadedResult::FromNotLoaded; + } + } + if (d.has_via_bot_id()) { + if (!App::userLoaded(peerFromUser(d.vvia_bot_id))) { + return DataIsLoadedResult::NotLoaded; + } + } + if (d.has_fwd_from() && !fwdInfoDataLoaded(d.vfwd_from)) { + return DataIsLoadedResult::NotLoaded; + } + if (d.has_entities() && !mentionUsersLoaded(d.ventities)) { + return DataIsLoadedResult::MentionNotLoaded; + } + } break; + case mtpc_messageService: { + const MTPDmessageService &d(msg.c_messageService()); + if (!d.is_post() && d.has_from_id()) { + if (!App::userLoaded(peerFromUser(d.vfrom_id))) { + return DataIsLoadedResult::FromNotLoaded; + } + } + switch (d.vaction.type()) { + case mtpc_messageActionChatAddUser: { + for_const(const MTPint &userId, d.vaction.c_messageActionChatAddUser().vusers.c_vector().v) { + if (!App::userLoaded(peerFromUser(userId))) { + return DataIsLoadedResult::NotLoaded; + } + } + } break; + case mtpc_messageActionChatJoinedByLink: { + if (!App::userLoaded(peerFromUser(d.vaction.c_messageActionChatJoinedByLink().vinviter_id))) { + return DataIsLoadedResult::NotLoaded; + } + } break; + case mtpc_messageActionChatDeleteUser: { + if (!App::userLoaded(peerFromUser(d.vaction.c_messageActionChatDeleteUser().vuser_id))) { + return DataIsLoadedResult::NotLoaded; + } + } break; + } + } break; + } + return DataIsLoadedResult::Ok; +} + +} // namespace + void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { switch (updates.type()) { case mtpc_updates: { @@ -3872,21 +3973,13 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { case mtpc_updateShortMessage: { const auto &d(updates.c_updateShortMessage()); - if (!App::userLoaded(d.vuser_id.v) || (d.has_via_bot_id() && !App::userLoaded(d.vvia_bot_id.v))) { + if (!App::userLoaded(d.vuser_id.v) + || (d.has_via_bot_id() && !App::userLoaded(d.vvia_bot_id.v)) + || (d.has_entities() && !mentionUsersLoaded(d.ventities)) + || (d.has_fwd_from() && !fwdInfoDataLoaded(d.vfwd_from))) { MTP_LOG(0, ("getDifference { good - getting user for updateShortMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); return getDifference(); } - if (d.has_fwd_from() && d.vfwd_from.type() == mtpc_messageFwdHeader) { - const auto &f(d.vfwd_from.c_messageFwdHeader()); - if (f.has_from_id() && !App::userLoaded(f.vfrom_id.v)) { - MTP_LOG(0, ("getDifference { good - getting user for updateShortMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); - return getDifference(); - } - if (f.has_channel_id() && !App::channelLoaded(f.vchannel_id.v)) { - MTP_LOG(0, ("getDifference { good - getting user for updateShortMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); - return getDifference(); - } - } if (!ptsUpdated(d.vpts.v, d.vpts_count.v, updates)) { return; } @@ -3906,22 +3999,15 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { case mtpc_updateShortChatMessage: { const auto &d(updates.c_updateShortChatMessage()); bool noFrom = !App::userLoaded(d.vfrom_id.v); - if (!App::chatLoaded(d.vchat_id.v) || noFrom || (d.has_via_bot_id() && !App::userLoaded(d.vvia_bot_id.v))) { + if (!App::chatLoaded(d.vchat_id.v) + || noFrom + || (d.has_via_bot_id() && !App::userLoaded(d.vvia_bot_id.v)) + || (d.has_entities() && !mentionUsersLoaded(d.ventities)) + || (d.has_fwd_from() && !fwdInfoDataLoaded(d.vfwd_from))) { MTP_LOG(0, ("getDifference { good - getting user for updateShortChatMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); if (noFrom && App::api()) App::api()->requestFullPeer(App::chatLoaded(d.vchat_id.v)); return getDifference(); } - if (d.has_fwd_from() && d.vfwd_from.type() == mtpc_messageFwdHeader) { - const auto &f(d.vfwd_from.c_messageFwdHeader()); - if (f.has_from_id() && !App::userLoaded(f.vfrom_id.v)) { - MTP_LOG(0, ("getDifference { good - getting user for updateShortChatMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); - return getDifference(); - } - if (f.has_channel_id() && !App::channelLoaded(f.vchannel_id.v)) { - MTP_LOG(0, ("getDifference { good - getting user for updateShortChatMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); - return getDifference(); - } - } if (!ptsUpdated(d.vpts.v, d.vpts_count.v, updates)) { return; } @@ -3948,6 +4034,9 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { feedUpdate(MTP_updateMessageID(d.vid, MTP_long(randomId))); // ignore real date if (peerId) { if (auto item = App::histItemById(peerToChannel(peerId), d.vid.v)) { + if (d.has_entities() && !mentionUsersLoaded(d.ventities)) { + api()->requestMessageData(item->history()->peer->asChannel(), item->id, nullptr); + } auto entities = d.has_entities() ? entitiesFromMTP(d.ventities.c_vector().v) : EntitiesInText(); item->setText({ text, entities }); item->updateMedia(d.has_media() ? (&d.vmedia) : nullptr); @@ -3972,73 +4061,6 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { } } -namespace { - -enum class DataIsLoadedResult { - NotLoaded = 0, - FromNotLoaded = 1, - Ok = 2, -}; -DataIsLoadedResult allDataLoadedForMessage(const MTPMessage &msg) { - switch (msg.type()) { - case mtpc_message: { - const MTPDmessage &d(msg.c_message()); - if (!d.is_post() && d.has_from_id()) { - if (!App::userLoaded(peerFromUser(d.vfrom_id))) { - return DataIsLoadedResult::FromNotLoaded; - } - } - if (d.has_via_bot_id()) { - if (!App::userLoaded(peerFromUser(d.vvia_bot_id))) { - return DataIsLoadedResult::NotLoaded; - } - } - if (d.has_fwd_from() && d.vfwd_from.type() == mtpc_messageFwdHeader) { - ChannelId fromChannelId = d.vfwd_from.c_messageFwdHeader().vchannel_id.v; - if (fromChannelId) { - if (!App::channelLoaded(peerFromChannel(fromChannelId))) { - return DataIsLoadedResult::NotLoaded; - } - } else { - if (!App::userLoaded(peerFromUser(d.vfwd_from.c_messageFwdHeader().vfrom_id))) { - return DataIsLoadedResult::NotLoaded; - } - } - } - } break; - case mtpc_messageService: { - const MTPDmessageService &d(msg.c_messageService()); - if (!d.is_post() && d.has_from_id()) { - if (!App::userLoaded(peerFromUser(d.vfrom_id))) { - return DataIsLoadedResult::FromNotLoaded; - } - } - switch (d.vaction.type()) { - case mtpc_messageActionChatAddUser: { - for_const(const MTPint &userId, d.vaction.c_messageActionChatAddUser().vusers.c_vector().v) { - if (!App::userLoaded(peerFromUser(userId))) { - return DataIsLoadedResult::NotLoaded; - } - } - } break; - case mtpc_messageActionChatJoinedByLink: { - if (!App::userLoaded(peerFromUser(d.vaction.c_messageActionChatJoinedByLink().vinviter_id))) { - return DataIsLoadedResult::NotLoaded; - } - } break; - case mtpc_messageActionChatDeleteUser: { - if (!App::userLoaded(peerFromUser(d.vaction.c_messageActionChatDeleteUser().vuser_id))) { - return DataIsLoadedResult::NotLoaded; - } - } break; - } - } break; - } - return DataIsLoadedResult::Ok; -} - -} // namespace - void MainWidget::feedUpdate(const MTPUpdate &update) { if (!MTP::authedId()) return;