magpie/API/api.cpp

211 lines
6.5 KiB
C++
Raw Normal View History

2023-11-24 23:48:01 +00:00
#include "api.h"
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
2023-12-16 01:44:25 +00:00
#include <QUrlQuery>
2023-11-24 23:48:01 +00:00
#include "codes.h"
2023-11-24 23:48:01 +00:00
constexpr const char* json = "application/json";
2023-12-16 01:44:25 +00:00
constexpr const char* urlEncoded = "application/x-www-form-urlencoded";
2023-11-24 23:48:01 +00:00
struct NetworkReplyDeleter {
void operator () (QNetworkReply* reply) {
reply->deleteLater();
}
};
API::API(const QUrl& address, QObject* parent):
QObject(parent),
address(address),
2023-12-16 01:44:25 +00:00
network(),
state(NoServer)
{}
2023-11-24 23:48:01 +00:00
2023-12-16 01:44:25 +00:00
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);
2023-11-24 23:48:01 +00:00
}
void API::test(const QString& path, const QJSValue& finished) {
qDebug() << "Testing" << path;
2023-12-17 00:06:04 +00:00
if (state == Offline)
return callCallback(finished, "Need to be online to test");
2023-12-16 01:44:25 +00:00
2023-12-17 00:06:04 +00:00
QUrl address(path);
2023-11-24 23:48:01 +00:00
QNetworkRequest request(path + "/info");
request.setHeader(QNetworkRequest::ContentTypeHeader, json);
QNetworkReply* reply = network.get(request);
connect(reply, &QNetworkReply::finished,
2023-12-17 00:06:04 +00:00
std::bind(&API::onTestFinished, this, reply, address, finished)
2023-11-24 23:48:01 +00:00
);
}
2023-12-17 00:06:04 +00:00
void API::onTestFinished(QNetworkReply* reply, const QUrl& addr, const QJSValue& finished) {
2023-11-24 23:48:01 +00:00
std::unique_ptr<QNetworkReply, NetworkReplyDeleter> rpl(reply);
QNetworkReply::NetworkError error = reply->error();
2023-12-17 00:06:04 +00:00
if (error != QNetworkReply::NoError)
return callCallback(finished, reply->errorString());
2023-11-24 23:48:01 +00:00
QVariant contentType = reply->header(QNetworkRequest::ContentTypeHeader);
if (!
contentType.isValid() ||
!contentType.canConvert<QString>() ||
contentType.toString() != json
) {
2023-12-17 00:06:04 +00:00
return callCallback(finished, "wrong response content type");
2023-11-24 23:48:01 +00:00
}
QByteArray data = reply->readAll();
QJsonDocument document = QJsonDocument::fromJson(data);
QJsonObject rootObj = document.object();
QJsonValue type = rootObj.value("type");
QJsonValue version = rootObj.value("version");
2023-12-17 00:06:04 +00:00
if (!type.isString() || !version.isString())
return callCallback(finished, "malformed json");
2023-11-24 23:48:01 +00:00
2023-12-17 00:06:04 +00:00
if (type.toString() != "pica")
return callCallback(finished, "server of this type (" + type.toString() + ") is not supported");
2023-11-24 23:48:01 +00:00
2023-12-17 00:06:04 +00:00
if (version.toString() != "0.0.1")
return callCallback(finished, "server of this version (" + version.toString() + ") is not supported");
2023-11-24 23:48:01 +00:00
callCallback(finished, QString(), {QJSValue(true)});
2023-12-17 00:06:04 +00:00
address = ""; //to provoke singal change even if it's the same server
setAddress(addr);
2023-11-24 23:48:01 +00:00
}
void API::sendRegister(const QString& login, const QString& password, const QJSValue& finished) {
2023-12-16 01:44:25 +00:00
qDebug() << "Registering...";
2023-12-17 00:06:04 +00:00
if (state != NotAuthenticated)
return callCallback(finished, "Can not register in current state");
2023-12-16 01:44:25 +00:00
QUrlQuery params({
{"login", login},
{"password", password}
});
QString path = address.path();
QUrl regUrl = address;
regUrl.setPath(path + "/register");
QNetworkRequest request(regUrl);
2023-12-16 01:44:25 +00:00
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::sendLogin(const QString& login, const QString& password, const QJSValue& finished) {
qDebug() << "Logging in...";
if (state != NotAuthenticated)
return callCallback(finished, "Can not register in current state");
QUrlQuery params({
{"login", login},
{"password", password}
});
QString path = address.path();
QUrl url = address;
url.setPath(path + "/login");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, urlEncoded);
QNetworkReply* reply = network.post(request, params.toString(QUrl::FullyEncoded).toUtf8());
connect(reply, &QNetworkReply::finished,
std::bind(&API::onLoginFinished, this, reply, finished)
);
}
void API::onRegisterFinished(QNetworkReply* reply, const QJSValue& finished) const {
2023-12-16 01:44:25 +00:00
std::unique_ptr<QNetworkReply, NetworkReplyDeleter> rpl(reply);
QNetworkReply::NetworkError error = reply->error();
2023-12-17 00:06:04 +00:00
if (error != QNetworkReply::NoError)
return callCallback(finished, reply->errorString());
2023-12-16 01:44:25 +00:00
QVariant contentType = reply->header(QNetworkRequest::ContentTypeHeader);
if (!
contentType.isValid() ||
!contentType.canConvert<QString>() ||
contentType.toString() != json
) {
return callCallback(finished, "wrong response content type");
2023-12-16 01:44:25 +00:00
}
QByteArray data = reply->readAll();
QJsonDocument document = QJsonDocument::fromJson(data);
QJsonObject rootObj = document.object();
QJsonValue res = rootObj.value("result");
if (!res.isDouble())
2023-12-17 00:06:04 +00:00
return callCallback(finished, "malformed json");
2023-12-16 01:44:25 +00:00
Codes::Register result = Codes::convertRegister(res.toInt());
bool success = result == Codes::Register::success;
QString err;
if (!success)
err = Codes::description(result);
2023-12-16 01:44:25 +00:00
callCallback(finished, err, {QJSValue(success)});
}
void API::onLoginFinished(QNetworkReply* reply, const QJSValue& finished) {
std::unique_ptr<QNetworkReply, NetworkReplyDeleter> rpl(reply);
QNetworkReply::NetworkError error = reply->error();
if (error != QNetworkReply::NoError)
return callCallback(finished, reply->errorString());
QVariant contentType = reply->header(QNetworkRequest::ContentTypeHeader);
if (!
contentType.isValid() ||
!contentType.canConvert<QString>() ||
contentType.toString() != json
) {
return callCallback(finished, "wrong response content type");
}
QByteArray data = reply->readAll();
QJsonDocument document = QJsonDocument::fromJson(data);
QJsonObject rootObj = document.object();
QJsonValue res = rootObj.value("result");
if (!res.isDouble())
return callCallback(finished, "malformed json");
//todo
2023-12-16 01:44:25 +00:00
}
2023-11-24 23:48:01 +00:00
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)});
}
}