2
0
mirror of https://github.com/ars3niy/tdlib-purple synced 2025-08-22 18:07:26 +00:00

Send read receipts only when conversation has focus

This commit is contained in:
Arseniy Lartsev 2021-01-01 14:47:21 +01:00
parent ec01fa2b5f
commit c8b55eb887
11 changed files with 81 additions and 44 deletions

View File

@ -878,10 +878,27 @@ void TdAccountData::removeActiveCall()
void TdAccountData::addPendingReadReceipt(ChatId chatId, MessageId messageId) void TdAccountData::addPendingReadReceipt(ChatId chatId, MessageId messageId)
{ {
m_pendingReadReceipts.push_back(ReadReceipt{chatId, messageId}); auto pChatReceipts = std::find_if(m_pendingReadReceipts.begin(), m_pendingReadReceipts.end(),
[chatId](const std::vector<ReadReceipt> &receipts) {
return (!receipts.empty() && (receipts[0].chatId == chatId));
});
if (pChatReceipts != m_pendingReadReceipts.end())
pChatReceipts->push_back(ReadReceipt{chatId, messageId});
else {
m_pendingReadReceipts.emplace_back();
m_pendingReadReceipts.back().push_back(ReadReceipt{chatId, messageId});
}
} }
void TdAccountData::extractPendingReadReceipts(std::vector<ReadReceipt>& receipts) void TdAccountData::extractPendingReadReceipts(ChatId chatId, std::vector<ReadReceipt>& receipts)
{ {
receipts = std::move(m_pendingReadReceipts); auto pChatReceipts = std::find_if(m_pendingReadReceipts.begin(), m_pendingReadReceipts.end(),
[chatId](const std::vector<ReadReceipt> &receipts) {
return (!receipts.empty() && (receipts[0].chatId == chatId));
});
if (pChatReceipts != m_pendingReadReceipts.end()) {
receipts = std::move(*pChatReceipts);
m_pendingReadReceipts.erase(pChatReceipts);
} else
receipts.clear();
} }

View File

@ -3,6 +3,7 @@
#include "buildopt.h" #include "buildopt.h"
#include "identifiers.h" #include "identifiers.h"
#include "transceiver.h"
#include <td/telegram/td_api.h> #include <td/telegram/td_api.h>
#include <map> #include <map>
@ -287,7 +288,9 @@ public:
} options; } options;
PurpleAccount *const purpleAccount; PurpleAccount *const purpleAccount;
TdAccountData(PurpleAccount *purpleAccount) : purpleAccount(purpleAccount) {} TdTransceiver &transceiver;
TdAccountData(PurpleAccount *purpleAccount, TdTransceiver &transceiver)
: purpleAccount(purpleAccount), transceiver(transceiver) {}
void updateUser(TdUserPtr user); void updateUser(TdUserPtr user);
void setUserStatus(UserId UserId, td::td_api::object_ptr<td::td_api::UserStatus> status); void setUserStatus(UserId UserId, td::td_api::object_ptr<td::td_api::UserStatus> status);
@ -388,7 +391,7 @@ public:
PendingMessageQueue pendingMessages; PendingMessageQueue pendingMessages;
void addPendingReadReceipt(ChatId chatId, MessageId messageId); void addPendingReadReceipt(ChatId chatId, MessageId messageId);
void extractPendingReadReceipts(std::vector<ReadReceipt> &receipts); void extractPendingReadReceipts(ChatId chatId, std::vector<ReadReceipt> &receipts);
private: private:
TdAccountData(const TdAccountData &other) = delete; TdAccountData(const TdAccountData &other) = delete;
TdAccountData &operator=(const TdAccountData &other) = delete; TdAccountData &operator=(const TdAccountData &other) = delete;
@ -463,8 +466,8 @@ private:
std::unique_ptr<PendingRequest> getPendingRequestImpl(uint64_t requestId); std::unique_ptr<PendingRequest> getPendingRequestImpl(uint64_t requestId);
PendingRequest * findPendingRequestImpl(uint64_t requestId); PendingRequest * findPendingRequestImpl(uint64_t requestId);
// Read receipts not sent immediately due to away status // Read receipts not sent immediately due to away status (grouped per chat)
std::vector<ReadReceipt> m_pendingReadReceipts; std::vector<std::vector<ReadReceipt>> m_pendingReadReceipts;
}; };
#endif #endif

1
call.h
View File

@ -1,7 +1,6 @@
#ifndef _CALL_H #ifndef _CALL_H
#define _CALL_H #define _CALL_H
#include "transceiver.h"
#include "account-data.h" #include "account-data.h"
bool initiateCall(int32_t userId, TdAccountData &account, TdTransceiver &transceiver); bool initiateCall(int32_t userId, TdAccountData &account, TdTransceiver &transceiver);

View File

@ -2,7 +2,6 @@
#define _CLIENT_UTILS_H #define _CLIENT_UTILS_H
#include "account-data.h" #include "account-data.h"
#include "transceiver.h"
#include <purple.h> #include <purple.h>
#include <thread> #include <thread>

View File

@ -2,7 +2,6 @@
#define _FILE_TRANSFER_H #define _FILE_TRANSFER_H
#include "account-data.h" #include "account-data.h"
#include "transceiver.h"
enum { enum {
FILE_DOWNLOAD_PRIORITY = 1, FILE_DOWNLOAD_PRIORITY = 1,

View File

@ -42,6 +42,39 @@ void sendConversationReadReceipts(TdAccountData &account, PurpleConversation *co
{ {
if (!conversationHasFocus(conv)) if (!conversationHasFocus(conv))
return; return;
ChatId chatId;
PurpleConversationType convType = purple_conversation_get_type(conv);
const char *convName = purple_conversation_get_name(conv);
if (convType == PURPLE_CONV_TYPE_IM) {
UserId privateChatUserId = purpleBuddyNameToUserId(convName);
SecretChatId secretChatId = purpleBuddyNameToSecretChatId(convName);
const td::td_api::chat *tdlibChat = nullptr;
if (privateChatUserId.valid())
tdlibChat = account.getPrivateChatByUserId(privateChatUserId);
else if (secretChatId.valid())
tdlibChat = account.getChatBySecretChat(secretChatId);
if (tdlibChat)
chatId = getId(*tdlibChat);
} else if (convType == PURPLE_CONV_TYPE_CHAT)
chatId = getTdlibChatId(convName);
std::vector<ReadReceipt> receipts;
account.extractPendingReadReceipts(chatId, receipts);
if (!receipts.empty()) {
purple_debug_misc(config::pluginId, "Sending %zu read receipts for chat %" G_GINT64_FORMAT "\n",
receipts.size(), chatId.value());
td::td_api::object_ptr<td::td_api::viewMessages> viewMessagesReq = td::td_api::make_object<td::td_api::viewMessages>();
viewMessagesReq->chat_id_ = chatId.value();
viewMessagesReq->force_read_ = true; // no idea what "closed chats" are at this point
viewMessagesReq->message_ids_.resize(receipts.size());
for (size_t i = 0; i < receipts.size(); i++)
viewMessagesReq->message_ids_[i] = receipts[i].messageId.value();
account.transceiver.sendQuery(std::move(viewMessagesReq), nullptr);
}
} }
void showMessageTextIm(TdAccountData &account, const char *purpleUserName, const char *text, void showMessageTextIm(TdAccountData &account, const char *purpleUserName, const char *text,

View File

@ -2,7 +2,6 @@
#define _RECEIVING_H #define _RECEIVING_H
#include "account-data.h" #include "account-data.h"
#include "transceiver.h"
#include <purple.h> #include <purple.h>
std::string makeNoticeWithSender(const td::td_api::chat &chat, const TgMessageInfo &message, std::string makeNoticeWithSender(const td::td_api::chat &chat, const TgMessageInfo &message,

View File

@ -2,7 +2,6 @@
#define _SECRET_CHAT_H #define _SECRET_CHAT_H
#include "account-data.h" #include "account-data.h"
#include "transceiver.h"
#include "format.h" #include "format.h"
void updateSecretChat(td::td_api::object_ptr<td::td_api::secretChat> secretChat, void updateSecretChat(td::td_api::object_ptr<td::td_api::secretChat> secretChat,

View File

@ -20,7 +20,7 @@ enum {
PurpleTdClient::PurpleTdClient(PurpleAccount *acct, ITransceiverBackend *testBackend) PurpleTdClient::PurpleTdClient(PurpleAccount *acct, ITransceiverBackend *testBackend)
: m_transceiver(this, acct, &PurpleTdClient::processUpdate, testBackend), : m_transceiver(this, acct, &PurpleTdClient::processUpdate, testBackend),
m_data(acct) m_data(acct, m_transceiver)
{ {
StickerConversionThread::setCallback(&PurpleTdClient::onAnimatedStickerConverted); StickerConversionThread::setCallback(&PurpleTdClient::onAnimatedStickerConverted);
m_account = acct; m_account = acct;
@ -919,28 +919,6 @@ void PurpleTdClient::sendReadReceipts(PurpleConversation *conversation)
sendConversationReadReceipts(m_data, conversation); sendConversationReadReceipts(m_data, conversation);
return; return;
} }
// temporary
std::vector<ReadReceipt> receipts;
m_data.extractPendingReadReceipts(receipts);
std::sort(receipts.begin(), receipts.end(),
[](const ReadReceipt &r1, const ReadReceipt &r2) {
return (r1.chatId.value() < r2.chatId.value());
});
unsigned i = 0;
while (i < receipts.size()) {
ChatId chatId = receipts[i].chatId;
td::td_api::object_ptr<td::td_api::viewMessages> viewMessagesReq = td::td_api::make_object<td::td_api::viewMessages>();
viewMessagesReq->chat_id_ = chatId.value();
viewMessagesReq->force_read_ = true; // no idea what "closed chats" are at this point
while ((i < receipts.size()) && (receipts[i].chatId == chatId)) {
viewMessagesReq->message_ids_.push_back(receipts[i].messageId.value());
i++;
}
m_transceiver.sendQuery(std::move(viewMessagesReq), nullptr);
}
} }
void PurpleTdClient::onIncomingMessage(td::td_api::object_ptr<td::td_api::message> message) void PurpleTdClient::onIncomingMessage(td::td_api::object_ptr<td::td_api::message> message)
@ -956,10 +934,8 @@ void PurpleTdClient::onIncomingMessage(td::td_api::object_ptr<td::td_api::messag
return; return;
} }
if (isReadReceiptsEnabled(m_account)) { if (isReadReceiptsEnabled(m_account))
m_data.addPendingReadReceipt(chatId, getId(*message)); m_data.addPendingReadReceipt(chatId, getId(*message));
sendReadReceipts(NULL);
}
IncomingMessage fullMessage; IncomingMessage fullMessage;
makeFullMessage(*chat, std::move(message), fullMessage, m_data); makeFullMessage(*chat, std::move(message), fullMessage, m_data);

View File

@ -2,7 +2,6 @@
#define _TD_CLIENT_H #define _TD_CLIENT_H
#include "account-data.h" #include "account-data.h"
#include "transceiver.h"
#include "client-utils.h" #include "client-utils.h"
#include <td/telegram/Log.h> #include <td/telegram/Log.h>
#include <purple.h> #include <purple.h>

View File

@ -276,12 +276,22 @@ void tgprpl_set_single_thread()
AccountThread::setSingleThread(); AccountThread::setSingleThread();
} }
struct PurpleConversationInfo {
std::string accountName;
std::string convName;
PurpleConversationType type;
};
static gboolean sendConversationReadReceipts(void *arg) static gboolean sendConversationReadReceipts(void *arg)
{ {
PurpleConversation *conv = static_cast<PurpleConversation *>(arg); std::unique_ptr<PurpleConversationInfo> info(static_cast<PurpleConversationInfo *>(arg));
PurpleTdClient *tdClient = getTdClient(purple_conversation_get_account(conv)); PurpleAccount *account = purple_accounts_find(info->accountName.c_str(), config::pluginId);
PurpleConversation *conv = NULL;
if (account != NULL)
conv = purple_find_conversation_with_account(info->type, info->convName.c_str(), account);
tdClient->sendReadReceipts(conv); if (conv != NULL)
getTdClient(account)->sendReadReceipts(conv);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
@ -293,7 +303,11 @@ conversation_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type)
if (!strcmp(purple_account_get_protocol_id(account), config::pluginId) && if (!strcmp(purple_account_get_protocol_id(account), config::pluginId) &&
(type == PURPLE_CONV_UPDATE_UNSEEN)) (type == PURPLE_CONV_UPDATE_UNSEEN))
{ {
g_timeout_add(500, sendConversationReadReceipts, conv); PurpleConversationInfo *arg = new PurpleConversationInfo;
arg->accountName = purple_account_get_username(account);
arg->convName = purple_conversation_get_name(conv);
arg->type = purple_conversation_get_type(conv);
g_timeout_add(500, sendConversationReadReceipts, arg);
} }
} }