mirror of
https://github.com/ars3niy/tdlib-purple
synced 2025-08-22 09:57:52 +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,
|
static void fetchHistoryRequest(TdAccountData &account, ChatId chatId, unsigned messagesFetched,
|
||||||
MessageId fetchBackFrom, MessageId lastReceivedMessage);
|
MessageId fetchBackFrom, MessageId lastReceivedMessage);
|
||||||
|
|
||||||
static void fetchHistoryResponse(TdAccountData &account, ChatId chatId, MessageId lastReceivedMessage,
|
static void fetchHistoryResponse(TdAccountData &account, ChatId chatId, MessageId stopAt,
|
||||||
unsigned messagesFetched,
|
unsigned messagesFetched,
|
||||||
td::td_api::object_ptr<td::td_api::Object> response)
|
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");
|
purple_debug_warning(config::pluginId, "Erroneous message in history, stopping\n");
|
||||||
break;
|
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",
|
purple_debug_misc(config::pluginId, "Found message %" G_GINT64_FORMAT ", stopping\n",
|
||||||
lastReceivedMessage.value());
|
stopAt.value());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((!lastReceivedMessage.valid() && (messagesFetched == 100)) ||
|
if ((!stopAt.valid() && (messagesFetched == 100)) ||
|
||||||
(messagesFetched == HISTORY_MESSAGES_ABSOLUTE_LIMIT))
|
(messagesFetched == HISTORY_MESSAGES_ABSOLUTE_LIMIT))
|
||||||
{
|
{
|
||||||
purple_debug_misc(config::pluginId, "Reached history limit, stopping\n");
|
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())
|
if (requestMoreFrom.valid())
|
||||||
fetchHistoryRequest(account, chatId, messagesFetched, requestMoreFrom, lastReceivedMessage);
|
fetchHistoryRequest(account, chatId, messagesFetched, requestMoreFrom, stopAt);
|
||||||
else {
|
else {
|
||||||
purple_debug_misc(config::pluginId, "Done fetching history for chat %" G_GINT64_FORMAT "\n",
|
purple_debug_misc(config::pluginId, "Done fetching history for chat %" G_GINT64_FORMAT "\n",
|
||||||
chatId.value());
|
chatId.value());
|
||||||
@ -1114,7 +1114,7 @@ static void fetchHistoryResponse(TdAccountData &account, ChatId chatId, MessageI
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void fetchHistoryRequest(TdAccountData &account, ChatId chatId, unsigned messagesFetched,
|
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>();
|
auto request = td::td_api::make_object<td::td_api::getChatHistory>();
|
||||||
request->chat_id_ = chatId.value();
|
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
|
purple_debug_misc(config::pluginId, "Requesting history for chat %" G_GINT64_FORMAT
|
||||||
" starting from %" G_GINT64_FORMAT "\n", chatId.value(), fetchBackFrom.value());
|
" starting from %" G_GINT64_FORMAT "\n", chatId.value(), fetchBackFrom.value());
|
||||||
account.transceiver.sendQuery(std::move(request),
|
account.transceiver.sendQuery(std::move(request),
|
||||||
[&account, chatId, messagesFetched, lastReceivedMessage](uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> response) {
|
[&account, chatId, messagesFetched, stopAt](uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> response) {
|
||||||
fetchHistoryResponse(account, chatId, lastReceivedMessage, messagesFetched, std::move(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))
|
if (!account.pendingMessages.isChatReady(chatId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
account.pendingMessages.setChatNotReady(chatId);
|
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,
|
void handleIncomingMessage(TdAccountData &account, const td::td_api::chat &chat,
|
||||||
td::td_api::object_ptr<td::td_api::message> message,
|
td::td_api::object_ptr<td::td_api::message> message,
|
||||||
PendingMessageQueue::MessageAction action);
|
PendingMessageQueue::MessageAction action);
|
||||||
void fetchHistory(TdAccountData &account, ChatId chatId, MessageId lastReceivedMessage);
|
void fetchHistory(TdAccountData &account, ChatId chatId, MessageId fetchFrom, MessageId stopAt);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -173,19 +173,7 @@ void PurpleTdClient::processUpdate(td::td_api::Object &update)
|
|||||||
|
|
||||||
case td::td_api::updateChatLastMessage::ID: {
|
case td::td_api::updateChatLastMessage::ID: {
|
||||||
auto &lastMessage = static_cast<td::td_api::updateChatLastMessage &>(update);
|
auto &lastMessage = static_cast<td::td_api::updateChatLastMessage &>(update);
|
||||||
ChatId chatId = getChatId(lastMessage);
|
updateChatLastMessage(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -943,8 +931,20 @@ void PurpleTdClient::onIncomingMessage(td::td_api::object_ptr<td::td_api::messag
|
|||||||
{
|
{
|
||||||
if (!message)
|
if (!message)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatId chatId = getChatId(*message);
|
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);
|
const td::td_api::chat *chat = m_data.getChat(chatId);
|
||||||
if (!chat) {
|
if (!chat) {
|
||||||
purple_debug_warning(config::pluginId, "Received message with unknown chat id %" G_GINT64_FORMAT "\n",
|
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);
|
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)
|
int PurpleTdClient::sendMessage(const char *buddyName, const char *message)
|
||||||
{
|
{
|
||||||
SecretChatId secretChatId = purpleBuddyNameToSecretChatId(buddyName);
|
SecretChatId secretChatId = purpleBuddyNameToSecretChatId(buddyName);
|
||||||
|
@ -90,8 +90,7 @@ private:
|
|||||||
// Login sequence end
|
// Login sequence end
|
||||||
|
|
||||||
void onIncomingMessage(td::td_api::object_ptr<td::td_api::message> message);
|
void onIncomingMessage(td::td_api::object_ptr<td::td_api::message> message);
|
||||||
void findMessageResponse(ChatId chatId, MessageId pendingMessageId,
|
void updateChatLastMessage(const td::td_api::updateChatLastMessage &lastMessage);
|
||||||
td::td_api::object_ptr<td::td_api::Object> object);
|
|
||||||
|
|
||||||
void updateUserStatus(UserId userId, td::td_api::object_ptr<td::td_api::UserStatus> status);
|
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);
|
void updateUser(td::td_api::object_ptr<td::td_api::user> user);
|
||||||
@ -150,6 +149,12 @@ private:
|
|||||||
std::vector<PurpleRoomlist *> m_pendingRoomLists;
|
std::vector<PurpleRoomlist *> m_pendingRoomLists;
|
||||||
td::td_api::object_ptr<td::td_api::proxy> m_addedProxy;
|
td::td_api::object_ptr<td::td_api::proxy> m_addedProxy;
|
||||||
td::td_api::object_ptr<td::td_api::proxies> m_proxies;
|
td::td_api::object_ptr<td::td_api::proxies> m_proxies;
|
||||||
|
|
||||||
|
struct ChatGap {
|
||||||
|
ChatId chatId;
|
||||||
|
MessageId lastMessage;
|
||||||
|
};
|
||||||
|
std::vector<ChatGap> m_chatGaps;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,11 +24,11 @@ TEST_F(MessageHistoryTest, TdlibSkipMessages)
|
|||||||
tgl.update(make_object<updateChatLastMessage>(
|
tgl.update(make_object<updateChatLastMessage>(
|
||||||
groupChatId, nullptr, 0
|
groupChatId, nullptr, 0
|
||||||
));
|
));
|
||||||
tgl.verifyRequest(getChatHistory(groupChatId, 0, 0, 30, false));
|
|
||||||
|
|
||||||
tgl.update(make_object<updateNewMessage>(
|
tgl.update(make_object<updateNewMessage>(
|
||||||
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6"))
|
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6"))
|
||||||
));
|
));
|
||||||
|
tgl.verifyRequest(getChatHistory(groupChatId, 6, 0, 30, false));
|
||||||
tgl.update(make_object<updateChatLastMessage>(
|
tgl.update(make_object<updateChatLastMessage>(
|
||||||
groupChatId,
|
groupChatId,
|
||||||
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6")),
|
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));
|
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(), "")));
|
account, ("last-message-chat" + std::to_string(groupChatId)).c_str(), "")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,11 +98,11 @@ TEST_F(MessageHistoryTest, TdlibSkipMessages_FlushAtLogout)
|
|||||||
tgl.update(make_object<updateChatLastMessage>(
|
tgl.update(make_object<updateChatLastMessage>(
|
||||||
groupChatId, nullptr, 0
|
groupChatId, nullptr, 0
|
||||||
));
|
));
|
||||||
tgl.verifyRequest(getChatHistory(groupChatId, 0, 0, 30, false));
|
|
||||||
|
|
||||||
tgl.update(make_object<updateNewMessage>(
|
tgl.update(make_object<updateNewMessage>(
|
||||||
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6"))
|
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6"))
|
||||||
));
|
));
|
||||||
|
tgl.verifyRequest(getChatHistory(groupChatId, 6, 0, 30, false));
|
||||||
tgl.update(make_object<updateChatLastMessage>(
|
tgl.update(make_object<updateChatLastMessage>(
|
||||||
groupChatId,
|
groupChatId,
|
||||||
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6")),
|
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6")),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user