diff --git a/receiving.cpp b/receiving.cpp index 3f69e13..a5f62d9 100644 --- a/receiving.cpp +++ b/receiving.cpp @@ -1056,7 +1056,7 @@ void handleIncomingMessage(TdAccountData &account, const td::td_api::chat &chat, static void fetchHistoryRequest(TdAccountData &account, ChatId chatId, unsigned messagesFetched, MessageId fetchBackFrom, MessageId lastReceivedMessage); -static void fetchHistoryResponse(TdAccountData &account, ChatId chatId, MessageId lastReceivedMessage, +static void fetchHistoryResponse(TdAccountData &account, ChatId chatId, MessageId stopAt, unsigned messagesFetched, td::td_api::object_ptr response) { @@ -1075,12 +1075,12 @@ static void fetchHistoryResponse(TdAccountData &account, ChatId chatId, MessageI purple_debug_warning(config::pluginId, "Erroneous message in history, stopping\n"); break; } - if (lastReceivedMessage.valid() && (getId(*message) == lastReceivedMessage)) { + if (stopAt.valid() && (getId(*message) == stopAt)) { purple_debug_misc(config::pluginId, "Found message %" G_GINT64_FORMAT ", stopping\n", - lastReceivedMessage.value()); + stopAt.value()); break; } - if ((!lastReceivedMessage.valid() && (messagesFetched == 100)) || + if ((!stopAt.valid() && (messagesFetched == 100)) || (messagesFetched == HISTORY_MESSAGES_ABSOLUTE_LIMIT)) { purple_debug_misc(config::pluginId, "Reached history limit, stopping\n"); @@ -1103,7 +1103,7 @@ static void fetchHistoryResponse(TdAccountData &account, ChatId chatId, MessageI } if (requestMoreFrom.valid()) - fetchHistoryRequest(account, chatId, messagesFetched, requestMoreFrom, lastReceivedMessage); + fetchHistoryRequest(account, chatId, messagesFetched, requestMoreFrom, stopAt); else { purple_debug_misc(config::pluginId, "Done fetching history for chat %" G_GINT64_FORMAT "\n", chatId.value()); @@ -1114,7 +1114,7 @@ static void fetchHistoryResponse(TdAccountData &account, ChatId chatId, MessageI } static void fetchHistoryRequest(TdAccountData &account, ChatId chatId, unsigned messagesFetched, - MessageId fetchBackFrom, MessageId lastReceivedMessage) + MessageId fetchBackFrom, MessageId stopAt) { auto request = td::td_api::make_object(); request->chat_id_ = chatId.value(); @@ -1125,16 +1125,16 @@ static void fetchHistoryRequest(TdAccountData &account, ChatId chatId, unsigned purple_debug_misc(config::pluginId, "Requesting history for chat %" G_GINT64_FORMAT " starting from %" G_GINT64_FORMAT "\n", chatId.value(), fetchBackFrom.value()); account.transceiver.sendQuery(std::move(request), - [&account, chatId, messagesFetched, lastReceivedMessage](uint64_t requestId, td::td_api::object_ptr response) { - fetchHistoryResponse(account, chatId, lastReceivedMessage, messagesFetched, std::move(response)); + [&account, chatId, messagesFetched, stopAt](uint64_t requestId, td::td_api::object_ptr response) { + fetchHistoryResponse(account, chatId, stopAt, messagesFetched, std::move(response)); }); } -void fetchHistory(TdAccountData &account, ChatId chatId, MessageId lastReceivedMessage) +void fetchHistory(TdAccountData &account, ChatId chatId, MessageId fetchFrom, MessageId stopAt) { if (!account.pendingMessages.isChatReady(chatId)) return; account.pendingMessages.setChatNotReady(chatId); - fetchHistoryRequest(account, chatId, 0, MessageId::invalid, lastReceivedMessage); + fetchHistoryRequest(account, chatId, 0, fetchFrom, stopAt); } diff --git a/receiving.h b/receiving.h index eedf2d4..5c7454d 100644 --- a/receiving.h +++ b/receiving.h @@ -53,7 +53,7 @@ void checkMessageReady(const IncomingMessage *message, TdTransceiver &transceive void handleIncomingMessage(TdAccountData &account, const td::td_api::chat &chat, td::td_api::object_ptr message, PendingMessageQueue::MessageAction action); -void fetchHistory(TdAccountData &account, ChatId chatId, MessageId lastReceivedMessage); +void fetchHistory(TdAccountData &account, ChatId chatId, MessageId fetchFrom, MessageId stopAt); #endif diff --git a/td-client.cpp b/td-client.cpp index 5221a74..807a57d 100644 --- a/td-client.cpp +++ b/td-client.cpp @@ -173,19 +173,7 @@ void PurpleTdClient::processUpdate(td::td_api::Object &update) case td::td_api::updateChatLastMessage::ID: { auto &lastMessage = static_cast(update); - ChatId chatId = getChatId(lastMessage); - m_data.updateChatOrder(chatId, lastMessage.order_); - if (lastMessage.last_message_) - saveChatLastMessage(m_data, chatId, getId(*lastMessage.last_message_)); - else { - MessageId lastMessageId = getChatLastMessage(m_data, chatId); - if (lastMessageId.valid()) { - purple_debug_misc(config::pluginId, "Skipped messages detected for chat %" G_GINT64_FORMAT - ", fetching history until %" G_GINT64_FORMAT "\n", - chatId.value(), lastMessageId.value()); - fetchHistory(m_data, chatId, lastMessageId); - } - } + updateChatLastMessage(lastMessage); break; } @@ -943,8 +931,20 @@ void PurpleTdClient::onIncomingMessage(td::td_api::object_ptrlastMessage; + m_chatGaps.erase(pGap); + purple_debug_misc(config::pluginId, + "Fetching skipped messages for chat %" G_GINT64_FORMAT + " between %" G_GINT64_FORMAT " and %" G_GINT64_FORMAT "\n", + chatId.value(), lastMessageId.value(), getId(*message).value()); + fetchHistory(m_data, chatId, getId(*message), lastMessageId); + } + const td::td_api::chat *chat = m_data.getChat(chatId); if (!chat) { purple_debug_warning(config::pluginId, "Received message with unknown chat id %" G_GINT64_FORMAT "\n", @@ -955,6 +955,31 @@ void PurpleTdClient::onIncomingMessage(td::td_api::object_ptr message); - void findMessageResponse(ChatId chatId, MessageId pendingMessageId, - td::td_api::object_ptr object); + void updateChatLastMessage(const td::td_api::updateChatLastMessage &lastMessage); void updateUserStatus(UserId userId, td::td_api::object_ptr status); void updateUser(td::td_api::object_ptr user); @@ -150,6 +149,12 @@ private: std::vector m_pendingRoomLists; td::td_api::object_ptr m_addedProxy; td::td_api::object_ptr m_proxies; + + struct ChatGap { + ChatId chatId; + MessageId lastMessage; + }; + std::vector m_chatGaps; }; #endif diff --git a/test/message-history-test.cpp b/test/message-history-test.cpp index c0c47c0..35514ca 100644 --- a/test/message-history-test.cpp +++ b/test/message-history-test.cpp @@ -24,11 +24,11 @@ TEST_F(MessageHistoryTest, TdlibSkipMessages) tgl.update(make_object( groupChatId, nullptr, 0 )); - tgl.verifyRequest(getChatHistory(groupChatId, 0, 0, 30, false)); tgl.update(make_object( makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6")) )); + tgl.verifyRequest(getChatHistory(groupChatId, 6, 0, 30, false)); tgl.update(make_object( groupChatId, makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6")), @@ -72,7 +72,20 @@ TEST_F(MessageHistoryTest, TdlibSkipMessages) ); tgl.verifyRequest(viewMessages(groupChatId, {6, 7, 5, 4, 3, 2}, true)); - ASSERT_EQ(std::string("7"), std::string(purple_account_get_string( + tgl.update(make_object( + makeMessage(8, userIds[0], groupChatId, false, 8, makeTextMessage("8")) + )); + tgl.update(make_object( + groupChatId, + makeMessage(8, userIds[0], groupChatId, false, 8, makeTextMessage("8")), + 0 + )); + prpl.verifyEvents( + ServGotChatEvent(connection, purpleChatId, userNameInChat, "8", PURPLE_MESSAGE_RECV, 8) + ); + tgl.verifyRequest(viewMessages(groupChatId, {8}, true)); + + ASSERT_EQ(std::string("8"), std::string(purple_account_get_string( account, ("last-message-chat" + std::to_string(groupChatId)).c_str(), ""))); } @@ -85,11 +98,11 @@ TEST_F(MessageHistoryTest, TdlibSkipMessages_FlushAtLogout) tgl.update(make_object( groupChatId, nullptr, 0 )); - tgl.verifyRequest(getChatHistory(groupChatId, 0, 0, 30, false)); tgl.update(make_object( makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6")) )); + tgl.verifyRequest(getChatHistory(groupChatId, 6, 0, 30, false)); tgl.update(make_object( groupChatId, makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6")),