#include "client.h" #include #include #include #include #include #include #include Client::Client(QString url, QString username, QString password) { this->url = url; this->username = username; this->password = password; } void Client::exists(QString gameID, std::function callback, std::function errorCallback) { QNetworkAccessManager manager; QUrl url(this->url); url = url.resolved("/api/v1/games/"+gameID+"/metadata"); QNetworkRequest request(url); request.setRawHeader("Authorization", toBase64Header(this->username, this->password).toUtf8()); QNetworkReply *reply = manager.get(request); QObject::connect(reply, &QNetworkReply::finished, [&]() { if (reply->error() == QNetworkReply::ContentNotFoundError) { callback(false); } else if (reply->error() == QNetworkReply::NoError) { callback(true); } else { errorCallback(reply->errorString()); } reply->deleteLater(); }); } void Client::version(std::function callback, std::function errorCallback) { QNetworkAccessManager manager; QUrl url(this->url); url = url.resolved(QUrl("/api/v1/version/")); QNetworkRequest request(url); request.setRawHeader("Authorization", toBase64Header(this->username, this->password).toUtf8()); QNetworkReply *reply = manager.get(request); QObject::connect(reply, &QNetworkReply::finished, [&]() { if (reply->error() == QNetworkReply::NoError) { QByteArray response = reply->readAll(); QJsonDocument doc = QJsonDocument::fromJson(response); Information info(doc.object()); callback(info); } else { errorCallback(reply->errorString()); } reply->deleteLater(); }); } void Client::hash(QString gameID, std::function callback, std::function errorCallback) { QNetworkAccessManager manager; QUrl url(this->url); url = url.resolved("/api/v1/games/"+gameID+"/metadata"); QNetworkRequest request(url); request.setRawHeader("Authorization", toBase64Header(this->username, this->password).toUtf8()); QNetworkReply *reply = manager.get(request); QObject::connect(reply, &QNetworkReply::finished, [&]() { if (reply->error() == QNetworkReply::NoError) { QByteArray response = reply->readAll(); QJsonDocument doc = QJsonDocument::fromJson(response); callback(doc.object()["md5"].toString()); } else { errorCallback(reply->errorString()); } reply->deleteLater(); }); } void Client::metadata(QString gameID, std::function callback, std::function errorCallback) { QNetworkAccessManager manager; QUrl url(this->url); url = url.resolved("/api/v1/games/"+gameID+"/metadata"); QNetworkRequest request(url); request.setRawHeader("Authorization", toBase64Header(this->username, this->password).toUtf8()); QNetworkReply *reply = manager.get(request); QObject::connect(reply, &QNetworkReply::finished, [&]() { if (reply->error() == QNetworkReply::NoError) { QByteArray response = reply->readAll(); QJsonDocument doc = QJsonDocument::fromJson(response); Metadata m(doc.object()); callback(m); } else { errorCallback(reply->errorString()); } reply->deleteLater(); }); } void Client::pushSave(QString archivePath, Metadata game, std::function errorCallback) { QUrl url(this->url); url = url.resolved("/api/v1/games/"+game.id()+"/metadata"); push(url, archivePath, game, errorCallback); } void Client::push(QUrl url, QString archivePath, Metadata g, std::function errorCallback) { static QNetworkAccessManager manager; QFile *file = new QFile(archivePath); if (!file->open(QIODevice::ReadOnly)) { qWarning() << "Cannot open file"; file->deleteLater(); return; } QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); QHttpPart namePart; namePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"name\"")); namePart.setBody(g.name().toUtf8()); QHttpPart versionPart; versionPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"version\"")); versionPart.setBody(QString::number(g.version()).toUtf8()); QHttpPart datePart; datePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"date\"")); datePart.setBody(g.date().toString(Qt::DateFormat::ISODateWithMs).toUtf8()); QHttpPart archivePart; archivePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/tar+gzip")); archivePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"payload\"")); archivePart.setBodyDevice(file); file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart multiPart->append(namePart); multiPart->append(versionPart); multiPart->append(datePart); multiPart->append(archivePart); QNetworkRequest req(url); req.setRawHeader("Authorization", toBase64Header(this->username, this->password).toUtf8()); QNetworkReply *reply = manager.put(req, file); file->setParent(reply); // auto-delete with reply /*QObject::connect(reply, &QNetworkReply::uploadProgress, [](qint64 s, qint64 t){ });*/ QObject::connect(reply, &QNetworkReply::finished, [=]{ if (reply->error() != QNetworkReply::NoError) { errorCallback(reply->errorString()); } reply->deleteLater(); file->close(); }); } QString Client::toBase64Header(QString username, QString password) { QString c = username+":"+password; return QString("Basic ")+c.toUtf8().toBase64(); }