diff --git a/client.cpp b/client.cpp index 02e8433..7e276e3 100644 --- a/client.cpp +++ b/client.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include Client::Client(QString url, QString username, QString password) { this->url = url; @@ -11,12 +13,37 @@ Client::Client(QString url, QString username, QString password) { 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) { @@ -36,7 +63,10 @@ void Client::hash(QString gameID, std::function callback, std::fu 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) { @@ -55,7 +85,10 @@ void Client::metadata(QString gameID, std::function callback, st 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) { @@ -69,3 +102,73 @@ void Client::metadata(QString gameID, std::function callback, st 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(); +} + + diff --git a/client.h b/client.h index e7b4178..cfd36ef 100644 --- a/client.h +++ b/client.h @@ -11,17 +11,17 @@ class Client public: Client(QString url, QString username, QString password); - bool exists(QString gameID, std::function callback, std::function errorCallback); + void exists(QString gameID, std::function callback, std::function errorCallback); void version(std::function callback, std::function errorCallback); void hash(QString gameID, std::function callback, std::function errorCallback); void metadata(QString gameID, std::function callback, std::function errorCallback); - void pushSave(QString archivePath, Metadata game, std::function callback, std::function errorCallback); + void pushSave(QString archivePath, Metadata game, std::function errorCallback); void pushBackup(QString archivePath, Metadata game, std::function callback, std::function errorCallback); void listArchives(QString gameID, std::function)> callback, std::function errorCallback); void archiveInfo(QString gameID, QString backupID, std::function callback, std::function errorCallback); void pull(QString gameID, QString archivePath, std::function callback, std::function errorCallback); void pullBackup(QString gameID, QString backupID, QString archivePath, std::function callback, std::function errorCallback); - bool ping(std::function callback, std::function errorCallback); + bool ping(); void all(std::function)> callback, std::function errorCallback); QString baseURL(); @@ -30,6 +30,9 @@ private: QString username; QString password; + void push(QUrl url, QString archivePath, Metadata g, std::function errorCallback); + QString toBase64Header(QString username, QString password); + }; #endif // CLIENT_H diff --git a/metadata.cpp b/metadata.cpp index d74ada3..09c1663 100644 --- a/metadata.cpp +++ b/metadata.cpp @@ -13,6 +13,26 @@ Metadata::Metadata(QJsonObject obj) this->_md5 = obj["md5"].toString(); } +QString Metadata::id() +{ + return this->_id; +} + +QString Metadata::name() +{ + return this->_name; +} + +uint64_t Metadata::version() +{ + return this->_version; +} + +QDateTime Metadata::date() +{ + return this->_date; +} + QString Metadata::md5() { return this->_md5; diff --git a/metadata.h b/metadata.h index 206507d..7eea11e 100644 --- a/metadata.h +++ b/metadata.h @@ -11,6 +11,10 @@ public: Metadata(QString name); Metadata(QJsonObject obj); + QString id(); + QString name(); + uint64_t version(); + QDateTime date(); QString md5(); private: QString _id;