6a18079953
Firstly, this abstract away behavior in the mod download models that can also be applied to other types of resources into a superclass, allowing other resource types to be implemented without so much code duplication. For that, this also generalizes the APIs used (currently, ModrinthAPI and FlameAPI) to be able to make requests to other types of resources. It also does a general cleanup of both of those. In particular, this makes use of std::optional instead of invalid values for errors and, well, optional values :p This is a squash of some commits that were becoming too interlaced together to be cleanly separated. Signed-off-by: flow <flowlnlnln@gmail.com>
215 lines
6.8 KiB
C++
215 lines
6.8 KiB
C++
#include "FlameAPI.h"
|
|
#include "FlameModIndex.h"
|
|
|
|
#include "Application.h"
|
|
#include "BuildConfig.h"
|
|
#include "Json.h"
|
|
|
|
#include "net/Upload.h"
|
|
|
|
auto FlameAPI::matchFingerprints(const QList<uint>& fingerprints, QByteArray* response) -> NetJob::Ptr
|
|
{
|
|
auto* netJob = new NetJob(QString("Flame::MatchFingerprints"), APPLICATION->network());
|
|
|
|
QJsonObject body_obj;
|
|
QJsonArray fingerprints_arr;
|
|
for (auto& fp : fingerprints) {
|
|
fingerprints_arr.append(QString("%1").arg(fp));
|
|
}
|
|
|
|
body_obj["fingerprints"] = fingerprints_arr;
|
|
|
|
QJsonDocument body(body_obj);
|
|
auto body_raw = body.toJson();
|
|
|
|
netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/fingerprints"), response, body_raw));
|
|
|
|
QObject::connect(netJob, &NetJob::finished, [response] { delete response; });
|
|
|
|
return netJob;
|
|
}
|
|
|
|
auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString
|
|
{
|
|
QEventLoop lock;
|
|
QString changelog;
|
|
|
|
auto* netJob = new NetJob(QString("Flame::FileChangelog"), APPLICATION->network());
|
|
auto* response = new QByteArray();
|
|
netJob->addNetAction(Net::Download::makeByteArray(
|
|
QString("https://api.curseforge.com/v1/mods/%1/files/%2/changelog")
|
|
.arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))),
|
|
response));
|
|
|
|
QObject::connect(netJob, &NetJob::succeeded, [netJob, response, &changelog] {
|
|
QJsonParseError parse_error{};
|
|
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
|
|
if (parse_error.error != QJsonParseError::NoError) {
|
|
qWarning() << "Error while parsing JSON response from Flame::FileChangelog at " << parse_error.offset
|
|
<< " reason: " << parse_error.errorString();
|
|
qWarning() << *response;
|
|
|
|
netJob->failed(parse_error.errorString());
|
|
return;
|
|
}
|
|
|
|
changelog = Json::ensureString(doc.object(), "data");
|
|
});
|
|
|
|
QObject::connect(netJob, &NetJob::finished, [response, &lock] {
|
|
delete response;
|
|
lock.quit();
|
|
});
|
|
|
|
netJob->start();
|
|
lock.exec();
|
|
|
|
return changelog;
|
|
}
|
|
|
|
auto FlameAPI::getModDescription(int modId) -> QString
|
|
{
|
|
QEventLoop lock;
|
|
QString description;
|
|
|
|
auto* netJob = new NetJob(QString("Flame::ModDescription"), APPLICATION->network());
|
|
auto* response = new QByteArray();
|
|
netJob->addNetAction(Net::Download::makeByteArray(
|
|
QString("https://api.curseforge.com/v1/mods/%1/description")
|
|
.arg(QString::number(modId)), response));
|
|
|
|
QObject::connect(netJob, &NetJob::succeeded, [netJob, response, &description] {
|
|
QJsonParseError parse_error{};
|
|
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
|
|
if (parse_error.error != QJsonParseError::NoError) {
|
|
qWarning() << "Error while parsing JSON response from Flame::ModDescription at " << parse_error.offset
|
|
<< " reason: " << parse_error.errorString();
|
|
qWarning() << *response;
|
|
|
|
netJob->failed(parse_error.errorString());
|
|
return;
|
|
}
|
|
|
|
description = Json::ensureString(doc.object(), "data");
|
|
});
|
|
|
|
QObject::connect(netJob, &NetJob::finished, [response, &lock] {
|
|
delete response;
|
|
lock.quit();
|
|
});
|
|
|
|
netJob->start();
|
|
lock.exec();
|
|
|
|
return description;
|
|
}
|
|
|
|
auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::IndexedVersion
|
|
{
|
|
auto versions_url_optional = getVersionsURL(args);
|
|
if (!versions_url_optional.has_value())
|
|
return {};
|
|
|
|
auto versions_url = versions_url_optional.value();
|
|
|
|
QEventLoop loop;
|
|
|
|
auto netJob = new NetJob(QString("Flame::GetLatestVersion(%1)").arg(args.addonId), APPLICATION->network());
|
|
auto response = new QByteArray();
|
|
ModPlatform::IndexedVersion ver;
|
|
|
|
netJob->addNetAction(Net::Download::makeByteArray(versions_url, response));
|
|
|
|
QObject::connect(netJob, &NetJob::succeeded, [response, args, &ver] {
|
|
QJsonParseError parse_error{};
|
|
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
|
|
if (parse_error.error != QJsonParseError::NoError) {
|
|
qWarning() << "Error while parsing JSON response from latest mod version at " << parse_error.offset
|
|
<< " reason: " << parse_error.errorString();
|
|
qWarning() << *response;
|
|
return;
|
|
}
|
|
|
|
try {
|
|
auto obj = Json::requireObject(doc);
|
|
auto arr = Json::requireArray(obj, "data");
|
|
|
|
QJsonObject latest_file_obj;
|
|
ModPlatform::IndexedVersion ver_tmp;
|
|
|
|
for (auto file : arr) {
|
|
auto file_obj = Json::requireObject(file);
|
|
auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj);
|
|
if(file_tmp.date > ver_tmp.date) {
|
|
ver_tmp = file_tmp;
|
|
latest_file_obj = file_obj;
|
|
}
|
|
}
|
|
|
|
ver = FlameMod::loadIndexedPackVersion(latest_file_obj);
|
|
} catch (Json::JsonException& e) {
|
|
qCritical() << "Failed to parse response from a version request.";
|
|
qCritical() << e.what();
|
|
qDebug() << doc;
|
|
}
|
|
});
|
|
|
|
QObject::connect(netJob, &NetJob::finished, [response, netJob, &loop] {
|
|
netJob->deleteLater();
|
|
delete response;
|
|
loop.quit();
|
|
});
|
|
|
|
netJob->start();
|
|
|
|
loop.exec();
|
|
|
|
return ver;
|
|
}
|
|
|
|
NetJob::Ptr FlameAPI::getProjects(QStringList addonIds, QByteArray* response) const
|
|
{
|
|
auto* netJob = new NetJob(QString("Flame::GetProjects"), APPLICATION->network());
|
|
|
|
QJsonObject body_obj;
|
|
QJsonArray addons_arr;
|
|
for (auto& addonId : addonIds) {
|
|
addons_arr.append(addonId);
|
|
}
|
|
|
|
body_obj["modIds"] = addons_arr;
|
|
|
|
QJsonDocument body(body_obj);
|
|
auto body_raw = body.toJson();
|
|
|
|
netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods"), response, body_raw));
|
|
|
|
QObject::connect(netJob, &NetJob::finished, [response] { delete response; });
|
|
QObject::connect(netJob, &NetJob::failed, [body_raw] { qDebug() << body_raw; });
|
|
|
|
return netJob;
|
|
}
|
|
|
|
NetJob::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) const
|
|
{
|
|
auto* netJob = new NetJob(QString("Flame::GetFiles"), APPLICATION->network());
|
|
|
|
QJsonObject body_obj;
|
|
QJsonArray files_arr;
|
|
for (auto& fileId : fileIds) {
|
|
files_arr.append(fileId);
|
|
}
|
|
|
|
body_obj["fileIds"] = files_arr;
|
|
|
|
QJsonDocument body(body_obj);
|
|
auto body_raw = body.toJson();
|
|
|
|
netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods/files"), response, body_raw));
|
|
|
|
QObject::connect(netJob, &NetJob::finished, [response] { delete response; });
|
|
QObject::connect(netJob, &NetJob::failed, [body_raw] { qDebug() << body_raw; });
|
|
|
|
return netJob;
|
|
}
|