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:
parent
ec01fa2b5f
commit
c8b55eb887
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
1
call.h
@ -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);
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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>
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user