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"