diff --git a/src/rocketchatbackend.cpp b/src/rocketchatbackend.cpp index f2f5126d..6548cc3c 100644 --- a/src/rocketchatbackend.cpp +++ b/src/rocketchatbackend.cpp @@ -1,275 +1,280 @@ /* * * Copyright 2016 Riccardo Iaconelli * * 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 "rocketchatbackend.h" #include #include #include #include "userdata.h" #include "ddpclient.h" #include "notification.h" RocketChatBackend c; void debug_callback(QJsonDocument doc) { qDebug() << "DEBUG:" << doc; } void process_backlog(QJsonDocument messages) { qDebug() << messages.object().value("messages").toArray().size(); RocketChatBackend::processIncomingMessages(messages.object().value("messages").toArray()); } QString RocketChatBackend::userID() const { return x_userID; } void RocketChatBackend::setUserID(QString & userid) { x_userID = userid; } void rooms_callback(QJsonDocument doc) { // qDebug() << doc; RoomModel *model = UserData::self()->roomModel(); // qDebug() << model; // model->reset(); QJsonArray removed = doc.object().value("remove").toArray(); QJsonArray updated = doc.object().value("update").toArray(); for (int i = 0; i < updated.size(); i++) { QJsonObject room = updated.at(i).toObject(); if (room.value("t").toString() != "d") { QString roomID = room.value("_id").toString(); // qDebug() << "Adding" << roomID<< room.value("name").toString() << room; MessageModel *roomModel = UserData::self()->getModelForRoom(roomID); // let's be extra safe around crashes if (UserData::self()->loginStatus() == DDPClient::LoggedIn) { Room r; r.id = roomID; r.name = room["name"].toString(); r.topic = room["topic"].toString(); qDebug() << "Adding room" << r.name << r.id << r.topic; model->addRoom(r); } QString params = QString("[\"%1\"]").arg(roomID); UserData::self()->ddp()->subscribe("stream-room-messages", QJsonDocument::fromJson(params.toLatin1())); QString userID = c.userID(); QString n_params = QString("[\"%1\"/\"%2\" ]").arg(userID).arg(QString("notification")); UserData::self()->ddp()->subscribe("stream-notify-user", QJsonDocument::fromJson(n_params.toLatin1())); // Load history QByteArray json = "[\""+roomID.toLatin1() + "\", null, 50, {\"$date\": "+ QString::number(roomModel->lastTimestamp()).toLatin1()+ "}]"; qDebug() << json; UserData::self()->ddp()->method("loadHistory", QJsonDocument::fromJson(json), process_backlog); } } qDebug() << "DEBUG:" << doc; } void subs_callback(QJsonDocument doc) { // qDebug() << doc; RoomModel *model = UserData::self()->roomModel(); // qDebug() << model; // model->reset(); QJsonArray removed = doc.object().value("remove").toArray(); QJsonArray updated = doc.object().value("update").toArray(); for (int i = 0; i < updated.size(); i++) { QJsonObject room = updated.at(i).toObject(); if (room.value("t").toString() != "d") { QString roomID = room.value("rid").toString(); // qDebug() << "Adding" << roomID<< room.value("name").toString() << room; MessageModel *roomModel = UserData::self()->getModelForRoom(roomID); // let's be extra safe around crashes if (UserData::self()->loginStatus() == DDPClient::LoggedIn) { Room r; r.id = roomID; r.name = room["name"].toString(); r.topic = room["topic"].toString(); qDebug() << "Adding room" << r.name << r.id << r.topic; model->addRoom(r); } QString params = QString("[\"%1\"]").arg(roomID); UserData::self()->ddp()->subscribe("stream-room-messages", QJsonDocument::fromJson(params.toLatin1())); // Load history QByteArray json = "[\""+roomID.toLatin1() + "\", null, 50, {\"$date\": "+ QString::number(roomModel->lastTimestamp()).toLatin1()+ "}]"; qDebug() << json; UserData::self()->ddp()->method("loadHistory", QJsonDocument::fromJson(json), process_backlog); } } qDebug() << "DEBUG:" << doc; } void RocketChatBackend::processIncomingMessages(QJsonArray messages) { foreach (const QJsonValue v, messages) { QJsonObject o = v.toObject(); Message m; QString roomId = o.value("rid").toString(); QString type = o.value("t").toString(); m.username = o.value("u").toObject().value("username").toString(); m.userID = o.value("u").toObject().value("_id").toString(); m.message = o.value("msg").toString(); m.messageID = o.value("_id").toString(); m.roomID = roomId; m.timestamp = (qint64)o.value("ts").toObject().value("$date").toDouble(); if (!type.isEmpty()) { m.systemMessage = true; m.systemMessageType = type; } else { m.systemMessage = false; } UserData::self()->getModelForRoom(roomId)->addMessage(m); } } RocketChatBackend::RocketChatBackend(QObject* parent) : QObject(parent) { // UserData::self()->ddp() = new DDPClient(, this); connect(UserData::self(), &UserData::loginStatusChanged, this, &RocketChatBackend::onLoginStatusChanged); connect(UserData::self()->ddp(), &DDPClient::changed, this, &RocketChatBackend::onChanged); connect(UserData::self()->ddp(), &DDPClient::added, this, &RocketChatBackend::onAdded); } RocketChatBackend::~RocketChatBackend() { } void RocketChatBackend::onLoginStatusChanged() { if (UserData::self()->loginStatus() == DDPClient::LoggedIn) { qDebug() << "GETTING LIST OF ROOMS"; // UserData::self()->ddp()->method("subscriptions/get", QJsonDocument::fromJson("{\"$date\": 0}"), rooms_callback); UserData::self()->ddp()->method("rooms/get", QJsonDocument::fromJson("{\"$date\": 0}"), rooms_callback); // UserData::self()->ddp()->subscribe("stream-room-messages", QJsonDocument::fromJson(params.toLatin1())); } } void RocketChatBackend::onLoggedIn() { // if (UserData::self()->loginStatus() != DDPClient::LoggedIn) { // qDebug() << "not yet logged in:" << UserData::self()->loginStatus(); // return; // } // // get list of rooms // UserData::self()->ddp()->method("rooms/get", QJsonDocument::fromJson("{\"$date\": 0}"), rooms_callback); } void RocketChatBackend::onAdded(QJsonObject object) { QString collection = object.value("collection").toString(); qDebug() << "ROCKET BACK" << object << collection; if (collection == "stream-room-messages") { } else if (collection == "users") { - qDebug() << "NEW USER"; + + if (object["username"].isNull()) { + // it's us! get ID + UserData::self()->setUserID(object["id"].toString()); + } +// qDebug() << "NEW USER" << object; } else if (collection == "rooms") { } } void RocketChatBackend::onChanged(QJsonObject object) { QString collection = object["collection"].toString(); qDebug() << "ROCKET BACK" << object << collection; if (collection == "stream-room-messages") { QJsonObject fields = object.value("fields").toObject(); QString roomId = fields.value("eventName").toString(); QJsonArray contents = fields.value("args").toArray(); RocketChatBackend::processIncomingMessages(contents); } else if (collection == "users") { qDebug() << "NEW USER"; } else if (collection == "rooms") { } else if (collection == "stream-notify-user"){ QJsonArray messages = object.value("fields").toObject().value("args").toArray(); foreach (const QJsonValue v, messages) { QJsonObject o = v.toObject(); Message m; QString roomId = o.value("rid").toString(); QString type = o.value("t").toString(); m.username = o.value("u").toObject().value("username").toString(); m.userID = o.value("u").toObject().value("_id").toString(); m.message = o.value("msg").toString(); m.messageID = o.value("_id").toString(); m.roomID = roomId; m.timestamp = (qint64)o.value("ts").toObject().value("$date").toDouble(); c.setUserID(m.userID); //check if its not a system message and message not sent by user itself if ( !type.isEmpty() && m.username != UserData::self()->userName()){ Notification::self()->showNotification(m.userID, m.username,m.message); } } } } diff --git a/src/userdata.cpp b/src/userdata.cpp index fd0f129d..411001df 100644 --- a/src/userdata.cpp +++ b/src/userdata.cpp @@ -1,212 +1,226 @@ /* * * Copyright 2016 Riccardo Iaconelli * * 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 "userdata.h" #include "roommodel.h" #include "ddpclient.h" UserData *UserData::m_self = 0; QString UserData::authToken() const { return m_authToken; } QString UserData::userName() const { return m_userName; } +QString UserData::userID() const +{ + return m_userID; +} + QString UserData::password() const { return m_password; } void UserData::setAuthToken(const QString& token) { qDebug() << "Setting token to" << token; QSettings s; m_authToken = token; s.setValue("authToken", token); } void UserData::setPassword(const QString& password) { m_password = password; } void UserData::setUserName(const QString& username) { m_userName = username; QSettings s; s.setValue("username", username); emit userNameChanged(); } +void UserData::setUserID(const QString& userID) +{ + m_userName = userID; + QSettings s; + s.setValue("userID", userID); + emit userIDChanged(); +} + RoomModel * UserData::roomModel() { if (!m_roomModel) { qDebug() << "creating new RoomModel"; m_roomModel = new RoomModel(this); qDebug() << m_roomModel; // m_roomModel->reset(); } return m_roomModel; } DDPClient * UserData::ddp() { if (!m_ddp) { m_ddp = new DDPClient(serverURL()); connect(m_ddp, &DDPClient::loginStatusChanged, this, &UserData::loginStatusChanged); // connect(m_ddp, &DDPClient::loginStatusChanged, this, [=](){qDebug() << "Signal received";}); } return m_ddp; } void UserData::sendMessage(const QString &roomID, const QString &message) { QString json = "{\"rid\": \"%1\", \"msg\": \"%2\"}"; json = json.arg(roomID, message); ddp()->method("sendMessage", QJsonDocument::fromJson(json.toUtf8())); } MessageModel * UserData::getModelForRoom(const QString& roomID) { if (m_messageModels.contains(roomID)) { // qDebug() << "Returning old model for " << roomID; return m_messageModels.value(roomID); } else { // qDebug() << "Creating a new model"; m_messageModels[roomID] = new MessageModel(roomID, this); return m_messageModels[roomID]; } } QString UserData::serverURL() const { return m_serverURL; } void UserData::setServerURL(const QString& serverURL) { if (m_serverURL == serverURL) { return; } QSettings s; s.setValue("serverURL", serverURL); m_serverURL = serverURL; // m_roomModel->reset(); emit serverURLChanged(); } DDPClient::LoginStatus UserData::loginStatus() { if (m_ddp) { return ddp()->loginStatus(); } else { return DDPClient::LoggedOut; } } void UserData::tryLogin() { qDebug() << "Attempting login" << userName() << "on" << serverURL(); // Reset model views foreach (const QString key, m_messageModels.keys()) { MessageModel *m = m_messageModels.take(key); delete m; } delete m_ddp; m_ddp = 0; // In the meantime, load cache... m_roomModel->reset(); // This creates a new ddp() object. // DDP will automatically try to connect and login. ddp(); } void UserData::logOut() { setAuthToken(QString()); setPassword(QString()); // m_ddp->logOut(); foreach (const QString key, m_messageModels.keys()) { MessageModel *m = m_messageModels.take(key); delete m; } delete m_ddp; m_ddp = 0; emit loginStatusChanged(); m_roomModel->clear(); } QString UserData::cacheBasePath() const { if (m_serverURL.isEmpty()) { return QString(); } return QStandardPaths::writableLocation(QStandardPaths::CacheLocation)+'/'+m_serverURL; } // QString UserData::activeRoom() const // { // return m_activeRoom; // } // void UserData::setActiveRoom(const QString& activeRoom) // { // m_activeRoom = activeRoom; // // roomModel()->setActiveRoom(activeRoom); // emit activeRoomChanged(); // } RoomWrapper * UserData::getRoom(const QString& roomID) { return roomModel()->findRoom(roomID); } UserData::UserData(QObject* parent): QObject(parent), m_ddp(0), m_roomModel(0) { QSettings s; m_serverURL = s.value("serverURL", "demo.rocket.chat").toString(); m_userName = s.value("username").toString(); + m_userID = s.value("userID").toString(); m_authToken = s.value("authToken").toString(); // roomModel()->reset(); } UserData * UserData::self() { if (!m_self) { m_self = new UserData; m_self->ddp(); // Create DDP object so we try to connect at startup m_self->roomModel()->reset(); // m_self->getModelForRoom("GENERAL"); } return m_self; } diff --git a/src/userdata.h b/src/userdata.h index 5e5f73d9..aaf34f9e 100644 --- a/src/userdata.h +++ b/src/userdata.h @@ -1,110 +1,116 @@ /* * * Copyright 2016 Riccardo Iaconelli * * 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 . * */ #ifndef USERDATA_H #define USERDATA_H #include #include #include #include "ddpclient.h" #include "roommodel.h" #include "messagemodel.h" class QString; class UserData: 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 password WRITE setPassword) // Q_PROPERTY (bool connected READ connected NOTIFY connectedChanged) Q_PROPERTY (DDPClient::LoginStatus loginStatus READ loginStatus NOTIFY loginStatusChanged) // Q_PROPERTY(QString activeRoom READ activeRoom WRITE setActiveRoom NOTIFY activeRoomChanged) public: static UserData* self(); void setUserName(const QString &username); QString userName() const; + void setUserID(const QString &userID); + QString userID() const; + void setPassword(const QString &password); QString password() const; void setAuthToken(const QString &token); QString authToken() const; bool connected(); DDPClient::LoginStatus loginStatus(); QString serverURL() const; void setServerURL(const QString &serverURL); // QString activeRoom() const; // void setActiveRoom(const QString &activeRoom); DDPClient *ddp(); Q_INVOKABLE RoomModel *roomModel(); Q_INVOKABLE void sendMessage(const QString &roomID, const QString &message); Q_INVOKABLE MessageModel* getModelForRoom(const QString &roomID); Q_INVOKABLE void tryLogin(); Q_INVOKABLE void logOut(); Q_INVOKABLE RoomWrapper* getRoom(const QString &roomID); // void setRoomModel(); QString cacheBasePath() const; signals: void userNameChanged(); + void userIDChanged(); void serverURLChanged(); void loginStatusChanged(); private: UserData(QObject *parent = 0); static UserData *m_self; QString m_password; QString m_userName; + QString m_userID; QString m_authToken; QString m_serverURL; DDPClient *m_ddp; RoomModel *m_roomModel; QHash< QString, MessageModel * > m_messageModels; }; inline static QObject *userdata_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) Q_UNUSED(scriptEngine) UserData *userData = UserData::self(); return userData; } #endif // USERDATA_H