diff --git a/CMakeLists.txt b/CMakeLists.txt index 89514ee7..7714e927 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,116 +1,116 @@ set(RUQOLA_VERSION "1.0.41") cmake_minimum_required(VERSION 3.5) project(Ruqola VERSION ${RUQOLA_VERSION}) set (CMAKE_CXX_STANDARD 11) -set(KF5_MIN_VERSION "5.57.0") +set(KF5_MIN_VERSION "5.59.0") set(REQUIRED_QT_VERSION "5.12.0") # Do NOT add quote set(RUQOLA_DEV_VERSION alpha) # add an extra space if(DEFINED RUQOLA_DEV_VERSION) set(RUQOLA_DEV_VERSION " ${RUQOLA_DEV_VERSION}") endif() set(RUQOLA_VERSION_STRING "${RUQOLA_VERSION}${RUQOLA_DEV_VERSION}") find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${Ruqola_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH}) if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() if (POLICY CMP0071) cmake_policy(SET CMP0071 NEW) endif() include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(KDEInstallDirs) include(KDECMakeSettings) include(ECMInstallIcons) include(ECMQtDeclareLoggingCategory) include(ECMAddTests) include(GenerateExportHeader) include(FeatureSummary) option(DISABLE_QTQUICK_COMPILER "Disable using qtquick compiler (true)" TRUE) option(PLUGINS_AUTHENTICATION_BASED_ON_O2 "Build authentication based on o2 lib (experimental)" FALSE) if (NOT WIN32) option(UNITY_SUPPORT "Build unity support" TRUE) endif() if (UNITY_SUPPORT) add_definitions(-DUNITY_SUPPORT) endif() find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core Gui Widgets Qml Quick WebSockets Network NetworkAuth Test) find_package(Qt5 CONFIG QUIET OPTIONAL_COMPONENTS QuickCompiler) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Kirigami2 CoreAddons I18n Crash Notifications SyntaxHighlighting DocTools ) if (WIN32 OR APPLE) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS IconThemes ) endif() find_package(Qt5Keychain) set_package_properties(Qt5Keychain PROPERTIES DESCRIPTION "Provides support for secure credentials storage" URL "https://github.com/frankosterfeld/qtkeychain" TYPE OPTIONAL) if (Qt5Keychain_FOUND) set(HAVE_QT5KEYCHAIN 1) else() set(HAVE_QT5KEYCHAIN 0) endif() include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) add_definitions(-DQT_NO_FOREACH) set(RUQOLA_LIB_VERSION "${RUQOLA_VERSION}") set(RUQOLA_LIB_SOVERSION "0") configure_file(config-ruqola.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ruqola.h) if(BUILD_TESTING) add_definitions(-DBUILD_TESTING) endif(BUILD_TESTING) if (PLUGINS_AUTHENTICATION_BASED_ON_O2) find_package(o2) endif() add_subdirectory(src) if (BUILD_TESTING) add_subdirectory(autotests) add_subdirectory(tests) endif() add_subdirectory(doc) if (${ECM_VERSION} STRGREATER "5.58.0") install(FILES ruqola.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) else() install(FILES ruqola.categories DESTINATION ${KDE_INSTALL_CONFDIR}) endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/autotests/convertertextabstractjobtest.cpp b/autotests/convertertextabstractjobtest.cpp index 25f73151..64fd20d8 100644 --- a/autotests/convertertextabstractjobtest.cpp +++ b/autotests/convertertextabstractjobtest.cpp @@ -1,48 +1,48 @@ /* Copyright (c) 2019 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 "convertertextabstractjobtest.h" #include "convertertextjob/convertertextabstractjob.h" #include class ConverterTextAbstractJobImpl : public ConverterTextAbstractJob { public: explicit ConverterTextAbstractJobImpl(QObject *parent = nullptr) : ConverterTextAbstractJob(parent) { + } + void start() override + { } - void start() override {} }; QTEST_GUILESS_MAIN(ConverterTextAbstractJobTest) - ConverterTextAbstractJobTest::ConverterTextAbstractJobTest(QObject *parent) : QObject(parent) { - } void ConverterTextAbstractJobTest::shouldHaveDefaultValue() { ConverterTextAbstractJobImpl job; QVERIFY(job.messageId().isEmpty()); } diff --git a/autotests/pinnedmessagemodeltest.cpp b/autotests/pinnedmessagemodeltest.cpp index e56ffabb..e39d67ac 100644 --- a/autotests/pinnedmessagemodeltest.cpp +++ b/autotests/pinnedmessagemodeltest.cpp @@ -1,36 +1,37 @@ /* Copyright (c) 2019 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 "pinnedmessagemodeltest.h" #include "model/pinnedmessagemodel.h" #include QTEST_GUILESS_MAIN(PinnedMessageModelTest) PinnedMessageModelTest::PinnedMessageModelTest(QObject *parent) : QObject(parent) { } void PinnedMessageModelTest::shouldHaveDefaultValues() { PinnedMessageModel w; QVERIFY(w.roomId().isEmpty()); + QVERIFY(!w.loadMorePinnedMessageInProgress()); } diff --git a/autotests/translatetextjobtest.cpp b/autotests/translatetextjobtest.cpp index dff8b049..b1996d66 100644 --- a/autotests/translatetextjobtest.cpp +++ b/autotests/translatetextjobtest.cpp @@ -1,31 +1,29 @@ /* Copyright (c) 2019 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 "translatetextjobtest.h" #include QTEST_GUILESS_MAIN(TranslateTextJobTest) TranslateTextJobTest::TranslateTextJobTest(QObject *parent) : QObject(parent) { - } diff --git a/src/rocketchatrestapi-qt5/restapiutil.h b/src/rocketchatrestapi-qt5/restapiutil.h index 183b9837..8fa13af2 100644 --- a/src/rocketchatrestapi-qt5/restapiutil.h +++ b/src/rocketchatrestapi-qt5/restapiutil.h @@ -1,212 +1,210 @@ /* Copyright (c) 2017-2019 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 RESTAPIUTIL_H #define RESTAPIUTIL_H #include #include "librestapi_private_export.h" namespace RestApiUtil { enum class RestApiUrlType { Login, Logout, Me, UsersCreate, UsersDelete, UsersCreateToken, UsersGetPresence, UsersInfo, UsersList, UsersRegister, UsersGetAvatar, UsersResetAvatar, UsersSetAvatar, UsersUpdate, UsersPresence, /*since 1.1.0*/ UsersUpdateOwnBasicInfo, UsersRegeneratePersonalAccessToken, UsersGetUsernameSuggestion, UsersRemovePersonalAccessToken, UsersGeneratePersonalAccessToken, ChatDelete, ChatGetMessage, ChatPinMessage, ChatPostMessage, ChatReact, ChatSearch, ChatStarMessage, ChatUnPinMessage, ChatUnStarMessage, ChatUpdate, ChatIgnoreUser, ChatReportMessage, //Since 1.0.0 ChatFollowMessage, ChatUnFollowMessage, ChatGetThreadsList, ChatSyncThreadMessages, ChatGetThreadMessages, ChatSyncThreadsList, ChatGetDeletedMessage, ChatSendMessage, ChatMessageReadReceipts, //Since 2.0.0 ChatGetPinnedMessages, ChannelsAddAll, //@since 0.75 ChannelsAddLeader, ChannelsAddModerator, ChannelsAddOwner, ChannelsArchive, ChannelsCleanHistory, ChannelsClose, ChannelsCreate, ChannelsGetIntegrations, ChannelsHistory, ChannelsInfo, ChannelsInvite, ChannelsKick, ChannelsLeave, ChannelsList, ChannelsListJoined, ChannelsOpen, ChannelsRemoveModerator, ChannelsRemoveOwner, //@since 0.75 ChannelsRemoveLeader, ChannelsRename, ChannelsSetDescription, ChannelsSetJoinCode, ChannelsSetPurpose, ChannelsSetReadOnly, ChannelsSetTopic, ChannelsSetType, ChannelsSetAnnouncement, ChannelsFiles, ChannelsUnarchive, ChannelsCounters, ChannelsMembers, ChannelsJoin, ChannelsOnline, //since 0.70 ChannelsModerators, //Since 0.71 ChannelsDelete, //since 0.65 ChannelsRoles, //since 0.63 ChannelsGetAllUserMentionsByChannel, ChannelsSetEncrypted, GroupsAddAll, GroupsAddModerator, GroupsAddOwner, GroupsAddLeader, GroupsArchive, GroupsClose, GroupsCreate, //since 0.70 GroupsDelete, GroupsGetIntegrations, GroupsHistory, GroupsInfo, GroupsInvite, GroupsKick, GroupsLeave, GroupsList, GroupsOpen, GroupsRemoveModerator, GroupRemoveOwner, GroupRemoveLeader, GroupsRename, GroupsSetDescription, GroupsSetPurpose, GroupsSetReadOnly, GroupsSetTopic, GroupsSetType, GroupsUnarchive, GroupsSetAnnouncement, GroupsFiles, GroupsListAll, GroupsMembers, //Since 0.65 GroupsRoles, GroupsCounters, GroupsSetEncrypted, ServerInfo, Settings, SettingsPublic, Spotlight, LoadEmojiCustom, DeleteEmojiCustom, CreateEmojiCustom, UpdateEmojiCustom, RoomsUpload, RoomsSaveNotification, ImClose, ImCreate, ImHistory, ImFiles, ImOpen, ImMessages, //Since 0.59 ImMembers, ImSetTopic, SubscriptionsRead, SubscriptionsUnRead, SettingsOauth, RoomsGet, RoomsFavorite, RoomscleanHistory, RoomsInfo, RoomsLeave, RoomsCreateDiscussion, RoomsGetDiscussions, ForgotPassword, PermissionsList, CommandsList, //since 0.70 E2ESetRoomKeyID, E2EfetchMyKeys, E2EupdateGroupKey, E2ESetUserPublicAndPrivateKeys, E2EGetUsersOfRoomWithoutKey, E2ERequestSubscriptionKeys, RolesList, RolesCreate, RolesAddUserToRole, //since 0.74 VideoConfJitsi, //Autotranslate @since 2.0 AutoTranslateGetSupportedLanguages, AutoTranslateSaveSettings, AutoTranslateTranslateMessage, - - }; LIBROCKETCHATRESTAPI_QT5_TESTS_EXPORT QString adaptUrl(const QString &url); LIBROCKETCHATRESTAPI_QT5_TESTS_EXPORT QString restUrl(RestApiUtil::RestApiUrlType type); LIBROCKETCHATRESTAPI_QT5_TESTS_EXPORT QString apiUri(); } #endif // RESTAPIUTIL_H diff --git a/src/ruqolacore/convertertextjob/convertertextabstractjob.cpp b/src/ruqolacore/convertertextjob/convertertextabstractjob.cpp index aee4a371..2d951ae4 100644 --- a/src/ruqolacore/convertertextjob/convertertextabstractjob.cpp +++ b/src/ruqolacore/convertertextjob/convertertextabstractjob.cpp @@ -1,43 +1,40 @@ /* Copyright (c) 2019 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 "convertertextabstractjob.h" ConverterTextAbstractJob::ConverterTextAbstractJob(QObject *parent) : QObject(parent) { - } ConverterTextAbstractJob::~ConverterTextAbstractJob() { - } QString ConverterTextAbstractJob::messageId() const { return mMessageId; } void ConverterTextAbstractJob::setMessageId(const QString &messageId) { mMessageId = messageId; } diff --git a/src/ruqolacore/convertertextjob/translatetextjob.cpp b/src/ruqolacore/convertertextjob/translatetextjob.cpp index be23317b..79a01294 100644 --- a/src/ruqolacore/convertertextjob/translatetextjob.cpp +++ b/src/ruqolacore/convertertextjob/translatetextjob.cpp @@ -1,38 +1,35 @@ /* Copyright (c) 2019 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 "translatetextjob.h" TranslateTextJob::TranslateTextJob(QObject *parent) : ConverterTextAbstractJob(parent) { - } TranslateTextJob::~TranslateTextJob() { - } void TranslateTextJob::start() { //TODO } diff --git a/src/ruqolacore/ddpapi/ddpclient.cpp b/src/ruqolacore/ddpapi/ddpclient.cpp index 6a3b6a2e..c11a2147 100644 --- a/src/ruqolacore/ddpapi/ddpclient.cpp +++ b/src/ruqolacore/ddpapi/ddpclient.cpp @@ -1,973 +1,972 @@ /* * Copyright 2016 Riccardo Iaconelli * Copyright (C) 2017-2019 Laurent Montel * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "ddpclient.h" #include "restapirequest.h" #include "utils.h" #include "ruqola_ddpapi_debug.h" #include "ruqola_ddpapi_command_debug.h" #include "rocketchatmessage.h" #include "ruqolawebsocket.h" #include "rocketchataccount.h" #include "messagequeue.h" #include "ruqolalogger.h" #include "rocketchatbackend.h" #include "plugins/pluginauthenticationinterface.h" #include #include #include #include namespace RuqolaTestWebSocket { LIBRUQOLACORE_EXPORT AbstractWebSocket *_k_ruqola_webSocket = nullptr; } void user_ignore(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("User Ignore:") + QJsonDocument(root).toJson()); } } void block_user(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Block User:") + QJsonDocument(root).toJson()); } } void unblock_user(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("UnBlock User:") + QJsonDocument(root).toJson()); } } void message_search(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Search Message:") + QJsonDocument(root).toJson()); } const QJsonObject obj = root.value(QLatin1String("result")).toObject(); account->displaySearchedMessage(obj); } void input_user_channel_autocomplete(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Input channel/User autocomplete:") + QJsonDocument(root).toJson()); } const QJsonObject obj = root.value(QLatin1String("result")).toObject(); account->inputTextCompleter(obj); } void process_backlog(const QJsonObject &root, RocketChatAccount *account) { const QJsonObject obj = root.value(QLatin1String("result")).toObject(); //qCDebug(RUQOLA_DDPAPI_LOG) << obj.value(QLatin1String("messages")).toArray().size(); account->rocketChatBackend()->processIncomingMessages(obj.value(QLatin1String("messages")).toArray()); } void add_user_to_room(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Add User To Room:") + QJsonDocument(root).toJson()); } } void star_message(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Star message:") + QJsonDocument(root).toJson()); } } void change_notifications_settings(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Change Notifications Settings:") + QJsonDocument(root).toJson()); } } void change_room_settings(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Change Room Settings:") + QJsonDocument(root).toJson()); } } void erase_room(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Delete Room:") + QJsonDocument(root).toJson()); } qDebug()<< "void erase_room(const QJsonObject &root, RocketChatAccount *account)"<ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Delete Message:") + QJsonDocument(root).toJson()); } } void channel_and_private_autocomplete(const QJsonObject &root, RocketChatAccount *account) { const QJsonObject obj = root.value(QLatin1String("result")).toObject(); account->loadAutoCompleteChannel(obj); if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Channel And Private AutoComplete:") + QJsonDocument(root).toJson()); } } void create_jitsi_conf_call(const QJsonObject &root, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Create Jitsi Conf Call:") + QJsonDocument(root).toJson()); } } void open_direct_channel(const QJsonObject &root, RocketChatAccount *account) { const QJsonObject obj = root.value(QLatin1String("result")).toObject(); if (!obj.isEmpty()) { const QString rid = obj.value(QLatin1String("rid")).toString(); if (!rid.isEmpty()) { account->ddp()->subscribeRoomMessage(rid); } } if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Open Direct channel:") + QJsonDocument(root).toJson()); } } void join_room(const QJsonObject &obj, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Join Room :") + QJsonDocument(obj).toJson()); } } void change_default_status(const QJsonObject &obj, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Change Default Status :") + QJsonDocument(obj).toJson()); } } void list_emoji_custom(const QJsonObject &obj, RocketChatAccount *account) { account->loadEmoji(obj); //qDebug() << " list emoji custom " << obj[QLatin1String("result")].toArray(); if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Load Emoji Custom :") + QJsonDocument(obj).toJson()); } } void empty_callback(const QJsonObject &obj, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Empty call back :") + QJsonDocument(obj).toJson()); } else { qCWarning(RUQOLA_DDPAPI_LOG) << "empty_callback "<< obj; } } void login_result(const QJsonObject &obj, RocketChatAccount *account) { if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Login result: ") + QJsonDocument(obj).toJson()); } else { qCWarning(RUQOLA_DDPAPI_LOG) << "Login result: "<< obj; } const QJsonObject result = obj.value(QLatin1String("result")).toObject(); //qDebug() << " result token " << result[QStringLiteral("token")].toString(); const qint64 tokenExpires = Utils::parseDate(QStringLiteral("tokenExpires"), result); //qDebug() << " result tokenExpires " << tokenExpires; account->settings()->setExpireToken(tokenExpires); } void create_channel(const QJsonObject &root, RocketChatAccount *account) { const QJsonObject obj = root.value(QLatin1String("result")).toObject(); if (!obj.isEmpty()) { const QString rid = obj.value(QLatin1String("rid")).toString(); if (!rid.isEmpty()) { account->joinRoom(rid); } if (account->ruqolaLogger()) { account->ruqolaLogger()->dataReceived(QByteArrayLiteral("create Channel :") + QJsonDocument(root).toJson()); } } } DDPClient::DDPClient(RocketChatAccount *account, QObject *parent) : QObject(parent) , m_uid(1) , m_loginJob(0) , m_loginStatus(NotConnected) , m_connected(false) , m_attemptedPasswordLogin(false) , mRocketChatMessage(new RocketChatMessage) , mRocketChatAccount(account) { } DDPClient::~DDPClient() { mWebSocket->close(); //Don't delete socket when we use specific socket. if (!RuqolaTestWebSocket::_k_ruqola_webSocket) { delete mWebSocket; mWebSocket = nullptr; } delete mRocketChatMessage; mRocketChatMessage = nullptr; } void DDPClient::setServerUrl(const QString &url) { mUrl = url; } void DDPClient::initializeWebSocket() { mWebSocket->ignoreSslErrors(); connect(mWebSocket, &AbstractWebSocket::connected, this, &DDPClient::onWSConnected); connect(mWebSocket, &AbstractWebSocket::textMessageReceived, this, &DDPClient::onTextMessageReceived); connect(mWebSocket, &AbstractWebSocket::disconnected, this, &DDPClient::onWSclosed); connect(mWebSocket, &AbstractWebSocket::sslErrors, this, &DDPClient::onSslErrors); } void DDPClient::start() { if (!mWebSocket) { if (!RuqolaTestWebSocket::_k_ruqola_webSocket) { mWebSocket = new RuqolaWebSocket(mRocketChatAccount->ruqolaLogger(), this); } else { mWebSocket = RuqolaTestWebSocket::_k_ruqola_webSocket; } initializeWebSocket(); } connect(mRocketChatAccount, &RocketChatAccount::serverUrlChanged, this, &DDPClient::onServerURLChange); if (!mUrl.isEmpty()) { const QUrl serverUrl = adaptUrl(mUrl); if (!serverUrl.isValid()) { setLoginStatus(LoginFailed); } else { mWebSocket->openUrl(serverUrl); qCDebug(RUQOLA_DDPAPI_LOG) << "Trying to connect to URL" << serverUrl; } } else { qCDebug(RUQOLA_DDPAPI_LOG) << "url is empty"; } } void DDPClient::setLoginJobId(quint64 jobid) { m_loginJob = jobid; } QUrl DDPClient::adaptUrl(const QString &url) { return Utils::generateServerUrl(url); } void DDPClient::onServerURLChange() { if (mRocketChatAccount->settings()->serverUrl() != mUrl || !mWebSocket->isValid()) { if (mWebSocket->isValid()) { mWebSocket->flush(); mWebSocket->close(); } mUrl = mRocketChatAccount->settings()->serverUrl(); mWebSocket->openUrl(adaptUrl(mUrl)); connect(mWebSocket, &AbstractWebSocket::connected, this, &DDPClient::onWSConnected); qCDebug(RUQOLA_DDPAPI_LOG) << "Reconnecting" << mUrl; } } DDPClient::LoginStatus DDPClient::loginStatus() const { return m_loginStatus; } void DDPClient::setLoginStatus(DDPClient::LoginStatus l) { qCDebug(RUQOLA_DDPAPI_LOG) << "Setting login status to" << l; m_loginStatus = l; Q_EMIT loginStatusChanged(); // reset flags if (l == LoginFailed) { m_attemptedPasswordLogin = false; } } bool DDPClient::isConnected() const { return m_connected; } bool DDPClient::isLoggedIn() const { return m_loginStatus == LoggedIn; } QString DDPClient::cachePath() const { return QStandardPaths::writableLocation(QStandardPaths::CacheLocation); } QQueue > DDPClient::messageQueue() const { return m_messageQueue; } quint64 DDPClient::leaveRoom(const QString &roomID) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->leaveRoom(roomID, m_uid); return method(result, empty_callback, DDPClient::Persistent); } quint64 DDPClient::hideRoom(const QString &roomID) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->hideRoom(roomID, m_uid); return method(result, empty_callback, DDPClient::Persistent); } quint64 DDPClient::toggleFavorite(const QString &roomID, bool favorite) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->toggleFavorite(roomID, favorite, m_uid); return method(result, empty_callback, DDPClient::Persistent); } quint64 DDPClient::createChannel(const QString &name, const QStringList &userList, bool readOnly) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->createChannel(name, userList, readOnly, m_uid); return method(result, create_channel, DDPClient::Persistent); } quint64 DDPClient::setRoomName(const QString &roomId, const QString &name) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setRoomName(roomId, name, m_uid); return method(result, change_room_settings, DDPClient::Persistent); } quint64 DDPClient::setRoomTopic(const QString &roomId, const QString &topic) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setRoomTopic(roomId, topic, m_uid); return method(result, change_room_settings, DDPClient::Persistent); } quint64 DDPClient::setRoomType(const QString &roomId, bool privateChannel) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setRoomType(roomId, privateChannel, m_uid); return method(result, change_room_settings, DDPClient::Persistent); } quint64 DDPClient::setRoomEncrypted(const QString &roomId, bool encrypted) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setRoomEncrypted(roomId, encrypted, m_uid); return method(result, change_room_settings, DDPClient::Persistent); } - quint64 DDPClient::setRoomDescription(const QString &roomId, const QString &description) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setRoomDescription(roomId, description, m_uid); return method(result, change_room_settings, DDPClient::Persistent); } quint64 DDPClient::archiveRoom(const QString &roomId) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->archiveRoom(roomId, m_uid); return method(result, change_room_settings, DDPClient::Persistent); } quint64 DDPClient::setRoomIsReadOnly(const QString &roomId, bool readOnly) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setRoomIsReadOnly(roomId, readOnly, m_uid); return method(result, change_room_settings, DDPClient::Persistent); } quint64 DDPClient::setRoomAnnouncement(const QString &roomId, const QString &announcement) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setRoomAnnouncement(roomId, announcement, m_uid); return method(result, change_room_settings, DDPClient::Persistent); } quint64 DDPClient::disableNotifications(const QString &roomId, bool disabled) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->disableNotifications(roomId, disabled, m_uid); return method(result, change_notifications_settings, DDPClient::Persistent); } quint64 DDPClient::hideUnreadStatus(const QString &roomId, bool disabled) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->hideUnreadStatus(roomId, disabled, m_uid); return method(result, change_notifications_settings, DDPClient::Persistent); } quint64 DDPClient::audioNotifications(const QString &roomId, const QString &value) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->audioNotifications(roomId, value, m_uid); return method(result, change_notifications_settings, DDPClient::Persistent); } quint64 DDPClient::mobilePushNotifications(const QString &roomId, const QString &value) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->mobilePushNotifications(roomId, value, m_uid); return method(result, change_notifications_settings, DDPClient::Persistent); } quint64 DDPClient::desktopNotifications(const QString &roomId, const QString &value) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->desktopNotifications(roomId, value, m_uid); return method(result, change_notifications_settings, DDPClient::Persistent); } quint64 DDPClient::emailNotifications(const QString &roomId, const QString &value) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->emailNotifications(roomId, value, m_uid); return method(result, change_notifications_settings, DDPClient::Persistent); } quint64 DDPClient::unreadAlert(const QString &roomId, const QString &value) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->unreadAlert(roomId, value, m_uid); return method(result, change_notifications_settings, DDPClient::Persistent); } void DDPClient::subscribeRoomMessage(const QString &roomId) { QJsonArray params; params.append(QJsonValue(roomId)); subscribe(QStringLiteral("stream-room-messages"), params); const QJsonArray params2{ QJsonValue(QStringLiteral("%1/%2").arg(roomId).arg(QStringLiteral("deleteMessage"))), - true + true }; subscribe(QStringLiteral("stream-notify-room"), params2); const QJsonArray params3{ QJsonValue(QStringLiteral("%1/%2").arg(roomId).arg(QStringLiteral("typing"))), - true + true }; subscribe(QStringLiteral("stream-notify-room"), params3); } quint64 DDPClient::eraseRoom(const QString &roomID) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->eraseRoom(roomID, m_uid); return method(result, erase_room, DDPClient::Persistent); } quint64 DDPClient::openDirectChannel(const QString &userId) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->openDirectChannel(userId, m_uid); return method(result, open_direct_channel, DDPClient::Persistent); } quint64 DDPClient::setReaction(const QString &emoji, const QString &messageId) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setReaction(emoji, messageId, m_uid); return method(result, empty_callback, DDPClient::Persistent); } quint64 DDPClient::createPrivateGroup(const QString &name, const QStringList &userList) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->createPrivateGroup(name, userList, m_uid); return method(result, empty_callback, DDPClient::Persistent); } quint64 DDPClient::deleteMessage(const QString &messageId) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->deleteMessage(messageId, m_uid); return method(result, delete_message, DDPClient::Persistent); } quint64 DDPClient::deleteFileMessage(const QString &roomId, const QString &fileid, const QString &channelType) { - const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->deleteFileMessage(fileid, m_uid); + const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->deleteFileMessage(fileid, m_uid); std::function callback = [ roomId, channelType ](const QJsonObject &root, RocketChatAccount *account) { - if (account->ruqolaLogger()) { - account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Delete Attachment File:") + QJsonDocument(root).toJson()); - } else { - qCDebug(RUQOLA_DDPAPI_LOG) << " parse users for room" << roomId; - } - account->roomFiles(roomId, channelType); - }; + if (account->ruqolaLogger()) { + account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Delete Attachment File:") + QJsonDocument(root).toJson()); + } else { + qCDebug(RUQOLA_DDPAPI_LOG) << " parse users for room" << roomId; + } + account->roomFiles(roomId, channelType); + }; return method(result, callback, DDPClient::Persistent); } quint64 DDPClient::joinRoom(const QString &roomId, const QString &joinCode) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->joinRoom(roomId, joinCode, m_uid); return method(result, join_room, DDPClient::Persistent); } quint64 DDPClient::setDefaultStatus(User::PresenceStatus status) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->setDefaultStatus(status, m_uid); return method(result, change_default_status, DDPClient::Persistent); } quint64 DDPClient::listEmojiCustom() { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->listEmojiCustom(m_uid); return method(result, list_emoji_custom, DDPClient::Persistent); } quint64 DDPClient::userAutocomplete(const QString &pattern, const QString &exception) { const quint64 subscribeId = m_uid; const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->userAutocomplete(pattern, exception, subscribeId); std::function callback = [=](const QJsonObject &root, RocketChatAccount *account) { - if (account->ruqolaLogger()) { - account->ruqolaLogger()->dataReceived(QByteArrayLiteral("User AutoComplete:") + QJsonDocument(root).toJson()); - } else { - qCDebug(RUQOLA_DDPAPI_LOG) << " User AutoComplete" << root; - } - account->insertCompleterUsers(); - - const RocketChatMessage::RocketChatMessageResult resultUnsubscribe = mRocketChatMessage->unsubscribe(subscribeId); - std::function callbackUnsubscribeAutoComplete - = [=](const QJsonObject &root, RocketChatAccount *account) { - if (account->ruqolaLogger()) { - account->ruqolaLogger()-> - dataReceived(QByteArrayLiteral( - "Unsubscribe AutoComplete:") + QJsonDocument(root).toJson()); - } else { - qDebug() << " Unsubscribe AutoComplete" << root; - qCDebug(RUQOLA_DDPAPI_LOG) << " Unsubscribe AutoComplete" << root; - } - }; - method(resultUnsubscribe, callbackUnsubscribeAutoComplete, DDPClient::Persistent); - }; + if (account->ruqolaLogger()) { + account->ruqolaLogger()->dataReceived(QByteArrayLiteral("User AutoComplete:") + QJsonDocument(root).toJson()); + } else { + qCDebug(RUQOLA_DDPAPI_LOG) << " User AutoComplete" << root; + } + account->insertCompleterUsers(); + + const RocketChatMessage::RocketChatMessageResult resultUnsubscribe = mRocketChatMessage->unsubscribe(subscribeId); + std::function callbackUnsubscribeAutoComplete + = [=](const QJsonObject &root, RocketChatAccount *account) { + if (account->ruqolaLogger()) { + account->ruqolaLogger()-> + dataReceived(QByteArrayLiteral( + "Unsubscribe AutoComplete:") + QJsonDocument(root).toJson()); + } else { + qDebug() << " Unsubscribe AutoComplete" << root; + qCDebug(RUQOLA_DDPAPI_LOG) << " Unsubscribe AutoComplete" << root; + } + }; + method(resultUnsubscribe, callbackUnsubscribeAutoComplete, DDPClient::Persistent); + }; return method(result, callback, DDPClient::Persistent); } quint64 DDPClient::channelAndPrivateAutocomplete(const QString &pattern, const QString &exception) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->channelAndPrivateAutocomplete(pattern, exception, m_uid); return method(result, channel_and_private_autocomplete, DDPClient::Persistent); } quint64 DDPClient::getUsersOfRoom(const QString &roomId, bool showAll) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->getUsersOfRoom(roomId, showAll, m_uid); std::function callback = [ roomId ](const QJsonObject &root, RocketChatAccount *account) { - if (account->ruqolaLogger()) { - account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Get Users of Room:") + QJsonDocument(root).toJson()); - } else { - qCDebug(RUQOLA_DDPAPI_LOG) << " parse users for room" << roomId; - } - account->parseUsersForRooms(root, roomId); - }; + if (account->ruqolaLogger()) { + account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Get Users of Room:") + QJsonDocument(root).toJson()); + } else { + qCDebug(RUQOLA_DDPAPI_LOG) << " parse users for room" << roomId; + } + account->parseUsersForRooms(root, roomId); + }; return method(result, callback, DDPClient::Persistent); } #if 0 quint64 DDPClient::roomFiles(const QString &roomId) { const quint64 subscribeId = m_uid; const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->roomFiles(roomId, subscribeId); std::function callback = [=](const QJsonObject &root, RocketChatAccount *account) { - if (account->ruqolaLogger()) { - account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Room File done:") + QJsonDocument(root).toJson()); - } else { - qDebug() << "Room Files " << root; - qCDebug(RUQOLA_DDPAPI_LOG) << " Room Files" << root; - } - account->insertFilesList(roomId); - - const RocketChatMessage::RocketChatMessageResult resultUnsubscribe = mRocketChatMessage->unsubscribe(subscribeId); - std::function callbackUnsubscribeAutoComplete - = [=](const QJsonObject &root, RocketChatAccount *account) { - if (account->ruqolaLogger()) { - account->ruqolaLogger()-> - dataReceived(QByteArrayLiteral( - "Unsubscribe room files:") + QJsonDocument(root).toJson()); - } else { - qDebug() - << " Unsubscribe room files" << root; - qCDebug(RUQOLA_DDPAPI_LOG) - << " Unsubscribe room files" << root; - } - }; - method(resultUnsubscribe, callbackUnsubscribeAutoComplete, DDPClient::Persistent); - }; + if (account->ruqolaLogger()) { + account->ruqolaLogger()->dataReceived(QByteArrayLiteral("Room File done:") + QJsonDocument(root).toJson()); + } else { + qDebug() << "Room Files " << root; + qCDebug(RUQOLA_DDPAPI_LOG) << " Room Files" << root; + } + account->insertFilesList(roomId); + + const RocketChatMessage::RocketChatMessageResult resultUnsubscribe = mRocketChatMessage->unsubscribe(subscribeId); + std::function callbackUnsubscribeAutoComplete + = [=](const QJsonObject &root, RocketChatAccount *account) { + if (account->ruqolaLogger()) { + account->ruqolaLogger()-> + dataReceived(QByteArrayLiteral( + "Unsubscribe room files:") + QJsonDocument(root).toJson()); + } else { + qDebug() + << " Unsubscribe room files" << root; + qCDebug(RUQOLA_DDPAPI_LOG) + << " Unsubscribe room files" << root; + } + }; + method(resultUnsubscribe, callbackUnsubscribeAutoComplete, DDPClient::Persistent); + }; return method(result, callback, DDPClient::Persistent); } + #endif quint64 DDPClient::createJitsiConfCall(const QString &roomId) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->createJitsiConfCall(roomId, m_uid); return method(result, create_jitsi_conf_call, DDPClient::Persistent); } quint64 DDPClient::clearUnreadMessages(const QString &roomID) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->readMessages(roomID, m_uid); return method(result, empty_callback, DDPClient::Persistent); } quint64 DDPClient::inputChannelAutocomplete(const QString &pattern, const QString &exceptions) { - const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->inputChannelAutocomplete(pattern, exceptions, m_uid); + const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->inputChannelAutocomplete(pattern, exceptions, m_uid); return method(result, input_user_channel_autocomplete, DDPClient::Persistent); } quint64 DDPClient::inputUserAutocomplete(const QString &pattern, const QString &exceptions) { - const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->inputUserAutocomplete(pattern, exceptions, m_uid); + const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->inputUserAutocomplete(pattern, exceptions, m_uid); return method(result, input_user_channel_autocomplete, DDPClient::Persistent); } quint64 DDPClient::loginProvider(const QString &credentialToken, const QString &credentialSecret) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->loginProvider(credentialToken, credentialSecret, m_uid); return method(result, empty_callback, DDPClient::Ephemeral); } quint64 DDPClient::login(const QString &username, const QString &password) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->login(username, password, mRocketChatAccount->settings()->twoFactorAuthenticationCode(), m_uid); return method(result, login_result, DDPClient::Ephemeral); } quint64 DDPClient::addUserToRoom(const QString &username, const QString &roomId) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->addUserToRoom(username, roomId, m_uid); return method(result, add_user_to_room, DDPClient::Persistent); } quint64 DDPClient::starMessage(const QString &messageId, const QString &rid, bool starred) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->starMessage(messageId, rid, starred, m_uid); return method(result, star_message, DDPClient::Persistent); } quint64 DDPClient::messageSearch(const QString &rid, const QString &pattern) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->messageSearch(rid, pattern, m_uid); return method(result, message_search, DDPClient::Persistent); } quint64 DDPClient::unBlockUser(const QString &rid, const QString &userId) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->unblockUser(rid, userId, m_uid); return method(result, unblock_user, DDPClient::Persistent); } quint64 DDPClient::blockUser(const QString &rid, const QString &userId) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->blockUser(rid, userId, m_uid); return method(result, block_user, DDPClient::Persistent); } quint64 DDPClient::informTypingStatus(const QString &roomId, bool typing, const QString &userName) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->informTypingStatus(roomId, userName, typing, m_uid); qint64 bytes = mWebSocket->sendTextMessage(result.result); if (bytes < result.result.length()) { qCDebug(RUQOLA_DDPAPI_LOG) << "ERROR! I couldn't send all of my message. This is a bug! (try again)"; qCDebug(RUQOLA_DDPAPI_LOG) << mWebSocket->isValid() << mWebSocket->error() << mWebSocket->requestUrl(); } else { qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "Successfully sent " << result.result; } const quint64 value = m_uid; m_uid++; return value; } quint64 DDPClient::ignoreUser(const QString &roomId, const QString &userId, bool ignore) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->ignoreUser(roomId, userId, ignore, m_uid); return method(result, user_ignore, DDPClient::Persistent); } - quint64 DDPClient::method(const RocketChatMessage::RocketChatMessageResult &result, std::function callback, DDPClient::MessageType messageType) { qint64 bytes = mWebSocket->sendTextMessage(result.result); if (bytes < result.result.length()) { qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "ERROR! I couldn't send all of my message. This is a bug! (try again)"; qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << mWebSocket->isValid() << mWebSocket->error() << mWebSocket->requestUrl(); if (messageType == DDPClient::Persistent) { m_messageQueue.enqueue(qMakePair(result.method, result.jsonDocument)); mRocketChatAccount->messageQueue()->processQueue(); } } else { qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "Successfully sent " << result.result; } m_callbackHash[m_uid] = callback; const quint64 value = m_uid; m_uid++; return value; } quint64 DDPClient::method(const QString &m, const QJsonDocument ¶ms, DDPClient::MessageType messageType) { return method(m, params, empty_callback, messageType); } quint64 DDPClient::method(const QString &method, const QJsonDocument ¶ms, std::function callback, DDPClient::MessageType messageType) { const RocketChatMessage::RocketChatMessageResult result = mRocketChatMessage->generateMethod(method, params, m_uid); qint64 bytes = mWebSocket->sendTextMessage(result.result); if (bytes < result.result.length()) { qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "ERROR! I couldn't send all of my message. This is a bug! (try again)"; qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << mWebSocket->isValid() << mWebSocket->error() << mWebSocket->requestUrl(); if (messageType == DDPClient::Persistent) { m_messageQueue.enqueue(qMakePair(result.method, result.jsonDocument)); mRocketChatAccount->messageQueue()->processQueue(); } } else { qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "Successfully sent " << result.result; } m_callbackHash[m_uid] = callback; const quint64 uidCurrent = m_uid; m_uid++; return uidCurrent; } void DDPClient::subscribe(const QString &collection, const QJsonArray ¶ms) { QJsonObject json; json[QStringLiteral("msg")] = QStringLiteral("sub"); json[QStringLiteral("id")] = QString::number(m_uid); json[QStringLiteral("name")] = collection; QJsonArray newParams = params; if (mRocketChatAccount->needAdaptNewSubscriptionRC60()) { QJsonArray args; QJsonObject obj; obj[QStringLiteral("useCollection")] = false; obj[QStringLiteral("args")] = args; newParams.append(obj); } json[QStringLiteral("params")] = newParams; qint64 bytes = mWebSocket->sendTextMessage(QString::fromUtf8(QJsonDocument(json).toJson(QJsonDocument::Compact))); if (bytes < json.length()) { qCDebug(RUQOLA_DDPAPI_LOG) << "ERROR! I couldn't send all of my message. This is a bug! (try again)"; qCDebug(RUQOLA_DDPAPI_LOG) << mWebSocket->isValid() << mWebSocket->error() << mWebSocket->requestUrl(); } else { qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "Successfully sent " << json; } m_uid++; } void DDPClient::onTextMessageReceived(const QString &message) { QJsonDocument response = QJsonDocument::fromJson(message.toUtf8()); if (!response.isNull() && response.isObject()) { QJsonObject root = response.object(); const QString messageType = root.value(QLatin1String("msg")).toString(); if (messageType == QLatin1String("updated")) { //nothing to do. qCDebug(RUQOLA_DDPAPI_LOG) << " message updated ! not implemented yet" << response; } else if (messageType == QLatin1String("result")) { quint64 id = root.value(QLatin1String("id")).toString().toULongLong(); if (m_callbackHash.contains(id)) { std::function callback = m_callbackHash.take(id); callback(root, mRocketChatAccount); } Q_EMIT result(id, QJsonDocument(root.value(QLatin1String("result")).toObject())); if (id == m_loginJob) { const QJsonObject error(root.value(QLatin1String("error")).toObject()); const QJsonValue errorValue(error.value(QLatin1String("error"))); if (errorValue.toInt() == 403) { qCDebug(RUQOLA_DDPAPI_LOG) << "Wrong password or token expired"; login(); // Let's keep trying to log in } else if (errorValue.toString() == QLatin1String("totp-required") || errorValue.toString() == QLatin1String("totp-invalid")) { qCDebug(RUQOLA_DDPAPI_LOG) << "A 2FA code or backup code is required to login"; setLoginStatus(LoginCodeRequired); } else if (!error.isEmpty()) { qCDebug(RUQOLA_DDPAPI_LOG) << error.value(QLatin1String("message")).toString(); setLoginStatus(LoginFailed); } else { const QString token = root.value(QLatin1String("result")).toObject().value(QLatin1String("token")).toString(); mRocketChatAccount->settings()->setAuthToken(token); mRocketChatAccount->restApi()->setAuthToken(token); mRocketChatAccount->restApi()->setUserId(root.value(QLatin1String("id")).toString()); setLoginStatus(DDPClient::LoggedIn); } } } else if (messageType == QLatin1String("connected")) { //qCDebug(RUQOLA_DDPAPI_LOG) << "Connected"; qDebug() << "Connected"; m_connected = true; setLoginStatus(DDPClient::LoggingIn); Q_EMIT connectedChanged(); } else if (messageType == QLatin1String("error")) { qWarning() << "ERROR!!" << message; } else if (messageType == QLatin1String("ping")) { qCDebug(RUQOLA_DDPAPI_LOG) << "Ping - Pong"; pong(); } else if (messageType == QLatin1String("added")) { qCDebug(RUQOLA_DDPAPI_LOG) << "ADDING element" <settings()->authToken().isEmpty() && !mRocketChatAccount->settings()->tokenExpired()) { m_attemptedPasswordLogin = true; QJsonObject json; json[QStringLiteral("resume")] = mRocketChatAccount->settings()->authToken(); m_loginJob = method(QStringLiteral("login"), QJsonDocument(json)); } else if (!mRocketChatAccount->settings()->password().isEmpty()) { // If we have a password and we couldn't log in, let's stop here if (m_attemptedPasswordLogin) { setLoginStatus(LoginFailed); return; } m_attemptedPasswordLogin = true; //m_loginJob = login(mRocketChatAccount->settings()->userName(), mRocketChatAccount->settings()->password()); if (mRocketChatAccount->defaultAuthenticationInterface()) { mRocketChatAccount->defaultAuthenticationInterface()->login(); } else { qCWarning(RUQOLA_DDPAPI_LOG) <<"No plugins loaded. Please verify your installation."; setLoginStatus(FailedToLoginPluginProblem); } } else { setLoginStatus(LoginFailed); } } void DDPClient::onWSConnected() { qCDebug(RUQOLA_DDPAPI_LOG) << "Websocket connected at URL" << mUrl; QJsonArray supportedVersions; supportedVersions.append(QLatin1String("1")); QJsonObject protocol; protocol[QStringLiteral("msg")] = QStringLiteral("connect"); protocol[QStringLiteral("version")] = QStringLiteral("1"); protocol[QStringLiteral("support")] = supportedVersions; QByteArray serialize = QJsonDocument(protocol).toJson(QJsonDocument::Compact); qint64 bytes = mWebSocket->sendTextMessage(QString::fromUtf8(serialize)); if (bytes < serialize.length()) { qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "onWSConnected: ERROR! I couldn't send all of my message. This is a bug! (try again)"; qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << mWebSocket->isValid() << mWebSocket->error() << mWebSocket->requestUrl(); } else { qCDebug(RUQOLA_DDPAPI_COMMAND_LOG) << "Successfully sent " << serialize; } } void DDPClient::onSslErrors(const QList &errors) { qCDebug(RUQOLA_DDPAPI_LOG) << "SSL error" << errors.count(); for (const QSslError &err : errors) { qCDebug(RUQOLA_DDPAPI_LOG) << "error ssl type:" << err.errorString(); } mWebSocket->ignoreSslErrors(); } void DDPClient::onWSclosed() { if (mWebSocket->closeCode() != QWebSocketProtocol::CloseCodeNormal) { qCDebug(RUQOLA_DDPAPI_LOG) << "WebSocket CLOSED" << mWebSocket->closeReason() << mWebSocket->error() << mWebSocket->closeCode(); } setLoginStatus(NotConnected); } void DDPClient::pong() { QJsonObject pong; pong[QStringLiteral("msg")] = QStringLiteral("pong"); mWebSocket->sendBinaryMessage(QJsonDocument(pong).toJson(QJsonDocument::Compact)); } void DDPClient::executeSubsCallBack(const QJsonObject &root) { const QJsonArray subs = root[QStringLiteral("subs")].toArray(); if (!subs.isEmpty()) { const quint64 id = subs.at(0).toString().toULongLong(); if (m_callbackHash.contains(id)) { std::function callback = m_callbackHash.take(id); callback(root, mRocketChatAccount); } } else { qCWarning(RUQOLA_DDPAPI_LOG) << "Problem with subs json " << root; } } diff --git a/src/ruqolacore/model/pinnedmessagemodel.cpp b/src/ruqolacore/model/pinnedmessagemodel.cpp index 1de03d2d..f49e4219 100644 --- a/src/ruqolacore/model/pinnedmessagemodel.cpp +++ b/src/ruqolacore/model/pinnedmessagemodel.cpp @@ -1,72 +1,82 @@ /* Copyright (c) 2019 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 "pinnedmessagemodel.h" #include "threadmessages.h" PinnedMessageModel::PinnedMessageModel(const QString &roomID, RocketChatAccount *account, Room *room, QObject *parent) : MessageModel(roomID, account, room, parent) { } PinnedMessageModel::~PinnedMessageModel() { } QString PinnedMessageModel::roomId() const { return mRoomId; } void PinnedMessageModel::setRoomId(const QString &threadMessageId) { mRoomId = threadMessageId; } void PinnedMessageModel::parse(const QJsonObject &obj) { ThreadMessages threadmessages; threadmessages.parseThreadMessages(obj); - for (int i = 0; i < threadmessages.count(); ++i) { + for (int i = 0, total = threadmessages.count(); i < total; ++i) { addMessage(threadmessages.at(i)); } } void PinnedMessageModel::parsePinnedMessages(const QJsonObject &obj) { clear(); parse(obj); } void PinnedMessageModel::loadMorePinnedMessages(const QJsonObject &obj) { parse(obj); } int PinnedMessageModel::total() const { return mTotal; } void PinnedMessageModel::setTotal(int total) { mTotal = total; } + +bool PinnedMessageModel::loadMorePinnedMessageInProgress() const +{ + return mLoadingInProgress; +} + +void PinnedMessageModel::setLoadMorePinnedMessageInProgress(bool inProgress) +{ + mLoadingInProgress = inProgress; +} diff --git a/src/ruqolacore/model/pinnedmessagemodel.h b/src/ruqolacore/model/pinnedmessagemodel.h index 81666bc6..8923131f 100644 --- a/src/ruqolacore/model/pinnedmessagemodel.h +++ b/src/ruqolacore/model/pinnedmessagemodel.h @@ -1,49 +1,53 @@ /* Copyright (c) 2019 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 PINNEDMESSAGEMODEL_H #define PINNEDMESSAGEMODEL_H #include "libruqola_private_export.h" #include "messagemodel.h" class LIBRUQOLACORE_TESTS_EXPORT PinnedMessageModel : public MessageModel { Q_OBJECT public: explicit PinnedMessageModel(const QString &roomID = QStringLiteral("no_room"), RocketChatAccount *account = nullptr, Room *room = nullptr, QObject *parent = nullptr); ~PinnedMessageModel(); Q_REQUIRED_RESULT QString roomId() const; void setRoomId(const QString &roomId); void parsePinnedMessages(const QJsonObject &obj); void loadMorePinnedMessages(const QJsonObject &obj); Q_REQUIRED_RESULT int total() const; void setTotal(int total); + Q_REQUIRED_RESULT bool loadMorePinnedMessageInProgress() const; + void setLoadMorePinnedMessageInProgress(bool inProgress); + private: void parse(const QJsonObject &obj); QString mRoomId; int mTotal = 0; + bool mLoadingInProgress = false; }; #endif // PINNEDMESSAGEMODEL_H diff --git a/src/ruqolacore/rocketchataccount.cpp b/src/ruqolacore/rocketchataccount.cpp index adf71e60..dd1a2e2b 100644 --- a/src/ruqolacore/rocketchataccount.cpp +++ b/src/ruqolacore/rocketchataccount.cpp @@ -1,1767 +1,1777 @@ /* Copyright (c) 2017-2019 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 "fileattachments.h" #include "emoticons/emojimanager.h" #include "model/emoticonmodel.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 "model/discussionsmodel.h" #include "model/threadsmodel.h" #include "model/filesforroomfilterproxymodel.h" #include "model/discussionsfilterproxymodel.h" #include "model/threadsfilterproxymodel.h" #include "model/mentionsmodel.h" #include "model/mentionsfilterproxymodel.h" #include "model/pinnedmessagemodel.h" #include "model/threadmessagemodel.h" #include "managerdatapaths.h" #include "authenticationmanager.h" #include "ddpapi/ddpclient.h" #include "discussions.h" #include "receivetypingnotificationmanager.h" #include "restapirequest.h" #include "serverconfiginfo.h" #include "threadmessages.h" #include "threads.h" #include "mentions.h" #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)"<accountName()); } mServerConfigInfo = new ServerConfigInfo(this, this); //Create it before loading settings mLoginMethodModel = new LoginMethodModel(this); mInputTextManager = new InputTextManager(this); connect(mInputTextManager, &InputTextManager::inputCompleter, this, &RocketChatAccount::inputAutocomplete); mInputThreadMessageTextManager = new InputTextManager(this); connect(mInputThreadMessageTextManager, &InputTextManager::inputCompleter, this, &RocketChatAccount::inputThreadMessageAutocomplete); mRuqolaServerConfig = new RuqolaServerConfig; mReceiveTypingNotificationManager = new ReceiveTypingNotificationManager(this); initializeAuthenticationPlugins(); mRocketChatBackend = new RocketChatBackend(this, this); mEmoticonModel = new EmoticonModel(this); //After loadSettings mEmojiManager = new EmojiManager(this); mEmojiManager->setServerUrl(mSettings->serverUrl()); mEmoticonModel->setEmoticons(mEmojiManager->unicodeEmojiList()); 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, this); mSearchMessageFilterProxyModel = new SearchMessageFilterProxyModel(this); mSearchMessageFilterProxyModel->setSourceModel(mSearchMessageModel); connect(mSearchMessageModel, &SearchMessageModel::stringNotFoundChanged, mSearchMessageFilterProxyModel, &SearchMessageFilterProxyModel::stringNotFoundChanged); mFilesModelForRoom = new FilesForRoomModel(this, this); mFilesModelForRoom->setObjectName(QStringLiteral("filesmodelforrooms")); mFilesForRoomFilterProxyModel = new FilesForRoomFilterProxyModel(this); mFilesForRoomFilterProxyModel->setObjectName(QStringLiteral("filesforroomfiltermodelproxy")); mFilesForRoomFilterProxyModel->setSourceModel(mFilesModelForRoom); connect(mFilesModelForRoom, &FilesForRoomModel::hasFullListChanged, mFilesForRoomFilterProxyModel, &FilesForRoomFilterProxyModel::hasFullListChanged); mDiscussionsModel = new DiscussionsModel(this); mDiscussionsModel->setObjectName(QStringLiteral("discussionsmodel")); mDiscussionsFilterProxyModel = new DiscussionsFilterProxyModel(this); mDiscussionsFilterProxyModel->setObjectName(QStringLiteral("discussionsfilterproxymodel")); mDiscussionsFilterProxyModel->setSourceModel(mDiscussionsModel); connect(mDiscussionsModel, &DiscussionsModel::hasFullListChanged, mDiscussionsFilterProxyModel, &DiscussionsFilterProxyModel::hasFullListChanged); mThreadsModel = new ThreadsModel(this); mThreadsModel->setObjectName(QStringLiteral("threadsmodel")); mThreadsFilterProxyModel = new ThreadsFilterProxyModel(this); mThreadsFilterProxyModel->setObjectName(QStringLiteral("threadsfiltermodelproxy")); mThreadsFilterProxyModel->setSourceModel(mThreadsModel); connect(mThreadsModel, &ThreadsModel::hasFullListChanged, mThreadsFilterProxyModel, &ThreadsFilterProxyModel::hasFullListChanged); mMentionsModel = new MentionsModel(this, this); mMentionsModel->setObjectName(QStringLiteral("mentionsmodel")); mMentionsFilterProxyModel = new MentionsFilterProxyModel(this); mMentionsFilterProxyModel->setObjectName(QStringLiteral("mentionsfiltermodelproxy")); mMentionsFilterProxyModel->setSourceModel(mMentionsModel); connect(mMentionsModel, &MentionsModel::hasFullListChanged, mMentionsFilterProxyModel, &MentionsFilterProxyModel::hasFullListChanged); mThreadMessageModel = new ThreadMessageModel(QString(), this, nullptr, this); mThreadMessageModel->setObjectName(QStringLiteral("threadmessagemodel")); mPinnedMessageModel = new PinnedMessageModel(QString(), this, nullptr, this); mPinnedMessageModel->setObjectName(QStringLiteral("pinnedmessagemodel")); mStatusModel = new StatusModel(this); mRoomModel = new RoomModel(this, 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, this); //TODO fix mem leak ! 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::removeSettings() { mSettings->removeSettings(); } 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 { return mFilesForRoomFilterProxyModel; } 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); } DiscussionsFilterProxyModel *RocketChatAccount::discussionsFilterProxyModel() const { return mDiscussionsFilterProxyModel; } ThreadsFilterProxyModel *RocketChatAccount::threadsFilterProxyModel() const { return mThreadsFilterProxyModel; } 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::reactOnMessage(const QString &messageId, const QString &emoji, bool shouldReact) { restApi()->reactOnMessage(messageId, emoji, shouldReact); } void RocketChatAccount::replyToMessage(const QString &roomID, const QString &message, const QString &messageId) { restApi()->postMessage(roomID, message); } void RocketChatAccount::sendMessage(const QString &roomID, const QString &message) { restApi()->postMessage(roomID, message); } void RocketChatAccount::updateMessage(const QString &roomID, const QString &messageId, const QString &message) { restApi()->updateMessage(roomID, messageId, message); } void RocketChatAccount::replyOnThread(const QString &roomID, const QString &threadMessageId, const QString &message) { restApi()->sendMessage(roomID, message, QString(), threadMessageId); } QString RocketChatAccount::avatarUrlFromDirectChannel(const QString &rid) { return mCache->avatarUrl(Utils::userIdFromDirectChannel(rid, userID())); } void RocketChatAccount::deleteFileMessage(const QString &roomId, const QString &fileId, const QString &channelType) { ddp()->deleteFileMessage(roomId, fileId, channelType); } QString RocketChatAccount::avatarUrl(const QString &userId) { return mCache->avatarUrl(userId); } void RocketChatAccount::insertAvatarUrl(const QString &userId, const QString &url) { mCache->insertAvatarUrl(userId, url); } RocketChatRestApi::RestApiRequest *RocketChatAccount::restApi() { if (!mRestApi) { mRestApi = new RocketChatRestApi::RestApiRequest(this); connect(mRestApi, &RocketChatRestApi::RestApiRequest::setChannelJoinDone, this, &RocketChatAccount::setChannelJoinDone); connect(mRestApi, &RocketChatRestApi::RestApiRequest::missingChannelPassword, this, &RocketChatAccount::missingChannelPassword); connect(mRestApi, &RocketChatRestApi::RestApiRequest::loadEmojiCustomDone, this, &RocketChatAccount::loadEmojiRestApi); connect(mRestApi, &RocketChatRestApi::RestApiRequest::openArchivedRoom, this, &RocketChatAccount::openArchivedRoom); connect(mRestApi, &RocketChatRestApi::RestApiRequest::channelMembersDone, this, &RocketChatAccount::parseUsersForRooms); connect(mRestApi, &RocketChatRestApi::RestApiRequest::channelFilesDone, this, &RocketChatAccount::slotChannelFilesDone); connect(mRestApi, &RocketChatRestApi::RestApiRequest::channelRolesDone, this, &RocketChatAccount::slotChannelRolesDone); connect(mRestApi, &RocketChatRestApi::RestApiRequest::searchMessageDone, this, &RocketChatAccount::slotSearchMessages); connect(mRestApi, &RocketChatRestApi::RestApiRequest::failed, this, &RocketChatAccount::jobFailed); connect(mRestApi, &RocketChatRestApi::RestApiRequest::spotlightDone, this, &RocketChatAccount::slotSplotLightDone); connect(mRestApi, &RocketChatRestApi::RestApiRequest::getThreadMessagesDone, this, &RocketChatAccount::slotGetThreadMessagesDone); connect(mRestApi, &RocketChatRestApi::RestApiRequest::getThreadsDone, this, &RocketChatAccount::slotGetThreadsListDone); connect(mRestApi, &RocketChatRestApi::RestApiRequest::getDiscussionsDone, this, &RocketChatAccount::slotGetDiscussionsListDone); connect(mRestApi, &RocketChatRestApi::RestApiRequest::channelGetAllUserMentionsDone, this, &RocketChatAccount::slotGetAllUserMentionsDone); connect(mRestApi, &RocketChatRestApi::RestApiRequest::getPinnedMessagesDone, this, &RocketChatAccount::slotGetPinnedMessagesDone); mRestApi->setServerUrl(mSettings->serverUrl()); mRestApi->setRestApiLogger(mRuqolaLogger); } return mRestApi; } void RocketChatAccount::leaveRoom(const QString &roomId, const QString &channelType) { if (channelType == QStringLiteral("c")) { restApi()->leaveChannel(roomId); } else if (channelType == QStringLiteral("p")) { restApi()->leaveGroups(roomId); } else { qCWarning(RUQOLA_LOG) << " unsupport leave room for type " << channelType; } } void RocketChatAccount::hideRoom(const QString &roomId, const QString &channelType) { restApi()->closeChannel(roomId, channelType); } 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); if (mSettings) { mDdp->setServerUrl(mSettings->serverUrl()); } mDdp->start(); } return mDdp; } bool RocketChatAccount::editingMode() const { return mEditingMode; } 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(); #ifdef USE_REASTAPI_JOB restApi()->logout(); #else QJsonObject user; user[QStringLiteral("username")] = mSettings->userName(); QJsonObject json; json[QStringLiteral("user")] = user; ddp()->method(QStringLiteral("logout"), QJsonDocument(json)); #endif delete mDdp; mDdp = nullptr; Q_EMIT logoutDone(accountName()); Q_EMIT loginStatusChanged(); qCDebug(RUQOLA_LOG) << "Successfully logged out!"; } void RocketChatAccount::clearUnreadMessages(const QString &roomId) { restApi()->markAsRead(roomId); } void RocketChatAccount::changeFavorite(const QString &roomId, bool checked) { if (mRuqolaServerConfig->hasAtLeastVersion(0, 64, 0)) { restApi()->markAsFavorite(roomId, checked); } else { ddp()->toggleFavorite(roomId, checked); } } void RocketChatAccount::openChannel(const QString &url) { //qCDebug(RUQOLA_LOG) << " void RocketChatAccount::openChannel(const QString &url)"<channelJoin(url, QString()); //TODO search correct room + select it. } void RocketChatAccount::setChannelJoinDone(const QString &roomId) { ddp()->subscribeRoomMessage(roomId); } void RocketChatAccount::openArchivedRoom(const QString &roomId) { //TODO } 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, const QString &channelType) { if (channelType == QStringLiteral("c")) { restApi()->channelDelete(roomId); } else if (channelType == QStringLiteral("p")) { restApi()->groupDelete(roomId); } else { qCWarning(RUQOLA_LOG) << " unsupport delete for type " << channelType; } } void RocketChatAccount::openDirectChannel(const QString &username) { //Laurent for the moment I didn't find a restapi method for it //TODO verify username vs userId //#ifdef USE_REASTAPI_JOB // restApi()->openDirectMessage(username); //#else ddp()->openDirectChannel(username); //#endif } void RocketChatAccount::createNewChannel(const QString &name, bool readOnly, bool privateRoom, const QString &userNames, bool encryptedRoom, const QString &password, bool broadcast) { //TODO use encrypted room //TODO use broadcast if (!name.trimmed().isEmpty()) { const QStringList lstUsers = userNames.split(QLatin1Char(','), QString::SkipEmptyParts); if (privateRoom) { //TODO add password ??? restApi()->createGroups(name, readOnly, lstUsers); } else { restApi()->createChannels(name, readOnly, lstUsers, password); } } else { qCDebug(RUQOLA_LOG) << "Channel name can't be empty"; } } void RocketChatAccount::joinRoom(const QString &roomId, const QString &joinCode) { restApi()->channelJoin(roomId, joinCode); } void RocketChatAccount::channelAndPrivateAutocomplete(const QString &pattern) { //TODO use restapi if (pattern.isEmpty()) { searchChannelModel()->clear(); } else { //Use restapi //Avoid to show own user #ifdef USE_REASTAPI_JOB restApi()->searchRoomUser(pattern); #else const QString addUserNameToException = userName(); ddp()->channelAndPrivateAutocomplete(pattern, addUserNameToException); #endif } } void RocketChatAccount::listEmojiCustom() { if (mRuqolaServerConfig->hasAtLeastVersion(0, 63, 0)) { restApi()->listEmojiCustom(); } else { ddp()->listEmojiCustom(); } } void RocketChatAccount::setDefaultStatus(User::PresenceStatus status) { //Not implemented yet //TODO use restapi if (statusModel()->currentUserStatus() != status) { ddp()->setDefaultStatus(status); } } void RocketChatAccount::changeDefaultStatus(int index) { setDefaultStatus(mStatusModel->status(index)); } void RocketChatAccount::loadEmojiRestApi(const QJsonObject &obj) { mEmojiManager->loadCustomEmoji(obj, true); } void RocketChatAccount::loadEmoji(const QJsonObject &obj) { mEmojiManager->loadCustomEmoji(obj, false); } void RocketChatAccount::deleteMessage(const QString &messageId, const QString &roomId) { restApi()->deleteMessage(roomId, messageId); } 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 = exception + QLatin1Char(',') + userName(); } //TODO use restapi ddp()->userAutocomplete(searchText, addUserNameToException); } } void RocketChatAccount::membersInRoom(const QString &roomId, const QString &roomType) { restApi()->membersInRoom(roomId, roomType); } void RocketChatAccount::parseUsersForRooms(const QJsonObject &obj, const QString &roomId) { UsersForRoomModel *usersModelForRoom = roomModel()->usersModelForRoom(roomId); if (usersModelForRoom) { usersModelForRoom->parseUsersForRooms(obj, mUserModel, true); } else { qCWarning(RUQOLA_LOG) << " Impossible to find room " << roomId; } } void RocketChatAccount::loadAutoCompleteChannel(const QJsonObject &obj) { mSearchChannelModel->parseChannels(obj); } void RocketChatAccount::roomFiles(const QString &roomId, const QString &channelType) { mFilesModelForRoom->initialize(); restApi()->filesInRoom(roomId, channelType); } MessageModel *RocketChatAccount::threadMessageModel() const { return mThreadMessageModel; } MentionsFilterProxyModel *RocketChatAccount::mentionsFilterProxyModel() const { return mMentionsFilterProxyModel; } MentionsModel *RocketChatAccount::mentionsModel() const { return mMentionsModel; } ThreadsModel *RocketChatAccount::threadsModel() const { return mThreadsModel; } DiscussionsModel *RocketChatAccount::discussionsModel() const { return mDiscussionsModel; } FilesForRoomModel *RocketChatAccount::filesModelForRoom() const { return mFilesModelForRoom; } EmoticonModel *RocketChatAccount::emoticonModel() const { return mEmoticonModel; } void RocketChatAccount::setEmoticonModel(EmoticonModel *emoticonModel) { mEmoticonModel = emoticonModel; } ReceiveTypingNotificationManager *RocketChatAccount::receiveTypingNotificationManager() const { return mReceiveTypingNotificationManager; } void RocketChatAccount::slotChannelRolesDone(const QJsonObject &obj, const QString &roomId) { Room *room = mRoomModel->findRoom(roomId); if (room) { Roles r; r.parseRole(obj); room->setRolesForRooms(r); } else { qCWarning(RUQOLA_LOG) << " Impossible to find room " << roomId; } } void RocketChatAccount::slotGetThreadMessagesDone(const QJsonObject &obj, const QString &threadMessageId) { if (mThreadMessageModel->threadMessageId() != threadMessageId) { mThreadMessageModel->setThreadMessageId(threadMessageId); mThreadMessageModel->parseThreadMessages(obj); } else { mThreadMessageModel->loadMoreThreadMessages(obj); } } void RocketChatAccount::slotGetDiscussionsListDone(const QJsonObject &obj, const QString &roomId) { if (mDiscussionsModel->roomId() != roomId) { mDiscussionsModel->parseDiscussions(obj, roomId); } else { mDiscussionsModel->addMoreDiscussions(obj); } mDiscussionsModel->setLoadMoreDiscussionsInProgress(false); } void RocketChatAccount::slotGetAllUserMentionsDone(const QJsonObject &obj, const QString &roomId) { if (mMentionsModel->roomId() != roomId) { mMentionsModel->parseMentions(obj, roomId); } else { mMentionsModel->addMoreMentions(obj); } mMentionsModel->setLoadMoreMentionsInProgress(false); } void RocketChatAccount::slotGetPinnedMessagesDone(const QJsonObject &obj, const QString &roomId) { - qDebug() << " obj " << obj << "roomId : " << roomId; if (mPinnedMessageModel->roomId() != roomId) { mPinnedMessageModel->setRoomID(roomId); mPinnedMessageModel->parsePinnedMessages(obj); } else { mPinnedMessageModel->loadMorePinnedMessages(obj); } + mPinnedMessageModel->setLoadMorePinnedMessageInProgress(false); } void RocketChatAccount::slotGetThreadsListDone(const QJsonObject &obj, const QString &roomId) { if (mThreadsModel->roomId() != roomId) { mThreadsModel->parseThreads(obj, roomId); } else { mThreadsModel->addMoreThreads(obj); } mThreadsModel->setLoadMoreThreadsInProgress(false); } void RocketChatAccount::slotSplotLightDone(const QJsonObject &obj) { //qDebug() << " void RocketChatAccount::slotSplotLightDone(const QJsonObject &obj)"<roomId() != roomId) { mFilesModelForRoom->parseFileAttachments(obj, roomId); } else { mFilesModelForRoom->addMoreFileAttachments(obj); } mFilesModelForRoom->setLoadMoreFilesInProgress(false); } void RocketChatAccount::loadMoreUsersInRoom(const QString &roomId, const QString &channelType) { UsersForRoomModel *usersModelForRoom = roomModel()->usersModelForRoom(roomId); const int offset = usersModelForRoom->usersCount(); if (offset < usersModelForRoom->total()) { restApi()->membersInRoom(roomId, channelType, offset, qMin(50, usersModelForRoom->total() - offset)); } } void RocketChatAccount::getPinnedMessages(const QString &roomId) { if (mRuqolaServerConfig->hasAtLeastVersion(1, 4, 0)) { restApi()->getPinnedMessages(roomId); } else { qCWarning(RUQOLA_LOG) << " RocketChatAccount::getPinnedMessages is not supported before server 2.0.0"; } } bool RocketChatAccount::hasPinnedMessagesSupport() const { return mRuqolaServerConfig->hasAtLeastVersion(1, 4, 0); } void RocketChatAccount::loadMoreFileAttachments(const QString &roomId, const QString &channelType) { if (!mFilesModelForRoom->loadMoreFilesInProgress()) { const int offset = mFilesModelForRoom->fileAttachments()->filesCount(); if (offset < mFilesModelForRoom->fileAttachments()->total()) { mFilesModelForRoom->setLoadMoreFilesInProgress(true); restApi()->filesInRoom(roomId, channelType, offset, qMin(50, mFilesModelForRoom->fileAttachments()->total() - offset)); } } } void RocketChatAccount::loadMoreDiscussions(const QString &roomId) { if (!mDiscussionsModel->loadMoreDiscussionsInProgress()) { const int offset = mDiscussionsModel->discussions()->discussionsCount(); if (offset < mDiscussionsModel->discussions()->total()) { mDiscussionsModel->setLoadMoreDiscussionsInProgress(true); restApi()->getDiscussions(roomId, offset, qMin(50, mDiscussionsModel->discussions()->total() - offset)); } } } void RocketChatAccount::loadMoreThreads(const QString &roomId) { if (!mThreadsModel->loadMoreThreadsInProgress()) { const int offset = mThreadsModel->threads()->threadsCount(); if (offset < mThreadsModel->threads()->total()) { restApi()->getThreadsList(roomId, offset, qMin(50, mThreadsModel->threads()->total() - offset)); } } } +void RocketChatAccount::loadMorePinnedMessages(const QString &roomId) +{ + if (!mPinnedMessageModel->loadMorePinnedMessageInProgress()) { + //TODO + /* + const int offset = mPinnedMessageModel->count(); + if (offset < mPinnedMessageModel->total()) { + restApi()->getThreadsList(roomId, offset, qMin(50, mPinnedMessageModel->total() - offset)); + } + */ + } +} + void RocketChatAccount::loadThreadMessagesHistory(const QString &threadMessageId) { if (mRuqolaServerConfig->hasAtLeastVersion(1, 0, 0)) { - //mThreadMessageModel->clear(); restApi()->getThreadMessages(threadMessageId); } else { qCWarning(RUQOLA_LOG) << " RocketChatAccount::getThreadMessages is not supported before server 1.0.0"; } - - //TODO } void RocketChatAccount::loadMoreMentions(const QString &roomId) { if (!mMentionsModel->loadMoreMentionsInProgress()) { const int offset = mMentionsModel->mentions()->mentionsCount(); if (offset < mMentionsModel->mentions()->total()) { mMentionsModel->setLoadMoreMentionsInProgress(true); restApi()->channelGetAllUserMentions(roomId, offset, qMin(50, mMentionsModel->mentions()->total() - offset)); } } } void RocketChatAccount::createJitsiConfCall(const QString &roomId) { //TODO use restapi ddp()->createJitsiConfCall(roomId); joinJitsiConfCall(roomId); } void RocketChatAccount::addUserToRoom(const QString &userId, const QString &roomId, const QString &channelType) { if (channelType == QStringLiteral("c")) { restApi()->addUserInChannel(roomId, userId); } else if (channelType == QStringLiteral("p")) { restApi()->addUserInGroup(roomId, userId); } } void RocketChatAccount::clearSearchModel() { mSearchMessageModel->clear(); } void RocketChatAccount::messageSearch(const QString &pattern, const QString &rid) { if (pattern.isEmpty()) { clearSearchModel(); } else { restApi()->searchMessages(rid, pattern); } } void RocketChatAccount::slotSearchMessages(const QJsonObject &obj) { mSearchMessageModel->parseResult(obj, true); } void RocketChatAccount::starMessage(const QString &messageId, bool starred) { restApi()->starMessage(messageId, starred); } void RocketChatAccount::pinMessage(const QString &messageId, bool pinned) { restApi()->pinMessage(messageId, pinned); } 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, const QString &channelType) { switch (infoType) { case Announcement: if (channelType == QStringLiteral("c")) { restApi()->changeChannelAnnouncement(roomId, newValue.toString()); } else if (channelType == QStringLiteral("p")) { if (mRuqolaServerConfig->hasAtLeastVersion(0, 70, 0)) { restApi()->changeGroupsAnnouncement(roomId, newValue.toString()); } else { ddp()->setRoomAnnouncement(roomId, newValue.toString()); } } else { qCWarning(RUQOLA_LOG) << " unsupport change announcement for type " << channelType; } break; case Description: if (channelType == QStringLiteral("c")) { restApi()->changeChannelDescription(roomId, newValue.toString()); } else if (channelType == QStringLiteral("p")) { restApi()->changeGroupsDescription(roomId, newValue.toString()); } else { qCWarning(RUQOLA_LOG) << " unsupport change description for type " << channelType; } break; case Name: if (channelType == QStringLiteral("c")) { restApi()->changeChannelName(roomId, newValue.toString()); } else if (channelType == QStringLiteral("p")) { restApi()->changeGroupName(roomId, newValue.toString()); } else { qCWarning(RUQOLA_LOG) << " unsupport change name for type " << channelType; } break; case Topic: if (channelType == QStringLiteral("c")) { restApi()->changeChannelTopic(roomId, newValue.toString()); } else if (channelType == QStringLiteral("p")) { restApi()->changeGroupsTopic(roomId, newValue.toString()); } else { //TODO : change topic in direct channel qCWarning(RUQOLA_LOG) << " unsupport change topic for type " << channelType; } break; case ReadOnly: if (channelType == QStringLiteral("c")) { restApi()->changeChannelReadOnly(roomId, newValue.toBool()); } else if (channelType == QStringLiteral("p")) { restApi()->changeGroupsReadOnly(roomId, newValue.toBool()); } else { qCWarning(RUQOLA_LOG) << " unsupport change readonly for type " << channelType; } break; case Archive: if (channelType == QStringLiteral("c")) { restApi()->archiveChannel(roomId, newValue.toBool()); } else if (channelType == QStringLiteral("p")) { restApi()->archiveGroups(roomId, newValue.toBool()); } else { qCWarning(RUQOLA_LOG) << " unsupport archiving for type " << channelType; } break; case RoomType: if (channelType == QStringLiteral("c")) { restApi()->setChannelType(roomId, newValue.toBool()); } else if (channelType == QStringLiteral("p")) { restApi()->setGroupType(roomId, newValue.toBool()); } else { qCWarning(RUQOLA_LOG) << " unsupport roomtype for type " << channelType; } break; case Encrypted: if (channelType == QStringLiteral("c")) { restApi()->changeChannelEncrypted(roomId, newValue.toBool()); } else if (channelType == QStringLiteral("p")) { restApi()->changeGroupsEncrypted(roomId, newValue.toBool()); } else { qCWarning(RUQOLA_LOG) << " unsupport encrypted mode for type " << channelType; } break; } } void RocketChatAccount::reportMessage(const QString &messageId, const QString &message) { if (mRuqolaServerConfig->hasAtLeastVersion(0, 64, 0)) { restApi()->reportMessage(messageId, message); } else { qCWarning(RUQOLA_LOG) << " RocketChatAccount::reportMessage is not supported before server 0.64"; } } void RocketChatAccount::getThreadMessages(const QString &threadMessageId) { if (mRuqolaServerConfig->hasAtLeastVersion(1, 0, 0)) { mThreadMessageModel->clear(); restApi()->getThreadMessages(threadMessageId); } else { qCWarning(RUQOLA_LOG) << " RocketChatAccount::getThreadMessages is not supported before server 1.0.0"; } } void RocketChatAccount::changeNotificationsSettings(const QString &roomId, RocketChatAccount::NotificationOptionsType notificationsType, const QVariant &newValue) { switch (notificationsType) { case DisableNotifications: restApi()->disableNotifications(roomId, newValue.toBool()); break; case HideUnreadStatus: restApi()->hideUnreadStatus(roomId, newValue.toBool()); break; case AudioNotifications: restApi()->audioNotifications(roomId, newValue.toString()); break; case DesktopNotifications: restApi()->desktopNotifications(roomId, newValue.toString()); break; case EmailNotifications: restApi()->emailNotifications(roomId, newValue.toString()); break; case MobilePushNotifications: restApi()->mobilePushNotifications(roomId, newValue.toString()); break; case UnreadAlert: restApi()->unreadAlert(roomId, newValue.toString()); break; case MuteGroupMentions: restApi()->muteGroupMentions(roomId, newValue.toBool()); break; case DesktopDurationNotifications: restApi()->desktopDurationNotifications(roomId, newValue.toInt()); break; case DesktopSoundNotifications: restApi()->desktopSoundNotifications(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_Enabled")) { mRuqolaServerConfig->setJitsiEnabled(value.toBool()); } 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 if (id == QLatin1String("E2E_Enable")) { mRuqolaServerConfig->setEncryptionEnabled(value.toBool()); } else if (id == QLatin1String("Message_AllowPinning")) { mRuqolaServerConfig->setAllowMessagePinningEnabled(value.toBool()); } else if (id == QLatin1String("Message_AllowSnippeting")) { mRuqolaServerConfig->setAllowMessageSnippetingEnabled(value.toBool()); } else if (id == QLatin1String("Message_AllowStarring")) { mRuqolaServerConfig->setAllowMessageStarringEnabled(value.toBool()); } else if (id == QLatin1String("Message_AllowDeleting")) { mRuqolaServerConfig->setAllowMessageDeletingEnabled(value.toBool()); } else if (id == QLatin1String("Threads_enabled")) { mRuqolaServerConfig->setThreadsEnabled(value.toBool()); } else if (id == QLatin1String("Discussion_enabled")) { mRuqolaServerConfig->setDiscussionEnabled(value.toBool()); } else if (id == QLatin1String("AutoTranslate_Enabled")) { mRuqolaServerConfig->setAutoTranslateEnabled(value.toBool()); } else if (id == QLatin1String("AutoTranslate_GoogleAPIKey")) { mRuqolaServerConfig->setAutoTranslateGoogleKey(value.toString()); } else { qCDebug(RUQOLA_LOG) << "Other public settings id " << id << value; } //TODO add Accounts_AllowUserStatusMessageChange when we will have a RestAPI method for it. } fillOauthModel(); } void RocketChatAccount::fillOauthModel() { QVector fillModel; for (int i = 0, total = mLstInfos.count(); i < total; ++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(); if (lstPlugins.isEmpty()) { qCWarning(RUQOLA_LOG) <<" No plugins loaded. Please verify your installation."; } 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::inputThreadMessageCompleterModel() const { return mInputThreadMessageTextManager->inputCompleterModel(); } 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(); } QString RocketChatAccount::twoFactorAuthenticationCode() const { return settings()->twoFactorAuthenticationCode(); } void RocketChatAccount::setAuthToken(const QString &token) { settings()->setAuthToken(token); } void RocketChatAccount::setPassword(const QString &password) { settings()->setPassword(password); } void RocketChatAccount::setTwoFactorAuthenticationCode(const QString &twoFactorAuthenticationCode) { settings()->setTwoFactorAuthenticationCode(twoFactorAuthenticationCode); } 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, const QString &channelType, bool initial) { //TODO port to restapi Q_UNUSED(channelType); 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::encryptedEnabled() const { return mRuqolaServerConfig->encryptionEnabled(); } bool RocketChatAccount::allowMessagePinningEnabled() const { return mRuqolaServerConfig->allowMessagePinningEnabled(); } bool RocketChatAccount::allowMessageSnippetingEnabled() const { return mRuqolaServerConfig->allowMessageSnippetingEnabled(); } bool RocketChatAccount::allowMessageStarringEnabled() const { return mRuqolaServerConfig->allowMessageStarringEnabled(); } bool RocketChatAccount::allowMessageDeletingEnabled() const { return mRuqolaServerConfig->allowMessageDeletingEnabled(); } bool RocketChatAccount::threadsEnabled() const { return mRuqolaServerConfig->threadsEnabled(); } bool RocketChatAccount::autoTranslateEnabled() const { return mRuqolaServerConfig->autoTranslateEnabled(); } bool RocketChatAccount::discussionEnabled() const { return mRuqolaServerConfig->discussionEnabled(); } QString RocketChatAccount::serverVersionStr() const { return mRuqolaServerConfig->serverVersionStr(); } ServerConfigInfo *RocketChatAccount::serverConfigInfo() const { return mServerConfigInfo; } bool RocketChatAccount::jitsiEnabled() const { return mRuqolaServerConfig->jitsiEnabled(); } void RocketChatAccount::groupInfo(const QString &roomId) { restApi()->groupInfo(roomId); } void RocketChatAccount::switchEditingMode(bool b) { if (mEditingMode != b) { mEditingMode = b; Q_EMIT editingModeChanged(); } } void RocketChatAccount::setSortUnreadOnTop(bool b) { if (settings()->setShowUnreadOnTop(b)) { mRoomFilterProxyModel->invalidate(); Q_EMIT sortUnreadOnTopChanged(); } } bool RocketChatAccount::sortUnreadOnTop() const { return settings()->showUnreadOnTop(); } void RocketChatAccount::kickUser(const QString &roomId, const QString &userId, const QString &channelType) { if (channelType == QStringLiteral("c")) { restApi()->channelKick(roomId, userId); } else if (channelType == QStringLiteral("p")) { restApi()->groupKick(roomId, userId); } else { qCWarning(RUQOLA_LOG) << " unsupport kickUser room for type " << channelType; } } void RocketChatAccount::rolesInRoom(const QString &roomId, const QString &channelType) { if (channelType == QStringLiteral("c")) { restApi()->getChannelRoles(roomId); } else if (channelType == QStringLiteral("p")) { restApi()->getGroupRoles(roomId); } else if (channelType == QStringLiteral("d")) { //No a problem here. } else { qCWarning(RUQOLA_LOG) << " unsupport get roles room for type " << channelType; } } void RocketChatAccount::switchingToRoom(const QString &roomID) { clearTypingNotification(); checkInitializedRoom(roomID); } void RocketChatAccount::changeRoles(const QString &roomId, const QString &userId, const QString &channelType, RocketChatAccount::RoleType roleType) { if (channelType == QStringLiteral("c")) { switch (roleType) { case RocketChatAccount::AddOwner: restApi()->channelAddOwner(roomId, userId); break; case RocketChatAccount::AddLeader: if (mRuqolaServerConfig->hasAtLeastVersion(0, 75, 0)) { restApi()->channelAddLeader(roomId, userId); } else { qCWarning(RUQOLA_LOG) << " RocketChatAccount::AddLeader is not supported before server 0.75"; } break; case RocketChatAccount::AddModerator: restApi()->channelAddModerator(roomId, userId); break; case RocketChatAccount::RemoveOwner: restApi()->channelRemoveOwner(roomId, userId); break; case RocketChatAccount::RemoveLeader: if (mRuqolaServerConfig->hasAtLeastVersion(0, 75, 0)) { restApi()->channelRemoveLeader(roomId, userId); } else { qCWarning(RUQOLA_LOG) << " RocketChatAccount::RemoveLeader is not supported before server 0.75"; } break; case RocketChatAccount::RemoveModerator: restApi()->channelRemoveModerator(roomId, userId); break; } } else if (channelType == QStringLiteral("p")) { switch (roleType) { case RocketChatAccount::AddOwner: restApi()->groupAddOwner(roomId, userId); break; case RocketChatAccount::AddLeader: restApi()->groupAddLeader(roomId, userId); break; case RocketChatAccount::AddModerator: restApi()->groupAddModerator(roomId, userId); break; case RocketChatAccount::RemoveOwner: restApi()->groupRemoveOwner(roomId, userId); break; case RocketChatAccount::RemoveLeader: restApi()->groupRemoveLeader(roomId, userId); break; case RocketChatAccount::RemoveModerator: restApi()->groupRemoveModerator(roomId, userId); break; } } else { qCWarning(RUQOLA_LOG) << " unsupport changeRoles room for type " << channelType; } } void RocketChatAccount::channelInfo(const QString &roomId) { restApi()->channelInfo(roomId); } 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); break; case InputTextManager::CompletionForType::User: ddp()->inputUserAutocomplete(pattern, exceptions); break; } } void RocketChatAccount::inputThreadMessageAutocomplete(const QString &pattern, const QString &exceptions, InputTextManager::CompletionForType type) { qDebug() << " void RocketChatAccount::inputThreadMessageAutocomplete(const QString &pattern, const QString &exceptions, InputTextManager::CompletionForType type)" << pattern; switch (type) { case InputTextManager::CompletionForType::Channel: ddp()->inputChannelAutocomplete(pattern, exceptions); break; case InputTextManager::CompletionForType::User: ddp()->inputUserAutocomplete(pattern, exceptions); break; } } PinnedMessageModel *RocketChatAccount::pinnedMessageModel() const { return mPinnedMessageModel; } 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::ignoreUser(const QString &rid, const QString &userId, bool ignore) { restApi()->ignoreUser(rid, userId, ignore); } void RocketChatAccount::blockUser(const QString &rid, bool block) { //TODO use restapi 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::clearTypingNotification() { mReceiveTypingNotificationManager->clearTypingNotification(); } void RocketChatAccount::checkInitializedRoom(const QString &roomId) { Room *r = mRoomModel->findRoom(roomId); if (r && !r->wasInitialized()) { r->setWasInitialized(true); ddp()->subscribeRoomMessage(roomId); if (!r->archived()) { membersInRoom(r->roomId(), r->channelType()); rolesInRoom(r->roomId(), r->channelType()); } loadHistory(r->roomId(), QString(), true /*initial loading*/); } else if (!r) { qWarning() << " Room " << roomId << " was no found! Need to open it"; //openDirectChannel(roomId); } QMetaObject::invokeMethod(this, &RocketChatAccount::switchedRooms, Qt::QueuedConnection); } void RocketChatAccount::openDocumentation() { QDesktopServices::openUrl(QUrl(QStringLiteral("help:/"))); } void RocketChatAccount::channelGetAllUserMentions(const QString &roomId) { mMentionsModel->initialize(); restApi()->channelGetAllUserMentions(roomId); } void RocketChatAccount::rolesChanged(const QJsonArray &contents) { for (int i = 0; i < contents.count(); ++i) { const QJsonObject obj = contents.at(i).toObject(); const QString scope = obj[QLatin1String("scope")].toString(); Room *room = mRoomModel->findRoom(scope); if (room) { room->updateRoles(obj); } } } void RocketChatAccount::createDiscussion(const QString &parentRoomId, const QString &discussionName, const QString &replyMessage, const QString &messageId) { restApi()->createDiscussion(parentRoomId, discussionName, replyMessage, messageId); } void RocketChatAccount::threadsInRoom(const QString &roomId) { if (mRuqolaServerConfig->hasAtLeastVersion(1, 0, 0)) { mThreadsModel->initialize(); restApi()->getThreadsList(roomId); } else { qCWarning(RUQOLA_LOG) << " RocketChatAccount::threadsInRoom is not supported before server 1.0.0"; } } void RocketChatAccount::discussionsInRoom(const QString &roomId) { if (mRuqolaServerConfig->hasAtLeastVersion(1, 0, 0)) { mDiscussionsModel->initialize(); restApi()->getDiscussions(roomId); } else { qCWarning(RUQOLA_LOG) << " RocketChatAccount::discussionsInRoom is not supported before server 1.0.0"; } } void RocketChatAccount::followMessage(const QString &messageId, bool follow) { if (follow) { restApi()->followMessage(messageId); } else { restApi()->unFollowMessage(messageId); } } diff --git a/src/ruqolacore/rocketchataccount.h b/src/ruqolacore/rocketchataccount.h index 926797e1..ceefa0f2 100644 --- a/src/ruqolacore/rocketchataccount.h +++ b/src/ruqolacore/rocketchataccount.h @@ -1,451 +1,452 @@ /* Copyright (c) 2017-2019 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 ROCKETCHATACCOUNT_H #define ROCKETCHATACCOUNT_H #include #include #include #include "rocketchataccountsettings.h" #include "libruqola_private_export.h" #include "authenticationinfo.h" #include "file.h" #include "inputtextmanager.h" class TypingNotification; class UsersModel; class RoomModel; class RoomWrapper; class MessageModel; class DDPClient; class MessageQueue; class RocketChatBackend; class RoomFilterProxyModel; class RuqolaLogger; class RuqolaServerConfig; class UserCompleterModel; class UserCompleterFilterProxyModel; class StatusModel; class RocketChatCache; class EmojiManager; class OtrManager; class UsersForRoomFilterProxyModel; class FilesForRoomFilterProxyModel; class FilesForRoomModel; class SearchChannelModel; class SearchChannelFilterProxyModel; class LoginMethodModel; class InputCompleterModel; class InputTextManager; class PluginAuthenticationInterface; class Room; class SearchMessageModel; class SearchMessageFilterProxyModel; class ThreadsFilterProxyModel; class ServerConfigInfo; class ReceiveTypingNotificationManager; class EmoticonModel; class DiscussionsFilterProxyModel; class DiscussionsModel; class ThreadsModel; class MentionsModel; class MentionsFilterProxyModel; class ThreadMessageModel; class PinnedMessageModel; namespace RocketChatRestApi { class RestApiRequest; } class LIBRUQOLACORE_EXPORT RocketChatAccount : public QObject { Q_OBJECT Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged) Q_PROPERTY(QString userID READ userID WRITE setUserID NOTIFY userIDChanged) Q_PROPERTY(QString serverUrl READ serverUrl WRITE setServerUrl NOTIFY serverUrlChanged) Q_PROPERTY(QString accountName READ accountName WRITE setAccountName NOTIFY accountNameChanged) Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged) Q_PROPERTY(QString twoFactorAuthenticationCode READ twoFactorAuthenticationCode WRITE setTwoFactorAuthenticationCode NOTIFY twoFactorAuthenticationCodeChanged) Q_PROPERTY(DDPClient::LoginStatus loginStatus READ loginStatus NOTIFY loginStatusChanged) Q_PROPERTY(bool editingMode READ editingMode NOTIFY editingModeChanged) Q_PROPERTY(bool sortUnreadOnTop READ sortUnreadOnTop NOTIFY sortUnreadOnTopChanged) public: explicit RocketChatAccount(const QString &accountName = QString(), QObject *parent = nullptr); ~RocketChatAccount(); enum RoomInfoType { Announcement, Description, Name, Topic, ReadOnly, Archive, RoomType, Encrypted, }; Q_ENUM(RoomInfoType) enum NotificationOptionsType { DisableNotifications, HideUnreadStatus, AudioNotifications, DesktopNotifications, DesktopDurationNotifications, DesktopSoundNotifications, EmailNotifications, MobilePushNotifications, UnreadAlert, MuteGroupMentions }; Q_ENUM(NotificationOptionsType) enum RoleType { AddOwner, AddLeader, AddModerator, RemoveOwner, RemoveLeader, RemoveModerator }; Q_ENUM(RoleType) Q_INVOKABLE UsersModel *usersModel() const; Q_INVOKABLE RoomModel *roomModel() const; Q_INVOKABLE RoomFilterProxyModel *roomFilterProxyModel() const; Q_INVOKABLE UsersForRoomFilterProxyModel *usersForRoomFilterProxyModel(const QString &roomId) const; Q_INVOKABLE RoomWrapper *getRoomWrapper(const QString &roomId); Q_INVOKABLE MessageModel *messageModelForRoom(const QString &roomID); Q_INVOKABLE QString getUserCurrentMessage(const QString &roomId); Q_INVOKABLE void setUserCurrentMessage(const QString &message, const QString &roomId); Q_INVOKABLE void textEditing(const QString &roomId, const QString &str); Q_INVOKABLE void leaveRoom(const QString &roomId, const QString &channelType); Q_INVOKABLE void hideRoom(const QString &roomId, const QString &channelType = QString()); Q_INVOKABLE void tryLogin(); Q_INVOKABLE void logOut(); Q_INVOKABLE void clearUnreadMessages(const QString &roomId); Q_INVOKABLE void changeFavorite(const QString &roomId, bool checked); Q_INVOKABLE void sendMessage(const QString &roomID, const QString &message); Q_INVOKABLE void updateMessage(const QString &roomID, const QString &messageId, const QString &message); Q_INVOKABLE void replyOnThread(const QString &roomID, const QString &threadMessageId, const QString &message); Q_INVOKABLE void openChannel(const QString &url); Q_INVOKABLE void joinJitsiConfCall(const QString &roomId); Q_INVOKABLE void createNewChannel(const QString &name, bool readOnly, bool privateRoom, const QString &userNames, bool encryptedRoom, const QString &password, bool broadcast); Q_INVOKABLE void joinRoom(const QString &roomId, const QString &joinCode = QString()); Q_INVOKABLE void openDirectChannel(const QString &username); Q_INVOKABLE void listEmojiCustom(); Q_INVOKABLE void setDefaultStatus(User::PresenceStatus status); Q_INVOKABLE void changeDefaultStatus(int index); Q_INVOKABLE void createJitsiConfCall(const QString &roomId); Q_INVOKABLE void deleteMessage(const QString &messageId, const QString &roomId); Q_INVOKABLE void userAutocomplete(const QString &searchText, const QString &exception); Q_INVOKABLE void eraseRoom(const QString &roomId, const QString &channelType); Q_INVOKABLE void changeChannelSettings(const QString &roomId, RocketChatAccount::RoomInfoType infoType, const QVariant &newValue, const QString &channelType = QString()); Q_INVOKABLE void changeNotificationsSettings(const QString &roomId, RocketChatAccount::NotificationOptionsType notificationsType, const QVariant &newValue); Q_INVOKABLE QString recordingVideoPath() const; Q_INVOKABLE QString recordingImagePath() const; Q_INVOKABLE void downloadFile(const QString &downloadFileUrl, const QUrl &localFile); Q_INVOKABLE void starMessage(const QString &messageId, bool starred); Q_INVOKABLE void pinMessage(const QString &messageId, bool pinned); Q_INVOKABLE void uploadFile(const QString &roomId, const QString &description, const QString &messageText, const QUrl &fileUrl); Q_INVOKABLE QString serverUrl() const; Q_INVOKABLE QString avatarUrl(const QString &userId); Q_INVOKABLE StatusModel *statusModel() const; Q_INVOKABLE Q_REQUIRED_RESULT QUrl attachmentUrl(const QString &url); Q_INVOKABLE void loadHistory(const QString &roomID, const QString &channelType = QString(), bool initial = false); Q_INVOKABLE Q_REQUIRED_RESULT bool allowEditingMessages() const; Q_INVOKABLE Q_REQUIRED_RESULT bool otrEnabled() const; Q_INVOKABLE void channelAndPrivateAutocomplete(const QString &pattern); Q_INVOKABLE UserCompleterFilterProxyModel *userCompleterFilterModelProxy() const; Q_INVOKABLE void roomFiles(const QString &roomId, const QString &channelType = QString()); Q_INVOKABLE FilesForRoomFilterProxyModel *filesForRoomFilterProxyModel() const; Q_INVOKABLE void addUserToRoom(const QString &username, const QString &roomId, const QString &channelType); Q_INVOKABLE SearchChannelFilterProxyModel *searchChannelFilterProxyModel() const; Q_INVOKABLE InputCompleterModel *inputCompleterModel() const; Q_INVOKABLE InputCompleterModel *inputThreadMessageCompleterModel() const; Q_INVOKABLE LoginMethodModel *loginMethodModel() const; Q_INVOKABLE Room *getRoom(const QString &roomId); Q_INVOKABLE DiscussionsFilterProxyModel *discussionsFilterProxyModel() const; Q_INVOKABLE ThreadsFilterProxyModel *threadsFilterProxyModel() const; Q_INVOKABLE MentionsFilterProxyModel *mentionsFilterProxyModel() const; Q_INVOKABLE void changeDefaultAuthentication(int index); Q_INVOKABLE void messageSearch(const QString &pattern, const QString &rid); Q_INVOKABLE SearchMessageFilterProxyModel *searchMessageFilterProxyModel() const; Q_INVOKABLE void setInputTextChanged(const QString &str, int position); Q_INVOKABLE QString replaceWord(const QString &newWord, const QString &str, int position); Q_INVOKABLE void blockUser(const QString &userId, bool block); Q_INVOKABLE QString avatarUrlFromDirectChannel(const QString &rid); Q_INVOKABLE void deleteFileMessage(const QString &roomId, const QString &fileId, const QString &channelType); Q_INVOKABLE void openDocumentation(); Q_INVOKABLE void clearSearchModel(); Q_INVOKABLE void reactOnMessage(const QString &messageId, const QString &emoji, bool shouldReact); Q_INVOKABLE void ignoreUser(const QString &rid, const QString &userId, bool ignore); Q_INVOKABLE ReceiveTypingNotificationManager *receiveTypingNotificationManager() const; Q_INVOKABLE Q_REQUIRED_RESULT bool encryptedEnabled() const; Q_INVOKABLE Q_REQUIRED_RESULT QString serverVersionStr() const; Q_INVOKABLE Q_REQUIRED_RESULT ServerConfigInfo *serverConfigInfo() const; Q_INVOKABLE Q_REQUIRED_RESULT bool jitsiEnabled() const; Q_INVOKABLE Q_REQUIRED_RESULT bool allowMessagePinningEnabled() const; Q_INVOKABLE Q_REQUIRED_RESULT bool allowMessageSnippetingEnabled() const; Q_INVOKABLE Q_REQUIRED_RESULT bool allowMessageStarringEnabled() const; Q_INVOKABLE Q_REQUIRED_RESULT bool allowMessageDeletingEnabled() const; Q_INVOKABLE Q_REQUIRED_RESULT bool autoTranslateEnabled() const; Q_INVOKABLE void channelInfo(const QString &roomId); Q_INVOKABLE void groupInfo(const QString &roomId); Q_INVOKABLE void channelGetAllUserMentions(const QString &roomId); Q_INVOKABLE void switchEditingMode(bool b); Q_INVOKABLE void setSortUnreadOnTop(bool b); Q_INVOKABLE void kickUser(const QString &rid, const QString &userId, const QString &channelType); Q_INVOKABLE void changeRoles(const QString &rid, const QString &userId, const QString &channelType, RocketChatAccount::RoleType roleType); Q_INVOKABLE void rolesInRoom(const QString &roomId, const QString &channelType); Q_INVOKABLE void switchingToRoom(const QString &roomID); Q_INVOKABLE void reportMessage(const QString &messageId, const QString &message); Q_INVOKABLE void getThreadMessages(const QString &threadMessageId); Q_INVOKABLE void createDiscussion(const QString &parentRoomName, const QString &discussionName, const QString &replyMessage, const QString &messageId); Q_INVOKABLE Q_REQUIRED_RESULT bool threadsEnabled() const; Q_INVOKABLE Q_REQUIRED_RESULT bool discussionEnabled() const; Q_INVOKABLE void threadsInRoom(const QString &roomId); Q_INVOKABLE void discussionsInRoom(const QString &roomId); Q_INVOKABLE void followMessage(const QString &messageId, bool follow); Q_INVOKABLE void replyToMessage(const QString &roomID, const QString &message, const QString &messageId); SearchChannelModel *searchChannelModel() const; UserCompleterModel *userCompleterModel() const; RocketChatAccountSettings *settings() const; DDPClient *ddp(); Q_REQUIRED_RESULT bool editingMode() const; Q_REQUIRED_RESULT bool sortUnreadOnTop() const; Q_REQUIRED_RESULT DDPClient::LoginStatus loginStatus(); RocketChatRestApi::RestApiRequest *restApi(); //Make it private in future void slotInformTypingStatus(const QString &room, bool typing); MessageQueue *messageQueue() const; RocketChatBackend *rocketChatBackend() const; RuqolaLogger *ruqolaLogger() const; void loadEmoji(const QJsonObject &obj); void parsePublicSettings(const QJsonObject &obj); RuqolaServerConfig *ruqolaServerConfig() const; void setUserName(const QString &username); Q_REQUIRED_RESULT QString userName() const; void setAccountName(const QString &servername); Q_REQUIRED_RESULT QString accountName() const; void setUserID(const QString &userID); Q_REQUIRED_RESULT QString userID() const; void setPassword(const QString &password); Q_REQUIRED_RESULT QString password() const; void setTwoFactorAuthenticationCode(const QString &twoFactorAuthenticationCode); Q_REQUIRED_RESULT QString twoFactorAuthenticationCode() const; void setAuthToken(const QString &token); Q_REQUIRED_RESULT QString authToken() const; void setServerUrl(const QString &serverUrl); void sendNotification(const QJsonArray &contents); void parseOtr(const QJsonArray &contents); void setServerVersion(const QString &version); Q_REQUIRED_RESULT bool needAdaptNewSubscriptionRC60() const; EmojiManager *emojiManager() const; Q_REQUIRED_RESULT QString userStatusIconFileName(const QString &id); void membersInRoom(const QString &roomId, const QString &roomType); void parseUsersForRooms(const QJsonObject &obj, const QString &roomId); void loadAutoCompleteChannel(const QJsonObject &obj); void insertCompleterUsers(); void inputTextCompleter(const QJsonObject &obj); PluginAuthenticationInterface *defaultAuthenticationInterface() const; SearchMessageModel *searchMessageModel() const; void displaySearchedMessage(const QJsonObject &obj); void updateUser(const QJsonObject &object); void removeSettings(); void rolesChanged(const QJsonArray &contents); Q_INVOKABLE EmoticonModel *emoticonModel() const; void setEmoticonModel(EmoticonModel *emoticonModel); FilesForRoomModel *filesModelForRoom() const; DiscussionsModel *discussionsModel() const; ThreadsModel *threadsModel() const; MentionsModel *mentionsModel() const; Q_INVOKABLE MessageModel *threadMessageModel() const; Q_INVOKABLE void loadMoreFileAttachments(const QString &roomId, const QString &channelType); Q_INVOKABLE void loadMoreDiscussions(const QString &roomId); Q_INVOKABLE void loadMoreThreads(const QString &roomId); Q_INVOKABLE void loadThreadMessagesHistory(const QString &roomId); Q_INVOKABLE void loadMoreMentions(const QString &roomId); Q_INVOKABLE void loadMoreUsersInRoom(const QString &roomId, const QString &channelType); Q_INVOKABLE void getPinnedMessages(const QString &roomId); Q_INVOKABLE Q_REQUIRED_RESULT bool hasPinnedMessagesSupport() const; Q_INVOKABLE PinnedMessageModel *pinnedMessageModel() const; + Q_INVOKABLE void loadMorePinnedMessages(const QString &roomId); Q_SIGNALS: void connectedChanged(); void accountNameChanged(); void userNameChanged(); void userIDChanged(); void passwordChanged(); void twoFactorAuthenticationCodeChanged(); void serverUrlChanged(); void loginStatusChanged(); void logoutDone(const QString &accountname); void added(const QJsonObject &item); void changed(const QJsonObject &item); void removed(const QJsonObject &item); void notification(const QString &title, const QString &message, const QPixmap &pixmap); void fileDownloaded(const QString &filePath, const QUrl &cacheImageUrl); void updateNotification(bool hasAlert, int nbUnread, const QString &accountName); void missingChannelPassword(const QString &roomId); void editingModeChanged(); void sortUnreadOnTopChanged(); void jobFailed(const QString &message); void switchedRooms(); private: Q_DISABLE_COPY(RocketChatAccount) void slotChannelFilesDone(const QJsonObject &obj, const QString &roomId); void slotChannelRolesDone(const QJsonObject &obj, const QString &roomId); void slotSplotLightDone(const QJsonObject &obj); void slotGetThreadMessagesDone(const QJsonObject &obj, const QString &threadMessageId); void slotGetThreadsListDone(const QJsonObject &obj, const QString &roomId); void slotGetDiscussionsListDone(const QJsonObject &obj, const QString &roomId); void slotGetAllUserMentionsDone(const QJsonObject &obj, const QString &roomId); void slotGetPinnedMessagesDone(const QJsonObject &obj, const QString &roomId); void loadEmojiRestApi(const QJsonObject &obj); void slotSearchMessages(const QJsonObject &obj); void slotNeedToUpdateNotification(); void insertAvatarUrl(const QString &userId, const QString &url); void loadSettings(const QString &accountFileName); void clearModels(); void fillOauthModel(); void initializeAuthenticationPlugins(); void setDefaultAuthentication(AuthenticationManager::OauthType type); void userStatusChanged(const User &user); void setChannelJoinDone(const QString &roomId); void openArchivedRoom(const QString &roomId); void checkInitializedRoom(const QString &roomId); void clearTypingNotification(); void inputAutocomplete(const QString &pattern, const QString &exceptions, InputTextManager::CompletionForType type); void inputThreadMessageAutocomplete(const QString &pattern, const QString &exceptions, InputTextManager::CompletionForType type); PluginAuthenticationInterface *mDefaultAuthenticationInterface = nullptr; QHash mLstPluginAuthenticationInterface; QVector mLstInfos; RocketChatAccountSettings *mSettings = nullptr; EmojiManager *mEmojiManager = nullptr; TypingNotification *mTypingNotification = nullptr; UsersModel *mUserModel = nullptr; RoomModel *mRoomModel = nullptr; RoomFilterProxyModel *mRoomFilterProxyModel = nullptr; DDPClient *mDdp = nullptr; RocketChatRestApi::RestApiRequest *mRestApi = nullptr; MessageQueue *mMessageQueue = nullptr; RocketChatBackend *mRocketChatBackend = nullptr; RuqolaLogger *mRuqolaLogger = nullptr; RuqolaServerConfig *mRuqolaServerConfig = nullptr; UserCompleterModel *mUserCompleterModel = nullptr; UserCompleterFilterProxyModel *mUserCompleterFilterModelProxy = nullptr; StatusModel *mStatusModel = nullptr; RocketChatCache *mCache = nullptr; OtrManager *mOtrManager = nullptr; SearchChannelModel *mSearchChannelModel = nullptr; SearchChannelFilterProxyModel *mSearchChannelFilterProxyModel = nullptr; LoginMethodModel *mLoginMethodModel = nullptr; InputTextManager *mInputTextManager = nullptr; InputTextManager *mInputThreadMessageTextManager = nullptr; SearchMessageModel *mSearchMessageModel = nullptr; SearchMessageFilterProxyModel *mSearchMessageFilterProxyModel = nullptr; ReceiveTypingNotificationManager *mReceiveTypingNotificationManager = nullptr; ServerConfigInfo *mServerConfigInfo = nullptr; FilesForRoomModel *mFilesModelForRoom = nullptr; FilesForRoomFilterProxyModel *mFilesForRoomFilterProxyModel = nullptr; DiscussionsFilterProxyModel *mDiscussionsFilterProxyModel = nullptr; DiscussionsModel *mDiscussionsModel = nullptr; ThreadsModel *mThreadsModel = nullptr; ThreadsFilterProxyModel *mThreadsFilterProxyModel = nullptr; MentionsModel *mMentionsModel = nullptr; MentionsFilterProxyModel *mMentionsFilterProxyModel = nullptr; EmoticonModel *mEmoticonModel = nullptr; ThreadMessageModel *mThreadMessageModel = nullptr; PinnedMessageModel *mPinnedMessageModel = nullptr; bool mEditingMode = false; }; #endif // ROCKETCHATACCOUNT_H