Requesting difference or messages when users from mentions not loaded.

This commit is contained in:
John Preston 2016-05-09 13:07:25 +03:00
parent 90a3a80bf6
commit b28e9a6167
5 changed files with 135 additions and 111 deletions

View File

@ -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<RequestMessageDataCallback> 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<MTPint>(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<MTPint>(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 {

View File

@ -29,7 +29,7 @@ public:
void init();
typedef SharedCallback<void, ChannelData*, MsgId> RequestMessageDataCallback;
void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback *callback);
void requestMessageData(ChannelData *channel, MsgId msgId, std_::unique_ptr<RequestMessageDataCallback> callback);
void requestFullPeer(PeerData *peer);
void requestPeer(PeerData *peer);

View File

@ -6843,7 +6843,7 @@ void HistoryMessage::createComponents(const CreateConfig &config) {
if (auto reply = Get<HistoryMessageReply>()) {
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<HistoryDependentItemCallback>(fullId()));
}
}
if (auto via = Get<HistoryMessageVia>()) {
@ -8192,7 +8192,7 @@ HistoryService::HistoryService(History *history, const MTPDmessageService &msg)
UpdateComponents(HistoryServicePinned::Bit());
MsgId pinnedMsgId = Get<HistoryServicePinned>()->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<HistoryDependentItemCallback>(fullId()));
}
}
setMessageByAction(msg.vaction);

View File

@ -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<ReplyEditMessageDataCallback>());
}
}
}
@ -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<ReplyEditMessageDataCallback>());
}
} else if (_pinnedBar) {
destroyPinnedBar();

View File

@ -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<MTPMessageEntity> &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;