File indexing completed on 2024-12-08 04:33:09

0001 /*
0002 
0003  * SPDX-FileCopyrightText: 2016 Riccardo Iaconelli <riccardo@kde.org>
0004  * SPDX-FileCopyrightText: 2017-2024 Laurent Montel <montel@kde.org>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.0-or-later
0007  *
0008  */
0009 
0010 #include "ddpclient.h"
0011 #include "messagequeue.h"
0012 #include "plugins/pluginauthenticationinterface.h"
0013 #include "rocketchataccount.h"
0014 #include "rocketchatbackend.h"
0015 #include "ruqola_ddpapi_command_debug.h"
0016 #include "ruqola_ddpapi_debug.h"
0017 #include "ruqolalogger.h"
0018 #include "ruqolawebsocket.h"
0019 #include "utils.h"
0020 
0021 #include "ddpapi/ddpauthenticationmanager.h"
0022 #include "ddpapi/ddpmanager.h"
0023 
0024 #include <QJsonArray>
0025 #include <QJsonDocument>
0026 #include <QJsonObject>
0027 #include <QStandardPaths>
0028 
0029 namespace RuqolaTestWebSocket
0030 {
0031 LIBRUQOLACORE_EXPORT AbstractWebSocket *_k_ruqola_webSocket = nullptr;
0032 }
0033 
0034 void video_conference_call(const QJsonObject &root, RocketChatAccount *account)
0035 {
0036     qDebug() << "video_conference_call  root " << root;
0037     if (account->ruqolaLogger()) {
0038         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Video Conference Call:") + QJsonDocument(root).toJson());
0039     }
0040 }
0041 
0042 void video_conference_rejected(const QJsonObject &root, RocketChatAccount *account)
0043 {
0044     qDebug() << "video_conference_rejected  root " << root;
0045     if (account->ruqolaLogger()) {
0046         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Video Conference Rejected:") + QJsonDocument(root).toJson());
0047     }
0048 }
0049 
0050 void video_conference_accepted(const QJsonObject &root, RocketChatAccount *account)
0051 {
0052     qDebug() << "video_conference_accepted  root " << root;
0053     if (account->ruqolaLogger()) {
0054         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Video Conference Accepted:") + QJsonDocument(root).toJson());
0055     }
0056 }
0057 
0058 void video_conference_confirmed(const QJsonObject &root, RocketChatAccount *account)
0059 {
0060     qDebug() << "video_conference_confirmed  root " << root;
0061     if (account->ruqolaLogger()) {
0062         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Video Conference Confirmed:") + QJsonDocument(root).toJson());
0063     }
0064 }
0065 
0066 void license_get_modules(const QJsonObject &root, RocketChatAccount *account)
0067 {
0068     // qDebug() << " root " << root;
0069     if (account->ruqolaLogger()) {
0070         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("License GetModule:") + QJsonDocument(root).toJson());
0071     }
0072     const QJsonArray obj = root.value(QLatin1String("result")).toArray();
0073     account->parseLicenses(obj);
0074 }
0075 
0076 void banner_dismiss(const QJsonObject &root, RocketChatAccount *account)
0077 {
0078     // qDebug() << " root " << root;
0079     if (account->ruqolaLogger()) {
0080         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Banner Dismiss:") + QJsonDocument(root).toJson());
0081     }
0082 }
0083 
0084 void list_custom_sounds(const QJsonObject &root, RocketChatAccount *account)
0085 {
0086     qDebug() << " root " << root;
0087     if (account->ruqolaLogger()) {
0088         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("list custom sounds:") + QJsonDocument(root).toJson());
0089     }
0090     const QJsonArray obj = root.value(QLatin1String("result")).toArray();
0091     account->parseCustomSounds(obj);
0092 }
0093 
0094 void delete_oauth_app(const QJsonObject &root, RocketChatAccount *account)
0095 {
0096     if (account->ruqolaLogger()) {
0097         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Delete Oauth app:") + QJsonDocument(root).toJson());
0098     }
0099     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0100     qDebug() << "delete_oauth_app root " << root;
0101 }
0102 
0103 void update_oauth_app(const QJsonObject &root, RocketChatAccount *account)
0104 {
0105     if (account->ruqolaLogger()) {
0106         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Update Oauth App:") + QJsonDocument(root).toJson());
0107     }
0108     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0109     account->setOauthAppUpdated(obj);
0110     qDebug() << "update_oauth_app root " << root;
0111 }
0112 
0113 void add_oauth_app(const QJsonObject &root, RocketChatAccount *account)
0114 {
0115     if (account->ruqolaLogger()) {
0116         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Add Oauth App:") + QJsonDocument(root).toJson());
0117     }
0118     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0119     account->setOauthAppAdded(obj);
0120 }
0121 
0122 void admin_status(const QJsonObject &root, RocketChatAccount *account)
0123 {
0124     qDebug() << " root " << root;
0125     if (account->ruqolaLogger()) {
0126         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Admin Status:") + QJsonDocument(root).toJson());
0127     }
0128 }
0129 
0130 void block_user(const QJsonObject &root, RocketChatAccount *account)
0131 {
0132     if (account->ruqolaLogger()) {
0133         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Block User:") + QJsonDocument(root).toJson());
0134     }
0135 }
0136 
0137 void unblock_user(const QJsonObject &root, RocketChatAccount *account)
0138 {
0139     if (account->ruqolaLogger()) {
0140         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("UnBlock User:") + QJsonDocument(root).toJson());
0141     }
0142 }
0143 
0144 void delete_custom_sound(const QJsonObject &root, RocketChatAccount *account)
0145 {
0146     if (account->ruqolaLogger()) {
0147         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Delete Custom Sound:") + QJsonDocument(root).toJson());
0148     }
0149 }
0150 
0151 void update_custom_sound(const QJsonObject &root, RocketChatAccount *account)
0152 {
0153     if (account->ruqolaLogger()) {
0154         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Update Custom Sound:") + QJsonDocument(root).toJson());
0155     }
0156 }
0157 
0158 void validateTempToken_2fa(const QJsonObject &root, RocketChatAccount *account)
0159 {
0160     if (account->ruqolaLogger()) {
0161         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Validate Temp Token 2FA:") + QJsonDocument(root).toJson());
0162     }
0163     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0164     account->totpVerify(obj);
0165 }
0166 
0167 void disable_2fa(const QJsonObject &root, RocketChatAccount *account)
0168 {
0169     if (account->ruqolaLogger()) {
0170         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Disable 2FA:") + QJsonDocument(root).toJson());
0171     }
0172     account->totpDisabledVerify(root);
0173 }
0174 
0175 void regenerateCodes_2fa(const QJsonObject &root, RocketChatAccount *account)
0176 {
0177     if (account->ruqolaLogger()) {
0178         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Regenerate Codes 2FA:") + QJsonDocument(root).toJson());
0179     }
0180     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0181     // TODO
0182     qDebug() << " regenerateCodes_2fa " << root;
0183 }
0184 
0185 void enable_2fa(const QJsonObject &root, RocketChatAccount *account)
0186 {
0187     if (account->ruqolaLogger()) {
0188         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Enable 2FA:") + QJsonDocument(root).toJson());
0189     }
0190     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0191     account->generate2FaTotp(obj);
0192 }
0193 
0194 void otr_end(const QJsonObject &root, RocketChatAccount *account)
0195 {
0196     qDebug() << "otr_end  " << root;
0197     if (account->ruqolaLogger()) {
0198         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Otr End:") + QJsonDocument(root).toJson());
0199     }
0200 }
0201 
0202 void input_user_channel_autocomplete(const QJsonObject &root, RocketChatAccount *account)
0203 {
0204     if (account->ruqolaLogger()) {
0205         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Input channel/User autocomplete:") + QJsonDocument(root).toJson());
0206     }
0207     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0208     account->inputTextManager()->inputTextCompleter(obj);
0209 }
0210 
0211 void room_name_exist(const QJsonObject &root, RocketChatAccount *account)
0212 {
0213     if (account->ruqolaLogger()) {
0214         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Check if Room Name Exist:") + QJsonDocument(root).toJson());
0215     }
0216     Q_EMIT account->ddp()->result(root.value(QLatin1String("id")).toString().toULongLong(), QJsonDocument(root));
0217 }
0218 
0219 void input_user_channel_autocomplete_thread(const QJsonObject &root, RocketChatAccount *account)
0220 {
0221     if (account->ruqolaLogger()) {
0222         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Input channel/User autocomplete thread dialog:") + QJsonDocument(root).toJson());
0223     }
0224     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0225 
0226     account->inputThreadMessageTextManager()->inputTextCompleter(obj);
0227 }
0228 
0229 void process_backlog(const QJsonObject &root, RocketChatAccount *account)
0230 {
0231     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0232     // qCDebug(RUQOLA_DDPAPI_LOG) << obj.value(QLatin1String("messages")).toArray().size();
0233     account->rocketChatBackend()->processIncomingMessages(obj.value(QLatin1String("messages")).toArray(), true);
0234 }
0235 
0236 void change_room_settings(const QJsonObject &root, RocketChatAccount *account)
0237 {
0238     if (account->ruqolaLogger()) {
0239         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Change Room Settings:") + QJsonDocument(root).toJson());
0240     }
0241 }
0242 
0243 void create_jitsi_conf_call(const QJsonObject &root, RocketChatAccount *account)
0244 {
0245     if (account->ruqolaLogger()) {
0246         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Create Jitsi Conf Call:") + QJsonDocument(root).toJson());
0247     }
0248 }
0249 
0250 void open_direct_channel(const QJsonObject &root, RocketChatAccount *account)
0251 {
0252     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0253     // qDebug() << " void open_direct_channel(const QJsonObject &root, RocketChatAccount *account)" << obj;
0254     if (!obj.isEmpty()) {
0255         const QString rid = obj.value(QLatin1String("rid")).toString();
0256         if (!rid.isEmpty()) {
0257             account->ddp()->subscribeRoomMessage(rid);
0258         }
0259     }
0260     if (account->ruqolaLogger()) {
0261         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Open Direct channel:") + QJsonDocument(root).toJson());
0262     }
0263 }
0264 
0265 void get_room_by_id(const QJsonObject &obj, RocketChatAccount *account)
0266 {
0267     if (account->ruqolaLogger()) {
0268         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Get Room By ID :") + QJsonDocument(obj).toJson());
0269     }
0270 }
0271 
0272 void open_room(const QJsonObject &obj, RocketChatAccount *account)
0273 {
0274     if (account->ruqolaLogger()) {
0275         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Open Room :") + QJsonDocument(obj).toJson());
0276     }
0277 }
0278 
0279 void join_room(const QJsonObject &obj, RocketChatAccount *account)
0280 {
0281     if (account->ruqolaLogger()) {
0282         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Join Room :") + QJsonDocument(obj).toJson());
0283     }
0284 }
0285 
0286 void change_default_status(const QJsonObject &obj, RocketChatAccount *account)
0287 {
0288     if (account->ruqolaLogger()) {
0289         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Change Default Status :") + QJsonDocument(obj).toJson());
0290     }
0291 }
0292 
0293 void empty_callback(const QJsonObject &obj, RocketChatAccount *account)
0294 {
0295     if (account->ruqolaLogger()) {
0296         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Empty call back :") + QJsonDocument(obj).toJson());
0297     } else {
0298         qCWarning(RUQOLA_DDPAPI_LOG) << "empty_callback " << obj;
0299     }
0300 }
0301 
0302 DDPClient::DDPClient(RocketChatAccount *account, QObject *parent)
0303     : QObject(parent)
0304     , m_uid(1)
0305     , mRocketChatMessage(new RocketChatMessage)
0306     , mRocketChatAccount(account)
0307     , mAuthenticationManager(new DDPAuthenticationManager(this, this))
0308 {
0309 }
0310 
0311 DDPClient::~DDPClient()
0312 {
0313     disconnect(mWebSocket, &AbstractWebSocket::disconnected, this, &DDPClient::onWSclosed);
0314     mWebSocket->close();
0315     // Don't delete socket when we use specific socket.
0316     if (!RuqolaTestWebSocket::_k_ruqola_webSocket) {
0317         delete mWebSocket;
0318         mWebSocket = nullptr;
0319     }
0320     delete mRocketChatMessage;
0321     mRocketChatMessage = nullptr;
0322 }
0323 
0324 void DDPClient::setServerUrl(const QString &url)
0325 {
0326     mUrl = url;
0327 }
0328 
0329 void DDPClient::initializeWebSocket()
0330 {
0331     mWebSocket->ignoreSslErrors();
0332     connect(mWebSocket, &AbstractWebSocket::connected, this, &DDPClient::onWSConnected);
0333     connect(mWebSocket, &AbstractWebSocket::textMessageReceived, this, &DDPClient::onTextMessageReceived);
0334     connect(mWebSocket, &AbstractWebSocket::disconnected, this, &DDPClient::onWSclosed);
0335     connect(mWebSocket, &AbstractWebSocket::socketError, this, &DDPClient::socketError);
0336     connect(mWebSocket, &AbstractWebSocket::sslErrors, this, &DDPClient::onSslErrors);
0337 }
0338 
0339 void DDPClient::start()
0340 {
0341     if (!mWebSocket) {
0342         if (!RuqolaTestWebSocket::_k_ruqola_webSocket) {
0343             mWebSocket = new RuqolaWebSocket(mRocketChatAccount->ruqolaLogger(), this);
0344         } else {
0345             mWebSocket = RuqolaTestWebSocket::_k_ruqola_webSocket;
0346         }
0347         initializeWebSocket();
0348     }
0349     connect(mRocketChatAccount, &RocketChatAccount::serverUrlChanged, this, &DDPClient::onServerURLChange);
0350 
0351     if (!mUrl.isEmpty()) {
0352         const QUrl serverUrl = adaptUrl(mUrl);
0353         if (serverUrl.isValid()) {
0354             mWebSocket->openUrl(serverUrl);
0355             qCDebug(RUQOLA_DDPAPI_LOG) << "Trying to connect to URL" << serverUrl;
0356             Q_EMIT connecting();
0357         }
0358     } else {
0359         qCDebug(RUQOLA_DDPAPI_LOG) << "url is empty";
0360     }
0361 }
0362 
0363 void DDPClient::connectWebSocket()
0364 {
0365     mWebSocket->openUrl(adaptUrl(mUrl));
0366     qCDebug(RUQOLA_DDPAPI_LOG) << "Reconnecting" << mUrl;
0367 }
0368 
0369 QUrl DDPClient::adaptUrl(const QString &url)
0370 {
0371     return Utils::generateServerUrl(url);
0372 }
0373 
0374 void DDPClient::onServerURLChange()
0375 {
0376     if (mRocketChatAccount->settings()->serverUrl() != mUrl || !mWebSocket->isValid()) {
0377         if (mWebSocket->isValid()) {
0378             mWebSocket->flush();
0379             mWebSocket->close();
0380         }
0381         mUrl = mRocketChatAccount->settings()->serverUrl();
0382         connectWebSocket();
0383     }
0384 }
0385 
0386 DDPAuthenticationManager *DDPClient::authenticationManager() const
0387 {
0388     return mAuthenticationManager;
0389 }
0390 
0391 bool DDPClient::isConnected() const
0392 {
0393     return m_connected;
0394 }
0395 
0396 QString DDPClient::cachePath() const
0397 {
0398     return QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
0399 }
0400 
0401 QQueue<QPair<QString, QJsonDocument>> DDPClient::messageQueue() const
0402 {
0403     return m_messageQueue;
0404 }
0405 
0406 quint64 DDPClient::setRoomEncrypted(const QString &roomId, bool encrypted)
0407 {
0408     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setRoomEncrypted(roomId, encrypted, m_uid);
0409     return method(result, change_room_settings, DDPClient::Persistent);
0410 }
0411 
0412 void DDPClient::subscribeRoomMessage(const QString &roomId)
0413 {
0414     QJsonArray params;
0415     params.append(QJsonValue(roomId));
0416     subscribe(QStringLiteral("stream-room-messages"), params);
0417 
0418     const QJsonArray params2{QJsonValue(QStringLiteral("%1/%2").arg(roomId, QStringLiteral("deleteMessage")))};
0419     subscribe(QStringLiteral("stream-notify-room"), params2);
0420     const QJsonArray params3{QJsonValue(QStringLiteral("%1/%2").arg(roomId, QStringLiteral("deleteMessageBulk")))};
0421     subscribe(QStringLiteral("stream-notify-room"), params3);
0422     const QJsonArray params4{QJsonValue(QStringLiteral("%1/%2").arg(roomId, QStringLiteral("user-activity")))}; // It seems that it's the new "typing"
0423     subscribe(QStringLiteral("stream-notify-room"), params4);
0424 }
0425 
0426 quint64 DDPClient::openDirectChannel(const QString &userId)
0427 {
0428     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->openDirectChannel(userId, m_uid);
0429     return method(result, open_direct_channel, DDPClient::Persistent);
0430 }
0431 
0432 quint64 DDPClient::deleteFileMessage(const QString &roomId, const QString &fileid, Room::RoomType channelType)
0433 {
0434     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->deleteFileMessage(fileid, m_uid);
0435 
0436     std::function<void(QJsonObject, RocketChatAccount *)> callback = [roomId, channelType](const QJsonObject &root, RocketChatAccount *account) {
0437         if (account->ruqolaLogger()) {
0438             account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Delete Attachment File:") + QJsonDocument(root).toJson());
0439         } else {
0440             qCDebug(RUQOLA_DDPAPI_LOG) << " parse users for room" << roomId;
0441         }
0442         account->roomFiles(roomId, channelType);
0443     };
0444 
0445     return method(result, callback, DDPClient::Persistent);
0446 }
0447 
0448 quint64 DDPClient::openRoom(const QString &roomId)
0449 {
0450     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->openRoom(roomId, m_uid);
0451     return method(result, open_room, DDPClient::Persistent);
0452 }
0453 
0454 quint64 DDPClient::getRoomById(const QString &roomId)
0455 {
0456     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->getRoomById(roomId, m_uid);
0457     return method(result, get_room_by_id, DDPClient::Persistent);
0458 }
0459 
0460 quint64 DDPClient::joinRoom(const QString &roomId, const QString &joinCode)
0461 {
0462     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->joinRoom(roomId, joinCode, m_uid);
0463     return method(result, join_room, DDPClient::Persistent);
0464 }
0465 
0466 quint64 DDPClient::setDefaultStatus(User::PresenceStatus status)
0467 {
0468     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setDefaultStatus(status, m_uid);
0469     return method(result, change_default_status, DDPClient::Persistent);
0470 }
0471 
0472 quint64 DDPClient::userAutocomplete(const QString &pattern, const QString &exception)
0473 {
0474     const quint64 subscribeId = m_uid;
0475     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->userAutocomplete(pattern, exception, subscribeId);
0476     std::function<void(QJsonObject, RocketChatAccount *)> callback = [=](const QJsonObject &root, RocketChatAccount *account) {
0477         if (account->ruqolaLogger()) {
0478             account->ruqolaLogger()->dataReceived(QByteArrayLiteral("User AutoComplete:") + QJsonDocument(root).toJson());
0479         } else {
0480             qCDebug(RUQOLA_DDPAPI_LOG) << " User AutoComplete" << root;
0481         }
0482         account->insertCompleterUsers();
0483 
0484         const RocketChatMessage::RocketChatMessageResult resultUnsubscribe = mRocketChatMessage->unsubscribe(subscribeId);
0485         std::function<void(QJsonObject, RocketChatAccount *)> callbackUnsubscribeAutoComplete = [=](const QJsonObject &root, RocketChatAccount *account) {
0486             if (account->ruqolaLogger()) {
0487                 account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Unsubscribe AutoComplete:") + QJsonDocument(root).toJson());
0488             } else {
0489                 qDebug() << " Unsubscribe AutoComplete" << root;
0490                 qCDebug(RUQOLA_DDPAPI_LOG) << " Unsubscribe AutoComplete" << root;
0491             }
0492         };
0493         method(resultUnsubscribe, callbackUnsubscribeAutoComplete, DDPClient::Persistent);
0494     };
0495 
0496     return method(result, callback, DDPClient::Persistent);
0497 }
0498 
0499 quint64 DDPClient::createJitsiConfCall(const QString &roomId)
0500 {
0501     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->createJitsiConfCall(roomId, m_uid);
0502     return method(result, create_jitsi_conf_call, DDPClient::Persistent);
0503 }
0504 
0505 quint64 DDPClient::roomNameExists(const QString &roomName)
0506 {
0507     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->roomNameExists(roomName, m_uid);
0508     return method(result, room_name_exist, DDPClient::Persistent);
0509 }
0510 
0511 quint64 DDPClient::inputChannelAutocomplete(const QString &roomId, const QString &pattern, const QString &exceptions, bool threadDialog)
0512 {
0513     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->inputChannelAutocomplete(roomId, pattern, exceptions, m_uid);
0514     if (threadDialog) {
0515         return method(result, input_user_channel_autocomplete_thread, DDPClient::Persistent);
0516     } else {
0517         return method(result, input_user_channel_autocomplete, DDPClient::Persistent);
0518     }
0519 }
0520 
0521 quint64 DDPClient::inputUserAutocomplete(const QString &roomId, const QString &pattern, const QString &exceptions, bool threadDialog)
0522 {
0523     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->inputUserAutocomplete(roomId, pattern, exceptions, m_uid);
0524     if (threadDialog) {
0525         return method(result, input_user_channel_autocomplete_thread, DDPClient::Persistent);
0526     } else {
0527         return method(result, input_user_channel_autocomplete, DDPClient::Persistent);
0528     }
0529 }
0530 
0531 quint64 DDPClient::unBlockUser(const QString &rid, const QString &userId)
0532 {
0533     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->unblockUser(rid, userId, m_uid);
0534     return method(result, unblock_user, DDPClient::Persistent);
0535 }
0536 
0537 quint64 DDPClient::listCustomSounds()
0538 {
0539     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->listCustomSounds(m_uid);
0540     return method(result, list_custom_sounds, DDPClient::Persistent);
0541 }
0542 
0543 quint64 DDPClient::deleteCustomSound(const QString &identifier)
0544 {
0545     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->deleteCustomSound(identifier, m_uid);
0546     return method(result, delete_custom_sound, DDPClient::Persistent);
0547 }
0548 
0549 quint64 DDPClient::uploadCustomSound(const QByteArray &sound)
0550 {
0551     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->uploadCustomSound(sound, m_uid);
0552     return method(result, update_custom_sound, DDPClient::Persistent);
0553 }
0554 
0555 quint64 DDPClient::streamNotifyUserOtrEnd(const QString &roomId, const QString &userId)
0556 {
0557     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->streamNotifyUserOtrEnd(roomId, userId, m_uid);
0558     qDebug() << " result " << result;
0559     return method(result, otr_end, DDPClient::Persistent);
0560 }
0561 
0562 quint64 DDPClient::streamNotifyUserOtrHandshake(const QString &userFrom, const QString &userTo, const QString &publicKey)
0563 {
0564     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->streamNotifyUserOtrHandshake(userFrom, userTo, publicKey, m_uid);
0565     return method(result, otr_end, DDPClient::Persistent);
0566 }
0567 
0568 quint64 DDPClient::enable2fa()
0569 {
0570     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->enable2fa(m_uid);
0571     return method(result, enable_2fa, DDPClient::Persistent);
0572 }
0573 
0574 quint64 DDPClient::disable2fa(const QString &code)
0575 {
0576     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->disable2fa(code, m_uid);
0577     return method(result, disable_2fa, DDPClient::Persistent);
0578 }
0579 
0580 quint64 DDPClient::regenerateCodes2fa(const QString &code)
0581 {
0582     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->regenerateCodes2fa(code, m_uid);
0583     return method(result, regenerateCodes_2fa, DDPClient::Persistent);
0584 }
0585 
0586 quint64 DDPClient::validateTempToken2fa(const QString &code)
0587 {
0588     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->validateTempToken2fa(code, m_uid);
0589     return method(result, validateTempToken_2fa, DDPClient::Persistent);
0590 }
0591 
0592 quint64 DDPClient::streamNotifyUserOtrAcknowledge(const QString &roomId, const QString &userId, const QString &publicKey)
0593 {
0594     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->streamNotifyUserOtrAcknowledge(roomId, userId, publicKey, m_uid);
0595     qDebug() << "streamNotifyUserOtrAcknowledge result " << result;
0596     return method(result, otr_end, DDPClient::Persistent);
0597 }
0598 
0599 quint64 DDPClient::addOAuthApp(const QString &name, bool active, const QString &redirectUrl)
0600 {
0601     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->addOAuthApp(name, active, redirectUrl, m_uid);
0602     return method(result, add_oauth_app, DDPClient::Persistent);
0603 }
0604 
0605 quint64 DDPClient::updateOAuthApp(const QString &name, bool active, const QString &redirectUrl)
0606 {
0607     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->updateOAuthApp(name, active, redirectUrl, m_uid);
0608     return method(result, update_oauth_app, DDPClient::Persistent);
0609 }
0610 
0611 quint64 DDPClient::blockUser(const QString &rid, const QString &userId)
0612 {
0613     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->blockUser(rid, userId, m_uid);
0614     return method(result, block_user, DDPClient::Persistent);
0615 }
0616 
0617 quint64 DDPClient::setAdminStatus(const QString &userId, bool admin)
0618 {
0619     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setAdminStatus(userId, admin, m_uid);
0620     return method(result, admin_status, DDPClient::Persistent);
0621 }
0622 
0623 quint64 DDPClient::deleteOAuthApp(const QString &appId)
0624 {
0625     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->deleteOAuthApp(appId, m_uid);
0626     return method(result, delete_oauth_app, DDPClient::Persistent);
0627 }
0628 
0629 quint64 DDPClient::bannerDismiss(const QString &bannerId)
0630 {
0631     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->bannerDismiss(bannerId, m_uid);
0632     return method(result, banner_dismiss, DDPClient::Persistent);
0633 }
0634 
0635 quint64 DDPClient::licenseGetModules()
0636 {
0637     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->licenseGetModules(m_uid);
0638     return method(result, license_get_modules, DDPClient::Persistent);
0639 }
0640 
0641 quint64 DDPClient::videoConferenceAccepted(const QString &roomId, const QString &callId, const QString &userId)
0642 {
0643     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->videoConferenceAccepted(roomId, callId, userId, m_uid);
0644     return method(result, video_conference_accepted, DDPClient::Persistent);
0645 }
0646 
0647 quint64 DDPClient::videoConferenceRejected(const QString &roomId, const QString &callId, const QString &userId)
0648 {
0649     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->videoConferenceRejected(roomId, callId, userId, m_uid);
0650     return method(result, video_conference_rejected, DDPClient::Persistent);
0651 }
0652 
0653 quint64 DDPClient::videoConferenceConfirmed(const QString &roomId, const QString &callId, const QString &userId)
0654 {
0655     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->videoConferenceConfirmed(roomId, callId, userId, m_uid);
0656     return method(result, video_conference_confirmed, DDPClient::Persistent);
0657 }
0658 
0659 quint64 DDPClient::videoConferenceCall(const QString &roomId, const QString &callId, const QString &userId)
0660 {
0661     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->videoConferenceCall(roomId, callId, userId, m_uid);
0662     return method(result, video_conference_call, DDPClient::Persistent);
0663 }
0664 
0665 quint64 DDPClient::informTypingStatus(const QString &roomId, bool typing, const QString &userName)
0666 {
0667     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->informTypingStatus(roomId, userName, typing, m_uid);
0668     const qint64 bytes = mWebSocket->sendTextMessage(result.result);
0669     if (bytes < result.result.length()) {
0670         qCDebug(RUQOLA_DDPAPI_LOG) << "ERROR! I couldn't send all of my message. This is a bug! (try again)";
0671         qCDebug(RUQOLA_DDPAPI_LOG) << mWebSocket->isValid() << mWebSocket->error() << mWebSocket->requestUrl();
0672     } else {
0673         qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "Successfully sent " << result.result;
0674     }
0675     const quint64 value = m_uid;
0676     m_uid++;
0677     return value;
0678 }
0679 
0680 quint64 DDPClient::method(const RocketChatMessage::RocketChatMessageResult &result,
0681                           const std::function<void(QJsonObject, RocketChatAccount *)> &callback,
0682                           DDPClient::MessageType messageType)
0683 {
0684     qint64 bytes = mWebSocket->sendTextMessage(result.result);
0685     if (bytes < result.result.length()) {
0686         qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "ERROR! I couldn't send all of my message. This is a bug! (try again)";
0687         qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << mWebSocket->isValid() << mWebSocket->error() << mWebSocket->requestUrl();
0688 
0689         if (messageType == DDPClient::Persistent) {
0690             m_messageQueue.enqueue(qMakePair(result.method, result.jsonDocument));
0691             mRocketChatAccount->messageQueue()->processQueue();
0692         }
0693     } else {
0694         qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "Successfully sent " << result.result;
0695     }
0696 
0697     m_callbackHash[m_uid] = callback;
0698 
0699     const quint64 value = m_uid;
0700     m_uid++;
0701     return value;
0702 }
0703 
0704 quint64 DDPClient::method(const QString &m, const QJsonDocument &params, DDPClient::MessageType messageType)
0705 {
0706     return method(m, params, empty_callback, messageType);
0707 }
0708 
0709 quint64 DDPClient::method(const QString &method,
0710                           const QJsonDocument &params,
0711                           const std::function<void(QJsonObject, RocketChatAccount *)> &callback,
0712                           DDPClient::MessageType messageType)
0713 {
0714     const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->generateMethod(method, params, m_uid);
0715     qint64 bytes = mWebSocket->sendTextMessage(result.result);
0716     if (bytes < result.result.length()) {
0717         qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "ERROR! I couldn't send all of my message. This is a bug! (try again)";
0718         qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << mWebSocket->isValid() << mWebSocket->error() << mWebSocket->requestUrl();
0719 
0720         if (messageType == DDPClient::Persistent) {
0721             m_messageQueue.enqueue(qMakePair(result.method, result.jsonDocument));
0722             mRocketChatAccount->messageQueue()->processQueue();
0723         }
0724     } else {
0725         qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "Successfully sent " << result.result;
0726     }
0727 
0728     m_callbackHash[m_uid] = callback;
0729 
0730     const quint64 uidCurrent = m_uid;
0731     m_uid++;
0732     return uidCurrent;
0733 }
0734 
0735 void DDPClient::unsubscribe(quint64 registerId)
0736 {
0737     const RocketChatMessage::RocketChatMessageResult resultUnsubscribe = mRocketChatMessage->unsubscribe(registerId);
0738     std::function<void(QJsonObject, RocketChatAccount *)> callbackUnsubscribeMethod = [=](const QJsonObject &root, RocketChatAccount *account) {
0739         if (account->ruqolaLogger()) {
0740             account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Unsubscribe Method:") + QJsonDocument(root).toJson());
0741         } else {
0742             qDebug() << " Unsubscribe Method" << root;
0743             qCDebug(RUQOLA_DDPAPI_LOG) << " Unsubscribe Method" << root;
0744         }
0745     };
0746     method(resultUnsubscribe, callbackUnsubscribeMethod, DDPClient::Persistent);
0747 }
0748 
0749 quint64 DDPClient::subscribe(const QString &collection, const QJsonArray &params)
0750 {
0751     quint64 registerId = m_uid;
0752     QJsonObject json;
0753     json[QLatin1String("msg")] = QStringLiteral("sub");
0754     json[QLatin1String("id")] = QString::number(m_uid);
0755     json[QLatin1String("name")] = collection;
0756 
0757     QJsonArray newParams = params;
0758 
0759     if (mRocketChatAccount->needAdaptNewSubscriptionRC60()) {
0760         QJsonArray args;
0761         QJsonObject obj;
0762         obj[QLatin1String("useCollection")] = false;
0763         obj[QLatin1String("args")] = args;
0764         newParams.append(std::move(obj));
0765     }
0766 
0767     json[QLatin1String("params")] = newParams;
0768     // qDebug() << "subscribe: json " << json;
0769     qint64 bytes = mWebSocket->sendTextMessage(QString::fromUtf8(QJsonDocument(json).toJson(QJsonDocument::Compact)));
0770     if (bytes < json.length()) {
0771         qCWarning(RUQOLA_DDPAPI_LOG) << "ERROR! I couldn't send all of my message. This is a bug! (try again)";
0772         qCWarning(RUQOLA_DDPAPI_LOG) << mWebSocket->isValid() << mWebSocket->error() << mWebSocket->requestUrl();
0773     } else {
0774         qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "Successfully sent " << json;
0775     }
0776     m_uid++;
0777     return registerId;
0778 }
0779 
0780 void DDPClient::registerSubscriber(const QString &collection, const QString &event, DDPManager *ddpManager, int subscriptionId)
0781 {
0782     const QPair<QString, QString> &key{collection, event};
0783 
0784     if (mEventSubscriptionHash.contains(key)) {
0785         qCCritical(RUQOLA_DDPAPI_LOG) << "ERROR! Another manager is subscribed to this event, registration failed.";
0786         return;
0787     }
0788 
0789     mEventSubscriptionHash[key] = {ddpManager, subscriptionId};
0790     // Registering the client through its existing subscribe API
0791     // TODO: check how useCollection and args are used
0792     const QString params = QStringLiteral(R"([
0793     "%1",
0794     {
0795         "useCollection": false,
0796         "args": []
0797     }
0798 ])")
0799                                .arg(event);
0800 
0801     subscribe(collection, Utils::strToJsonArray(params));
0802 }
0803 
0804 void DDPClient::deregisterSubscriber(const QString &collection, const QString &event, DDPManager *ddpManager, int subscriptionId)
0805 {
0806     const QPair<QString, QString> key{collection, event};
0807 
0808     if (!mEventSubscriptionHash.contains(key)) {
0809         qCWarning(RUQOLA_DDPAPI_LOG) << "No DDPManager is subscribed to this event" << key;
0810         return;
0811     }
0812 
0813     const QPair<DDPManager *, int> subscriptionParams = mEventSubscriptionHash.value(key);
0814     const auto unsubscriptionParams = QPair<DDPManager *, int>{ddpManager, subscriptionId};
0815     if (subscriptionParams != unsubscriptionParams) {
0816         qCWarning(RUQOLA_DDPAPI_LOG) << "Unsubscription parameters don't match subscription parameters.";
0817         qCWarning(RUQOLA_DDPAPI_LOG).nospace() << "Subscription parameters: " << subscriptionParams << ", unsubscription parameters: " << unsubscriptionParams;
0818         return;
0819     }
0820 
0821     qCDebug(RUQOLA_DDPAPI_LOG) << "Subscription to event" << key << "was removed successfully.";
0822     mEventSubscriptionHash.remove(key);
0823 }
0824 
0825 quint64 DDPClient::invokeMethodAndRegister(const QString &methodName, const QJsonArray &params, DDPManager *ddpManager, int operationId)
0826 {
0827     qCDebug(RUQOLA_DDPAPI_LOG) << Q_FUNC_INFO << "invoked with" << methodName << params;
0828     mMethodResponseHash[m_uid] = QPair<DDPManager *, int>(ddpManager, operationId);
0829     return method(methodName, QJsonDocument(params));
0830 }
0831 
0832 void DDPClient::deregisterFromMethodResponse(quint64 methodId, DDPManager *ddpManager, int operationId)
0833 {
0834     if (!mMethodResponseHash.contains(methodId)) {
0835         qCWarning(RUQOLA_DDPAPI_LOG) << "No API manager is registered to this method's responses. Method id:" << methodId;
0836         return;
0837     }
0838 
0839     const auto registerParams = mMethodResponseHash[methodId];
0840     const QPair<DDPManager *, int> deregisterParams{ddpManager, operationId};
0841     if (registerParams != deregisterParams) {
0842         qCWarning(RUQOLA_DDPAPI_LOG) << "Registration parameters for this method don't match the ones in the unregister request.";
0843         qCWarning(RUQOLA_DDPAPI_LOG).nospace() << "Method ID: " << methodId << ", registration parameters: " << registerParams
0844                                                << ", deregistration parameters: " << deregisterParams;
0845         return;
0846     }
0847 
0848     qCDebug(RUQOLA_DDPAPI_LOG) << "Registration to method" << methodId << "was removed successfully.";
0849     mMethodResponseHash.remove(methodId);
0850 }
0851 
0852 void DDPClient::onTextMessageReceived(const QString &message)
0853 {
0854     QJsonDocument response = QJsonDocument::fromJson(message.toUtf8());
0855     if (!response.isNull() && response.isObject()) {
0856         QJsonObject root = response.object();
0857 
0858         const QString messageType = root.value(QLatin1String("msg")).toString();
0859 
0860         if (messageType == QLatin1String("updated")) {
0861             // nothing to do.
0862             qCDebug(RUQOLA_DDPAPI_LOG) << mRocketChatAccount->accountName() << " message updated ! not implemented yet" << response;
0863         } else if (messageType == QLatin1String("result")) {
0864             quint64 id = root.value(QLatin1String("id")).toString().toULongLong();
0865 
0866             // Checking first if any of the new DDPManager claimed the result,
0867             // otherwise defaulting to old behaviour.
0868             if (mMethodResponseHash.contains(id)) {
0869                 QPair<DDPManager *, int> managerOperationPair = mMethodResponseHash[id];
0870                 managerOperationPair.first->processMethodResponse(managerOperationPair.second, root);
0871                 return;
0872             }
0873 
0874             if (m_callbackHash.contains(id)) {
0875                 std::function<void(QJsonObject, RocketChatAccount *)> callback = m_callbackHash.take(id);
0876                 callback(root, mRocketChatAccount);
0877             }
0878 
0879             Q_EMIT result(id, QJsonDocument(root.value(QLatin1String("result")).toObject()));
0880         } else if (messageType == QLatin1String("connected")) {
0881             qCDebug(RUQOLA_DDPAPI_LOG) << mRocketChatAccount->accountName() << " Connected!";
0882             m_connected = true;
0883             Q_EMIT connectedChanged();
0884         } else if (messageType == QLatin1String("error")) {
0885             qWarning() << mRocketChatAccount->accountName() << " ERROR!!" << message;
0886         } else if (messageType == QLatin1String("ping")) {
0887             qCDebug(RUQOLA_DDPAPI_LOG) << mRocketChatAccount->accountName() << "Ping - Pong";
0888             pong();
0889         } else if (messageType == QLatin1String("added")) {
0890             qCDebug(RUQOLA_DDPAPI_LOG) << mRocketChatAccount->accountName() << "ADDING element" << response;
0891             Q_EMIT added(root);
0892         } else if (messageType == QLatin1String("changed")) {
0893             qCDebug(RUQOLA_DDPAPI_LOG) << mRocketChatAccount->accountName() << "Changed element" << response;
0894             Q_EMIT changed(root);
0895         } else if (messageType == QLatin1String("ready")) {
0896             qCDebug(RUQOLA_DDPAPI_LOG) << mRocketChatAccount->accountName() << "READY element" << response;
0897             executeSubsCallBack(root);
0898         } else if (messageType == QLatin1String("removed")) {
0899             qCDebug(RUQOLA_DDPAPI_LOG) << mRocketChatAccount->accountName() << "REMOVED element" << response;
0900             Q_EMIT removed(root);
0901         } else if (messageType == QLatin1String("nosub")) {
0902             const QString id = root.value(QStringLiteral("id")).toString();
0903             qCDebug(RUQOLA_DDPAPI_LOG) << mRocketChatAccount->accountName() << "Unsubscribe element" << message << id;
0904             const QJsonObject errorObj = root[QLatin1String("error")].toObject();
0905             if (!errorObj.isEmpty()) {
0906                 qWarning() << mRocketChatAccount->accountName() << "Error unsubscribing from" << id;
0907                 qWarning() << mRocketChatAccount->accountName() << "ERROR: " << errorObj[QLatin1String("error")].toString();
0908                 qWarning() << mRocketChatAccount->accountName() << "Message: " << errorObj[QLatin1String("message")].toString();
0909                 qWarning() << mRocketChatAccount->accountName() << "Reason: " << errorObj[QLatin1String("reason")].toString();
0910                 qWarning() << mRocketChatAccount->accountName() << "-- Error found END --";
0911             }
0912         } else {
0913             // The very first message we receive is {"server_id":"0"}, can't find it in the spec, just ignore it.
0914             if (messageType.isEmpty() && !root.value(QStringLiteral("server_id")).isUndefined()) {
0915                 return;
0916             }
0917             qWarning() << mRocketChatAccount->accountName() << "received something unhandled:" << messageType << message;
0918         }
0919     } else {
0920         qWarning() << mRocketChatAccount->accountName() << "received something unhandled unknown " << message;
0921     }
0922 }
0923 
0924 quint64 DDPClient::loadHistory(const QJsonArray &params)
0925 {
0926     return method(QStringLiteral("loadHistory"), QJsonDocument(params), process_backlog);
0927 }
0928 
0929 void DDPClient::login()
0930 {
0931     if (mRocketChatAccount->defaultAuthenticationInterface()) {
0932         mRocketChatAccount->defaultAuthenticationInterface()->login();
0933     } else {
0934         qCWarning(RUQOLA_DDPAPI_LOG) << "No plugins loaded. Please verify your installation.";
0935     }
0936 }
0937 
0938 void DDPClient::enqueueLogin()
0939 {
0940     if (isConnected()) {
0941         login();
0942     } else {
0943         // if the connection is already in, it's enough to wait for the web socket to connect
0944         mLoginEnqueued = true;
0945         if (!mWebSocket->isValid()) {
0946             connectWebSocket();
0947         }
0948     }
0949 }
0950 
0951 void DDPClient::onWSConnected()
0952 {
0953     qCDebug(RUQOLA_DDPAPI_LOG) << "Websocket connected at URL" << mUrl;
0954 
0955     QJsonArray supportedVersions;
0956     supportedVersions.append(QLatin1String("1"));
0957     QJsonObject protocol;
0958     protocol[QLatin1String("msg")] = QStringLiteral("connect");
0959     protocol[QLatin1String("version")] = QStringLiteral("1");
0960     protocol[QLatin1String("support")] = supportedVersions;
0961     const QByteArray serialize = QJsonDocument(protocol).toJson(QJsonDocument::Compact);
0962     qint64 bytes = mWebSocket->sendTextMessage(QString::fromUtf8(serialize));
0963     if (bytes < serialize.length()) {
0964         qCWarning(RUQOLA_DDPAPI_COMMAND_LOG) << "onWSConnected: ERROR! I couldn't send all of my message. This is a bug! (try again)";
0965         qCWarning(RUQOLA_DDPAPI_COMMAND_LOG) << mWebSocket->isValid() << mWebSocket->error() << mWebSocket->requestUrl();
0966     } else {
0967         qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "Successfully sent " << serialize;
0968     }
0969 
0970     if (mLoginEnqueued) {
0971         login();
0972         mLoginEnqueued = false;
0973     }
0974 }
0975 
0976 void DDPClient::onSslErrors(const QList<QSslError> &errors)
0977 {
0978     qCDebug(RUQOLA_DDPAPI_LOG) << "SSL error" << errors.count();
0979     for (const QSslError &err : errors) {
0980         qCWarning(RUQOLA_DDPAPI_LOG) << "error ssl type:" << err.errorString();
0981     }
0982     mWebSocket->ignoreSslErrors();
0983 }
0984 
0985 void DDPClient::onWSclosed()
0986 {
0987     const bool normalClose = mWebSocket->closeCode() == QWebSocketProtocol::CloseCodeNormal;
0988     if (normalClose) {
0989         Q_EMIT disconnectedByServer();
0990     } else {
0991         qCWarning(RUQOLA_DDPAPI_LOG) << "WebSocket CLOSED reason:" << mWebSocket->closeReason() << " error: " << mWebSocket->error()
0992                                      << " close code : " << mWebSocket->closeCode() << " error string " << mWebSocket->errorString();
0993         authenticationManager()->setLoginStatus(DDPAuthenticationManager::GenericError);
0994         Q_EMIT wsClosedSocketError();
0995     }
0996 
0997     m_connected = false;
0998     Q_EMIT connectedChanged();
0999 }
1000 
1001 void DDPClient::pong()
1002 {
1003     QJsonObject pong;
1004     pong[QLatin1String("msg")] = QStringLiteral("pong");
1005     mWebSocket->sendBinaryMessage(QJsonDocument(pong).toJson(QJsonDocument::Compact));
1006 }
1007 
1008 void DDPClient::executeSubsCallBack(const QJsonObject &root)
1009 {
1010     const QJsonArray subs = root[QLatin1String("subs")].toArray();
1011     if (!subs.isEmpty()) {
1012         const quint64 id = subs.at(0).toString().toULongLong();
1013         if (m_callbackHash.contains(id)) {
1014             std::function<void(QJsonObject, RocketChatAccount *)> callback = m_callbackHash.take(id);
1015             callback(root, mRocketChatAccount);
1016         }
1017     } else {
1018         qCWarning(RUQOLA_DDPAPI_LOG) << "Problem with subs json " << root;
1019     }
1020 }
1021 
1022 // Otr end
1023 //["{\"msg\":\"method\",\"id\":\"22\",\"method\":\"stream-notify-user\",\"params\":[\"YbwG4T2uB3wZSZSKB/otr\",\"end\",{\"roomId\":\"4faACeGzSvG7xMcTyYbwG4T2uB3wZSZSKB\",\"userId\":\"4faACeGzSvG7xMcTy\"}]}"]
1024 // Otr handshake
1025 //\"msg\":\"method\",\"id\":\"24\",\"method\":\"stream-notify-user\",\"params\":[\"YbwG4T2uB3wZSZSKB/otr\",\"handshake\",{\"roomId\":\"4faACeGzSvG7xMcTyYbwG4T2uB3wZSZSKB\",\"userId\":\"4faACeGzSvG7xMcTy\",\"publicKey\":\"{\\\
1026 
1027 #include "moc_ddpclient.cpp"