3c0d046b3f
And a bit of optimization: 1. Lookup handlers from hashtable 2. Pre-initialize commonly used strings 3. Avoid unnecessary QVariantMap lookups 4. Shortened logging statements
350 lines
16 KiB
C++
350 lines
16 KiB
C++
/*
|
|
Copyright (C) 2020 Sebastian J. Wolf
|
|
|
|
This file is part of Fernschreiber.
|
|
|
|
Fernschreiber is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Fernschreiber is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#include "tdlibreceiver.h"
|
|
|
|
#define LOG(x) qDebug() << "[TDLibReceiver]" << x
|
|
|
|
namespace {
|
|
const QString ID("id");
|
|
const QString LIST("list");
|
|
const QString CHAT_ID("chat_id");
|
|
const QString POSITION("position");
|
|
const QString POSITIONS("positions");
|
|
const QString ORDER("order");
|
|
const QString LAST_MESSAGE("last_message");
|
|
const QString UNREAD_COUNT("unread_count");
|
|
const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id");
|
|
const QString LAST_READ_OUTBOX_MESSAGE_ID("last_read_outbox_message_id");
|
|
|
|
const QString TYPE("@type");
|
|
const QString TYPE_CHAT_POSITION("chatPosition");
|
|
const QString TYPE_CHAT_LIST_MAIN("chatListMain");
|
|
}
|
|
|
|
static QString getChatPositionOrder(const QVariantMap &position)
|
|
{
|
|
if (position.value(TYPE).toString() == TYPE_CHAT_POSITION &&
|
|
position.value(LIST).toMap().value(TYPE) == TYPE_CHAT_LIST_MAIN) {
|
|
return position.value(ORDER).toString();
|
|
}
|
|
return QString();
|
|
}
|
|
|
|
static QString findChatPositionOrder(const QVariantList &positions)
|
|
{
|
|
const int n = positions.count();
|
|
for (int i = 0; i < n; i++) {
|
|
const QString order(getChatPositionOrder(positions.at(i).toMap()));
|
|
if (!order.isEmpty()) {
|
|
return order;
|
|
}
|
|
}
|
|
return QString();
|
|
}
|
|
|
|
TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(parent)
|
|
{
|
|
this->tdLibClient = tdLibClient;
|
|
this->isActive = true;
|
|
|
|
handlers.insert("updateOption", &TDLibReceiver::processUpdateOption);
|
|
handlers.insert("updateAuthorizationState", &TDLibReceiver::processUpdateAuthorizationState);
|
|
handlers.insert("updateConnectionState", &TDLibReceiver::processUpdateConnectionState);
|
|
handlers.insert("updateUser", &TDLibReceiver::processUpdateUser);
|
|
handlers.insert("updateUserStatus", &TDLibReceiver::processUpdateUserStatus);
|
|
handlers.insert("updateFile", &TDLibReceiver::processUpdateFile);
|
|
handlers.insert("file", &TDLibReceiver::processFile);
|
|
handlers.insert("updateNewChat", &TDLibReceiver::processUpdateNewChat);
|
|
handlers.insert("updateUnreadMessageCount", &TDLibReceiver::processUpdateUnreadMessageCount);
|
|
handlers.insert("updateUnreadChatCount", &TDLibReceiver::processUpdateUnreadChatCount);
|
|
handlers.insert("updateChatLastMessage", &TDLibReceiver::processUpdateChatLastMessage);
|
|
handlers.insert("updateChatOrder", &TDLibReceiver::processUpdateChatOrder);
|
|
handlers.insert("updateChatPosition", &TDLibReceiver::processUpdateChatPosition);
|
|
handlers.insert("updateChatReadInbox", &TDLibReceiver::processUpdateChatReadInbox);
|
|
handlers.insert("updateChatReadOutbox", &TDLibReceiver::processUpdateChatReadOutbox);
|
|
handlers.insert("updateBasicGroup", &TDLibReceiver::processUpdateBasicGroup);
|
|
handlers.insert("updateSupergroup", &TDLibReceiver::processUpdateSuperGroup);
|
|
handlers.insert("updateChatOnlineMemberCount", &TDLibReceiver::processChatOnlineMemberCountUpdated);
|
|
handlers.insert("messages", &TDLibReceiver::processMessages);
|
|
handlers.insert("updateNewMessage", &TDLibReceiver::processUpdateNewMessage);
|
|
handlers.insert("message", &TDLibReceiver::processMessage);
|
|
handlers.insert("updateMessageSendSucceeded", &TDLibReceiver::processMessageSendSucceeded);
|
|
handlers.insert("updateActiveNotifications", &TDLibReceiver::processUpdateActiveNotifications);
|
|
handlers.insert("updateNotificationGroup", &TDLibReceiver::processUpdateNotificationGroup);
|
|
handlers.insert("updateChatNotificationSettings", &TDLibReceiver::processUpdateChatNotificationSettings);
|
|
handlers.insert("updateMessageContent", &TDLibReceiver::processUpdateMessageContent);
|
|
handlers.insert("updateDeleteMessages", &TDLibReceiver::processUpdateDeleteMessages);
|
|
}
|
|
|
|
void TDLibReceiver::setActive(const bool &active)
|
|
{
|
|
if (active) {
|
|
LOG("Activating receiver loop...");
|
|
} else {
|
|
LOG("Deactivating receiver loop, this may take a while...");
|
|
}
|
|
this->isActive = active;
|
|
}
|
|
|
|
void TDLibReceiver::receiverLoop()
|
|
{
|
|
LOG("Starting receiver loop");
|
|
const double WAIT_TIMEOUT = 5.0;
|
|
while (this->isActive) {
|
|
const char *result = td_json_client_receive(this->tdLibClient, WAIT_TIMEOUT);
|
|
if (result) {
|
|
QJsonDocument receivedJsonDocument = QJsonDocument::fromJson(QByteArray(result));
|
|
qDebug().noquote() << "[TDLibReceiver] Raw result: " << receivedJsonDocument.toJson(QJsonDocument::Indented);
|
|
processReceivedDocument(receivedJsonDocument);
|
|
}
|
|
}
|
|
LOG("Stopping receiver loop");
|
|
}
|
|
|
|
void TDLibReceiver::processReceivedDocument(const QJsonDocument &receivedJsonDocument)
|
|
{
|
|
QVariantMap receivedInformation = receivedJsonDocument.object().toVariantMap();
|
|
QString objectTypeName = receivedInformation.value("@type").toString();
|
|
|
|
Handler handler = handlers.value(objectTypeName);
|
|
if (handler) {
|
|
(this->*handler)(receivedInformation);
|
|
} else {
|
|
LOG("Unhandled object type" << objectTypeName);
|
|
}
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateOption(const QVariantMap &receivedInformation)
|
|
{
|
|
QString currentOption = receivedInformation.value("name").toString();
|
|
if (currentOption == "version") {
|
|
QString detectedVersion = receivedInformation.value("value").toMap().value("value").toString();
|
|
LOG("TD Lib version detected: " << detectedVersion);
|
|
emit versionDetected(detectedVersion);
|
|
} else {
|
|
QVariant currentValue = receivedInformation.value("value").toMap().value("value");
|
|
LOG("Option updated: " << currentOption << currentValue);
|
|
emit optionUpdated(currentOption, currentValue);
|
|
}
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateAuthorizationState(const QVariantMap &receivedInformation)
|
|
{
|
|
QString authorizationState = receivedInformation.value("authorization_state").toMap().value("@type").toString();
|
|
LOG("Authorization state changed: " << authorizationState);
|
|
emit authorizationStateChanged(authorizationState);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateConnectionState(const QVariantMap &receivedInformation)
|
|
{
|
|
QString connectionState = receivedInformation.value("state").toMap().value("@type").toString();
|
|
LOG("Connection state changed: " << connectionState);
|
|
emit connectionStateChanged(connectionState);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateUser(const QVariantMap &receivedInformation)
|
|
{
|
|
QVariantMap userInformation = receivedInformation.value("user").toMap();
|
|
// LOG("User was updated: " << userInformation.value("username").toString() << userInformation.value("first_name").toString() << userInformation.value("last_name").toString());
|
|
emit userUpdated(userInformation);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateUserStatus(const QVariantMap &receivedInformation)
|
|
{
|
|
QString userId = receivedInformation.value("user_id").toString();
|
|
QVariantMap userStatusInformation = receivedInformation.value("status").toMap();
|
|
// LOG("User status was updated: " << receivedInformation.value("user_id").toString() << userStatusInformation.value("@type").toString());
|
|
emit userStatusUpdated(userId, userStatusInformation);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateFile(const QVariantMap &receivedInformation)
|
|
{
|
|
QVariantMap fileInformation = receivedInformation.value("file").toMap();
|
|
LOG("File was updated: " << fileInformation.value(ID).toString());
|
|
emit fileUpdated(fileInformation);
|
|
}
|
|
|
|
void TDLibReceiver::processFile(const QVariantMap &receivedInformation)
|
|
{
|
|
LOG("File was updated: " << receivedInformation.value(ID).toString());
|
|
emit fileUpdated(receivedInformation);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateNewChat(const QVariantMap &receivedInformation)
|
|
{
|
|
QVariantMap chatInformation = receivedInformation.value("chat").toMap();
|
|
LOG("New chat discovered: " << chatInformation.value(ID).toString() << chatInformation.value("title").toString());
|
|
emit newChatDiscovered(chatInformation);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateUnreadMessageCount(const QVariantMap &receivedInformation)
|
|
{
|
|
QVariantMap messageCountInformation;
|
|
messageCountInformation.insert("chat_list_type", receivedInformation.value("chat_list").toMap().value("@type"));
|
|
messageCountInformation.insert("unread_count", receivedInformation.value("unread_count"));
|
|
messageCountInformation.insert("unread_unmuted_count", receivedInformation.value("unread_unmuted_count"));
|
|
LOG("Unread message count updated: " << messageCountInformation.value("chat_list_type").toString() << messageCountInformation.value("unread_count").toString());
|
|
emit unreadMessageCountUpdated(messageCountInformation);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateUnreadChatCount(const QVariantMap &receivedInformation)
|
|
{
|
|
QVariantMap chatCountInformation;
|
|
chatCountInformation.insert("chat_list_type", receivedInformation.value("chat_list").toMap().value("@type"));
|
|
chatCountInformation.insert("marked_as_unread_count", receivedInformation.value("marked_as_unread_count"));
|
|
chatCountInformation.insert("marked_as_unread_unmuted_count", receivedInformation.value("marked_as_unread_unmuted_count"));
|
|
chatCountInformation.insert("total_count", receivedInformation.value("total_count"));
|
|
chatCountInformation.insert("unread_count", receivedInformation.value("unread_count"));
|
|
chatCountInformation.insert("unread_unmuted_count", receivedInformation.value("unread_unmuted_count"));
|
|
LOG("Unread chat count updated: " << chatCountInformation.value("chat_list_type").toString() << chatCountInformation.value("unread_count").toString());
|
|
emit unreadChatCountUpdated(chatCountInformation);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateChatLastMessage(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chat_id(receivedInformation.value(CHAT_ID).toString());
|
|
const QString order(findChatPositionOrder(receivedInformation.value(POSITIONS).toList()));
|
|
const QVariantMap lastMessage = receivedInformation.value(LAST_MESSAGE).toMap();
|
|
LOG("Last message of chat" << chat_id << "updated, order" << order << "type" << lastMessage.value("@type").toString());
|
|
emit chatLastMessageUpdated(chat_id, order, lastMessage);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateChatOrder(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chat_id(receivedInformation.value(CHAT_ID).toString());
|
|
const QString order(receivedInformation.value(ORDER).toString());
|
|
LOG("Chat order updated for ID" << chat_id << "to" << order);
|
|
emit chatOrderUpdated(chat_id, order);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateChatPosition(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chat_id(receivedInformation.value(CHAT_ID).toString());
|
|
const QString order(receivedInformation.value(POSITION).toMap().value(ORDER).toString());
|
|
LOG("Chat position updated for ID" << chat_id << "new order" << order);
|
|
emit chatOrderUpdated(chat_id, order);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateChatReadInbox(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chat_id(receivedInformation.value(CHAT_ID).toString());
|
|
const QString unread_count(receivedInformation.value(UNREAD_COUNT).toString());
|
|
LOG("Chat read information updated for" << chat_id << "unread count:" << unread_count);
|
|
emit chatReadInboxUpdated(chat_id, receivedInformation.value(LAST_READ_INBOX_MESSAGE_ID).toString(), unread_count.toInt());
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateChatReadOutbox(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chat_id(receivedInformation.value(CHAT_ID).toString());
|
|
const QString last_read_outbox_message_id(receivedInformation.value(LAST_READ_OUTBOX_MESSAGE_ID).toString());
|
|
LOG("Sent messages read information updated for" << chat_id << "last read message ID:" << last_read_outbox_message_id);
|
|
emit chatReadOutboxUpdated(chat_id, last_read_outbox_message_id);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateBasicGroup(const QVariantMap &receivedInformation)
|
|
{
|
|
QString basicGroupId = receivedInformation.value("basic_group").toMap().value(ID).toString();
|
|
LOG("Basic group information updated for " << basicGroupId);
|
|
emit basicGroupUpdated(basicGroupId, receivedInformation.value("basic_group").toMap());
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateSuperGroup(const QVariantMap &receivedInformation)
|
|
{
|
|
QString superGroupId = receivedInformation.value("supergroup").toMap().value(ID).toString();
|
|
LOG("Super group information updated for " << superGroupId);
|
|
emit superGroupUpdated(superGroupId, receivedInformation.value("supergroup").toMap());
|
|
}
|
|
|
|
void TDLibReceiver::processChatOnlineMemberCountUpdated(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chatId = receivedInformation.value(CHAT_ID).toString();
|
|
LOG("Online member count updated for chat " << chatId);
|
|
emit chatOnlineMemberCountUpdated(chatId, receivedInformation.value("online_member_count").toInt());
|
|
}
|
|
|
|
void TDLibReceiver::processMessages(const QVariantMap &receivedInformation)
|
|
{
|
|
LOG("Received new messages, amount: " << receivedInformation.value("total_count").toString());
|
|
emit messagesReceived(receivedInformation.value("messages").toList());
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateNewMessage(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chatId = receivedInformation.value("message").toMap().value(CHAT_ID).toString();
|
|
LOG("Received new message for chat " << chatId);
|
|
emit newMessageReceived(chatId, receivedInformation.value("message").toMap());
|
|
}
|
|
|
|
void TDLibReceiver::processMessage(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chatId = receivedInformation.value(CHAT_ID).toString();
|
|
const QString messageId = receivedInformation.value(ID).toString();
|
|
LOG("Received message " << chatId << messageId);
|
|
emit messageInformation(messageId, receivedInformation);
|
|
}
|
|
|
|
void TDLibReceiver::processMessageSendSucceeded(const QVariantMap &receivedInformation)
|
|
{
|
|
QString oldMessageId = receivedInformation.value("old_message_id").toString();
|
|
QVariantMap message = receivedInformation.value("message").toMap();
|
|
const QString messageId = message.value(ID).toString();
|
|
LOG("Message send succeeded " << messageId << oldMessageId);
|
|
emit messageSendSucceeded(messageId, oldMessageId, message);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateActiveNotifications(const QVariantMap &receivedInformation)
|
|
{
|
|
LOG("Received active notification groups");
|
|
emit activeNotificationsUpdated(receivedInformation.value("groups").toList());
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateNotificationGroup(const QVariantMap &receivedInformation)
|
|
{
|
|
LOG("Received updated notification group");
|
|
emit notificationGroupUpdated(receivedInformation);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateNotification(const QVariantMap &receivedInformation)
|
|
{
|
|
LOG("Received notification update");
|
|
emit notificationUpdated(receivedInformation);
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateChatNotificationSettings(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chatId = receivedInformation.value(CHAT_ID).toString();
|
|
LOG("Received new notification settings for chat " << chatId);
|
|
emit chatNotificationSettingsUpdated(chatId, receivedInformation.value("notification_settings").toMap());
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateMessageContent(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chatId = receivedInformation.value(CHAT_ID).toString();
|
|
QString messageId = receivedInformation.value("message_id").toString();
|
|
LOG("Message content updated " << chatId << messageId);
|
|
emit messageContentUpdated(chatId, messageId, receivedInformation.value("new_content").toMap());
|
|
}
|
|
|
|
void TDLibReceiver::processUpdateDeleteMessages(const QVariantMap &receivedInformation)
|
|
{
|
|
const QString chatId = receivedInformation.value(CHAT_ID).toString();
|
|
QVariantList messageIds = receivedInformation.value("message_ids").toList();
|
|
LOG("Some messages were deleted " << chatId);
|
|
emit messagesDeleted(chatId, messageIds);
|
|
}
|