mirror of
https://github.com/ars3niy/tdlib-purple
synced 2025-08-22 01:49:29 +00:00
Prevent message duplication after fetching skipped messages
This commit is contained in:
parent
41b514634b
commit
92fa3f314f
@ -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<td::td_api::Object> 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<td::td_api::getChatHistory>();
|
||||
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<td::td_api::Object> response) {
|
||||
fetchHistoryResponse(account, chatId, lastReceivedMessage, messagesFetched, std::move(response));
|
||||
[&account, chatId, messagesFetched, stopAt](uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> 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);
|
||||
}
|
||||
|
@ -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<td::td_api::message> message,
|
||||
PendingMessageQueue::MessageAction action);
|
||||
void fetchHistory(TdAccountData &account, ChatId chatId, MessageId lastReceivedMessage);
|
||||
void fetchHistory(TdAccountData &account, ChatId chatId, MessageId fetchFrom, MessageId stopAt);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -173,19 +173,7 @@ void PurpleTdClient::processUpdate(td::td_api::Object &update)
|
||||
|
||||
case td::td_api::updateChatLastMessage::ID: {
|
||||
auto &lastMessage = static_cast<td::td_api::updateChatLastMessage &>(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_ptr<td::td_api::messag
|
||||
{
|
||||
if (!message)
|
||||
return;
|
||||
|
||||
ChatId chatId = getChatId(*message);
|
||||
|
||||
auto pGap = std::find_if(m_chatGaps.begin(), m_chatGaps.end(),
|
||||
[chatId](const ChatGap &gap) { return (gap.chatId == chatId); });
|
||||
if (pGap != m_chatGaps.end()) {
|
||||
MessageId lastMessageId = pGap->lastMessage;
|
||||
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<td::td_api::messag
|
||||
handleIncomingMessage(m_data, *chat, std::move(message), PendingMessageQueue::Append);
|
||||
}
|
||||
|
||||
void PurpleTdClient::updateChatLastMessage(const td::td_api::updateChatLastMessage &lastMessage)
|
||||
{
|
||||
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
|
||||
", last seen message %" G_GINT64_FORMAT "\n",
|
||||
chatId.value(), lastMessageId.value());
|
||||
if (std::find_if(m_chatGaps.begin(), m_chatGaps.end(),
|
||||
[chatId](const ChatGap &gap) {
|
||||
return (gap.chatId == chatId);
|
||||
}) == m_chatGaps.end()) {
|
||||
m_chatGaps.emplace_back();
|
||||
m_chatGaps.back().chatId = chatId;
|
||||
m_chatGaps.back().lastMessage = lastMessageId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PurpleTdClient::sendMessage(const char *buddyName, const char *message)
|
||||
{
|
||||
SecretChatId secretChatId = purpleBuddyNameToSecretChatId(buddyName);
|
||||
|
@ -90,8 +90,7 @@ private:
|
||||
// Login sequence end
|
||||
|
||||
void onIncomingMessage(td::td_api::object_ptr<td::td_api::message> message);
|
||||
void findMessageResponse(ChatId chatId, MessageId pendingMessageId,
|
||||
td::td_api::object_ptr<td::td_api::Object> object);
|
||||
void updateChatLastMessage(const td::td_api::updateChatLastMessage &lastMessage);
|
||||
|
||||
void updateUserStatus(UserId userId, td::td_api::object_ptr<td::td_api::UserStatus> status);
|
||||
void updateUser(td::td_api::object_ptr<td::td_api::user> user);
|
||||
@ -150,6 +149,12 @@ private:
|
||||
std::vector<PurpleRoomlist *> m_pendingRoomLists;
|
||||
td::td_api::object_ptr<td::td_api::proxy> m_addedProxy;
|
||||
td::td_api::object_ptr<td::td_api::proxies> m_proxies;
|
||||
|
||||
struct ChatGap {
|
||||
ChatId chatId;
|
||||
MessageId lastMessage;
|
||||
};
|
||||
std::vector<ChatGap> m_chatGaps;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -24,11 +24,11 @@ TEST_F(MessageHistoryTest, TdlibSkipMessages)
|
||||
tgl.update(make_object<updateChatLastMessage>(
|
||||
groupChatId, nullptr, 0
|
||||
));
|
||||
tgl.verifyRequest(getChatHistory(groupChatId, 0, 0, 30, false));
|
||||
|
||||
tgl.update(make_object<updateNewMessage>(
|
||||
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6"))
|
||||
));
|
||||
tgl.verifyRequest(getChatHistory(groupChatId, 6, 0, 30, false));
|
||||
tgl.update(make_object<updateChatLastMessage>(
|
||||
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<updateNewMessage>(
|
||||
makeMessage(8, userIds[0], groupChatId, false, 8, makeTextMessage("8"))
|
||||
));
|
||||
tgl.update(make_object<updateChatLastMessage>(
|
||||
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<updateChatLastMessage>(
|
||||
groupChatId, nullptr, 0
|
||||
));
|
||||
tgl.verifyRequest(getChatHistory(groupChatId, 0, 0, 30, false));
|
||||
|
||||
tgl.update(make_object<updateNewMessage>(
|
||||
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6"))
|
||||
));
|
||||
tgl.verifyRequest(getChatHistory(groupChatId, 6, 0, 30, false));
|
||||
tgl.update(make_object<updateChatLastMessage>(
|
||||
groupChatId,
|
||||
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6")),
|
||||
|
Loading…
x
Reference in New Issue
Block a user