diff --git a/src/restapi/restapirequest.cpp b/src/restapi/restapirequest.cpp index 85fcd920..103fdc95 100644 --- a/src/restapi/restapirequest.cpp +++ b/src/restapi/restapirequest.cpp @@ -1,342 +1,365 @@ /* Copyright (c) 2017-2018 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "restapimethod.h" #include "restapirequest.h" #include "ruqola_restapi_debug.h" #include "serverinfojob.h" #include "uploadfilejob.h" #include "misc/owninfojob.h" #include "getavatarjob.h" #include "logoutjob.h" #include "privateinfojob.h" #include "channellistjob.h" #include "loginjob.h" #include "downloadfilejob.h" #include "chat/starmessagejob.h" #include "chat/postmessagejob.h" #include "chat/deletemessagejob.h" -#include "channels/changechanneltopicjob.h" -#include "groups/changegroupstopicjob.h" +#include "channels/changechanneltopicjob.h" #include "channels/changechannelannouncementjob.h" +#include "channels/createchanneljob.h" + #include "groups/changegroupsannouncementjob.h" +#include "groups/changegroupstopicjob.h" +#include "groups/creategroupsjob.h" #include #include #include #include #include #include #include #include #include #include #include #include #include RestApiRequest::RestApiRequest(QObject *parent) : QObject(parent) { mRestApiMethod = new RestApiMethod; mCookieJar = new QNetworkCookieJar; mNetworkAccessManager = new QNetworkAccessManager(this); mNetworkAccessManager->setCookieJar(mCookieJar); connect(mNetworkAccessManager, &QNetworkAccessManager::finished, this, &RestApiRequest::slotResult); connect(mNetworkAccessManager, &QNetworkAccessManager::sslErrors, this, &RestApiRequest::slotSslErrors); } RestApiRequest::~RestApiRequest() { delete mRestApiMethod; } void RestApiRequest::setRuqolaLogger(RuqolaLogger *logger) { mRuqolaLogger = logger; } void RestApiRequest::initializeCookies() { QString url = serverUrl(); if (!url.isEmpty()) { QString host; QStringList lsthost = url.split(QStringLiteral("//")); if (lsthost.count() < 2) { host = url; } else { host = lsthost.at(1); } if (!mUserId.isEmpty()) { QNetworkCookie userIdCookie; userIdCookie.setDomain(host); userIdCookie.setName(QByteArrayLiteral("rc_uid")); userIdCookie.setValue(mUserId.toLocal8Bit()); mCookieJar->insertCookie(userIdCookie); } if (!mAuthToken.isEmpty()) { QNetworkCookie tokenCookie; tokenCookie.setDomain(host); tokenCookie.setName(QByteArrayLiteral("rc_token")); tokenCookie.setValue(mAuthToken.toLocal8Bit()); mCookieJar->insertCookie(tokenCookie); } } else { qCWarning(RUQOLA_RESTAPI_LOG) << "We can not initialize cookies as server url is empty."; } } void RestApiRequest::setAuthToken(const QString &authToken) { const bool isChanged = (mAuthToken != authToken); mAuthToken = authToken; if (isChanged) { if (!mAuthToken.isEmpty()) { initializeCookies(); } } } void RestApiRequest::setUserId(const QString &userId) { const bool isChanged = (mUserId != userId); mUserId = userId; if (isChanged) { if (!mUserId.isEmpty()) { initializeCookies(); } } } void RestApiRequest::slotResult(QNetworkReply *reply) { if (reply->error() != QNetworkReply::NoError) { qCWarning(RUQOLA_RESTAPI_LOG) << " Error reply - "<errorString(); } } void RestApiRequest::slotSslErrors(QNetworkReply *reply, const QList &error) { qCDebug(RUQOLA_RESTAPI_LOG) << " void RestApiRequest::slotSslErrors(QNetworkReply *reply, const QList &error)" << error.count(); reply->ignoreSslErrors(error); } void RestApiRequest::setPassword(const QString &password) { mPassword = password; } void RestApiRequest::setUserName(const QString &userName) { mUserName = userName; } QString RestApiRequest::serverUrl() const { return mRestApiMethod->serverUrl(); } void RestApiRequest::setServerUrl(const QString &serverUrl) { mRestApiMethod->setServerUrl(serverUrl); } QString RestApiRequest::authToken() const { return mAuthToken; } QString RestApiRequest::userId() const { return mUserId; } void RestApiRequest::login() { LoginJob *job = new LoginJob(this); connect(job, &LoginJob::loginDone, this, &RestApiRequest::slotLogin); initializeRestApiJob(job, false); job->setPassword(mPassword); job->setUserName(mUserName); job->start(); } void RestApiRequest::slotLogin(const QString &authToken, const QString &userId) { mAuthToken = authToken; mUserId = userId; } void RestApiRequest::slotLogout() { mUserId.clear(); mAuthToken.clear(); Q_EMIT logoutDone(); } void RestApiRequest::initializeRestApiJob(RestApiAbstractJob *job, bool needAuthentication) { job->setNetworkAccessManager(mNetworkAccessManager); job->setRuqolaLogger(mRuqolaLogger); job->setRestApiMethod(mRestApiMethod); if (needAuthentication) { job->setAuthToken(mAuthToken); job->setUserId(mUserId); } } void RestApiRequest::logout() { LogoutJob *job = new LogoutJob(this); connect(job, &LogoutJob::logoutDone, this, &RestApiRequest::slotLogout); initializeRestApiJob(job, true); job->start(); } void RestApiRequest::channelList() { ChannelListJob *job = new ChannelListJob(this); //TODO connect(job, &ChannelListJob::channelListDone, this, &RestApiRequest::slotLogout); initializeRestApiJob(job, true); job->start(); } void RestApiRequest::getAvatar(const QString &userId) { GetAvatarJob *job = new GetAvatarJob(this); connect(job, &GetAvatarJob::avatar, this, &RestApiRequest::avatar); initializeRestApiJob(job, false); job->setAvatarUserId(userId); job->start(); } void RestApiRequest::getPrivateSettings() { PrivateInfoJob *job = new PrivateInfoJob(this); connect(job, &PrivateInfoJob::privateInfoDone, this, &RestApiRequest::privateInfoDone); initializeRestApiJob(job, true); job->start(); } void RestApiRequest::getOwnInfo() { OwnInfoJob *job = new OwnInfoJob(this); connect(job, &OwnInfoJob::ownInfoDone, this, &RestApiRequest::getOwnInfoDone); initializeRestApiJob(job, true); job->start(); } void RestApiRequest::starMessage(const QString &messageId, bool starred) { StarMessageJob *job = new StarMessageJob(this); initializeRestApiJob(job, true); job->setMessageId(messageId); job->setStarMessage(starred); job->start(); } void RestApiRequest::downloadFile(const QUrl &url, const QString &mimeType, bool storeInCache, const QUrl &localFileUrl) { DownloadFileJob *job = new DownloadFileJob(this); //Rename signal connect(job, &DownloadFileJob::downloadFileDone, this, &RestApiRequest::getDataDone); job->setUrl(url); job->setMimeType(mimeType); job->setLocalFileUrl(localFileUrl); job->setStoreInCache(storeInCache); initializeRestApiJob(job, true); job->start(); } void RestApiRequest::serverInfo() { ServerInfoJob *job = new ServerInfoJob(this); initializeRestApiJob(job, false); connect(job, &ServerInfoJob::serverInfoDone, this, &RestApiRequest::getServerInfoDone); job->start(); } void RestApiRequest::uploadFile(const QString &roomId, const QString &description, const QString &text, const QUrl &filename) { UploadFileJob *job = new UploadFileJob(this); initializeRestApiJob(job, true); job->setDescription(description); job->setMessageText(text); job->setFilenameUrl(filename); job->setRoomId(roomId); job->start(); } void RestApiRequest::changeChannelTopic(const QString &roomId, const QString &topic) { ChangeChannelTopicJob *job = new ChangeChannelTopicJob(this); initializeRestApiJob(job, true); job->setRoomId(roomId); job->setTopic(topic); job->start(); } void RestApiRequest::changeGroupsTopic(const QString &roomId, const QString &topic) { ChangeGroupsTopicJob *job = new ChangeGroupsTopicJob(this); initializeRestApiJob(job, true); job->setRoomId(roomId); job->setTopic(topic); job->start(); } void RestApiRequest::changeChannelAnnouncement(const QString &roomId, const QString &announcement) { ChangeGroupsAnnouncementJob *job = new ChangeGroupsAnnouncementJob(this); initializeRestApiJob(job, true); job->setRoomId(roomId); job->setAnnouncement(announcement); job->start(); } void RestApiRequest::changeGroupsAnnouncement(const QString &roomId, const QString &announcement) { ChangeGroupsAnnouncementJob *job = new ChangeGroupsAnnouncementJob(this); initializeRestApiJob(job, true); job->setRoomId(roomId); job->setAnnouncement(announcement); job->start(); } void RestApiRequest::postMessage(const QString &roomId, const QString &text) { PostMessageJob *job = new PostMessageJob(this); initializeRestApiJob(job, true); job->setRoomId(roomId); job->setText(text); job->start(); } void RestApiRequest::deleteMessage(const QString &roomId, const QString &messageId) { DeleteMessageJob *job = new DeleteMessageJob(this); initializeRestApiJob(job, true); job->setRoomId(roomId); job->setMessageId(messageId); job->start(); } + +void RestApiRequest::createChannels(const QString &channelName, bool readOnly, const QStringList &members) +{ + CreateChannelJob *job = new CreateChannelJob(this); + initializeRestApiJob(job, true); + job->setChannelName(channelName); + job->setReadOnly(readOnly); + job->setMembers(members); + job->start(); +} + +void RestApiRequest::createGroups(const QString &channelName, bool readOnly, const QStringList &members) +{ + CreateGroupsJob *job = new CreateGroupsJob(this); + initializeRestApiJob(job, true); + job->setChannelName(channelName); + job->setReadOnly(readOnly); + job->setMembers(members); + job->start(); +} diff --git a/src/restapi/restapirequest.h b/src/restapi/restapirequest.h index a325d042..1599f949 100644 --- a/src/restapi/restapirequest.h +++ b/src/restapi/restapirequest.h @@ -1,101 +1,103 @@ /* Copyright (c) 2017-2018 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef RESTAPIREQUEST_H #define RESTAPIREQUEST_H #include #include #include #include "restapiutil.h" class QNetworkAccessManager; class QNetworkReply; class QNetworkCookieJar; class RestApiMethod; class RuqolaLogger; class RestApiAbstractJob; class RestApiRequest : public QObject { Q_OBJECT public: explicit RestApiRequest(QObject *parent = nullptr); ~RestApiRequest(); void setRuqolaLogger(RuqolaLogger *logger); QString userId() const; QString authToken() const; void setUserId(const QString &userId); void setAuthToken(const QString &authToken); //Assign/get server url QString serverUrl() const; void setServerUrl(const QString &serverUrl); void setUserName(const QString &userName); void setPassword(const QString &password); void login(); void logout(); void channelList(); void getAvatar(const QString &userId); void serverInfo(); void getPrivateSettings(); void getOwnInfo(); void starMessage(const QString &messageId, bool starred); void uploadFile(const QString &roomId, const QString &description, const QString &text, const QUrl &filename); void downloadFile(const QUrl &url, const QString &mimeType = QStringLiteral("text/plain"), bool storeInCache = true, const QUrl &localFileUrl = QUrl()); void changeChannelTopic(const QString &roomId, const QString &topic); void changeGroupsTopic(const QString &roomId, const QString &topic); void changeChannelAnnouncement(const QString &roomId, const QString &announcement); void changeGroupsAnnouncement(const QString &roomId, const QString &announcement); void postMessage(const QString &roomId, const QString &text); void deleteMessage(const QString &roomId, const QString &messageId); + void createChannels(const QString &channelName, bool readOnly, const QStringList &members); + void createGroups(const QString &channelName, bool readOnly, const QStringList &members); Q_SIGNALS: void avatar(const QString &userId, const QString &url); void logoutDone(); void loginDone(const QString &authToken, const QString &userId); void getDataDone(const QByteArray &data, const QUrl &url, bool useCache, const QUrl &localFileUrl); void getServerInfoDone(const QString &version); void getOwnInfoDone(const QByteArray &data); void privateInfoDone(const QByteArray &data); private: Q_DISABLE_COPY(RestApiRequest) void initializeCookies(); void slotResult(QNetworkReply *reply); void slotSslErrors(QNetworkReply *reply, const QList &error); void slotLogout(); void slotLogin(const QString &authToken, const QString &userId); void initializeRestApiJob(RestApiAbstractJob *job, bool needAuthentication); QNetworkAccessManager *mNetworkAccessManager = nullptr; QNetworkCookieJar *mCookieJar = nullptr; RestApiMethod *mRestApiMethod = nullptr; RuqolaLogger *mRuqolaLogger = nullptr; QString mUserId; QString mAuthToken; QString mUserName; QString mPassword; }; #endif // RESTAPIREQUEST_H diff --git a/src/rocketchataccount.cpp b/src/rocketchataccount.cpp index f61c3586..c0153424 100644 --- a/src/rocketchataccount.cpp +++ b/src/rocketchataccount.cpp @@ -1,1029 +1,1037 @@ /* Copyright (c) 2017-2018 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "model/messagemodel.h" #include "rocketchataccount.h" #include "model/roommodel.h" #include "roomwrapper.h" #include "typingnotification.h" #include "model/usersmodel.h" #include "ruqola_debug.h" #include "ruqola.h" #include "messagequeue.h" #include "rocketchatbackend.h" #include "model/roomfilterproxymodel.h" #include "ruqolalogger.h" #include "ruqolaserverconfig.h" #include "model/usercompletermodel.h" #include "model/usercompleterfilterproxymodel.h" #include "model/statusmodel.h" #include "utils.h" #include "rocketchatcache.h" #include "emojimanager.h" #include "otrmanager.h" #include "inputtextmanager.h" #include "model/usersforroommodel.h" #include "model/filesforroommodel.h" #include "model/searchchannelfilterproxymodel.h" #include "model/searchchannelmodel.h" #include "model/loginmethodmodel.h" #include "model/inputcompletermodel.h" #include "model/searchmessagemodel.h" #include "model/searchmessagefilterproxymodel.h" #include "managerdatapaths.h" #include "authenticationmanager.h" #include "ddpapi/ddpclient.h" #include "restapi/restapirequest.h" #include #include #include #include #include #include #define USE_REASTAPI_JOB 1 RocketChatAccount::RocketChatAccount(const QString &accountFileName, QObject *parent) : QObject(parent) { qCDebug(RUQOLA_LOG) << " RocketChatAccount::RocketChatAccount(const QString &accountFileName, QObject *parent)"<setServerUrl(mSettings->serverUrl()); mOtrManager = new OtrManager(this); mRoomFilterProxyModel = new RoomFilterProxyModel(this); mUserCompleterModel = new UserCompleterModel(this); mUserCompleterFilterModelProxy = new UserCompleterFilterProxyModel(this); mUserCompleterFilterModelProxy->setSourceModel(mUserCompleterModel); mSearchChannelModel = new SearchChannelModel(this); mSearchChannelFilterProxyModel = new SearchChannelFilterProxyModel(this); mSearchChannelFilterProxyModel->setSourceModel(mSearchChannelModel); mSearchMessageModel = new SearchMessageModel(this); mSearchMessageFilterProxyModel = new SearchMessageFilterProxyModel(this); mSearchMessageFilterProxyModel->setSourceModel(mSearchMessageModel); mStatusModel = new StatusModel(this); mRoomModel = new RoomModel(this); connect(mRoomModel, &RoomModel::needToUpdateNotification, this, &RocketChatAccount::slotNeedToUpdateNotification); mRoomFilterProxyModel->setSourceModel(mRoomModel); mUserModel = new UsersModel(this); connect(mUserModel, &UsersModel::userStatusChanged, this, &RocketChatAccount::userStatusChanged); mMessageQueue = new MessageQueue(this); mTypingNotification = new TypingNotification(this); mCache = new RocketChatCache(this, this); connect(mCache, &RocketChatCache::fileDownloaded, this, &RocketChatAccount::fileDownloaded); connect(mTypingNotification, &TypingNotification::informTypingStatus, this, &RocketChatAccount::slotInformTypingStatus); QTimer::singleShot(0, this, &RocketChatAccount::clearModels); } RocketChatAccount::~RocketChatAccount() { delete mCache; mCache = nullptr; delete mRuqolaServerConfig; delete mRuqolaLogger; } void RocketChatAccount::loadSettings(const QString &accountFileName) { delete mSettings; mSettings = new RocketChatAccountSettings(accountFileName, this); connect(mSettings, &RocketChatAccountSettings::serverURLChanged, this, &RocketChatAccount::serverUrlChanged); connect(mSettings, &RocketChatAccountSettings::userIDChanged, this, &RocketChatAccount::userIDChanged); connect(mSettings, &RocketChatAccountSettings::userNameChanged, this, &RocketChatAccount::userNameChanged); connect(mSettings, &RocketChatAccountSettings::passwordChanged, this, &RocketChatAccount::passwordChanged); } void RocketChatAccount::slotNeedToUpdateNotification() { bool hasAlert = false; int nbUnread = 0; mRoomModel->getUnreadAlertFromAccount(hasAlert, nbUnread); Q_EMIT updateNotification(hasAlert, nbUnread, accountName()); } void RocketChatAccount::clearModels() { // Clear rooms data and refill it with data in the cache, if there is mRoomModel->reset(); mMessageQueue->loadCache(); //Try to send queue message mMessageQueue->processQueue(); } SearchChannelFilterProxyModel *RocketChatAccount::searchChannelFilterProxyModel() const { return mSearchChannelFilterProxyModel; } SearchChannelModel *RocketChatAccount::searchChannelModel() const { return mSearchChannelModel; } UserCompleterModel *RocketChatAccount::userCompleterModel() const { return mUserCompleterModel; } UserCompleterFilterProxyModel *RocketChatAccount::userCompleterFilterModelProxy() const { return mUserCompleterFilterModelProxy; } EmojiManager *RocketChatAccount::emojiManager() const { return mEmojiManager; } QString RocketChatAccount::userStatusIconFileName(const QString &name) { return mUserModel->userStatusIconFileName(name); } StatusModel *RocketChatAccount::statusModel() const { return mStatusModel; } RuqolaServerConfig *RocketChatAccount::ruqolaServerConfig() const { return mRuqolaServerConfig; } RuqolaLogger *RocketChatAccount::ruqolaLogger() const { return mRuqolaLogger; } RoomFilterProxyModel *RocketChatAccount::roomFilterProxyModel() const { return mRoomFilterProxyModel; } UsersForRoomFilterProxyModel *RocketChatAccount::usersForRoomFilterProxyModel(const QString &roomId) const { return mRoomModel->usersForRoomFilterProxyModel(roomId); } FilesForRoomFilterProxyModel *RocketChatAccount::filesForRoomFilterProxyModel(const QString &roomId) const { return mRoomModel->filesForRoomFilterProxyModel(roomId); } RocketChatBackend *RocketChatAccount::rocketChatBackend() const { return mRocketChatBackend; } MessageQueue *RocketChatAccount::messageQueue() const { return mMessageQueue; } RocketChatAccountSettings *RocketChatAccount::settings() const { return mSettings; } void RocketChatAccount::slotInformTypingStatus(const QString &room, bool typing) { ddp()->informTypingStatus(room, typing, mSettings->userName()); } RoomModel *RocketChatAccount::roomModel() const { return mRoomModel; } UsersModel *RocketChatAccount::usersModel() const { return mUserModel; } Room *RocketChatAccount::getRoom(const QString &roomId) { return mRoomModel->findRoom(roomId); } RoomWrapper *RocketChatAccount::getRoomWrapper(const QString &roomId) { return mRoomModel->findRoomWrapper(roomId); } MessageModel *RocketChatAccount::messageModelForRoom(const QString &roomID) { return mRoomModel->messageModel(roomID); } QString RocketChatAccount::getUserCurrentMessage(const QString &roomId) { return mRoomModel->inputMessage(roomId); } void RocketChatAccount::setUserCurrentMessage(const QString &message, const QString &roomId) { mRoomModel->setInputMessage(roomId, message); } void RocketChatAccount::setInputTextChanged(const QString &str, int position) { mInputTextManager->setInputTextChanged(str, position); } QString RocketChatAccount::replaceWord(const QString &newWord, const QString &str, int position) { return mInputTextManager->replaceWord(newWord, str, position); } void RocketChatAccount::textEditing(const QString &roomId, const QString &str) { mTypingNotification->setText(roomId, str); } void RocketChatAccount::sendMessage(const QString &roomID, const QString &message) { #ifdef USE_REASTAPI_JOB restApi()->postMessage(roomID, message); #else QJsonObject json; json[QStringLiteral("rid")] = roomID; json[QStringLiteral("msg")] = message; ddp()->method(QStringLiteral("sendMessage"), QJsonDocument(json), DDPClient::Persistent); #endif } void RocketChatAccount::updateMessage(const QString &roomID, const QString &messageId, const QString &message) { QJsonObject json; json[QStringLiteral("rid")] = roomID; json[QStringLiteral("msg")] = message; json[QStringLiteral("_id")] = messageId; ddp()->method(QStringLiteral("updateMessage"), QJsonDocument(json), DDPClient::Persistent); } QString RocketChatAccount::avatarUrlFromDirectChannel(const QString &rid) { return mCache->avatarUrl(Utils::userIdFromDirectChannel(rid, userID())); } void RocketChatAccount::deleteFileMessage(const QString &roomId, const QString &fileId) { ddp()->deleteFileMessage(roomId, fileId); } QString RocketChatAccount::avatarUrl(const QString &userId) { return mCache->avatarUrl(userId); } void RocketChatAccount::insertAvatarUrl(const QString &userId, const QString &url) { mCache->insertAvatarUrl(userId, url); } RestApiRequest *RocketChatAccount::restApi() { if (!mRestApi) { mRestApi = new RestApiRequest(this); mRestApi->setServerUrl(mSettings->serverUrl()); } return mRestApi; } void RocketChatAccount::leaveRoom(const QString &roomId) { ddp()->leaveRoom(roomId); } void RocketChatAccount::hideRoom(const QString &roomId) { ddp()->hideRoom(roomId); } DDPClient *RocketChatAccount::ddp() { if (!mDdp) { mDdp = new DDPClient(this, this); connect(mDdp, &DDPClient::loginStatusChanged, this, &RocketChatAccount::loginStatusChanged); connect(mDdp, &DDPClient::connectedChanged, this, &RocketChatAccount::connectedChanged); connect(mDdp, &DDPClient::changed, this, &RocketChatAccount::changed); connect(mDdp, &DDPClient::added, this, &RocketChatAccount::added); connect(mDdp, &DDPClient::removed, this, &RocketChatAccount::removed); mDdp->setServerUrl(mSettings->serverUrl()); mDdp->start(); } return mDdp; } DDPClient::LoginStatus RocketChatAccount::loginStatus() { if (mDdp) { return ddp()->loginStatus(); } else { return DDPClient::LoggedOut; } } void RocketChatAccount::tryLogin() { qCDebug(RUQOLA_LOG) << "Attempting login" << mSettings->userName() << "on" << mSettings->serverUrl(); delete mDdp; mDdp = nullptr; // This creates a new ddp() object. // DDP will automatically try to connect and login. ddp(); // In the meantime, load cache... mRoomModel->reset(); } void RocketChatAccount::logOut() { mSettings->logout(); mRoomModel->clear(); QJsonObject user; user[QStringLiteral("username")] = mSettings->userName(); QJsonObject json; json[QStringLiteral("user")] = user; ddp()->method(QStringLiteral("logout"), QJsonDocument(json)); delete mDdp; mDdp = nullptr; Q_EMIT logoutDone(accountName()); Q_EMIT loginStatusChanged(); qCDebug(RUQOLA_LOG) << "Successfully logged out!"; } void RocketChatAccount::clearUnreadMessages(const QString &roomId) { //TODO don't send message when we don't have unread message ddp()->clearUnreadMessages(roomId); } void RocketChatAccount::changeFavorite(const QString &roomId, bool checked) { ddp()->toggleFavorite(roomId, checked); } void RocketChatAccount::openChannel(const QString &url) { qCDebug(RUQOLA_LOG) << " void RocketChatAccount::openChannel(const QString &url)"<joinRoom(url, QString()); //TODO search correct room + select it. } void RocketChatAccount::joinJitsiConfCall(const QString &roomId) { qCDebug(RUQOLA_LOG) << " void RocketChatAccount::joinJitsiConfCall(const QString &roomId)"<uniqueId() + roomId).toUtf8(), QCryptographicHash::Md5).toHex()); #if defined(Q_OS_IOS) || defined(Q_OS_ANDROID) const QString scheme = "org.jitsi.meet://"; #else const QString scheme = QStringLiteral("https://"); #endif const QString url = scheme + mRuqolaServerConfig->jitsiMeetUrl() + QLatin1Char('/') + mRuqolaServerConfig->jitsiMeetPrefix() + hash; const QUrl clickedUrl = QUrl::fromUserInput(url); QDesktopServices::openUrl(clickedUrl); } void RocketChatAccount::eraseRoom(const QString &roomId) { ddp()->eraseRoom(roomId); } void RocketChatAccount::openDirectChannel(const QString &username) { ddp()->openDirectChannel(username); } void RocketChatAccount::createNewChannel(const QString &name, bool readOnly, bool privateRoom, const QString &userNames) { if (!name.trimmed().isEmpty()) { const QStringList lstUsers = userNames.split(QLatin1Char(','), QString::SkipEmptyParts); +#ifdef USE_REASTAPI_JOB + if (privateRoom) { + restApi()->createGroups(name, readOnly, lstUsers); + } else { + restApi()->createChannels(name, readOnly, lstUsers); + } +#else if (privateRoom) { ddp()->createPrivateGroup(name, lstUsers); } else { ddp()->createChannel(name, lstUsers, readOnly); } +#endif } else { qCDebug(RUQOLA_LOG) << "Channel name can't be empty"; } } void RocketChatAccount::joinRoom(const QString &roomId, const QString &joinCode) { ddp()->joinRoom(roomId, joinCode); ddp()->subscribeRoomMessage(roomId); } void RocketChatAccount::channelAndPrivateAutocomplete(const QString &pattern) { if (pattern.isEmpty()) { searchChannelModel()->clear(); } else { //Avoid to show own user const QString addUserNameToException = userName(); ddp()->channelAndPrivateAutocomplete(pattern, addUserNameToException); } } void RocketChatAccount::listEmojiCustom() { ddp()->listEmojiCustom(); } void RocketChatAccount::setDefaultStatus(User::PresenceStatus status) { ddp()->setDefaultStatus(status); } void RocketChatAccount::changeDefaultStatus(int index) { setDefaultStatus(mStatusModel->status(index)); } void RocketChatAccount::loadEmoji(const QJsonObject &obj) { mEmojiManager->loadEmoji(obj); } void RocketChatAccount::deleteMessage(const QString &messageId, const QString &roomId) { #if USE_REASTAPI_JOB restApi()->deleteMessage(roomId, messageId); #else ddp()->deleteMessage(messageId); #endif } void RocketChatAccount::insertFilesList(const QString &roomId) { FilesForRoomModel *filesForRoomModel = roomModel()->filesModelForRoom(roomId); if (filesForRoomModel) { filesForRoomModel->setFiles(rocketChatBackend()->files()); } else { qCWarning(RUQOLA_LOG) << " Impossible to find room " << roomId; } } void RocketChatAccount::insertCompleterUsers() { userCompleterModel()->insertUsers(rocketChatBackend()->users()); } void RocketChatAccount::userAutocomplete(const QString &searchText, const QString &exception) { //Clear before to create new search userCompleterModel()->clear(); rocketChatBackend()->clearUsersList(); if (!searchText.isEmpty()) { //Avoid to show own user QString addUserNameToException; if (exception.isEmpty()) { addUserNameToException = userName(); } else { addUserNameToException += QLatin1Char(',') + userName(); } ddp()->userAutocomplete(searchText, addUserNameToException); } } void RocketChatAccount::getUsersOfRoom(const QString &roomId) { ddp()->getUsersOfRoom(roomId, true); } void RocketChatAccount::parseUsersForRooms(const QString &roomId, const QJsonObject &root) { UsersForRoomModel *usersModelForRoom = roomModel()->usersModelForRoom(roomId); if (usersModelForRoom) { usersModelForRoom->parseUsersForRooms(root, mUserModel); } else { qCWarning(RUQOLA_LOG) << " Impossible to find room " << roomId; } } void RocketChatAccount::loadAutoCompleteChannel(const QJsonObject &obj) { mSearchChannelModel->parseChannels(obj); } UsersForRoomModel *RocketChatAccount::usersModelForRoom(const QString &roomId) const { return mRoomModel->usersModelForRoom(roomId); } void RocketChatAccount::roomFiles(const QString &roomId) { rocketChatBackend()->clearFilesList(); ddp()->roomFiles(roomId); } void RocketChatAccount::createJitsiConfCall(const QString &roomId) { ddp()->createJitsiConfCall(roomId); joinJitsiConfCall(roomId); } void RocketChatAccount::addUserToRoom(const QString &username, const QString &roomId) { ddp()->addUserToRoom(username, roomId); } void RocketChatAccount::clearSearchModel() { mSearchMessageModel->clear(); } void RocketChatAccount::messageSearch(const QString &pattern, const QString &rid) { if (pattern.isEmpty()) { clearSearchModel(); } else { ddp()->messageSearch(rid, pattern); } } void RocketChatAccount::starMessage(const QString &messageId, const QString &rid, bool starred) { #ifdef USE_REASTAPI_JOB restApi()->starMessage(messageId, starred); #else ddp()->starMessage(messageId, rid, starred); #endif } void RocketChatAccount::uploadFile(const QString &roomId, const QString &description, const QString &messageText, const QUrl &fileUrl) { restApi()->uploadFile(roomId, description, messageText, fileUrl); } void RocketChatAccount::changeChannelSettings(const QString &roomId, RocketChatAccount::RoomInfoType infoType, const QVariant &newValue) { switch (infoType) { case Announcement: #ifdef USE_REASTAPI_JOB_IMPOSSIBLE //TODO #else ddp()->setRoomAnnouncement(roomId, newValue.toString()); #endif break; case Description: ddp()->setRoomDescription(roomId, newValue.toString()); break; case Name: ddp()->setRoomName(roomId, newValue.toString()); break; case Topic: #ifdef USE_REASTAPI_JOB_IMPOSSIBLE restApi()->changeChannelTopic(roomId, newValue.toString()); #else ddp()->setRoomTopic(roomId, newValue.toString()); #endif break; case ReadOnly: ddp()->setRoomIsReadOnly(roomId, newValue.toBool()); break; case Archive: //No argument here. ddp()->archiveRoom(roomId); break; case RoomType: ddp()->setRoomType(roomId, newValue.toBool()); break; } } void RocketChatAccount::changeNotificationsSettings(const QString &roomId, RocketChatAccount::NotificationOptionsType notificationsType, const QVariant &newValue) { switch (notificationsType) { case DisableNotifications: ddp()->disableNotifications(roomId, newValue.toBool()); break; case HideUnreadStatus: ddp()->hideUnreadStatus(roomId, newValue.toBool()); break; case AudioNotifications: ddp()->audioNotifications(roomId, newValue.toString()); break; case DesktopNotifications: ddp()->desktopNotifications(roomId, newValue.toString()); break; case EmailNotifications: ddp()->emailNotifications(roomId, newValue.toString()); break; case MobilePushNotifications: ddp()->mobilePushNotifications(roomId, newValue.toString()); break; case UnreadAlert: ddp()->unreadAlert(roomId, newValue.toString()); break; } } void RocketChatAccount::parsePublicSettings(const QJsonObject &obj) { QJsonArray configs = obj.value(QLatin1String("result")).toArray(); for (QJsonValueRef currentConfig : configs) { QJsonObject currentConfObject = currentConfig.toObject(); const QString id = currentConfObject[QStringLiteral("_id")].toString(); const QVariant value = currentConfObject[QStringLiteral("value")].toVariant(); if (id == QLatin1String("uniqueID")) { mRuqolaServerConfig->setUniqueId(value.toString()); } else if (id == QLatin1String("Jitsi_Domain")) { mRuqolaServerConfig->setJitsiMeetUrl(value.toString()); } else if (id == QLatin1String("Jitsi_URL_Room_Prefix")) { mRuqolaServerConfig->setJitsiMeetPrefix(value.toString()); } else if (id == QLatin1String("FileUpload_Storage_Type")) { mRuqolaServerConfig->setFileUploadStorageType(value.toString()); } else if (id == QLatin1String("Message_AllowEditing")) { mRuqolaServerConfig->setAllowMessageEditing(value.toBool()); } else if (id == QLatin1String("Message_AllowEditing_BlockEditInMinutes")) { mRuqolaServerConfig->setBlockEditingMessageInMinutes(value.toInt()); } else if (id == QLatin1String("OTR_Enable")) { mRuqolaServerConfig->setOtrEnabled(value.toBool()); } else if (id.contains(QRegularExpression(QStringLiteral("^Accounts_OAuth_\\w+")))) { if (value.toBool()) { mRuqolaServerConfig->addOauthService(id); } } else if (id == QLatin1String("Site_Url")) { mRuqolaServerConfig->setSiteUrl(value.toString()); } else if (id == QLatin1String("Site_Name")) { mRuqolaServerConfig->setSiteName(value.toString()); } else { qCDebug(RUQOLA_LOG) << "Other public settings id " << id << value; } } fillOauthModel(); } void RocketChatAccount::fillOauthModel() { QVector fillModel; for (int i = 0; i < mLstInfos.count(); ++i) { if (mRuqolaServerConfig->canShowOauthService(mLstInfos.at(i).oauthType())) { fillModel.append(mLstInfos.at(i)); } } mLoginMethodModel->setAuthenticationInfos(fillModel); } void RocketChatAccount::changeDefaultAuthentication(int index) { setDefaultAuthentication(mLoginMethodModel->loginType(index)); } void RocketChatAccount::setDefaultAuthentication(AuthenticationManager::OauthType type) { PluginAuthenticationInterface *interface = mLstPluginAuthenticationInterface.value(type); if (interface) { mDefaultAuthenticationInterface = interface; } else { qCWarning(RUQOLA_LOG) << "No interface defined for " << type; } } SearchMessageFilterProxyModel *RocketChatAccount::searchMessageFilterProxyModel() const { return mSearchMessageFilterProxyModel; } SearchMessageModel *RocketChatAccount::searchMessageModel() const { return mSearchMessageModel; } void RocketChatAccount::initializeAuthenticationPlugins() { //TODO change it when we change server //Clean up at the end. const QVector lstPlugins = AuthenticationManager::self()->pluginsList(); qCDebug(RUQOLA_LOG) <<" void RocketChatAccount::initializeAuthenticationPlugins()" << lstPlugins.count(); mLstPluginAuthenticationInterface.clear(); mLstInfos.clear(); for (PluginAuthentication *abstractPlugin : lstPlugins) { AuthenticationInfo info; info.setIconName(abstractPlugin->iconName()); info.setName(abstractPlugin->name()); info.setOauthType(abstractPlugin->type()); if (info.isValid()) { mLstInfos.append(info); } PluginAuthenticationInterface *interface = abstractPlugin->createInterface(this); interface->setAccount(this); mRuqolaServerConfig->addRuqolaAuthenticationSupport(abstractPlugin->type()); mLstPluginAuthenticationInterface.insert(abstractPlugin->type(), interface); //For the moment initialize default interface if (abstractPlugin->type() == AuthenticationManager::OauthType::Password) { mDefaultAuthenticationInterface = interface; } qCDebug(RUQOLA_LOG) << " plugin type " << abstractPlugin->type(); } //TODO fill ??? or store QVector } PluginAuthenticationInterface *RocketChatAccount::defaultAuthenticationInterface() const { return mDefaultAuthenticationInterface; } InputCompleterModel *RocketChatAccount::inputCompleterModel() const { return mInputTextManager->inputCompleterModel(); } LoginMethodModel *RocketChatAccount::loginMethodModel() const { return mLoginMethodModel; } QString RocketChatAccount::authToken() const { return settings()->authToken(); } QString RocketChatAccount::userName() const { return settings()->userName(); } void RocketChatAccount::setAccountName(const QString &accountname) { //Initialize new account room ManagerDataPaths::self()->initializeAccountPath(accountname); qDebug() << "void RocketChatAccount::setAccountName(const QString &servername)"<accountConfigFileName(accountname)); settings()->setAccountName(accountname); } QString RocketChatAccount::accountName() const { return settings()->accountName(); } QString RocketChatAccount::userID() const { return settings()->userId(); } QString RocketChatAccount::password() const { return settings()->password(); } void RocketChatAccount::setAuthToken(const QString &token) { settings()->setAuthToken(token); } void RocketChatAccount::setPassword(const QString &password) { settings()->setPassword(password); } void RocketChatAccount::setUserName(const QString &username) { settings()->setUserName(username); } void RocketChatAccount::setUserID(const QString &userID) { settings()->setUserId(userID); } QString RocketChatAccount::serverUrl() const { return settings()->serverUrl(); } void RocketChatAccount::setServerUrl(const QString &serverURL) { settings()->setServerUrl(serverURL); restApi()->setServerUrl(serverURL); mEmojiManager->setServerUrl(serverURL); } QString RocketChatAccount::recordingVideoPath() const { return mCache->recordingVideoPath(accountName()); } QString RocketChatAccount::recordingImagePath() const { return mCache->recordingImagePath(accountName()); } void RocketChatAccount::downloadFile(const QString &downloadFileUrl, const QUrl &localFile) { mCache->downloadFile(downloadFileUrl, localFile, false); } QUrl RocketChatAccount::attachmentUrl(const QString &url) { return mCache->attachmentUrl(url); } void RocketChatAccount::loadHistory(const QString &roomID, bool initial) { MessageModel *roomModel = messageModelForRoom(roomID); if (roomModel) { //TODO add autotest for it ! QJsonArray params; params.append(QJsonValue(roomID)); // Load history const qint64 endDateTime = roomModel->lastTimestamp(); if (initial || roomModel->isEmpty()) { params.append(QJsonValue(QJsonValue::Null)); params.append(QJsonValue(50)); // Max number of messages to load; QJsonObject dateObject; //qDebug() << "roomModel->lastTimestamp()" << roomModel->lastTimestamp() << " ROOMID " << roomID; dateObject[QStringLiteral("$date")] = QJsonValue(endDateTime); params.append(dateObject); } else { const qint64 startDateTime = roomModel->generateNewStartTimeStamp(endDateTime); QJsonObject dateObjectEnd; dateObjectEnd[QStringLiteral("$date")] = QJsonValue(endDateTime); //qDebug() << " QDATE TIME END" << QDateTime::fromMSecsSinceEpoch(endDateTime) << " START " << QDateTime::fromMSecsSinceEpoch(startDateTime) << " ROOMID" << roomID; params.append(dateObjectEnd); params.append(QJsonValue(50)); // Max number of messages to load; QJsonObject dateObjectStart; //qDebug() << "roomModel->lastTimestamp()" << roomModel->lastTimestamp() << " ROOMID " << roomID; dateObjectStart[QStringLiteral("$date")] = QJsonValue(startDateTime); params.append(dateObjectStart); } ddp()->loadHistory(params); } else { qCWarning(RUQOLA_LOG) << "Room is not found " << roomID; } } void RocketChatAccount::setServerVersion(const QString &version) { qCDebug(RUQOLA_LOG) << " void RocketChatAccount::setServerVersion(const QString &version)" << version; mRuqolaServerConfig->setServerVersion(version); } bool RocketChatAccount::needAdaptNewSubscriptionRC60() const { return mRuqolaServerConfig->needAdaptNewSubscriptionRC60(); } bool RocketChatAccount::otrEnabled() const { return mRuqolaServerConfig->otrEnabled(); } bool RocketChatAccount::allowEditingMessages() const { return mRuqolaServerConfig->allowMessageEditing(); } void RocketChatAccount::parseOtr(const QJsonArray &contents) { const Otr t = mOtrManager->parseOtr(contents); qDebug() << " void RocketChatAccount::parseOtr(const QJsonArray &contents)"<avatarUrlFromCacheOnly(sender); //qDebug() << " iconFileName"<inputChannelAutocomplete(pattern, exceptions); } void RocketChatAccount::inputUserAutocomplete(const QString &pattern, const QString &exceptions) { ddp()->inputUserAutocomplete(pattern, exceptions); } void RocketChatAccount::inputTextCompleter(const QJsonObject &obj) { mInputTextManager->inputTextCompleter(obj); } void RocketChatAccount::displaySearchedMessage(const QJsonObject &obj) { mSearchMessageModel->parseResult(obj); } void RocketChatAccount::updateUser(const QJsonObject &object) { mUserModel->updateUser(object); } void RocketChatAccount::userStatusChanged(const User &user) { //qDebug() << " void RocketChatAccount::userStatusChanged(const User &user)"<setCurrentPresenceStatus(Utils::presenceStatusFromString(user.status())); } mRoomModel->userStatusChanged(user); } void RocketChatAccount::blockUser(const QString &rid, bool block) { if (rid.isEmpty()) { qCWarning(RUQOLA_LOG) << " void RocketChatAccount::blockUser EMPTY rid ! block " << block; } else { //qDebug() << " void RocketChatAccount::blockUser userId " << userId << " block " << block << " rid " << rid << " own userdId" << userID(); const QString userId = Utils::userIdFromDirectChannel(rid, userID()); if (block) { ddp()->blockUser(rid, userId); } else { ddp()->unBlockUser(rid, userId); } } } void RocketChatAccount::initializeRoom(const QString &roomId, bool loadInitialHistory) { ddp()->subscribeRoomMessage(roomId); getUsersOfRoom(roomId); if (loadInitialHistory) { //Load history loadHistory(roomId, true /*initial loading*/); } } void RocketChatAccount::openDocumentation() { QDesktopServices::openUrl(QUrl(QStringLiteral("help:/"))); }