Don't show irrelevant groups by default

chatListModel.showAllChats property can be used to switch visibility
of irrelevant groups on and off.
This commit is contained in:
Slava Monich 2020-10-04 04:27:49 +03:00
parent 1b261c224f
commit 56bc1135a7
6 changed files with 470 additions and 150 deletions

View file

@ -27,6 +27,7 @@ namespace {
const QString ID("id");
const QString DATE("date");
const QString TEXT("text");
const QString TYPE("type");
const QString TITLE("title");
const QString PHOTO("photo");
const QString SMALL("small");
@ -35,6 +36,8 @@ namespace {
const QString CONTENT("content");
const QString LAST_MESSAGE("last_message");
const QString SENDER_USER_ID("sender_user_id");
const QString BASIC_GROUP_ID("basic_group_id");
const QString SUPERGROUP_ID("supergroup_id");
const QString UNREAD_COUNT("unread_count");
const QString NOTIFICATION_SETTINGS("notification_settings");
const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id");
@ -42,8 +45,12 @@ namespace {
const QString TYPE_MAP("type");
const QString IS_CHANNEL("is_channel");
const QString TYPE("@type");
const QString _TYPE("@type");
const QString TYPE_MESSAGE_TEXT("messageText");
const QString TYPE_CHAT_TYPE_PRIVATE("chatTypePrivate");
const QString TYPE_CHAT_TYPE_BASIC_GROUP("chatTypeBasicGroup");
const QString TYPE_CHAT_TYPE_SUPERGROUP("chatTypeSupergroup");
const QString TYPE_CHAT_TYPE_SECRET("chatTypeSecret");
}
class ChatListModel::ChatData
@ -52,6 +59,7 @@ public:
enum Role {
RoleDisplay = Qt::DisplayRole,
RoleChatId,
RoleChatType,
RoleTitle,
RolePhotoSmall,
RoleUnreadCount,
@ -59,6 +67,7 @@ public:
RoleLastMessageSenderId,
RoleLastMessageDate,
RoleLastMessageText,
RoleChatMemberStatus,
RoleIsChannel
};
@ -75,29 +84,50 @@ public:
qlonglong senderMessageDate() const;
QString senderMessageText() const;
bool isChannel() const;
bool isHidden() const;
bool updateUnreadCount(int unreadCount);
bool updateLastReadInboxMessageId(qlonglong messageId);
QVector<int> updateLastMessage(const QVariantMap &message);
QVector<int> updateGroup(const TDLibWrapper::Group *group);
static TDLibWrapper::ChatType chatTypeFromString(const QString &type);
public:
QVariantMap chatData;
QString chatId;
qlonglong chatId;
qlonglong order;
qlonglong groupId;
TDLibWrapper::ChatType chatType;
TDLibWrapper::ChatMemberStatus memberStatus;
QVariantMap userInformation;
};
ChatListModel::ChatData::ChatData(const QVariantMap &data, const QVariantMap &userInformation) :
ChatListModel::ChatData::ChatData(const QVariantMap &data, const QVariantMap &userInfo) :
chatData(data),
chatId(data.value(ID).toString()),
order(data.value(ORDER).toLongLong())
chatId(data.value(ID).toLongLong()),
order(data.value(ORDER).toLongLong()),
groupId(0),
memberStatus(TDLibWrapper::ChatMemberStatusUnknown),
userInformation(userInfo)
{
this->userInformation = userInformation;
const QVariantMap type(data.value(TYPE).toMap());
switch (chatType = chatTypeFromString(type.value(_TYPE).toString())) {
case TDLibWrapper::ChatTypeBasicGroup:
groupId = type.value(BASIC_GROUP_ID).toLongLong();
break;
case TDLibWrapper::ChatTypeSupergroup:
groupId = type.value(SUPERGROUP_ID).toLongLong();
break;
case TDLibWrapper::ChatTypeUnknown:
case TDLibWrapper::ChatTypePrivate:
case TDLibWrapper::ChatTypeSecret:
break;
}
}
int ChatListModel::ChatData::compareTo(const ChatData *other) const
{
if (order == other->order) {
return chatId.compare(other->chatId);
return (chatId < other->chatId) ? 1 : -1;
} else {
// This puts most recent ones to the top of the list
return (order < other->order) ? 1 : -1;
@ -159,6 +189,32 @@ bool ChatListModel::ChatData::isChannel() const
return chatData.value(TYPE_MAP).toMap().value(IS_CHANNEL).toBool();
}
bool ChatListModel::ChatData::isHidden() const
{
// Cover all enum values so that compiler warns us when/if enum gets extended
switch (chatType) {
case TDLibWrapper::ChatTypeBasicGroup:
case TDLibWrapper::ChatTypeSupergroup:
switch (memberStatus) {
case TDLibWrapper::ChatMemberStatusLeft:
case TDLibWrapper::ChatMemberStatusUnknown:
return true;
case TDLibWrapper::ChatMemberStatusCreator:
case TDLibWrapper::ChatMemberStatusAdministrator:
case TDLibWrapper::ChatMemberStatusMember:
case TDLibWrapper::ChatMemberStatusRestricted:
case TDLibWrapper::ChatMemberStatusBanned:
break;
}
break;
case TDLibWrapper::ChatTypeUnknown:
case TDLibWrapper::ChatTypePrivate:
case TDLibWrapper::ChatTypeSecret:
break;
}
return false;
}
bool ChatListModel::ChatData::updateUnreadCount(int count)
{
const int prevUnreadCount(unreadCount());
@ -195,7 +251,30 @@ QVector<int> ChatListModel::ChatData::updateLastMessage(const QVariantMap &messa
return changedRoles;
}
ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper)
QVector<int> ChatListModel::ChatData::updateGroup(const TDLibWrapper::Group *group)
{
QVector<int> changedRoles;
if (group && groupId == group->groupId) {
const TDLibWrapper::ChatMemberStatus groupMemberStatus = group->chatMemberStatus();
if (memberStatus != groupMemberStatus) {
memberStatus = groupMemberStatus;
changedRoles.append(RoleChatMemberStatus);
}
}
return changedRoles;
}
TDLibWrapper::ChatType ChatListModel::ChatData::chatTypeFromString(const QString &type)
{
return (type == TYPE_CHAT_TYPE_PRIVATE) ? TDLibWrapper::ChatTypePrivate :
(type == TYPE_CHAT_TYPE_BASIC_GROUP) ? TDLibWrapper::ChatTypeBasicGroup :
(type == TYPE_CHAT_TYPE_SUPERGROUP) ? TDLibWrapper::ChatTypeSupergroup :
(type == TYPE_CHAT_TYPE_SECRET) ? TDLibWrapper::ChatTypeSecret :
TDLibWrapper::ChatTypeUnknown;
}
ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper) : showHiddenChats(false)
{
this->tdLibWrapper = tdLibWrapper;
connect(tdLibWrapper, SIGNAL(newChatDiscovered(QString, QVariantMap)), this, SLOT(handleChatDiscovered(QString, QVariantMap)));
@ -205,6 +284,8 @@ ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper)
connect(tdLibWrapper, SIGNAL(chatReadOutboxUpdated(QString, QString)), this, SLOT(handleChatReadOutboxUpdated(QString, QString)));
connect(tdLibWrapper, SIGNAL(messageSendSucceeded(QString, QString, QVariantMap)), this, SLOT(handleMessageSendSucceeded(QString, QString, QVariantMap)));
connect(tdLibWrapper, SIGNAL(chatNotificationSettingsUpdated(QString, QVariantMap)), this, SLOT(handleChatNotificationSettingsUpdated(QString, QVariantMap)));
connect(tdLibWrapper, SIGNAL(superGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong)));
connect(tdLibWrapper, SIGNAL(basicGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong)));
// Don't start the timer until we have at least one chat
relativeTimeRefreshTimer = new QTimer(this);
@ -217,6 +298,7 @@ ChatListModel::~ChatListModel()
{
LOG("Destroying myself...");
qDeleteAll(chatList);
qDeleteAll(hiddenChats.values());
}
QHash<int,QByteArray> ChatListModel::roleNames() const
@ -224,6 +306,7 @@ QHash<int,QByteArray> ChatListModel::roleNames() const
QHash<int,QByteArray> roles;
roles.insert(ChatData::RoleDisplay, "display");
roles.insert(ChatData::RoleChatId, "chat_id");
roles.insert(ChatData::RoleChatType, "chat_type");
roles.insert(ChatData::RoleTitle, "title");
roles.insert(ChatData::RolePhotoSmall, "photo_small");
roles.insert(ChatData::RoleUnreadCount, "unread_count");
@ -231,6 +314,7 @@ QHash<int,QByteArray> ChatListModel::roleNames() const
roles.insert(ChatData::RoleLastMessageSenderId, "last_message_sender_id");
roles.insert(ChatData::RoleLastMessageDate, "last_message_date");
roles.insert(ChatData::RoleLastMessageText, "last_message_text");
roles.insert(ChatData::RoleChatMemberStatus, "chat_member_status");
roles.insert(ChatData::RoleIsChannel, "is_channel");
return roles;
}
@ -248,6 +332,7 @@ QVariant ChatListModel::data(const QModelIndex &index, int role) const
switch ((ChatData::Role)role) {
case ChatData::RoleDisplay: return data->chatData;
case ChatData::RoleChatId: return data->chatId;
case ChatData::RoleChatType: return data->chatType;
case ChatData::RoleTitle: return data->title();
case ChatData::RolePhotoSmall: return data->photoSmall();
case ChatData::RoleUnreadCount: return data->unreadCount();
@ -255,6 +340,7 @@ QVariant ChatListModel::data(const QModelIndex &index, int role) const
case ChatData::RoleLastMessageSenderId: return data->senderUserId();
case ChatData::RoleLastMessageText: return data->senderMessageText();
case ChatData::RoleLastMessageDate: return data->senderMessageDate();
case ChatData::RoleChatMemberStatus: return data->memberStatus;
case ChatData::RoleIsChannel: return data->isChannel();
}
}
@ -307,30 +393,98 @@ int ChatListModel::updateChatOrder(int chatIndex)
return newIndex;
}
void ChatListModel::handleChatDiscovered(const QString &chatId, const QVariantMap &chatToBeAdded)
void ChatListModel::addVisibleChat(ChatData *chat)
{
ChatData *chat = new ChatData(chatToBeAdded, tdLibWrapper->getUserInformation());
const int n = chatList.size();
int chatIndex;
for (chatIndex = 0; chatIndex < n && chat->compareTo(chatList.at(chatIndex)) >= 0; chatIndex++);
LOG("Adding new chat" << chatId << "at" << chatIndex);
beginInsertRows(QModelIndex(), chatIndex, chatIndex);
chatList.insert(chatIndex, chat);
chatIndexMap.insert(chat->chatId, chatIndex);
int pos;
for (pos = 0; pos < n && chat->compareTo(chatList.at(pos)) >= 0; pos++);
LOG("Adding chat" << chat->chatId << "at" << pos);
beginInsertRows(QModelIndex(), pos, pos);
chatList.insert(pos, chat);
chatIndexMap.insert(chat->chatId, pos);
// Update damaged part of the map
for (int i = chatIndex + 1; i <= n; i++) {
for (int i = pos + 1; i <= n; i++) {
chatIndexMap.insert(chatList.at(i)->chatId, i);
}
endInsertRows();
}
// Start timestamp refresh timer when the first chat is discovered
void ChatListModel::updateChatVisibility(const TDLibWrapper::Group *group)
{
// See if any group has been removed from from view
for (int i = 0; i < chatList.size(); i++) {
ChatData *chat = chatList.at(i);
const QVector<int> changedRoles(chat->updateGroup(group));
if (chat->isHidden() && !showHiddenChats) {
LOG("Hiding chat" << chat->chatId << "at" << i);
beginRemoveRows(QModelIndex(), i, i);
chatList.removeAt(i);
// Update damaged part of the map
const int n = chatList.size();
for (int pos = i; pos < n; pos++) {
chatIndexMap.insert(chatList.at(pos)->chatId, pos);
}
i--;
hiddenChats.insert(chat->chatId, chat);
endRemoveRows();
} else if (!changedRoles.isEmpty()) {
const QModelIndex modelIndex(index(i));
emit dataChanged(modelIndex, modelIndex, changedRoles);
}
}
// And see if any group been added to the view
const QList<ChatData*> hiddenChatList = hiddenChats.values();
const int n = hiddenChatList.size();
for (int j = 0; j < n; j++) {
ChatData *chat = hiddenChatList.at(j);
chat->updateGroup(group);
if (!chat->isHidden() || showHiddenChats) {
hiddenChats.remove(chat->chatId);
addVisibleChat(chat);
}
}
}
bool ChatListModel::showAllChats() const
{
return showHiddenChats;
}
void ChatListModel::setShowAllChats(bool showAll)
{
if (showHiddenChats != showAll) {
showHiddenChats = showAll;
updateChatVisibility(Q_NULLPTR);
emit showAllChatsChanged();
}
}
void ChatListModel::handleChatDiscovered(const QString &, const QVariantMap &chatToBeAdded)
{
ChatData *chat = new ChatData(chatToBeAdded, tdLibWrapper->getUserInformation());
const TDLibWrapper::Group *group = tdLibWrapper->getGroup(chat->groupId);
if (group) {
chat->updateGroup(group);
}
if (chat->isHidden()) {
LOG("Hidden chat" << chat->chatId);
hiddenChats.insert(chat->chatId, chat);
} else {
addVisibleChat(chat);
// Start timestamp refresh timer when the first visible chat is discovered
if (!relativeTimeRefreshTimer->isActive()) {
relativeTimeRefreshTimer->start();
}
}
}
void ChatListModel::handleChatLastMessageUpdated(const QString &chatId, const QString &order, const QVariantMap &lastMessage)
void ChatListModel::handleChatLastMessageUpdated(const QString &id, const QString &order, const QVariantMap &lastMessage)
{
bool ok;
const qlonglong chatId = id.toLongLong(&ok);
if (ok) {
if (chatIndexMap.contains(chatId)) {
int chatIndex = chatIndexMap.value(chatId);
LOG("Updating last message for chat" << chatId <<" at index" << chatIndex << "new order" << order);
@ -340,22 +494,44 @@ void ChatListModel::handleChatLastMessageUpdated(const QString &chatId, const QS
}
const QModelIndex modelIndex(index(chatIndex));
emit dataChanged(modelIndex, modelIndex, chat->updateLastMessage(lastMessage));
} else {
ChatData *chat = hiddenChats.value(chatId);
if (chat) {
LOG("Updating last message for hidden chat" << chatId << "new order" << order);
chat->setOrder(order);
chat->chatData.insert(LAST_MESSAGE, lastMessage);
}
}
}
}
void ChatListModel::handleChatOrderUpdated(const QString &chatId, const QString &order)
void ChatListModel::handleChatOrderUpdated(const QString &id, const QString &order)
{
bool ok;
const qlonglong chatId = id.toLongLong(&ok);
if (ok) {
if (chatIndexMap.contains(chatId)) {
LOG("Updating chat order of" << chatId << "to" << order);
int chatIndex = chatIndexMap.value(chatId);
if (chatList.at(chatIndex)->setOrder(order)) {
updateChatOrder(chatIndex);
}
} else {
ChatData *chat = hiddenChats.value(chatId);
if (chat) {
LOG("Updating order of hidden chat" << chatId << "to" << order);
chat->setOrder(order);
}
}
}
}
void ChatListModel::handleChatReadInboxUpdated(const QString &chatId, const QString &lastReadInboxMessageId, int unreadCount)
void ChatListModel::handleChatReadInboxUpdated(const QString &id, const QString &lastReadInboxMessageId, int unreadCount)
{
bool ok;
const qlonglong chatId = id.toLongLong(&ok);
if (ok) {
const qlonglong messageId = lastReadInboxMessageId.toLongLong();
if (chatIndexMap.contains(chatId)) {
LOG("Updating chat unread count for" << chatId << "unread messages" << unreadCount << ", last read message ID: " << lastReadInboxMessageId);
const int chatIndex = chatIndexMap.value(chatId);
@ -365,16 +541,27 @@ void ChatListModel::handleChatReadInboxUpdated(const QString &chatId, const QStr
if (chat->updateUnreadCount(unreadCount)) {
changedRoles.append(ChatData::RoleUnreadCount);
}
if (chat->updateLastReadInboxMessageId(lastReadInboxMessageId.toLongLong())) {
if (chat->updateLastReadInboxMessageId(messageId)) {
changedRoles.append(ChatData::RoleLastReadInboxMessageId);
}
const QModelIndex modelIndex(index(chatIndex));
emit dataChanged(modelIndex, modelIndex, changedRoles);
} else {
ChatData *chat = hiddenChats.value(chatId);
if (chat) {
LOG("Updating unread count for hidden chat" << chatId << "unread messages" << unreadCount << ", last read message ID: " << lastReadInboxMessageId);
chat->updateUnreadCount(unreadCount);
chat->updateLastReadInboxMessageId(messageId);
}
}
}
}
void ChatListModel::handleChatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId)
void ChatListModel::handleChatReadOutboxUpdated(const QString &id, const QString &lastReadOutboxMessageId)
{
bool ok;
const qlonglong chatId = id.toLongLong(&ok);
if (ok) {
if (chatIndexMap.contains(chatId)) {
LOG("Updating last read message for" << chatId << "last ID" << lastReadOutboxMessageId);
const int chatIndex = chatIndexMap.value(chatId);
@ -382,22 +569,40 @@ void ChatListModel::handleChatReadOutboxUpdated(const QString &chatId, const QSt
chat->chatData.insert(LAST_READ_OUTBOX_MESSAGE_ID, lastReadOutboxMessageId);
const QModelIndex modelIndex(index(chatIndex));
emit dataChanged(modelIndex, modelIndex);
} else {
ChatData *chat = hiddenChats.value(chatId);
if (chat) {
chat->chatData.insert(LAST_READ_OUTBOX_MESSAGE_ID, lastReadOutboxMessageId);
}
}
}
}
void ChatListModel::handleMessageSendSucceeded(const QString &messageId, const QString &oldMessageId, const QVariantMap &message)
{
const QString chatId(message.value(CHAT_ID).toString());
bool ok;
const qlonglong chatId(message.value(CHAT_ID).toLongLong(&ok));
if (ok) {
if (chatIndexMap.contains(chatId)) {
const int chatIndex = chatIndexMap.value(chatId);
LOG("Updating last message for chat" << chatId << "at index" << chatIndex << ", as message was sent, old ID:" << oldMessageId << ", new ID:" << messageId);
const QModelIndex modelIndex(index(chatIndex));
emit dataChanged(modelIndex, modelIndex, chatList.at(chatIndex)->updateLastMessage(message));
} else {
ChatData *chat = hiddenChats.value(chatId);
if (chat) {
LOG("Updating last message for hidden chat" << chatId << ", as message was sent, old ID:" << oldMessageId << ", new ID:" << messageId);
chat->chatData.insert(LAST_MESSAGE, message);
}
}
}
}
void ChatListModel::handleChatNotificationSettingsUpdated(const QString &chatId, const QVariantMap &chatNotificationSettings)
void ChatListModel::handleChatNotificationSettingsUpdated(const QString &id, const QVariantMap &chatNotificationSettings)
{
bool ok;
const qlonglong chatId = id.toLongLong(&ok);
if (ok) {
if (chatIndexMap.contains(chatId)) {
const int chatIndex = chatIndexMap.value(chatId);
LOG("Updating notification settings for chat" << chatId << "at index" << chatIndex);
@ -405,8 +610,19 @@ void ChatListModel::handleChatNotificationSettingsUpdated(const QString &chatId,
chat->chatData.insert(NOTIFICATION_SETTINGS, chatNotificationSettings);
const QModelIndex modelIndex(index(chatIndex));
emit dataChanged(modelIndex, modelIndex);
} else {
ChatData *chat = hiddenChats.value(chatId);
if (chat) {
chat->chatData.insert(NOTIFICATION_SETTINGS, chatNotificationSettings);
}
}
}
}
void ChatListModel::handleGroupUpdated(qlonglong groupId)
{
updateChatVisibility(tdLibWrapper->getGroup(groupId));
}
void ChatListModel::handleRelativeTimeRefreshTimer()
{

View file

@ -26,6 +26,8 @@
class ChatListModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(bool showAllChats READ showAllChats WRITE setShowAllChats NOTIFY showAllChatsChanged)
public:
ChatListModel(TDLibWrapper *tdLibWrapper);
~ChatListModel() override;
@ -36,6 +38,9 @@ public:
Q_INVOKABLE void redrawModel();
bool showAllChats() const;
void setShowAllChats(bool showAll);
private slots:
void handleChatDiscovered(const QString &chatId, const QVariantMap &chatInformation);
void handleChatLastMessageUpdated(const QString &chatId, const QString &order, const QVariantMap &lastMessage);
@ -44,18 +49,25 @@ private slots:
void handleChatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId);
void handleMessageSendSucceeded(const QString &messageId, const QString &oldMessageId, const QVariantMap &message);
void handleChatNotificationSettingsUpdated(const QString &chatId, const QVariantMap &chatNotificationSettings);
void handleGroupUpdated(qlonglong groupId);
void handleRelativeTimeRefreshTimer();
private:
int updateChatOrder(int chatIndex);
signals:
void showAllChatsChanged();
private:
class ChatData;
void addVisibleChat(ChatData *chat);
void updateChatVisibility(const TDLibWrapper::Group *group);
int updateChatOrder(int chatIndex);
private:
TDLibWrapper *tdLibWrapper;
QTimer *relativeTimeRefreshTimer;
QList<ChatData*> chatList;
QHash<QString,int> chatIndexMap;
QHash<qlonglong,int> chatIndexMap;
QHash<qlonglong,ChatData*> hiddenChats;
bool showHiddenChats;
};
#endif // CHATLISTMODEL_H

View file

@ -27,6 +27,8 @@ namespace {
const QString POSITION("position");
const QString POSITIONS("positions");
const QString ORDER("order");
const QString BASIC_GROUP("basic_group");
const QString SUPERGROUP("supergroup");
const QString LAST_MESSAGE("last_message");
const QString UNREAD_COUNT("unread_count");
const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id");
@ -264,16 +266,18 @@ void TDLibReceiver::processUpdateChatReadOutbox(const QVariantMap &receivedInfor
void TDLibReceiver::processUpdateBasicGroup(const QVariantMap &receivedInformation)
{
QString basicGroupId = receivedInformation.value("basic_group").toMap().value(ID).toString();
const QVariantMap basicGroup(receivedInformation.value(BASIC_GROUP).toMap());
const qlonglong basicGroupId = basicGroup.value(ID).toLongLong();
LOG("Basic group information updated for " << basicGroupId);
emit basicGroupUpdated(basicGroupId, receivedInformation.value("basic_group").toMap());
emit basicGroupUpdated(basicGroupId, basicGroup);
}
void TDLibReceiver::processUpdateSuperGroup(const QVariantMap &receivedInformation)
{
QString superGroupId = receivedInformation.value("supergroup").toMap().value(ID).toString();
const QVariantMap supergroup(receivedInformation.value(SUPERGROUP).toMap());
const qlonglong superGroupId = supergroup.value(ID).toLongLong();
LOG("Super group information updated for " << superGroupId);
emit superGroupUpdated(superGroupId, receivedInformation.value("supergroup").toMap());
emit superGroupUpdated(superGroupId, supergroup);
}
void TDLibReceiver::processChatOnlineMemberCountUpdated(const QVariantMap &receivedInformation)

View file

@ -50,8 +50,8 @@ signals:
void chatOrderUpdated(const QString &chatId, const QString &order);
void chatReadInboxUpdated(const QString &chatId, const QString &lastReadInboxMessageId, const int &unreadCount);
void chatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId);
void basicGroupUpdated(const QString &groupId, const QVariantMap &groupInformation);
void superGroupUpdated(const QString &groupId, const QVariantMap &groupInformation);
void basicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation);
void superGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation);
void chatOnlineMemberCountUpdated(const QString &chatId, const int &onlineMemberCount);
void messagesReceived(const QVariantList &messages);
void newMessageReceived(const QString &chatId, const QVariantMap &message);

View file

@ -38,6 +38,11 @@
# define VERBOSE(x)
#endif
namespace {
const QString STATUS("status");
const QString _TYPE("@type");
}
TDLibWrapper::TDLibWrapper(QObject *parent) : QObject(parent), settings("harbour-fernschreiber", "settings")
{
LOG("Initializing TD Lib...");
@ -67,8 +72,8 @@ TDLibWrapper::TDLibWrapper(QObject *parent) : QObject(parent), settings("harbour
connect(this->tdLibReceiver, SIGNAL(chatOrderUpdated(QString, QString)), this, SLOT(handleChatOrderUpdated(QString, QString)));
connect(this->tdLibReceiver, SIGNAL(chatReadInboxUpdated(QString, QString, int)), this, SLOT(handleChatReadInboxUpdated(QString, QString, int)));
connect(this->tdLibReceiver, SIGNAL(chatReadOutboxUpdated(QString, QString)), this, SLOT(handleChatReadOutboxUpdated(QString, QString)));
connect(this->tdLibReceiver, SIGNAL(basicGroupUpdated(QString, QVariantMap)), this, SLOT(handleBasicGroupUpdated(QString, QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(superGroupUpdated(QString, QVariantMap)), this, SLOT(handleSuperGroupUpdated(QString, QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(basicGroupUpdated(qlonglong, QVariantMap)), this, SLOT(handleBasicGroupUpdated(qlonglong, QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(superGroupUpdated(qlonglong, QVariantMap)), this, SLOT(handleSuperGroupUpdated(qlonglong, QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(chatOnlineMemberCountUpdated(QString, int)), this, SLOT(handleChatOnlineMemberCountUpdated(QString, int)));
connect(this->tdLibReceiver, SIGNAL(messagesReceived(QVariantList)), this, SLOT(handleMessagesReceived(QVariantList)));
connect(this->tdLibReceiver, SIGNAL(newMessageReceived(QString, QVariantMap)), this, SLOT(handleNewMessageReceived(QString, QVariantMap)));
@ -94,12 +99,14 @@ TDLibWrapper::~TDLibWrapper()
while (this->tdLibReceiver->isRunning()) {
QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
}
qDeleteAll(basicGroups.values());
qDeleteAll(superGroups.values());
td_json_client_destroy(this->tdLibClient);
}
void TDLibWrapper::sendRequest(const QVariantMap &requestObject)
{
LOG("Sending request to TD Lib, object type name:" << requestObject.value("@type").toString());
LOG("Sending request to TD Lib, object type name:" << requestObject.value(_TYPE).toString());
QJsonDocument requestDocument = QJsonDocument::fromVariant(requestObject);
VERBOSE(requestDocument.toJson().constData());
td_json_client_send(this->tdLibClient, requestDocument.toJson().constData());
@ -124,7 +131,7 @@ void TDLibWrapper::setAuthenticationPhoneNumber(const QString &phoneNumber)
{
LOG("Set authentication phone number " << phoneNumber);
QVariantMap requestObject;
requestObject.insert("@type", "setAuthenticationPhoneNumber");
requestObject.insert(_TYPE, "setAuthenticationPhoneNumber");
requestObject.insert("phone_number", phoneNumber);
QVariantMap phoneNumberSettings;
phoneNumberSettings.insert("allow_flash_call", false);
@ -137,7 +144,7 @@ void TDLibWrapper::setAuthenticationCode(const QString &authenticationCode)
{
LOG("Set authentication code " << authenticationCode);
QVariantMap requestObject;
requestObject.insert("@type", "checkAuthenticationCode");
requestObject.insert(_TYPE, "checkAuthenticationCode");
requestObject.insert("code", authenticationCode);
this->sendRequest(requestObject);
}
@ -146,7 +153,7 @@ void TDLibWrapper::setAuthenticationPassword(const QString &authenticationPasswo
{
LOG("Set authentication password " << authenticationPassword);
QVariantMap requestObject;
requestObject.insert("@type", "checkAuthenticationPassword");
requestObject.insert(_TYPE, "checkAuthenticationPassword");
requestObject.insert("password", authenticationPassword);
this->sendRequest(requestObject);
}
@ -155,7 +162,7 @@ void TDLibWrapper::getChats()
{
LOG("Getting chats");
QVariantMap requestObject;
requestObject.insert("@type", "getChats");
requestObject.insert(_TYPE, "getChats");
requestObject.insert("limit", 5);
this->sendRequest(requestObject);
}
@ -164,7 +171,7 @@ void TDLibWrapper::downloadFile(const QString &fileId)
{
LOG("Downloading file " << fileId);
QVariantMap requestObject;
requestObject.insert("@type", "downloadFile");
requestObject.insert(_TYPE, "downloadFile");
requestObject.insert("file_id", fileId);
requestObject.insert("synchronous", false);
requestObject.insert("offset", 0);
@ -177,7 +184,7 @@ void TDLibWrapper::openChat(const QString &chatId)
{
LOG("Opening chat " << chatId);
QVariantMap requestObject;
requestObject.insert("@type", "openChat");
requestObject.insert(_TYPE, "openChat");
requestObject.insert("chat_id", chatId);
this->sendRequest(requestObject);
}
@ -186,7 +193,7 @@ void TDLibWrapper::closeChat(const QString &chatId)
{
LOG("Closing chat " << chatId);
QVariantMap requestObject;
requestObject.insert("@type", "closeChat");
requestObject.insert(_TYPE, "closeChat");
requestObject.insert("chat_id", chatId);
this->sendRequest(requestObject);
}
@ -195,7 +202,7 @@ void TDLibWrapper::getChatHistory(const QString &chatId, const qlonglong &fromMe
{
LOG("Retrieving chat history" << chatId << fromMessageId << offset << limit << onlyLocal);
QVariantMap requestObject;
requestObject.insert("@type", "getChatHistory");
requestObject.insert(_TYPE, "getChatHistory");
requestObject.insert("chat_id", chatId);
requestObject.insert("from_message_id", fromMessageId);
requestObject.insert("offset", offset);
@ -208,7 +215,7 @@ void TDLibWrapper::viewMessage(const QString &chatId, const QString &messageId)
{
LOG("Mark message as viewed" << chatId << messageId);
QVariantMap requestObject;
requestObject.insert("@type", "viewMessages");
requestObject.insert(_TYPE, "viewMessages");
requestObject.insert("chat_id", chatId);
requestObject.insert("force_read", false);
QVariantList messageIds;
@ -221,16 +228,16 @@ void TDLibWrapper::sendTextMessage(const QString &chatId, const QString &message
{
LOG("Sending text message" << chatId << message << replyToMessageId);
QVariantMap requestObject;
requestObject.insert("@type", "sendMessage");
requestObject.insert(_TYPE, "sendMessage");
requestObject.insert("chat_id", chatId);
if (replyToMessageId != "0") {
requestObject.insert("reply_to_message_id", replyToMessageId);
}
QVariantMap inputMessageContent;
inputMessageContent.insert("@type", "inputMessageText");
inputMessageContent.insert(_TYPE, "inputMessageText");
QVariantMap formattedText;
formattedText.insert("text", message);
formattedText.insert("@type", "formattedText");
formattedText.insert(_TYPE, "formattedText");
inputMessageContent.insert("text", formattedText);
requestObject.insert("input_message_content", inputMessageContent);
this->sendRequest(requestObject);
@ -240,19 +247,19 @@ void TDLibWrapper::sendPhotoMessage(const QString &chatId, const QString &filePa
{
LOG("Sending photo message" << chatId << filePath << message << replyToMessageId);
QVariantMap requestObject;
requestObject.insert("@type", "sendMessage");
requestObject.insert(_TYPE, "sendMessage");
requestObject.insert("chat_id", chatId);
if (replyToMessageId != "0") {
requestObject.insert("reply_to_message_id", replyToMessageId);
}
QVariantMap inputMessageContent;
inputMessageContent.insert("@type", "inputMessagePhoto");
inputMessageContent.insert(_TYPE, "inputMessagePhoto");
QVariantMap formattedText;
formattedText.insert("text", message);
formattedText.insert("@type", "formattedText");
formattedText.insert(_TYPE, "formattedText");
inputMessageContent.insert("caption", formattedText);
QVariantMap photoInputFile;
photoInputFile.insert("@type", "inputFileLocal");
photoInputFile.insert(_TYPE, "inputFileLocal");
photoInputFile.insert("path", filePath);
inputMessageContent.insert("photo", photoInputFile);
@ -264,19 +271,19 @@ void TDLibWrapper::sendVideoMessage(const QString &chatId, const QString &filePa
{
LOG("Sending video message" << chatId << filePath << message << replyToMessageId);
QVariantMap requestObject;
requestObject.insert("@type", "sendMessage");
requestObject.insert(_TYPE, "sendMessage");
requestObject.insert("chat_id", chatId);
if (replyToMessageId != "0") {
requestObject.insert("reply_to_message_id", replyToMessageId);
}
QVariantMap inputMessageContent;
inputMessageContent.insert("@type", "inputMessageVideo");
inputMessageContent.insert(_TYPE, "inputMessageVideo");
QVariantMap formattedText;
formattedText.insert("text", message);
formattedText.insert("@type", "formattedText");
formattedText.insert(_TYPE, "formattedText");
inputMessageContent.insert("caption", formattedText);
QVariantMap videoInputFile;
videoInputFile.insert("@type", "inputFileLocal");
videoInputFile.insert(_TYPE, "inputFileLocal");
videoInputFile.insert("path", filePath);
inputMessageContent.insert("video", videoInputFile);
@ -288,19 +295,19 @@ void TDLibWrapper::sendDocumentMessage(const QString &chatId, const QString &fil
{
LOG("Sending document message" << chatId << filePath << message << replyToMessageId);
QVariantMap requestObject;
requestObject.insert("@type", "sendMessage");
requestObject.insert(_TYPE, "sendMessage");
requestObject.insert("chat_id", chatId);
if (replyToMessageId != "0") {
requestObject.insert("reply_to_message_id", replyToMessageId);
}
QVariantMap inputMessageContent;
inputMessageContent.insert("@type", "inputMessageDocument");
inputMessageContent.insert(_TYPE, "inputMessageDocument");
QVariantMap formattedText;
formattedText.insert("text", message);
formattedText.insert("@type", "formattedText");
formattedText.insert(_TYPE, "formattedText");
inputMessageContent.insert("caption", formattedText);
QVariantMap documentInputFile;
documentInputFile.insert("@type", "inputFileLocal");
documentInputFile.insert(_TYPE, "inputFileLocal");
documentInputFile.insert("path", filePath);
inputMessageContent.insert("document", documentInputFile);
@ -312,7 +319,7 @@ void TDLibWrapper::getMessage(const QString &chatId, const QString &messageId)
{
LOG("Retrieving message" << chatId << messageId);
QVariantMap requestObject;
requestObject.insert("@type", "getMessage");
requestObject.insert(_TYPE, "getMessage");
requestObject.insert("chat_id", chatId);
requestObject.insert("message_id", messageId);
this->sendRequest(requestObject);
@ -322,10 +329,10 @@ void TDLibWrapper::setOptionInteger(const QString &optionName, const int &option
{
LOG("Setting integer option" << optionName << optionValue);
QVariantMap requestObject;
requestObject.insert("@type", "setOption");
requestObject.insert(_TYPE, "setOption");
requestObject.insert("name", optionName);
QVariantMap optionValueMap;
optionValueMap.insert("@type", "optionValueInteger");
optionValueMap.insert(_TYPE, "optionValueInteger");
optionValueMap.insert("value", optionValue);
requestObject.insert("value", optionValueMap);
this->sendRequest(requestObject);
@ -335,7 +342,7 @@ void TDLibWrapper::setChatNotificationSettings(const QString &chatId, const QVar
{
LOG("Notification settings for chat " << chatId << notificationSettings);
QVariantMap requestObject;
requestObject.insert("@type", "setChatNotificationSettings");
requestObject.insert(_TYPE, "setChatNotificationSettings");
requestObject.insert("chat_id", chatId);
requestObject.insert("notification_settings", notificationSettings);
this->sendRequest(requestObject);
@ -345,11 +352,11 @@ void TDLibWrapper::editMessageText(const QString &chatId, const QString &message
{
LOG("Editing message text" << chatId << messageId);
QVariantMap requestObject;
requestObject.insert("@type", "editMessageText");
requestObject.insert(_TYPE, "editMessageText");
requestObject.insert("chat_id", chatId);
requestObject.insert("message_id", messageId);
QVariantMap inputMessageContent;
inputMessageContent.insert("@type", "inputMessageText");
inputMessageContent.insert(_TYPE, "inputMessageText");
QVariantMap formattedText;
formattedText.insert("text", message);
inputMessageContent.insert("text", formattedText);
@ -361,7 +368,7 @@ void TDLibWrapper::deleteMessages(const QString &chatId, const QVariantList mess
{
LOG("Deleting some messages" << chatId << messageIds);
QVariantMap requestObject;
requestObject.insert("@type", "deleteMessages");
requestObject.insert(_TYPE, "deleteMessages");
requestObject.insert("chat_id", chatId);
requestObject.insert("message_ids", messageIds);
requestObject.insert("revoke", true);
@ -380,7 +387,7 @@ void TDLibWrapper::getMapThumbnailFile(const QString &chatId, const double &lati
int boundsHeight = std::min(std::max(height, 16), 1024);
QVariantMap requestObject;
requestObject.insert("@type", "getMapThumbnailFile");
requestObject.insert(_TYPE, "getMapThumbnailFile");
requestObject.insert("location", location);
requestObject.insert("zoom", 17); //13-20
requestObject.insert("width", boundsWidth);
@ -412,16 +419,28 @@ QVariantMap TDLibWrapper::getUnreadChatInformation()
return this->unreadChatInformation;
}
QVariantMap TDLibWrapper::getBasicGroup(const QString &groupId)
QVariantMap TDLibWrapper::getBasicGroup(qlonglong groupId) const
{
const Group* group = basicGroups.value(groupId);
if (group) {
LOG("Returning basic group information for ID" << groupId);
return this->basicGroups.value(groupId).toMap();
return group->groupInfo;
} else {
LOG("No super group information for ID" << groupId);
return QVariantMap();
}
}
QVariantMap TDLibWrapper::getSuperGroup(const QString &groupId)
QVariantMap TDLibWrapper::getSuperGroup(qlonglong groupId) const
{
const Group* group = superGroups.value(groupId);
if (group) {
LOG("Returning super group information for ID" << groupId);
return this->superGroups.value(groupId).toMap();
return group->groupInfo;
} else {
LOG("No super group information for ID" << groupId);
return QVariantMap();
}
}
QVariantMap TDLibWrapper::getChat(const QString &chatId)
@ -595,7 +614,7 @@ void TDLibWrapper::handleUserStatusUpdated(const QString &userId, const QVariant
LOG("Own user status information updated :)");
this->userInformation.insert("status", userStatusInformation);
}
LOG("User status information updated:" << userId << userStatusInformation.value("@type").toString());
LOG("User status information updated:" << userId << userStatusInformation.value(_TYPE).toString());
QVariantMap updatedUserInformation = this->allUsers.value(userId).toMap();
updatedUserInformation.insert("status", userStatusInformation);
this->allUsers.insert(userId, updatedUserInformation);
@ -650,16 +669,14 @@ void TDLibWrapper::handleChatReadOutboxUpdated(const QString &chatId, const QStr
emit chatReadOutboxUpdated(chatId, lastReadOutboxMessageId);
}
void TDLibWrapper::handleBasicGroupUpdated(const QString &groupId, const QVariantMap &groupInformation)
void TDLibWrapper::handleBasicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation)
{
this->basicGroups.insert(groupId, groupInformation);
emit basicGroupUpdated(groupId, groupInformation);
emit basicGroupUpdated(updateGroup(groupId, groupInformation, &basicGroups)->groupId);
}
void TDLibWrapper::handleSuperGroupUpdated(const QString &groupId, const QVariantMap &groupInformation)
void TDLibWrapper::handleSuperGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation)
{
this->superGroups.insert(groupId, groupInformation);
emit superGroupUpdated(groupId, groupInformation);
emit superGroupUpdated(updateGroup(groupId, groupInformation, &superGroups)->groupId);
}
void TDLibWrapper::handleChatOnlineMemberCountUpdated(const QString &chatId, const int &onlineMemberCount)
@ -721,7 +738,7 @@ void TDLibWrapper::setInitialParameters()
{
LOG("Sending initial parameters to TD Lib");
QVariantMap requestObject;
requestObject.insert("@type", "setTdlibParameters");
requestObject.insert(_TYPE, "setTdlibParameters");
QVariantMap initialParameters;
initialParameters.insert("api_id", TDLIB_API_ID);
initialParameters.insert("api_hash", TDLIB_API_HASH);
@ -743,7 +760,7 @@ void TDLibWrapper::setEncryptionKey()
{
LOG("Setting database encryption key");
QVariantMap requestObject;
requestObject.insert("@type", "checkDatabaseEncryptionKey");
requestObject.insert(_TYPE, "checkDatabaseEncryptionKey");
// see https://github.com/tdlib/td/issues/188#issuecomment-379536139
requestObject.insert("encryption_key", "");
this->sendRequest(requestObject);
@ -753,7 +770,7 @@ void TDLibWrapper::setLogVerbosityLevel()
{
LOG("Setting log verbosity level to something less chatty");
QVariantMap requestObject;
requestObject.insert("@type", "setLogVerbosityLevel");
requestObject.insert(_TYPE, "setLogVerbosityLevel");
requestObject.insert("new_verbosity_level", 2);
this->sendRequest(requestObject);
}
@ -784,3 +801,40 @@ void TDLibWrapper::initializeOpenWith()
}
}
const TDLibWrapper::Group *TDLibWrapper::updateGroup(qlonglong groupId, const QVariantMap &groupInfo, QHash<qlonglong,Group*> *groups)
{
Group* group = groups->value(groupId);
if (!group) {
group = new Group(groupId);
groups->insert(groupId, group);
}
group->groupInfo = groupInfo;
return group;
}
const TDLibWrapper::Group* TDLibWrapper::getGroup(qlonglong groupId) const
{
if (groupId) {
const Group* group = superGroups.value(groupId);
return group ? group : basicGroups.value(groupId);
}
return Q_NULLPTR;
}
TDLibWrapper::ChatMemberStatus TDLibWrapper::chatMemberStatusFromString(const QString &status)
{
// Most common ones first
return (status == QStringLiteral("chatMemberStatusMember")) ? ChatMemberStatusMember :
(status == QStringLiteral("chatMemberStatusLeft")) ? ChatMemberStatusLeft :
(status == QStringLiteral("chatMemberStatusCreator")) ? ChatMemberStatusCreator :
(status == QStringLiteral("chatMemberStatusAdministrator")) ? ChatMemberStatusAdministrator :
(status == QStringLiteral("chatMemberStatusRestricted")) ? ChatMemberStatusRestricted :
(status == QStringLiteral("chatMemberStatusBanned")) ? ChatMemberStatusBanned :
ChatMemberStatusUnknown;
}
TDLibWrapper::ChatMemberStatus TDLibWrapper::Group::chatMemberStatus() const
{
const QString statusType(groupInfo.value(STATUS).toMap().value(_TYPE).toString());
return statusType.isEmpty() ? ChatMemberStatusUnknown : chatMemberStatusFromString(statusType);
}

View file

@ -61,6 +61,35 @@ public:
};
Q_ENUM(ConnectionState)
enum ChatType {
ChatTypeUnknown,
ChatTypePrivate,
ChatTypeBasicGroup,
ChatTypeSupergroup,
ChatTypeSecret
};
Q_ENUM(ChatType)
enum ChatMemberStatus {
ChatMemberStatusUnknown,
ChatMemberStatusCreator,
ChatMemberStatusAdministrator,
ChatMemberStatusMember,
ChatMemberStatusRestricted,
ChatMemberStatusLeft,
ChatMemberStatusBanned
};
Q_ENUM(ChatMemberStatus)
class Group {
public:
Group(qlonglong id) : groupId(id) { }
ChatMemberStatus chatMemberStatus() const;
public:
const qlonglong groupId;
QVariantMap groupInfo;
};
Q_INVOKABLE QString getVersion();
Q_INVOKABLE TDLibWrapper::AuthorizationState getAuthorizationState();
Q_INVOKABLE TDLibWrapper::ConnectionState getConnectionState();
@ -68,8 +97,8 @@ public:
Q_INVOKABLE QVariantMap getUserInformation(const QString &userId);
Q_INVOKABLE QVariantMap getUnreadMessageInformation();
Q_INVOKABLE QVariantMap getUnreadChatInformation();
Q_INVOKABLE QVariantMap getBasicGroup(const QString &groupId);
Q_INVOKABLE QVariantMap getSuperGroup(const QString &groupId);
Q_INVOKABLE QVariantMap getBasicGroup(qlonglong groupId) const;
Q_INVOKABLE QVariantMap getSuperGroup(qlonglong groupId) const;
Q_INVOKABLE QVariantMap getChat(const QString &chatId);
Q_INVOKABLE void copyFileToDownloads(const QString &filePath);
Q_INVOKABLE void openFileOnDevice(const QString &filePath);
@ -101,6 +130,10 @@ public:
Q_INVOKABLE void deleteMessages(const QString &chatId, const QVariantList messageIds);
Q_INVOKABLE void getMapThumbnailFile(const QString &chatId, const double &latitude, const double &longitude, const int &width, const int &height);
public:
const Group* getGroup(qlonglong groupId) const;
static ChatMemberStatus chatMemberStatusFromString(const QString &status);
signals:
void versionDetected(const QString &version);
void ownUserIdFound(const QString &ownUserId);
@ -116,8 +149,8 @@ signals:
void chatReadInboxUpdated(const QString &chatId, const QString &lastReadInboxMessageId, const int &unreadCount);
void chatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId);
void userUpdated(const QString &userId, const QVariantMap &userInformation);
void basicGroupUpdated(const QString &groupId, const QVariantMap &groupInformation);
void superGroupUpdated(const QString &groupId, const QVariantMap &groupInformation);
void basicGroupUpdated(qlonglong groupId);
void superGroupUpdated(qlonglong groupId);
void chatOnlineMemberCountUpdated(const QString &chatId, const int &onlineMemberCount);
void messagesReceived(const QVariantList &messages);
void newMessageReceived(const QString &chatId, const QVariantMap &message);
@ -147,8 +180,8 @@ public slots:
void handleChatOrderUpdated(const QString &chatId, const QString &order);
void handleChatReadInboxUpdated(const QString &chatId, const QString &lastReadInboxMessageId, const int &unreadCount);
void handleChatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId);
void handleBasicGroupUpdated(const QString &groupId, const QVariantMap &groupInformation);
void handleSuperGroupUpdated(const QString &groupId, const QVariantMap &groupInformation);
void handleBasicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation);
void handleSuperGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation);
void handleChatOnlineMemberCountUpdated(const QString &chatId, const int &onlineMemberCount);
void handleMessagesReceived(const QVariantList &messages);
void handleNewMessageReceived(const QString &chatId, const QVariantMap &message);
@ -161,6 +194,13 @@ public slots:
void handleMessageContentUpdated(const QString &chatId, const QString &messageId, const QVariantMap &newContent);
void handleMessagesDeleted(const QString &chatId, const QVariantList &messageIds);
private:
void setInitialParameters();
void setEncryptionKey();
void setLogVerbosityLevel();
void initializeOpenWith();
const Group *updateGroup(qlonglong groupId, const QVariantMap &groupInfo, QHash<qlonglong,Group*> *groups);
private:
void *tdLibClient;
TDLibReceiver *tdLibReceiver;
@ -174,15 +214,9 @@ private:
QVariantMap chats;
QVariantMap unreadMessageInformation;
QVariantMap unreadChatInformation;
QVariantMap basicGroups;
QVariantMap superGroups;
QHash<qlonglong,Group*> basicGroups;
QHash<qlonglong,Group*> superGroups;
QSettings settings;
void setInitialParameters();
void setEncryptionKey();
void setLogVerbosityLevel();
void initializeOpenWith();
};
#endif // TDLIBWRAPPER_H