#include "api.h" #include #include #include #include constexpr const char* json = "application/json"; constexpr const char* urlEncoded = "application/x-www-form-urlencoded"; struct NetworkReplyDeleter { void operator () (QNetworkReply* reply) { reply->deleteLater(); } }; API::API(const QUrl& address, QObject* parent): QObject(parent), address(address), network(), state(NoServer) {} QUrl API::getAddress() const { return address; } API::State API::getState() const { return state; } void API::setAddress(const QUrl& path) { if (address == path) return; if (state == Authenticated) { //do something } address = path; state = address.isEmpty() ? NoServer : NotAuthenticated; emit addressChanged(address); emit stateChanged(state); } void API::test(const QString& path, const QJSValue& finished) { qDebug() << "Testing" << path; if (state == Offline) { QString err = "Need to be online to test"; qDebug() << "Test for" << path << "failed:" << err; callCallback(finished, err); return; } QNetworkRequest request(path + "/info"); request.setHeader(QNetworkRequest::ContentTypeHeader, json); QNetworkReply* reply = network.get(request); connect(reply, &QNetworkReply::finished, std::bind(&API::onTestFinished, this, reply, finished) ); } void API::onTestFinished(QNetworkReply* reply, const QJSValue& finished) const { std::unique_ptr rpl(reply); QNetworkReply::NetworkError error = reply->error(); if (error != QNetworkReply::NoError) { QString err = reply->errorString(); qDebug() << "Test for" << reply->url() << "failed:" << err; callCallback(finished, err); return; } QVariant contentType = reply->header(QNetworkRequest::ContentTypeHeader); if (! contentType.isValid() || !contentType.canConvert() || contentType.toString() != json ) { QString err("wrong response content type"); qDebug() << "Test for" << reply->url() << "failed:" << err; callCallback(finished, err); return; } QByteArray data = reply->readAll(); QJsonDocument document = QJsonDocument::fromJson(data); QJsonObject rootObj = document.object(); QJsonValue type = rootObj.value("type"); QJsonValue version = rootObj.value("version"); if (!type.isString() || !version.isString()) { QString err("malformed json"); qDebug() << "Test for" << reply->url() << "failed:" << err; callCallback(finished, err); return; } if (type.toString() != "pica") { QString err("server of this type (" + type.toString() + ") is not supported"); qDebug() << "Test for" << reply->url() << "failed:" << err; callCallback(finished, err); return; } if (version.toString() != "0.0.1") { QString err("server of this version (" + version.toString() + ") is not supported"); qDebug() << "Test for" << reply->url() << "failed:" << err; callCallback(finished, err); return; } callCallback(finished, QString(), {QJSValue(true)}); } void API::sendRegister(const QString& login, const QString& password, const QJSValue &finished) { qDebug() << "Registering..."; if (state != NotAuthenticated) { QString err = "Can not register in current state"; qDebug() << "Register failed:" << err; callCallback(finished, err); return; } QUrlQuery params({ {"login", login}, {"password", password} }); QNetworkRequest request(address.path() + "/register"); request.setHeader(QNetworkRequest::ContentTypeHeader, urlEncoded); QNetworkReply* reply = network.post(request, params.toString(QUrl::FullyEncoded).toUtf8()); connect(reply, &QNetworkReply::finished, std::bind(&API::onRegisterFinished, this, reply, finished) ); } void API::onRegisterFinished(QNetworkReply *reply, const QJSValue &finished) const { std::unique_ptr rpl(reply); QNetworkReply::NetworkError error = reply->error(); if (error != QNetworkReply::NoError) { QString err = reply->errorString(); qDebug() << "Register failed:" << err; callCallback(finished, err); return; } QVariant contentType = reply->header(QNetworkRequest::ContentTypeHeader); if (! contentType.isValid() || !contentType.canConvert() || contentType.toString() != json ) { QString err("wrong response content type"); qDebug() << "Register failed:" << err; callCallback(finished, err); return; } QByteArray data = reply->readAll(); QJsonDocument document = QJsonDocument::fromJson(data); QJsonObject rootObj = document.object(); QJsonValue result = rootObj.value("result"); if (!result.isString()) { QString err("malformed json"); qDebug() << "Register failed:" << err; callCallback(finished, err); return; } if (result.toString() != "ok") { QString err("Registration result was not okay"); qDebug() << "Register failed:" << err; callCallback(finished, err); return; } callCallback(finished, QString(), {QJSValue(true)}); } void API::callCallback(const QJSValue& callback, const QString& error, const QJSValueList& arguments) const { if (callback.isCallable()) { if (error.isEmpty()) callback.call(QJSValueList({QJSValue(QJSValue::NullValue)}) + arguments); else callback.call({QJSValue(error)}); } }