mirror of
https://github.com/ars3niy/tdlib-purple
synced 2025-08-22 01:49:29 +00:00
Finished fetching message history when tdlib skips messages
This commit is contained in:
parent
67962619d4
commit
41b514634b
@ -434,14 +434,18 @@ void removeGroupChat(PurpleAccount *purpleAccount, const td::td_api::chat &chat)
|
||||
|
||||
if (purpleChat)
|
||||
purple_blist_remove_chat(purpleChat);
|
||||
std::string setting = lastMessageSetting(getId(chat));
|
||||
purple_account_remove_setting(purpleAccount, setting.c_str());
|
||||
// TODO: uncomment when updateNewChat(chat_list=NULL) + updateChatChatList(non-NULL) at login
|
||||
// no longer removes chat
|
||||
//std::string setting = lastMessageSetting(getId(chat));
|
||||
//purple_account_remove_setting(purpleAccount, setting.c_str());
|
||||
}
|
||||
|
||||
void removePrivateChat(TdAccountData &account, const td::td_api::chat &chat)
|
||||
{
|
||||
std::string setting = lastMessageSetting(getId(chat));
|
||||
purple_account_remove_setting(account.purpleAccount, setting.c_str());
|
||||
// TODO: uncomment when updateNewChat(chat_list=NULL) + updateChatChatList(non-NULL) at login
|
||||
// no longer removes chat
|
||||
//std::string setting = lastMessageSetting(getId(chat));
|
||||
//purple_account_remove_setting(account.purpleAccount, setting.c_str());
|
||||
}
|
||||
|
||||
void saveChatLastMessage(TdAccountData &account, ChatId chatId, MessageId messageId)
|
||||
|
@ -8,6 +8,10 @@
|
||||
#include "call.h"
|
||||
#include <algorithm>
|
||||
|
||||
enum {
|
||||
HISTORY_MESSAGES_ABSOLUTE_LIMIT = 10000
|
||||
};
|
||||
|
||||
std::string makeNoticeWithSender(const td::td_api::chat &chat, const TgMessageInfo &message,
|
||||
const char *noticeText, PurpleAccount *account)
|
||||
{
|
||||
@ -1057,35 +1061,43 @@ static void fetchHistoryResponse(TdAccountData &account, ChatId chatId, MessageI
|
||||
td::td_api::object_ptr<td::td_api::Object> response)
|
||||
{
|
||||
MessageId requestMoreFrom = MessageId::invalid;
|
||||
const td::td_api::chat *chat = account.getChat(chatId);
|
||||
|
||||
if (response && (response->get_id() == td::td_api::messages::ID)) {
|
||||
td::td_api::messages &messages = static_cast<td::td_api::messages &>(*response);
|
||||
if (!messages.messages_.empty()) {
|
||||
const td::td_api::chat *chat = account.getChat(chatId);
|
||||
auto stop = messages.messages_.begin();
|
||||
MessageId lastMessageId = MessageId::invalid;
|
||||
for (; stop != messages.messages_.end(); ++stop) {
|
||||
td::td_api::object_ptr<td::td_api::message> message = std::move(*stop);
|
||||
if (!message ||
|
||||
(lastReceivedMessage.valid() && (getId(*message) == lastReceivedMessage)) ||
|
||||
(!lastReceivedMessage.valid() && (messagesFetched == 100)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
messagesFetched++;
|
||||
lastMessageId = getId(*message);
|
||||
if (chat)
|
||||
handleIncomingMessage(account, *chat, std::move(message), PendingMessageQueue::Prepend);
|
||||
purple_debug_misc(config::pluginId, "Fetched %zu messages for chat %" G_GINT64_FORMAT "\n",
|
||||
messages.messages_.size(), chatId.value());
|
||||
auto stop = messages.messages_.begin();
|
||||
MessageId lastMessageId = MessageId::invalid;
|
||||
for (; stop != messages.messages_.end(); ++stop) {
|
||||
td::td_api::object_ptr<td::td_api::message> message = std::move(*stop);
|
||||
if (!message) {
|
||||
purple_debug_warning(config::pluginId, "Erroneous message in history, stopping\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (stop == messages.messages_.end())
|
||||
requestMoreFrom = lastMessageId;
|
||||
if (lastReceivedMessage.valid() && (getId(*message) == lastReceivedMessage)) {
|
||||
purple_debug_misc(config::pluginId, "Found message %" G_GINT64_FORMAT ", stopping\n",
|
||||
lastReceivedMessage.value());
|
||||
break;
|
||||
}
|
||||
if ((!lastReceivedMessage.valid() && (messagesFetched == 100)) ||
|
||||
(messagesFetched == HISTORY_MESSAGES_ABSOLUTE_LIMIT))
|
||||
{
|
||||
purple_debug_misc(config::pluginId, "Reached history limit, stopping\n");
|
||||
break;
|
||||
}
|
||||
messagesFetched++;
|
||||
lastMessageId = getId(*message);
|
||||
if (chat)
|
||||
handleIncomingMessage(account, *chat, std::move(message), PendingMessageQueue::Prepend);
|
||||
}
|
||||
|
||||
if (stop == messages.messages_.end())
|
||||
requestMoreFrom = lastMessageId;
|
||||
} else {
|
||||
std::string message = formatMessage(_("Failed to fetch earlier messages: {}"),
|
||||
getDisplayedError(response));
|
||||
purple_debug_warning(config::pluginId, "%s\n", message.c_str());
|
||||
const td::td_api::chat *chat = account.getChat(chatId);
|
||||
if (chat)
|
||||
showChatNotification(account, *chat, message.c_str(), PURPLE_MESSAGE_ERROR);
|
||||
}
|
||||
@ -1093,6 +1105,8 @@ static void fetchHistoryResponse(TdAccountData &account, ChatId chatId, MessageI
|
||||
if (requestMoreFrom.valid())
|
||||
fetchHistoryRequest(account, chatId, messagesFetched, requestMoreFrom, lastReceivedMessage);
|
||||
else {
|
||||
purple_debug_misc(config::pluginId, "Done fetching history for chat %" G_GINT64_FORMAT "\n",
|
||||
chatId.value());
|
||||
std::vector<IncomingMessage> readyMessages;
|
||||
account.pendingMessages.setChatReady(chatId, readyMessages);
|
||||
showMessages(readyMessages, account);
|
||||
@ -1108,6 +1122,8 @@ static void fetchHistoryRequest(TdAccountData &account, ChatId chatId, unsigned
|
||||
request->limit_ = 30;
|
||||
request->offset_ = 0;
|
||||
request->only_local_ = false;
|
||||
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));
|
||||
|
@ -176,11 +176,15 @@ void PurpleTdClient::processUpdate(td::td_api::Object &update)
|
||||
ChatId chatId = getChatId(lastMessage);
|
||||
m_data.updateChatOrder(chatId, lastMessage.order_);
|
||||
if (lastMessage.last_message_)
|
||||
saveChatLastMessage(m_data, getChatId(lastMessage), getId(*lastMessage.last_message_));
|
||||
saveChatLastMessage(m_data, chatId, getId(*lastMessage.last_message_));
|
||||
else {
|
||||
MessageId lastMessageId = getChatLastMessage(m_data, chatId);
|
||||
if (lastMessageId.valid())
|
||||
{}//fetchHistory(m_data, chatId, lastMessageId);
|
||||
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;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ add_executable(tests EXCLUDE_FROM_ALL
|
||||
secret-chat-test.cpp
|
||||
message-split-test.cpp
|
||||
message-order-test.cpp
|
||||
message-history-test.cpp
|
||||
test-transceiver.cpp
|
||||
libpurple-mock.cpp
|
||||
printout.cpp
|
||||
|
@ -17,6 +17,7 @@ void CommTest::SetUp()
|
||||
connection = new PurpleConnection;
|
||||
connection->state = PURPLE_DISCONNECTED;
|
||||
connection->account = account;
|
||||
purple_connection_set_protocol_data(connection, NULL);
|
||||
account->gc = connection;
|
||||
prpl.discardEvents();
|
||||
setUiName("Pidgin");
|
||||
|
130
test/message-history-test.cpp
Normal file
130
test/message-history-test.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
#include "supergroup-test.h"
|
||||
|
||||
class MessageHistoryTest: public SupergroupTest {
|
||||
protected:
|
||||
const std::string userNameInChat = userFirstNames[0] + " " + userLastNames[0];
|
||||
};
|
||||
|
||||
TEST_F(MessageHistoryTest, TdlibSkipMessages_LastMessageUnknown)
|
||||
{
|
||||
loginWithSupergroup();
|
||||
|
||||
tgl.update(make_object<updateChatLastMessage>(
|
||||
groupChatId, nullptr, 0
|
||||
));
|
||||
tgl.verifyNoRequests();
|
||||
}
|
||||
|
||||
TEST_F(MessageHistoryTest, TdlibSkipMessages)
|
||||
{
|
||||
const int purpleChatId = 1;
|
||||
purple_account_set_string(account, ("last-message-chat" + std::to_string(groupChatId)).c_str(), "1");
|
||||
loginWithSupergroup();
|
||||
|
||||
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.update(make_object<updateChatLastMessage>(
|
||||
groupChatId,
|
||||
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6")),
|
||||
0
|
||||
));
|
||||
|
||||
tgl.update(make_object<updateNewMessage>(
|
||||
makeMessage(7, userIds[0], groupChatId, false, 7, makeTextMessage("7"))
|
||||
));
|
||||
tgl.update(make_object<updateChatLastMessage>(
|
||||
groupChatId,
|
||||
makeMessage(7, userIds[0], groupChatId, false, 7, makeTextMessage("7")),
|
||||
0
|
||||
));
|
||||
prpl.verifyNoEvents();
|
||||
tgl.verifyNoRequests();
|
||||
|
||||
std::vector<object_ptr<message>> history;
|
||||
history.push_back(makeMessage(5, userIds[0], groupChatId, false, 5, makeTextMessage("5")));
|
||||
history.push_back(makeMessage(4, userIds[0], groupChatId, false, 4, makeTextMessage("4")));
|
||||
tgl.reply(make_object<messages>(history.size(), std::move(history)));
|
||||
prpl.verifyNoEvents();
|
||||
tgl.verifyRequest(getChatHistory(groupChatId, 4, 0, 30, false));
|
||||
|
||||
history.clear();
|
||||
history.push_back(makeMessage(3, userIds[0], groupChatId, false, 3, makeTextMessage("3")));
|
||||
history.push_back(makeMessage(2, userIds[0], groupChatId, false, 2, makeTextMessage("2")));
|
||||
history.push_back(makeMessage(1, userIds[0], groupChatId, false, 1, makeTextMessage("1")));
|
||||
tgl.reply(make_object<messages>(history.size(), std::move(history)));
|
||||
|
||||
prpl.verifyEvents(
|
||||
ServGotJoinedChatEvent(connection, purpleChatId, groupChatPurpleName, groupChatTitle),
|
||||
ChatSetTopicEvent(groupChatPurpleName, "", ""),
|
||||
ChatClearUsersEvent(groupChatPurpleName),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "2", PURPLE_MESSAGE_RECV, 2),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "3", PURPLE_MESSAGE_RECV, 3),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "4", PURPLE_MESSAGE_RECV, 4),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "5", PURPLE_MESSAGE_RECV, 5),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "6", PURPLE_MESSAGE_RECV, 6),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "7", PURPLE_MESSAGE_RECV, 7)
|
||||
);
|
||||
tgl.verifyRequest(viewMessages(groupChatId, {6, 7, 5, 4, 3, 2}, true));
|
||||
|
||||
ASSERT_EQ(std::string("7"), std::string(purple_account_get_string(
|
||||
account, ("last-message-chat" + std::to_string(groupChatId)).c_str(), "")));
|
||||
}
|
||||
|
||||
TEST_F(MessageHistoryTest, TdlibSkipMessages_FlushAtLogout)
|
||||
{
|
||||
const int purpleChatId = 1;
|
||||
purple_account_set_string(account, ("last-message-chat" + std::to_string(groupChatId)).c_str(), "1");
|
||||
loginWithSupergroup();
|
||||
|
||||
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.update(make_object<updateChatLastMessage>(
|
||||
groupChatId,
|
||||
makeMessage(6, userIds[0], groupChatId, false, 6, makeTextMessage("6")),
|
||||
0
|
||||
));
|
||||
prpl.verifyNoEvents();
|
||||
tgl.verifyNoRequests();
|
||||
|
||||
std::vector<object_ptr<message>> history;
|
||||
history.push_back(makeMessage(5, userIds[0], groupChatId, false, 5, makeTextMessage("5")));
|
||||
history.push_back(makeMessage(4, userIds[0], groupChatId, false, 4, makeTextMessage("4")));
|
||||
tgl.reply(make_object<messages>(history.size(), std::move(history)));
|
||||
prpl.verifyNoEvents();
|
||||
tgl.verifyRequest(getChatHistory(groupChatId, 4, 0, 30, false));
|
||||
|
||||
history.clear();
|
||||
history.push_back(makeMessage(3, userIds[0], groupChatId, false, 3, makeTextMessage("3")));
|
||||
history.push_back(makeMessage(2, userIds[0], groupChatId, false, 2, makeTextMessage("2")));
|
||||
tgl.reply(make_object<messages>(history.size(), std::move(history)));
|
||||
prpl.verifyNoEvents();
|
||||
tgl.verifyRequest(getChatHistory(groupChatId, 2, 0, 30, false));
|
||||
|
||||
pluginInfo().close(connection);
|
||||
prpl.verifyEvents(
|
||||
ServGotJoinedChatEvent(connection, purpleChatId, groupChatPurpleName, groupChatTitle),
|
||||
ChatSetTopicEvent(groupChatPurpleName, "", ""),
|
||||
ChatClearUsersEvent(groupChatPurpleName),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "2", PURPLE_MESSAGE_RECV, 2),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "3", PURPLE_MESSAGE_RECV, 3),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "4", PURPLE_MESSAGE_RECV, 4),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "5", PURPLE_MESSAGE_RECV, 5),
|
||||
ServGotChatEvent(connection, purpleChatId, userNameInChat, "6", PURPLE_MESSAGE_RECV, 6)
|
||||
);
|
||||
tgl.verifyRequest(viewMessages(groupChatId, {6, 5, 4, 3, 2}, true));
|
||||
|
||||
ASSERT_EQ(std::string("6"), std::string(purple_account_get_string(
|
||||
account, ("last-message-chat" + std::to_string(groupChatId)).c_str(), "")));
|
||||
}
|
@ -1,20 +1,8 @@
|
||||
#include "fixture.h"
|
||||
#include "supergroup-test.h"
|
||||
#include <glib/gstrfuncs.h>
|
||||
|
||||
static const char *NotificationWho = " ";
|
||||
|
||||
class SupergroupTest: public CommTest {
|
||||
protected:
|
||||
const int32_t groupId = 700;
|
||||
const int64_t groupChatId = -7000;
|
||||
const std::string groupChatTitle = "Title";
|
||||
const std::string groupChatPurpleName = "chat" + std::to_string(groupChatId);
|
||||
|
||||
void loginWithSupergroup(object_ptr<supergroupFullInfo> fullInfo = nullptr,
|
||||
object_ptr<chatMembers> recentMembers = nullptr,
|
||||
object_ptr<chatMembers> administrators = nullptr);
|
||||
};
|
||||
|
||||
void SupergroupTest::loginWithSupergroup(object_ptr<supergroupFullInfo> fullInfo,
|
||||
object_ptr<chatMembers> recentMembers,
|
||||
object_ptr<chatMembers> administrators)
|
||||
|
18
test/supergroup-test.h
Normal file
18
test/supergroup-test.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef _SUPERGROUP_TEST_H
|
||||
#define _SUPERGROUP_TEST_H
|
||||
|
||||
#include "fixture.h"
|
||||
|
||||
class SupergroupTest: public CommTest {
|
||||
protected:
|
||||
const int32_t groupId = 700;
|
||||
const int64_t groupChatId = -7000;
|
||||
const std::string groupChatTitle = "Title";
|
||||
const std::string groupChatPurpleName = "chat" + std::to_string(groupChatId);
|
||||
|
||||
void loginWithSupergroup(object_ptr<supergroupFullInfo> fullInfo = nullptr,
|
||||
object_ptr<chatMembers> recentMembers = nullptr,
|
||||
object_ptr<chatMembers> administrators = nullptr);
|
||||
};
|
||||
|
||||
#endif
|
@ -457,6 +457,15 @@ static void compare(const createNewSecretChat &actual, const createNewSecretChat
|
||||
COMPARE(user_id_);
|
||||
}
|
||||
|
||||
static void compare(const getChatHistory &actual, const getChatHistory &expected)
|
||||
{
|
||||
COMPARE(chat_id_);
|
||||
COMPARE(from_message_id_);
|
||||
COMPARE(offset_);
|
||||
COMPARE(limit_);
|
||||
COMPARE(only_local_);
|
||||
}
|
||||
|
||||
static void compareRequests(const Function &actual, const Function &expected,
|
||||
std::vector<std::string> &m_inputPhotoPaths)
|
||||
{
|
||||
@ -508,6 +517,7 @@ static void compareRequests(const Function &actual, const Function &expected,
|
||||
C(searchPublicChat)
|
||||
C(joinChat)
|
||||
C(createNewSecretChat)
|
||||
C(getChatHistory)
|
||||
default: ASSERT_TRUE(false) << "Unsupported request " << requestToString(actual);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user