#include "beerservice.h" #include #include #include #include #include #include #include "settingsservice.h" BeerService::BeerService() : QObject{nullptr} { m_actions = { { ActionGet, "get" }, { ActionAdd, "add" }, { ActionDelete, "del" }, { ActionModify, "mod" } }; restoreStash(); connect(&m_socket, &QWebSocket::textMessageReceived, this, [this](QString message) { QJsonParseError err; QJsonDocument doc = QJsonDocument::fromJson(message.toLocal8Bit(), &err); if (err.error != QJsonParseError::NoError) { qWarning() << "Json parse error:" << err.errorString() << message; return; } QString entity = doc.object().value("entity").toString(); const QList listeners = m_listeners.values(entity); for (QObject *listener : listeners) { QString event = doc.object().value("event").toString(); QVariant data = doc.object().value("data").toVariant(); QMetaObject::invokeMethod(listener, event.toLatin1(), Qt::QueuedConnection, Q_ARG(QVariant, data)); } }); connect(&m_socket, &QWebSocket::errorOccurred, this, [this](QAbstractSocket::SocketError error) { qInfo() << error << m_socket.errorString(); }); connect(&m_socket, &QWebSocket::connected, this, [this]() { while (!m_commandStash.isEmpty()) { sendCommand(m_commandStash.takeFirst().toMap()); } }); connect(&m_socket, &QWebSocket::stateChanged, this, &BeerService::connectedChanged); connect(settings(), &SettingsService::serverAddressChanged, this, &BeerService::reconnect); connect(settings(), &SettingsService::selectedUserIdChanged, this, &BeerService::reconnect); reconnect(); } BeerService::~BeerService() { saveStash(); m_socket.close(); } SettingsService *BeerService::settings() const { return SettingsService::instance(); } void BeerService::sendCommand(const QString &entity, Action action, const QVariantMap &data) { Q_ASSERT(action != ActionUndefined); sendCommand(QVariantMap { { "entity", entity }, { "action", m_actions[action] }, { "data", data } }); } void BeerService::connectListener(QObject *listener) { QString entity = listener->property("entity").toString(); m_listeners.insert(entity, listener); } void BeerService::removeListener(QObject *listener) { QString entity = listener->property("entity").toString(); m_listeners.remove(entity, listener); } QString BeerService::stashFileName() const { return QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/command.stash"; } void BeerService::saveStash() const { if (m_commandStash.isEmpty()) { return; } QFile stash(stashFileName()); if (stash.open(QIODevice::WriteOnly)) { stash.write(QJsonDocument::fromVariant(m_commandStash).toJson(QJsonDocument::Compact)); stash.close(); } else { qWarning() << stash.errorString(); } } void BeerService::restoreStash() { QFile stash(stashFileName()); if (stash.open(QIODevice::ReadOnly)) { QJsonDocument doc = QJsonDocument::fromJson(stash.readAll()); m_commandStash = doc.array().toVariantList(); stash.close(); stash.remove(); } else { qWarning() << stash.errorString(); } } void BeerService::reconnect() { if (connected()) { m_socket.close(); } QString userId = settings()->selectedUserId(); QUrl serverUrl(QString("ws://%1").arg(settings()->serverAddress())); QNetworkRequest request(serverUrl); request.setRawHeader("Authorization", "Basic " + QString("%1:pass").arg(userId).toLatin1().toBase64()); m_socket.open(request); } void BeerService::sendCommand(const QVariantMap &command) { if (connected()) { QJsonDocument doc = QJsonDocument::fromVariant(command); m_socket.sendTextMessage(doc.toJson(QJsonDocument::Compact)); } else { m_commandStash << command; } } bool BeerService::connected() const { return QAbstractSocket::ConnectedState == m_socket.state(); }