aboutsummaryrefslogtreecommitdiff
path: root/launcher/modplatform/flame/FlameCheckUpdate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'launcher/modplatform/flame/FlameCheckUpdate.cpp')
-rw-r--r--launcher/modplatform/flame/FlameCheckUpdate.cpp209
1 files changed, 82 insertions, 127 deletions
diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp
index 12d99029..3658bf8d 100644
--- a/launcher/modplatform/flame/FlameCheckUpdate.cpp
+++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp
@@ -10,7 +10,6 @@
#include "ModDownloadTask.h"
static FlameAPI api;
-static ModPlatform::ProviderCapabilities ProviderCaps;
bool FlameCheckUpdate::abort()
{
@@ -64,156 +63,112 @@ ModPlatform::IndexedPack getProjectInfo(ModPlatform::IndexedVersion& ver_info)
return pack;
}
-/* Check for update:
- * - Get latest version available
- * - Compare hash of the latest version with the current hash
- * - If equal, no updates, else, there's updates, so add to the list
- * */
-void FlameCheckUpdate::executeTask()
+ModPlatform::IndexedVersion getFileInfo(int addonId, int fileId)
{
- setStatus(tr("Preparing mods for CurseForge..."));
- setProgress(0, 5);
-
- QHash<int, Mod> mappings;
+ ModPlatform::IndexedVersion ver;
- // Create all hashes
- std::list<uint> murmur_hashes;
+ QEventLoop loop;
- auto best_hash_type = ProviderCaps.hashType(ModPlatform::Provider::FLAME).first();
- for (auto mod : m_mods) {
- QByteArray jar_data;
+ auto get_file_info_job = new NetJob("Flame::GetFileInfoJob", APPLICATION->network());
- try {
- jar_data = FS::read(mod.fileinfo().absoluteFilePath());
- } catch (FS::FileSystemException& e) {
- qCritical() << QString("Failed to open / read JAR file of %1").arg(mod.name());
- qCritical() << QString("Reason: ") << e.cause();
+ auto response = new QByteArray();
+ auto url = QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(QString::number(addonId), QString::number(fileId));
+ auto dl = Net::Download::makeByteArray(url, response);
+ get_file_info_job->addNetAction(dl);
- failed(e.what());
+ QObject::connect(get_file_info_job, &NetJob::succeeded, [response, &ver]() {
+ QJsonParseError parse_error{};
+ QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
+ if (parse_error.error != QJsonParseError::NoError) {
+ qWarning() << "Error while parsing JSON response from FlameCheckUpdate at " << parse_error.offset
+ << " reason: " << parse_error.errorString();
+ qWarning() << *response;
return;
}
- QByteArray jar_data_treated;
- for (char c : jar_data) {
- // CF-specific
- if (!(c == 9 || c == 10 || c == 13 || c == 32))
- jar_data_treated.push_back(c);
+ try {
+ auto doc_obj = Json::requireObject(doc);
+ auto data_obj = Json::requireObject(doc_obj, "data");
+ ver = FlameMod::loadIndexedPackVersion(data_obj);
+ } catch (Json::JsonException& e) {
+ qWarning() << e.cause();
+ qDebug() << doc;
}
+ });
- auto murmur_hash = MurmurHash2(jar_data_treated, jar_data_treated.length());
- murmur_hashes.emplace_back(murmur_hash);
+ QObject::connect(get_file_info_job, &NetJob::finished, [&loop, get_file_info_job] {
+ get_file_info_job->deleteLater();
+ loop.quit();
+ });
- mappings.insert(mod.metadata()->mod_id().toInt(), mod);
- }
+ get_file_info_job->start();
+ loop.exec();
- auto* response = new QByteArray();
- auto job = api.matchFingerprints(murmur_hashes, response);
+ return ver;
+}
- QEventLoop lock;
+/* Check for update:
+ * - Get latest version available
+ * - Compare hash of the latest version with the current hash
+ * - If equal, no updates, else, there's updates, so add to the list
+ * */
+void FlameCheckUpdate::executeTask()
+{
+ setStatus(tr("Preparing mods for CurseForge..."));
- connect(job.get(), &Task::succeeded, this, [this, response, &mappings] {
- QJsonParseError parse_error{};
- QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
- if (parse_error.error != QJsonParseError::NoError) {
- qWarning() << "Error while parsing JSON response from FlameCheckUpdate at " << parse_error.offset
- << " reason: " << parse_error.errorString();
- qWarning() << *response;
+ int i = 0;
+ for (auto mod : m_mods) {
+ setStatus(tr("Getting API response from CurseForge for '%1'").arg(mod.name()));
+ setProgress(i++, m_mods.size());
+
+ auto latest_ver = api.getLatestVersion({ mod.metadata()->project_id.toString(), m_game_versions, m_loaders });
- failed(parse_error.errorString());
+ // Check if we were aborted while getting the latest version
+ if (m_was_aborted) {
+ aborted();
return;
}
- setStatus(tr("Parsing the first API response from CurseForge..."));
- setProgress(2, 5);
-
- try {
- auto doc_obj = Json::requireObject(doc);
- auto data_obj = Json::ensureObject(doc_obj, "data");
- auto match_arr = Json::ensureArray(data_obj, "exactMatches");
- for (auto match : match_arr) {
- auto match_obj = Json::ensureObject(match);
-
- ModPlatform::IndexedVersion current_ver;
- try {
- auto file_obj = Json::requireObject(match_obj, "file");
- current_ver = FlameMod::loadIndexedPackVersion(file_obj);
- } catch (Json::JsonException& e) {
- qCritical() << "Error while parsing Flame indexed version";
- qCritical() << e.what();
- failed(tr("An error occured while parsing a CurseForge indexed version!"));
- return;
- }
-
- auto mod_iter = mappings.find(current_ver.addonId.toInt());
- if (mod_iter == mappings.end()) {
- qCritical() << "Failed to remap mod from Flame!";
- qDebug() << match_obj;
- continue;
- }
-
- auto mod = mod_iter.value();
-
- setStatus(tr("Waiting for the API response from CurseForge for '%1'...").arg(mod.name()));
- setProgress(3, 5);
-
- auto latest_ver = api.getLatestVersion({ current_ver.addonId.toString(), m_game_versions, m_loaders });
-
- // Check if we were aborted while getting the latest version
- if (m_was_aborted) {
- aborted();
- return;
- }
-
- setStatus(tr("Parsing the API response from CurseForge for '%1'...").arg(mod.name()));
- setProgress(4, 5);
-
- if (!latest_ver.addonId.isValid()) {
- emit checkFailed(
- mod,
- tr("No valid version found for this mod. It's probably unavailable for the current game version / mod loader."));
- continue;
- }
-
- if (latest_ver.downloadUrl.isEmpty() && latest_ver.fileId != current_ver.fileId) {
- auto pack = getProjectInfo(latest_ver);
- auto recover_url = QString("%1/download/%2").arg(pack.websiteUrl, latest_ver.fileId.toString());
- emit checkFailed(mod, tr("Mod has a new update available, but is opted-out on CurseForge"), recover_url);
-
- continue;
- }
-
- if (!latest_ver.hash.isEmpty() && (current_ver.hash != latest_ver.hash || mod.status() == ModStatus::NotInstalled)) {
- // Fake pack with the necessary info to pass to the download task :)
- ModPlatform::IndexedPack pack;
- pack.name = mod.name();
- pack.addonId = mod.metadata()->project_id;
- pack.websiteUrl = mod.homeurl();
- for (auto& author : mod.authors())
- pack.authors.append({ author });
- pack.description = mod.description();
- pack.provider = ModPlatform::Provider::FLAME;
-
- auto download_task = new ModDownloadTask(pack, latest_ver, m_mods_folder);
- m_updatable.emplace_back(mod.name(), current_ver.hash, current_ver.version, latest_ver.version,
- api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()),
- ModPlatform::Provider::FLAME, download_task);
- }
- }
+ setStatus(tr("Parsing the API response from CurseForge for '%1'...").arg(mod.name()));
- } catch (Json::JsonException& e) {
- failed(e.cause() + " : " + e.what());
+ if (!latest_ver.addonId.isValid()) {
+ emit checkFailed(mod, tr("No valid version found for this mod. It's probably unavailable for the current game "
+ "version / mod loader."));
+ continue;
}
- });
- connect(job.get(), &Task::finished, &lock, &QEventLoop::quit);
+ if (latest_ver.downloadUrl.isEmpty() && latest_ver.fileId != mod.metadata()->file_id) {
+ auto pack = getProjectInfo(latest_ver);
+ auto recover_url = QString("%1/download/%2").arg(pack.websiteUrl, latest_ver.fileId.toString());
+ emit checkFailed(mod, tr("Mod has a new update available, but is opted-out on CurseForge"), recover_url);
- setStatus(tr("Waiting for the first API response from CurseForge..."));
- setProgress(1, 5);
+ continue;
+ }
- m_net_job = job.get();
- job->start();
+ if (!latest_ver.hash.isEmpty() && (mod.metadata()->hash != latest_ver.hash || mod.status() == ModStatus::NotInstalled)) {
+ // Fake pack with the necessary info to pass to the download task :)
+ ModPlatform::IndexedPack pack;
+ pack.name = mod.name();
+ pack.slug = mod.metadata()->slug;
+ pack.addonId = mod.metadata()->project_id;
+ pack.websiteUrl = mod.homeurl();
+ for (auto& author : mod.authors())
+ pack.authors.append({ author });
+ pack.description = mod.description();
+ pack.provider = ModPlatform::Provider::FLAME;
+
+ auto old_version = mod.version();
+ if (old_version.isEmpty() && mod.status() != ModStatus::NotInstalled) {
+ auto current_ver = getFileInfo(latest_ver.addonId.toInt(), mod.metadata()->file_id.toInt());
+ old_version = current_ver.version;
+ }
- lock.exec();
+ auto download_task = new ModDownloadTask(pack, latest_ver, m_mods_folder);
+ m_updatable.emplace_back(mod.name(), mod.metadata()->hash, old_version, latest_ver.version,
+ api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()),
+ ModPlatform::Provider::FLAME, download_task);
+ }
+ }
emitSucceeded();
}