File indexing completed on 2024-12-08 10:25:53

0001 /*
0002 
0003  * SPDX-FileCopyrightText: 2016 Riccardo Iaconelli <riccardo@kde.org>
0004  * SPDX-FileCopyrightText: 2018-2024 Laurent Montel <montel@kde.org>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.0-or-later
0007  *
0008  */
0009 
0010 #include "rocketchatbackend.h"
0011 #include "connection.h"
0012 #include "ddpapi/ddpclient.h"
0013 #include "model/messagesmodel.h"
0014 #include "model/usersmodel.h"
0015 #include "receivetypingnotificationmanager.h"
0016 #include "rocketchataccount.h"
0017 #include "ruqola_debug.h"
0018 #include "ruqola_message_debug.h"
0019 #include "ruqola_unknown_collectiontype_debug.h"
0020 #include "ruqolalogger.h"
0021 #include "videoconference/videoconferencemessageinfomanager.h"
0022 
0023 #include <QJsonArray>
0024 
0025 void process_updatePublicsettings(const QJsonObject &obj, RocketChatAccount *account)
0026 {
0027     // qDebug() << " obj " << obj;
0028     // Update it.
0029     account->parsePublicSettings(obj, true);
0030 
0031     // qCDebug(RUQOLA_LOG) << " configs"<<configs;
0032     if (account->ruqolaLogger()) {
0033         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Update Public Settings:") + QJsonDocument(obj).toJson());
0034     }
0035 }
0036 
0037 void process_publicsettings(const QJsonObject &obj, RocketChatAccount *account)
0038 {
0039     // qDebug() << " obj " << obj;
0040     account->parsePublicSettings(obj, false);
0041 
0042     // qCDebug(RUQOLA_LOG) << " configs"<<configs;
0043     if (account->ruqolaLogger()) {
0044         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Public Settings:") + QJsonDocument(obj).toJson());
0045     }
0046 }
0047 
0048 void process_publicsettings_administrator(const QJsonObject &obj, RocketChatAccount *account)
0049 {
0050     Q_EMIT account->publicSettingLoaded(obj);
0051 
0052     // qCDebug(RUQOLA_LOG) << " configs"<<configs;
0053     if (account->ruqolaLogger()) {
0054         account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Administrator Public Settings:") + QJsonDocument(obj).toJson());
0055     }
0056 }
0057 
0058 void rooms_parsing(const QJsonObject &root, RocketChatAccount *account)
0059 {
0060     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0061     RoomModel *model = account->roomModel();
0062 
0063     // qDebug() << " doc " << doc;
0064 
0065     // QJsonArray removed = obj.value(QLatin1String("remove")).toArray();
0066     // qDebug() << " rooms_parsing: room removed *************************************************" << removed;
0067     const QJsonArray updated = obj.value(QLatin1String("update")).toArray();
0068     // qDebug() << " rooms_parsing: updated  *******************************************************: "<< updated;
0069 
0070     for (int i = 0; i < updated.size(); i++) {
0071         QJsonObject roomJson = updated.at(i).toObject();
0072         const QString roomType = roomJson.value(QLatin1String("t")).toString();
0073         if (account->ruqolaLogger()) {
0074             QJsonDocument d;
0075             d.setObject(roomJson);
0076 
0077             account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Rooms:") + d.toJson());
0078         }
0079         // TODO: why checking the room type?
0080         if (roomType == QLatin1Char('c') // Chat
0081             || roomType == QLatin1Char('p') /*Private chat*/
0082             || roomType == QLatin1Char('d') /*Direct chat*/) {
0083             // let's be extra safe around crashes
0084             if (account->loginStatus() == DDPAuthenticationManager::LoggedIn) {
0085                 model->updateRoom(roomJson);
0086             }
0087         }
0088     }
0089 }
0090 
0091 void getsubscription_parsing(const QJsonObject &root, RocketChatAccount *account)
0092 {
0093     const QJsonObject obj = root.value(QLatin1String("result")).toObject();
0094     RoomModel *model = account->roomModel();
0095 
0096     // qDebug() << " doc " << doc;
0097 
0098     const QJsonArray removed = obj.value(QLatin1String("remove")).toArray();
0099     if (!removed.isEmpty()) {
0100         // TODO implement it.
0101         qDebug() << " room removed " << removed;
0102     }
0103 
0104     const QJsonArray updated = obj.value(QLatin1String("update")).toArray();
0105     // qDebug() << " updated : "<< updated;
0106 
0107     for (int i = 0; i < updated.size(); i++) {
0108         QJsonObject room = updated.at(i).toObject();
0109 
0110         const QString roomType = room.value(QLatin1String("t")).toString();
0111         if (account->ruqolaLogger()) {
0112             QJsonDocument d;
0113             d.setObject(room);
0114 
0115             account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Rooms subscriptions:") + d.toJson());
0116         }
0117         if (roomType == QLatin1Char('c') // Chat
0118             || roomType == QLatin1Char('p') // Private chat
0119             || roomType == QLatin1Char('d')) { // Direct chat
0120             // let's be extra safe around crashes
0121             if (account->loginStatus() == DDPAuthenticationManager::LoggedIn) {
0122                 model->addRoom(room);
0123             }
0124         } else if (roomType == QLatin1Char('l')) { // Live chat
0125             qCDebug(RUQOLA_LOG) << "Live Chat not implemented yet";
0126         }
0127     }
0128     // We need to load all room after get subscription to update parameters
0129     QJsonObject params;
0130     // TODO use timeStamp too
0131     params[QLatin1String("$date")] = QJsonValue(0); // get ALL rooms we've ever seen
0132     // Add timestamp https://developer.rocket.chat/reference/api/realtime-api/method-calls/get-rooms
0133     account->ddp()->method(QStringLiteral("rooms/get"), QJsonDocument(params), rooms_parsing);
0134 
0135     account->initializeAccount();
0136 }
0137 
0138 RocketChatBackend::RocketChatBackend(RocketChatAccount *account, QObject *parent)
0139     : QObject(parent)
0140     , mRocketChatAccount(account)
0141 {
0142     connect(mRocketChatAccount, &RocketChatAccount::loginStatusChanged, this, &RocketChatBackend::slotLoginStatusChanged);
0143     connect(mRocketChatAccount, &RocketChatAccount::userIdChanged, this, &RocketChatBackend::slotUserIDChanged);
0144     connect(mRocketChatAccount, &RocketChatAccount::changed, this, &RocketChatBackend::slotChanged);
0145     connect(mRocketChatAccount, &RocketChatAccount::added, this, &RocketChatBackend::slotAdded);
0146     connect(mRocketChatAccount, &RocketChatAccount::removed, this, &RocketChatBackend::slotRemoved);
0147     connect(mRocketChatAccount, &RocketChatAccount::connectedChanged, this, &RocketChatBackend::slotConnectedChanged);
0148     connect(mRocketChatAccount, &RocketChatAccount::passwordChanged, this, &RocketChatBackend::tryAutoLogin);
0149 }
0150 
0151 RocketChatBackend::~RocketChatBackend() = default;
0152 
0153 // TODO load public info even if we are not connected.
0154 void RocketChatBackend::slotConnectedChanged()
0155 {
0156     auto ddp = mRocketChatAccount->ddp();
0157     if (!ddp->isConnected()) {
0158         return;
0159     }
0160 
0161     auto restApi = mRocketChatAccount->restApi();
0162 
0163     restApi->serverInfo(false);
0164     connect(restApi, &RocketChatRestApi::Connection::serverInfoDone, this, &RocketChatBackend::parseServerVersionDone, Qt::UniqueConnection);
0165     connect(restApi, &RocketChatRestApi::Connection::serverInfoFailed, this, &RocketChatBackend::slotGetServerInfoFailed, Qt::UniqueConnection);
0166     connect(restApi, &RocketChatRestApi::Connection::privateInfoDone, this, &RocketChatBackend::slotPrivateInfoDone, Qt::UniqueConnection);
0167 
0168     mRocketChatAccount->loadAccountSettings();
0169 }
0170 
0171 void RocketChatBackend::loadPublicSettings(qint64 timeStamp)
0172 {
0173     auto ddp = mRocketChatAccount->ddp();
0174     // https://developer.rocket.chat/reference/api/realtime-api/method-calls/get-public-settings
0175     QJsonObject params;
0176     if (timeStamp != -1) {
0177         // "params": [ { "$date": 1480377601 } ]
0178         params[QLatin1String("$date")] = timeStamp;
0179         qDebug() << " params " << params;
0180         ddp->method(QStringLiteral("public-settings/get"), QJsonDocument(params), process_updatePublicsettings);
0181 
0182     } else {
0183         ddp->method(QStringLiteral("public-settings/get"), QJsonDocument(params), process_publicsettings);
0184     }
0185 }
0186 
0187 void RocketChatBackend::loadPublicSettingsAdministrator(qint64 timeStamp)
0188 {
0189     auto ddp = mRocketChatAccount->ddp();
0190     if (!ddp->isConnected()) {
0191         return;
0192     }
0193     // https://developer.rocket.chat/reference/api/realtime-api/method-calls/get-public-settings
0194     QJsonObject params;
0195     if (timeStamp != -1) {
0196         // "params": [ { "$date": 1480377601 } ]
0197         params[QLatin1String("$date")] = timeStamp;
0198     }
0199     qDebug() << " params " << params;
0200     ddp->method(QStringLiteral("public-settings/get"), QJsonDocument(params), process_publicsettings_administrator);
0201 }
0202 
0203 void RocketChatBackend::slotGetServerInfoFailed(bool useDeprecatedVersion)
0204 {
0205     if (!useDeprecatedVersion) {
0206         mRocketChatAccount->restApi()->serverInfo(true);
0207     }
0208 }
0209 
0210 void RocketChatBackend::updateVideoConferenceInfo(const Message &m)
0211 {
0212     // Update video conf info
0213     if (m.messageType() == Message::MessageType::VideoConference) {
0214         const auto blocks{m.blocks()};
0215         for (const auto &b : blocks) {
0216             if (!b.callId().isEmpty()) {
0217                 mRocketChatAccount->videoConferenceMessageInfoManager()->addCallId(b.callId());
0218             }
0219         }
0220     }
0221 }
0222 
0223 void RocketChatBackend::removeMessageFromLocalDatabase(const QStringList &messageIds, const QString &roomId)
0224 {
0225     if (messageIds.isEmpty()) {
0226         return;
0227     }
0228     auto messageModel = mRocketChatAccount->messageModelForRoom(roomId);
0229     for (const auto &message : messageIds) {
0230         const QString messageId{message};
0231         messageModel->deleteMessage(messageId);
0232         Room *room = mRocketChatAccount->room(roomId);
0233         if (room) {
0234             mRocketChatAccount->deleteMessageFromDatabase(room->displayFName(), messageId);
0235         }
0236         // We don't know if we delete a message from thread. So look at in threadModel if we have this identifier
0237         MessagesModel *threadMessageModel = mRocketChatAccount->threadMessageModel();
0238         threadMessageModel->deleteMessage(messageId);
0239     }
0240 }
0241 
0242 void RocketChatBackend::addMessagesFromLocalDataBase(const QVector<Message> &messages)
0243 {
0244     if (messages.isEmpty()) {
0245         return;
0246     }
0247     MessagesModel *messageModel = nullptr;
0248     for (const auto &message : messages) {
0249         if (!messageModel) {
0250             const QString roomId = message.roomId();
0251             messageModel = mRocketChatAccount->messageModelForRoom(roomId);
0252         }
0253         updateVideoConferenceInfo(message);
0254         if (messageModel) {
0255             if (!message.threadMessageId().isEmpty()) {
0256                 mRocketChatAccount->updateThreadMessageList(message);
0257                 // qDebug() << " Update thread message";
0258             }
0259         } else {
0260             qCWarning(RUQOLA_MESSAGE_LOG) << " MessageModel is empty for :" << message.roomId() << " It's a bug for sure.";
0261         }
0262     }
0263     if (messageModel) {
0264         messageModel->addMessages(messages);
0265     }
0266 }
0267 
0268 void RocketChatBackend::processIncomingMessages(const QJsonArray &messages, bool loadHistory, bool restApi)
0269 {
0270     QHash<MessagesModel *, QVector<Message>> dispatcher;
0271     QString lastRoomId;
0272     MessagesModel *messageModel = nullptr;
0273     Room *room = nullptr;
0274     for (const QJsonValue &v : messages) {
0275         QJsonObject o = v.toObject();
0276         if (mRocketChatAccount->ruqolaLogger()) {
0277             QJsonDocument d;
0278             d.setObject(o);
0279             mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("Message:") + d.toJson());
0280         } else {
0281             qCDebug(RUQOLA_MESSAGE_LOG) << " new message: " << o;
0282         }
0283         Message m(mRocketChatAccount->emojiManager());
0284         m.parseMessage(o, restApi);
0285         updateVideoConferenceInfo(m);
0286         const QString roomId = m.roomId();
0287         if (roomId != lastRoomId) {
0288             messageModel = mRocketChatAccount->messageModelForRoom(roomId);
0289             room = mRocketChatAccount->room(roomId);
0290             lastRoomId = roomId;
0291         }
0292         if (messageModel) {
0293             if (!m.threadMessageId().isEmpty()) {
0294                 mRocketChatAccount->updateThreadMessageList(m);
0295                 // qDebug() << " Update thread message";
0296             }
0297             if (room) {
0298                 mRocketChatAccount->addMessageToDataBase(room->displayFName(), m);
0299                 if (!loadHistory) {
0300                     room->newMessageAdded();
0301                 }
0302             }
0303             dispatcher[messageModel].append(std::move(m));
0304         } else {
0305             qCWarning(RUQOLA_MESSAGE_LOG) << " MessageModel is empty for :" << m.roomId() << " It's a bug for sure.";
0306         }
0307     }
0308     for (auto it = dispatcher.cbegin(); it != dispatcher.cend(); ++it) {
0309         it.key()->addMessages(it.value());
0310     }
0311 }
0312 
0313 void RocketChatBackend::slotLoginStatusChanged()
0314 {
0315     if (mRocketChatAccount->loginStatus() == DDPAuthenticationManager::LoggedIn) {
0316         // Now that we are logged in the ddp authentication manager has all the information we need
0317         auto restApi = mRocketChatAccount->restApi();
0318         mRocketChatAccount->settings()->setAuthToken(mRocketChatAccount->ddp()->authenticationManager()->authToken());
0319         mRocketChatAccount->settings()->setExpireToken(mRocketChatAccount->ddp()->authenticationManager()->tokenExpires());
0320         restApi->setAuthToken(mRocketChatAccount->ddp()->authenticationManager()->authToken());
0321         restApi->setUserId(mRocketChatAccount->ddp()->authenticationManager()->userId());
0322 
0323         connect(restApi, &RocketChatRestApi::Connection::getOwnInfoDone, mRocketChatAccount, &RocketChatAccount::parseOwnInfoDone, Qt::UniqueConnection);
0324         QJsonObject params;
0325         // TODO use timeStamp too
0326         params[QLatin1String("$date")] = QJsonValue(0); // get ALL rooms we've ever seen
0327 
0328         std::function<void(QJsonObject, RocketChatAccount *)> subscription_callback = [=](const QJsonObject &obj, RocketChatAccount *account) {
0329             getsubscription_parsing(obj, account);
0330         };
0331 
0332         auto ddp = mRocketChatAccount->ddp();
0333         ddp->method(QStringLiteral("subscriptions/get"), QJsonDocument(params), subscription_callback);
0334 
0335         restApi->listAllPermissions();
0336         restApi->getPrivateSettings();
0337         restApi->getOwnInfo();
0338     }
0339 }
0340 
0341 void RocketChatBackend::slotPrivateInfoDone(const QJsonObject &data)
0342 {
0343     qDebug() << "parse private info not implemented . Needed ? "; // << data;
0344 }
0345 
0346 void RocketChatBackend::parseServerVersionDone(const QString &version)
0347 {
0348     // qCDebug(RUQOLA_LOG) << " void RocketChatBackend::parseServerVersionDone(const QString &version)******************" << version;
0349     mRocketChatAccount->setServerVersion(version);
0350     tryAutoLogin();
0351 }
0352 
0353 void RocketChatBackend::tryAutoLogin()
0354 {
0355     if (mRocketChatAccount->serverVersion().isEmpty() || mRocketChatAccount->password().isEmpty()) {
0356         return;
0357     }
0358     mRocketChatAccount->ddp()->login();
0359 }
0360 
0361 QVector<File> RocketChatBackend::files() const
0362 {
0363     return mFiles;
0364 }
0365 
0366 QVector<User> RocketChatBackend::users() const
0367 {
0368     return mUsers;
0369 }
0370 
0371 void RocketChatBackend::slotRemoved(const QJsonObject &object)
0372 {
0373     const QString collection = object.value(QLatin1String("collection")).toString();
0374     if (collection == QLatin1String("users")) {
0375         const QString id = object.value(QLatin1String("id")).toString();
0376         mRocketChatAccount->usersModel()->removeUser(id);
0377         if (mRocketChatAccount->ruqolaLogger()) {
0378             QJsonDocument d;
0379             d.setObject(object);
0380             mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("users: Removed user:") + d.toJson());
0381         } else {
0382             qDebug() << "USER REMOVED VALUE" << object;
0383         }
0384     } else if (collection == QLatin1String("stream-notify-logged")) {
0385         qDebug() << "removed stream-notify-logged " << object;
0386     } else {
0387         qDebug() << " RocketChatBackend::slotRemove " << collection << " object " << object;
0388         qCDebug(RUQOLA_UNKNOWN_COLLECTIONTYPE_LOG) << " Other collection type  removed " << collection << " object " << object;
0389     }
0390 }
0391 
0392 void RocketChatBackend::slotAdded(const QJsonObject &object)
0393 {
0394     const QString collection = object.value(QLatin1String("collection")).toString();
0395     // qDebug() << " void RocketChatBackend::slotAdded(const QJsonObject &object)" << object;
0396     if (collection == QLatin1String("stream-room-messages")) {
0397         qCDebug(RUQOLA_LOG) << mRocketChatAccount->accountName() << ":stream-room-messages : " << object;
0398     } else if (collection == QLatin1String("users")) {
0399         const QJsonObject fields = object.value(QLatin1String("fields")).toObject();
0400         const QString username = fields.value(QLatin1String("username")).toString();
0401         if (username == mRocketChatAccount->settings()->userName()) {
0402             mRocketChatAccount->settings()->setUserId(object[QLatin1String("id")].toString());
0403             qCDebug(RUQOLA_LOG) << "User id set to " << mRocketChatAccount->settings()->userId();
0404         } else {
0405             // TODO add current user ? me ?
0406             User user;
0407             user.parseUser(object);
0408             if (mRocketChatAccount->ruqolaLogger()) {
0409                 QJsonDocument d;
0410                 d.setObject(object);
0411                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("users: Add User:") + d.toJson());
0412             } else {
0413                 qCDebug(RUQOLA_LOG) << "USER ADDED VALUE" << object;
0414             }
0415             mRocketChatAccount->usersModel()->addUser(user);
0416         }
0417         qCDebug(RUQOLA_LOG) << "NEW USER ADDED: " << username << fields;
0418     } else if (collection == QLatin1String("rooms")) {
0419         qCDebug(RUQOLA_LOG) << "NEW ROOMS ADDED: " << object;
0420     } else if (collection == QLatin1String("stream-notify-user")) {
0421         // qDebug() << "stream-notify-user: " << object;
0422     } else if (collection == QLatin1String("stream-notify-all")) {
0423         // void RocketChatBackend::slotChanged(const QJsonObject &object)
0424         // QJsonObject({"collection":"stream-notify-all","fields":{"args":[{"soundData":{"_id":"oikq5aYewRkYBGebK","_updatedAt":{"$date":1603350166714},"extension":"mp3","name":"test"}}],"eventName":"deleteCustomSound"},"id":"id","msg":"changed"})
0425 
0426         // qCDebug(RUQOLA_UNKNOWN_COLLECTIONTYPE_LOG) << mRocketChatAccount->accountName() << ":stream-notify-all: " << object;
0427         // TODO verify that all is ok !
0428     } else if (collection == QLatin1String("autocompleteRecords")) {
0429         if (mRocketChatAccount->ruqolaLogger()) {
0430             QJsonDocument d;
0431             d.setObject(object);
0432             mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("autocompleteRecords: Add User:") + d.toJson());
0433         } else {
0434             qCDebug(RUQOLA_LOG) << "AutoCompleteRecords VALUE" << object;
0435         }
0436         User user;
0437         user.parseUser(object);
0438         mUsers.append(std::move(user));
0439     } else if (collection == QLatin1String("room_files")) {
0440         if (mRocketChatAccount->ruqolaLogger()) {
0441             QJsonDocument d;
0442             d.setObject(object);
0443             mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("room_files: Add Files:") + d.toJson());
0444         } else {
0445             qCDebug(RUQOLA_LOG) << "room_files VALUE" << object;
0446         }
0447         File file;
0448         file.parseFile(object, false);
0449         mFiles.append(std::move(file));
0450     } else if (collection == QLatin1String("stream-notify-room")) {
0451         // qCDebug(RUQOLA_UNKNOWN_COLLECTIONTYPE_LOG) << mRocketChatAccount->accountName() << ":stream-notify-room not implemented: "<< object;
0452     } else if (collection == QLatin1String("stream-notify-logged")) {
0453         // qCDebug(RUQOLA_UNKNOWN_COLLECTIONTYPE_LOG) << mRocketChatAccount->accountName() << ": stream-notify-logged not implemented: "<< object;
0454     } else {
0455         qCDebug(RUQOLA_UNKNOWN_COLLECTIONTYPE_LOG) << mRocketChatAccount->accountName() << ":Unknown added element: " << object;
0456     }
0457 }
0458 
0459 void RocketChatBackend::slotChanged(const QJsonObject &object)
0460 {
0461     const QString collection = object[QLatin1String("collection")].toString();
0462     const QJsonObject fields = object.value(QLatin1String("fields")).toObject();
0463     const QJsonArray contents = fields.value(QLatin1String("args")).toArray();
0464 
0465     if (collection == QLatin1String("stream-room-messages")) {
0466         qDebug() << " RocketChatBackend::slotChanged stream-room-messages " << contents;
0467         processIncomingMessages(contents, false);
0468     } else if (collection == QLatin1String("users")) {
0469         if (mRocketChatAccount->ruqolaLogger()) {
0470             QJsonDocument d;
0471             d.setObject(object);
0472             mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("users: User Changed:") + d.toJson());
0473         } else {
0474             qCDebug(RUQOLA_LOG) << "USER CHANGED" << object;
0475         }
0476     } else if (collection == QLatin1String("rooms")) {
0477         if (mRocketChatAccount->ruqolaLogger()) {
0478             QJsonDocument d;
0479             d.setObject(object);
0480             mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("rooms: Room Changed:") + d.toJson());
0481         } else {
0482             qCDebug(RUQOLA_LOG) << "ROOMS CHANGED: " << object;
0483         }
0484     } else if (collection == QLatin1String("stream-notify-user")) {
0485         const QString eventname = fields.value(QLatin1String("eventName")).toString();
0486         qCDebug(RUQOLA_LOG) << " EVENT " << eventname << "account name: " << mRocketChatAccount->accountName() << " contents " << contents
0487                             << fields.value(QLatin1String("args")).toArray().toVariantList();
0488 
0489         if (eventname.endsWith(QLatin1String("/subscriptions-changed"))) {
0490             RoomModel *model = mRocketChatAccount->roomModel();
0491             model->updateSubscription(contents);
0492             if (mRocketChatAccount->ruqolaLogger()) {
0493                 QJsonDocument d;
0494                 d.setObject(fields);
0495                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-user: subscriptions-changed:") + d.toJson());
0496             } else {
0497                 qCDebug(RUQOLA_LOG) << "stream-notify-user: subscriptions-changed " << object;
0498             }
0499         } else if (eventname.endsWith(QLatin1String("/rooms-changed"))) {
0500             RoomModel *model = mRocketChatAccount->roomModel();
0501             // qDebug() << " EVENT " << eventname << " contents " << contents << fields.value(QLatin1String("args")).toArray().toVariantList();
0502             const QString actionName = contents[0].toString();
0503             if (actionName == QLatin1String("updated")) {
0504                 qCDebug(RUQOLA_LOG) << " Update room " << contents;
0505                 const QJsonObject roomData = contents[1].toObject();
0506                 model->updateRoom(roomData);
0507                 mRocketChatAccount->updateUserInRoom(roomData);
0508             } else if (actionName == QLatin1String("inserted")) {
0509                 qCDebug(RUQOLA_LOG) << "****************************************** insert new Room !!!!!" << contents;
0510                 const QJsonObject roomData = contents[1].toObject();
0511                 model->insertRoom(roomData);
0512             } else if (actionName == QLatin1String("removed")) {
0513                 qCDebug(RUQOLA_LOG) << "Remove channel" << contents;
0514                 const QJsonObject roomData = contents[1].toObject();
0515                 // TODO use rid
0516                 model->removeRoom(QString());
0517             } else {
0518                 qWarning() << "rooms-changed invalid actionName " << actionName;
0519             }
0520             if (mRocketChatAccount->ruqolaLogger()) {
0521                 QJsonDocument d;
0522                 d.setObject(object);
0523                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-user: Room Changed:") + d.toJson());
0524             }
0525         } else if (eventname.endsWith(QLatin1String("/notification"))) {
0526             if (mRocketChatAccount->ruqolaLogger()) {
0527                 QJsonDocument d;
0528                 d.setObject(object);
0529                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-user: notification:") + d.toJson());
0530             } else {
0531                 qCDebug(RUQOLA_UNKNOWN_COLLECTIONTYPE_LOG) << "NOTIFICATION: " << object;
0532             }
0533             mRocketChatAccount->sendNotification(contents);
0534         } else if (eventname.endsWith(QLatin1String("/webrtc"))) {
0535             if (mRocketChatAccount->ruqolaLogger()) {
0536                 QJsonDocument d;
0537                 d.setObject(object);
0538                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-user: webrtc: ") + d.toJson());
0539             } else {
0540                 qCDebug(RUQOLA_LOG) << "WEBRTC CHANGED: " << object;
0541             }
0542             qCWarning(RUQOLA_LOG) << "stream-notify-user : WEBRTC ? " << eventname << " contents " << contents;
0543         } else if (eventname.endsWith(QLatin1String("/otr"))) {
0544             if (mRocketChatAccount->ruqolaLogger()) {
0545                 QJsonDocument d;
0546                 d.setObject(object);
0547                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-user: otr: ") + d.toJson());
0548             } else {
0549                 qCDebug(RUQOLA_LOG) << "OTR CHANGED: " << object;
0550             }
0551             mRocketChatAccount->parseOtr(contents);
0552             qCDebug(RUQOLA_UNKNOWN_COLLECTIONTYPE_LOG) << "stream-notify-user : OTR ? " << eventname << " contents " << contents;
0553         } else if (eventname.endsWith(QLatin1String("/message"))) {
0554             if (mRocketChatAccount->ruqolaLogger()) {
0555                 QJsonDocument d;
0556                 d.setObject(object);
0557                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-user: message: ") + d.toJson());
0558             } else {
0559                 qCDebug(RUQOLA_LOG) << "stream-notify-user : Message: " << object;
0560             }
0561             const QJsonObject roomData = contents[0].toObject();
0562             mRocketChatAccount->addMessage(roomData);
0563             qCDebug(RUQOLA_LOG) << "stream-notify-user : Message  " << eventname << " contents " << contents;
0564             qDebug() << "stream-notify-user : Message  " << eventname << " contents " << contents;
0565         } else if (eventname.endsWith(QLatin1String("/userData"))) {
0566             if (mRocketChatAccount->ruqolaLogger()) {
0567                 QJsonDocument d;
0568                 d.setObject(object);
0569                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-user: userData event: ") + d.toJson());
0570             } else {
0571                 qCDebug(RUQOLA_LOG) << "stream-notify-user: userData event: " << object;
0572             }
0573             mRocketChatAccount->updateUserData(contents);
0574             // TODO update avatar
0575             qCDebug(RUQOLA_LOG) << "stream-notify-user : message event " << eventname << " contents " << contents;
0576 
0577         } else if (eventname.endsWith(QLatin1String("/video-conference"))) {
0578             qDebug() << " *******************************************************************" << eventname << " contents " << contents;
0579             if (mRocketChatAccount->ruqolaLogger()) {
0580                 QJsonDocument d;
0581                 d.setObject(object);
0582                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-user: video-conference ") + d.toJson());
0583             } else {
0584                 qCDebug(RUQOLA_LOG) << "stream-notify-user: video-conference :account name:" << mRocketChatAccount->accountName() << "object" << object;
0585             }
0586             mRocketChatAccount->parseVideoConference(contents);
0587             qCDebug(RUQOLA_LOG) << "stream-notify-user : message event " << eventname << " contents " << contents;
0588         } else {
0589             if (mRocketChatAccount->ruqolaLogger()) {
0590                 QJsonDocument d;
0591                 d.setObject(object);
0592                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-user: Unknown event: ") + d.toJson());
0593             } else {
0594                 qCDebug(RUQOLA_UNKNOWN_COLLECTIONTYPE_LOG) << "Unknown change: " << object;
0595             }
0596             qCDebug(RUQOLA_LOG) << "stream-notify-user : message event " << eventname << " contents " << contents;
0597         }
0598     } else if (collection == QLatin1String("stream-notify-room")) {
0599         qCDebug(RUQOLA_LOG) << " stream-notify-room " << collection << " object " << object;
0600         const QString eventname = fields.value(QLatin1String("eventName")).toString();
0601         qCDebug(RUQOLA_LOG) << " EVENT " << eventname << " contents " << contents << fields.value(QLatin1String("args")).toArray().toVariantList();
0602 
0603         if (eventname.endsWith(QLatin1String("/deleteMessage"))) {
0604             // qDebug() << " deleteMessage :" << object;
0605             if (mRocketChatAccount->ruqolaLogger()) {
0606                 QJsonDocument d;
0607                 d.setObject(object);
0608                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-room: DeleteMessage:") + d.toJson());
0609             } else {
0610                 qCDebug(RUQOLA_LOG) << "Delete message" << object;
0611             }
0612             // Move code in rocketChatAccount ?
0613 
0614             QString roomId = eventname;
0615             roomId.remove(QStringLiteral("/deleteMessage"));
0616             MessagesModel *messageModel = mRocketChatAccount->messageModelForRoom(roomId);
0617             if (messageModel) {
0618                 const QString messageId = contents.at(0).toObject()[QLatin1String("_id")].toString();
0619                 messageModel->deleteMessage(messageId);
0620                 Room *room = mRocketChatAccount->room(roomId);
0621                 if (room) {
0622                     mRocketChatAccount->deleteMessageFromDatabase(room->displayFName(), messageId);
0623                 }
0624                 // We don't know if we delete a message from thread. So look at in threadModel if we have this identifier
0625                 MessagesModel *threadMessageModel = mRocketChatAccount->threadMessageModel();
0626                 threadMessageModel->deleteMessage(messageId);
0627             } else {
0628                 qCWarning(RUQOLA_MESSAGE_LOG) << " MessageModel is empty for :" << roomId << " It's a bug for sure.";
0629             }
0630         } else if (eventname.endsWith(QLatin1String("/user-activity"))) {
0631             if (mRocketChatAccount->ruqolaLogger()) {
0632                 QJsonDocument d;
0633                 d.setObject(object);
0634                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-room: typing:") + d.toJson());
0635             } else {
0636                 qCDebug(RUQOLA_LOG) << "typing message" << object;
0637             }
0638 
0639             QString roomId = eventname;
0640             roomId.remove(QStringLiteral("/user-activity"));
0641             // TODO Perhaps not necessary to convert to variantlist. Need to investigate
0642             // qCWarning(RUQOLA_LOG) << "stream-notify-room:  typing event ? " << eventname << " content  " << contents.toVariantList();
0643             const QString typingUserName = contents.toVariantList().at(0).toString();
0644             if (typingUserName != mRocketChatAccount->settings()->userName()) {
0645                 const bool status = contents.toVariantList().at(1).toBool();
0646                 mRocketChatAccount->receiveTypingNotificationManager()->insertTypingNotification(roomId, typingUserName, status);
0647             }
0648         } else if (eventname.endsWith(QLatin1String("/deleteMessageBulk"))) {
0649             if (mRocketChatAccount->ruqolaLogger()) {
0650                 QJsonDocument d;
0651                 d.setObject(object);
0652                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("deleteMessageBulk: DeleteMessage:") + d.toJson());
0653             } else {
0654                 qCDebug(RUQOLA_LOG) << "Delete message" << object;
0655             }
0656             qDebug() << " DELETE MESSAGE Bulk not IMPLEMENTED yet";
0657             QString roomId = eventname;
0658             roomId.remove(QStringLiteral("/deleteMessageBulk"));
0659             qDebug() << " deleteMessageBulk " << collection << " object " << object;
0660             // QJsonObject({"collection":"stream-notify-room","fields":{"args":[{"excludePinned":false,"ignoreDiscussion":true,"rid":"QgCf8GcnXYW5QXiHN","ts":{"$gt":{"$date":946681200000},"$lt":{"$date":1599602400000}},"users":[]}],"eventName":"QgCf8GcnXYW5QXiHN/deleteMessageBulk"},"id":"id","msg":"changed"})
0661         } else {
0662             if (mRocketChatAccount->ruqolaLogger()) {
0663                 QJsonDocument d;
0664                 d.setObject(object);
0665                 mRocketChatAccount->ruqolaLogger()->dataReceived(QByteArrayLiteral("stream-notify-room:  Unknown event ?") + d.toJson());
0666             } else {
0667                 qCDebug(RUQOLA_UNKNOWN_COLLECTIONTYPE_LOG) << "stream-notify-room:  Unknown event ? " << eventname;
0668             }
0669         }
0670     } else if (collection == QLatin1String("stream-notify-logged")) {
0671         const QString eventname = fields.value(QLatin1String("eventName")).toString();
0672         qCDebug(RUQOLA_LOG) << " EVENT " << eventname << " contents " << contents << fields.value(QLatin1String("args")).toArray().toVariantList();
0673         if (eventname == QLatin1String("roles-change")) {
0674             mRocketChatAccount->rolesChanged(contents);
0675         } else if (eventname == QLatin1String("updateAvatar")) {
0676             mRocketChatAccount->avatarChanged(contents);
0677         } else if (eventname == QLatin1String("updateEmojiCustom")) {
0678             mRocketChatAccount->addUpdateEmojiCustomList(contents);
0679         } else if (eventname == QLatin1String("Users:NameChanged")) {
0680             mRocketChatAccount->setNameChanged(contents);
0681         } else if (eventname == QLatin1String("Users:Deleted")) {
0682             mRocketChatAccount->deleteUser(contents);
0683         } else if (eventname == QLatin1String("deleteCustomUserStatus")) {
0684             mRocketChatAccount->deleteCustomUserStatus(contents);
0685         } else if (eventname == QLatin1String("updateCustomUserStatus")) {
0686             mRocketChatAccount->updateCustomUserStatus(contents);
0687         } else if (eventname == QLatin1String("user-status")) {
0688             mRocketChatAccount->setUserStatusChanged(contents);
0689         } else if (eventname == QLatin1String("deleteEmojiCustom")) {
0690             mRocketChatAccount->deleteEmojiCustom(contents);
0691         } else if (eventname == QLatin1String("permissions-changed")) {
0692             mRocketChatAccount->permissionUpdated(contents);
0693         } else if (eventname == QLatin1String("private-settings-changed")) {
0694             mRocketChatAccount->privateSettingsUpdated(contents);
0695         } else {
0696             qWarning() << "stream-notify-logged not supported " << fields;
0697         }
0698     } else if (collection == QLatin1String("stream-notify-all")) {
0699         const QString eventname = fields.value(QLatin1String("eventName")).toString();
0700         if (eventname == QLatin1String("deleteCustomSound")) {
0701             mRocketChatAccount->deleteCustomSound(contents);
0702         } else if (eventname == QLatin1String("updateCustomSound")) {
0703             mRocketChatAccount->updateCustomSound(contents);
0704         } else {
0705             qDebug() << " NEED TO IMPLEMENT stream-notify-all " << object;
0706         }
0707         //{"collection":"stream-notify-all","fields":{"args":[{"soundData":{"_id":"LmShBQiqaCJDbgduR","_updatedAt":{"$date":1603350386481},"extension":"mp3","name":"ss"}}],"eventName":"deleteCustomSound"},"id":"id","msg":"changed"}
0708     } else if (collection == QLatin1String("stream-stdout")) {
0709         // const QString eventname = fields.value(QLatin1String("eventName")).toString();
0710         mRocketChatAccount->addStdoutInfo(contents);
0711     } else if (collection == QLatin1String("stream-roles")) {
0712         const QString eventname = fields.value(QLatin1String("eventName")).toString();
0713         if (eventname == QLatin1String("roles")) {
0714             mRocketChatAccount->updateRoles(contents);
0715         }
0716     } else {
0717         qCDebug(RUQOLA_UNKNOWN_COLLECTIONTYPE_LOG) << " Other collection type changed " << collection << " object " << object;
0718     }
0719 }
0720 
0721 void RocketChatBackend::clearFilesList()
0722 {
0723     mFiles.clear();
0724 }
0725 
0726 void RocketChatBackend::clearUsersList()
0727 {
0728     mUsers.clear();
0729 }
0730 
0731 void RocketChatBackend::slotUserIDChanged()
0732 {
0733     // TODO verify if we don"t send two subscription.
0734     const QString userId{mRocketChatAccount->settings()->userId()};
0735     {
0736         // Subscribe notification.
0737         QJsonArray params;
0738         params.append(QJsonValue(QStringLiteral("%1/%2").arg(userId, QStringLiteral("notification"))));
0739         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-user"), params);
0740     }
0741     {
0742         // Subscribe room-changed.
0743         QJsonArray params;
0744         params.append(QJsonValue(QStringLiteral("%1/%2").arg(userId, QStringLiteral("rooms-changed"))));
0745         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-user"), params);
0746     }
0747     {
0748         // Subscribe subscriptions-changed
0749         QJsonArray params;
0750         params.append(QJsonValue(QStringLiteral("%1/%2").arg(userId, QStringLiteral("subscriptions-changed"))));
0751         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-user"), params);
0752     }
0753     {
0754         // Subscribe message
0755         QJsonArray params;
0756         params.append(QJsonValue(QStringLiteral("%1/%2").arg(userId, QStringLiteral("message"))));
0757         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-user"), params);
0758     }
0759     {
0760         // Subscribe message
0761         QJsonArray params;
0762         params.append(QJsonValue(QStringLiteral("%1/%2").arg(userId, QStringLiteral("otr"))));
0763         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-user"), params);
0764     }
0765     {
0766         // Subscribe message
0767         QJsonArray params;
0768         params.append(QJsonValue(QStringLiteral("%1/%2").arg(userId, QStringLiteral("webrtc"))));
0769         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-user"), params);
0770     }
0771     {
0772         // Subscribe message
0773         QJsonArray params;
0774         params.append(QJsonValue(QStringLiteral("%1/%2").arg(userId, QStringLiteral("video-conference"))));
0775         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-user"), params);
0776     }
0777     {
0778         // Subscribe avatardata
0779         QJsonArray params;
0780         params.append(QJsonValue(QStringLiteral("%1/%2").arg(userId, QStringLiteral("userData"))));
0781         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-user"), params);
0782     }
0783     {
0784         // Subscribe users in room ? //TODO verify it.
0785         QJsonArray params;
0786         params.append(QJsonValue(QStringLiteral("%1/%2").arg(userId, QStringLiteral("webrtc"))));
0787         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-room-users"), params);
0788     }
0789     // stream-notify-all
0790     {
0791         const QJsonArray params{QJsonValue(QStringLiteral("updateAvatar"))};
0792         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-all"), params);
0793     }
0794     { // Verify as in RC we don't have it
0795         const QJsonArray params{QJsonValue(QStringLiteral("roles-change"))};
0796         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-all"), params);
0797     }
0798     //    { // Verify as in RC we don't have it
0799     //        const QJsonArray params{QJsonValue(QStringLiteral("video-conference"))};
0800     //        mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-all"), params);
0801     //    }
0802     // Sound
0803     {
0804         const QJsonArray params{QJsonValue(QStringLiteral("deleteCustomSound"))};
0805         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-all"), params);
0806     }
0807     {
0808         const QJsonArray params{QJsonValue(QStringLiteral("updateCustomSound"))};
0809         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-all"), params);
0810     }
0811     {
0812         const QJsonArray params{QJsonValue(QStringLiteral("updateEmojiCustom"))};
0813         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-all"), params);
0814     }
0815     {
0816         const QJsonArray params{QJsonValue(QStringLiteral("deleteEmojiCustom"))};
0817         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-all"), params);
0818     }
0819     {
0820         const QJsonArray params{QJsonValue(QStringLiteral("public-settings-changed"))};
0821         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-all"), params);
0822     }
0823     { // Verify it
0824         const QJsonArray params{QJsonValue(QStringLiteral("permissions-changed"))};
0825         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-all"), params);
0826     }
0827     // stream-notify-logged
0828     {
0829         const QJsonArray params{QJsonValue(QStringLiteral("updateEmojiCustom"))};
0830         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0831     }
0832     // stream-notify-logged
0833     {
0834         const QJsonArray params{QJsonValue(QStringLiteral("deleteEmojiCustom"))};
0835         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0836     }
0837     // stream-notify-logged
0838     {
0839         const QJsonArray params{QJsonValue(QStringLiteral("roles-change"))};
0840         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0841     }
0842     // stream-notify-logged
0843     {
0844         const QJsonArray params{QJsonValue(QStringLiteral("updateAvatar"))};
0845         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0846     }
0847     // stream-notify-logged
0848     {
0849         const QJsonArray params{QJsonValue(QStringLiteral("Users:NameChanged"))};
0850         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0851     }
0852     // stream-notify-logged
0853     {
0854         const QJsonArray params{QJsonValue(QStringLiteral("Users:Deleted"))};
0855         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0856     }
0857     {
0858         const QJsonArray params{QJsonValue(QStringLiteral("deleteCustomUserStatus"))};
0859         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0860     }
0861     {
0862         const QJsonArray params{QJsonValue(QStringLiteral("updateCustomUserStatus"))};
0863         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0864     }
0865     {
0866         const QJsonArray params{QJsonValue(QStringLiteral("user-status"))};
0867         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0868     }
0869     {
0870         const QJsonArray params{QJsonValue(QStringLiteral("permissions-changed"))};
0871         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0872     }
0873     {
0874         const QJsonArray params{QJsonValue(QStringLiteral("private-settings-changed"))};
0875         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-notify-logged"), params);
0876     }
0877     {
0878         const QJsonArray params{QJsonValue(QStringLiteral("roles"))};
0879         mRocketChatAccount->ddp()->subscribe(QStringLiteral("stream-roles"), params);
0880     }
0881 }
0882 
0883 #include "moc_rocketchatbackend.cpp"