aboutsummaryrefslogtreecommitdiff
path: root/launcher/modplatform/modrinth
diff options
context:
space:
mode:
authorTrial97 <alexandru.tripon97@gmail.com>2023-05-31 20:12:12 +0300
committerTrial97 <alexandru.tripon97@gmail.com>2023-05-31 20:12:12 +0300
commit29c3dc40ef7f5b1fce5ab5970a39613d0f7f5089 (patch)
treece92f8a86d08531879105a16194a14391c0ae2ea /launcher/modplatform/modrinth
parente8ee4497f77a571b305a48b70f84c8729b800859 (diff)
parent954d4d701a136e79c25b58f9680d26a555a6e6fe (diff)
downloadPrismLauncher-29c3dc40ef7f5b1fce5ab5970a39613d0f7f5089.tar.gz
PrismLauncher-29c3dc40ef7f5b1fce5ab5970a39613d0f7f5089.tar.bz2
PrismLauncher-29c3dc40ef7f5b1fce5ab5970a39613d0f7f5089.zip
Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into logdir
Diffstat (limited to 'launcher/modplatform/modrinth')
-rw-r--r--launcher/modplatform/modrinth/ModrinthAPI.cpp91
-rw-r--r--launcher/modplatform/modrinth/ModrinthAPI.h138
-rw-r--r--launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp27
-rw-r--r--launcher/modplatform/modrinth/ModrinthCheckUpdate.h4
-rw-r--r--launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp28
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackIndex.cpp13
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackIndex.h2
7 files changed, 182 insertions, 121 deletions
diff --git a/launcher/modplatform/modrinth/ModrinthAPI.cpp b/launcher/modplatform/modrinth/ModrinthAPI.cpp
index 747cf4c3..29e3d129 100644
--- a/launcher/modplatform/modrinth/ModrinthAPI.cpp
+++ b/launcher/modplatform/modrinth/ModrinthAPI.cpp
@@ -1,24 +1,29 @@
+// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
#include "ModrinthAPI.h"
#include "Application.h"
#include "Json.h"
+#include "net/NetJob.h"
#include "net/Upload.h"
-auto ModrinthAPI::currentVersion(QString hash, QString hash_format, QByteArray* response) -> NetJob::Ptr
+Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, QByteArray* response)
{
- auto* netJob = new NetJob(QString("Modrinth::GetCurrentVersion"), APPLICATION->network());
+ auto netJob = makeShared<NetJob>(QString("Modrinth::GetCurrentVersion"), APPLICATION->network());
netJob->addNetAction(Net::Download::makeByteArray(
QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1?algorithm=%2").arg(hash, hash_format), response));
- QObject::connect(netJob, &NetJob::finished, [response] { delete response; });
+ QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
return netJob;
}
-auto ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format, QByteArray* response) -> NetJob::Ptr
+Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format, QByteArray* response)
{
- auto* netJob = new NetJob(QString("Modrinth::GetCurrentVersions"), APPLICATION->network());
+ auto netJob = makeShared<NetJob>(QString("Modrinth::GetCurrentVersions"), APPLICATION->network());
QJsonObject body_obj;
@@ -30,28 +35,31 @@ auto ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format
netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files"), response, body_raw));
- QObject::connect(netJob, &NetJob::finished, [response] { delete response; });
+ QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
return netJob;
}
-auto ModrinthAPI::latestVersion(QString hash,
- QString hash_format,
- std::list<Version> mcVersions,
- ModLoaderTypes loaders,
- QByteArray* response) -> NetJob::Ptr
+Task::Ptr ModrinthAPI::latestVersion(QString hash,
+ QString hash_format,
+ std::optional<std::list<Version>> mcVersions,
+ std::optional<ModLoaderTypes> loaders,
+ QByteArray* response)
{
- auto* netJob = new NetJob(QString("Modrinth::GetLatestVersion"), APPLICATION->network());
+ auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersion"), APPLICATION->network());
QJsonObject body_obj;
- Json::writeStringList(body_obj, "loaders", getModLoaderStrings(loaders));
+ if (loaders.has_value())
+ Json::writeStringList(body_obj, "loaders", getModLoaderStrings(loaders.value()));
- QStringList game_versions;
- for (auto& ver : mcVersions) {
- game_versions.append(ver.toString());
+ if (mcVersions.has_value()) {
+ QStringList game_versions;
+ for (auto& ver : mcVersions.value()) {
+ game_versions.append(ver.toString());
+ }
+ Json::writeStringList(body_obj, "game_versions", game_versions);
}
- Json::writeStringList(body_obj, "game_versions", game_versions);
QJsonDocument body(body_obj);
auto body_raw = body.toJson();
@@ -59,50 +67,67 @@ auto ModrinthAPI::latestVersion(QString hash,
netJob->addNetAction(Net::Upload::makeByteArray(
QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1/update?algorithm=%2").arg(hash, hash_format), response, body_raw));
- QObject::connect(netJob, &NetJob::finished, [response] { delete response; });
+ QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
return netJob;
}
-auto ModrinthAPI::latestVersions(const QStringList& hashes,
- QString hash_format,
- std::list<Version> mcVersions,
- ModLoaderTypes loaders,
- QByteArray* response) -> NetJob::Ptr
+Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes,
+ QString hash_format,
+ std::optional<std::list<Version>> mcVersions,
+ std::optional<ModLoaderTypes> loaders,
+ QByteArray* response)
{
- auto* netJob = new NetJob(QString("Modrinth::GetLatestVersions"), APPLICATION->network());
+ auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersions"), APPLICATION->network());
QJsonObject body_obj;
Json::writeStringList(body_obj, "hashes", hashes);
Json::writeString(body_obj, "algorithm", hash_format);
- Json::writeStringList(body_obj, "loaders", getModLoaderStrings(loaders));
+ if (loaders.has_value())
+ Json::writeStringList(body_obj, "loaders", getModLoaderStrings(loaders.value()));
- QStringList game_versions;
- for (auto& ver : mcVersions) {
- game_versions.append(ver.toString());
+ if (mcVersions.has_value()) {
+ QStringList game_versions;
+ for (auto& ver : mcVersions.value()) {
+ game_versions.append(ver.toString());
+ }
+ Json::writeStringList(body_obj, "game_versions", game_versions);
}
- Json::writeStringList(body_obj, "game_versions", game_versions);
QJsonDocument body(body_obj);
auto body_raw = body.toJson();
netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files/update"), response, body_raw));
- QObject::connect(netJob, &NetJob::finished, [response] { delete response; });
+ QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
return netJob;
}
-auto ModrinthAPI::getProjects(QStringList addonIds, QByteArray* response) const -> NetJob*
+Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, QByteArray* response) const
{
- auto netJob = new NetJob(QString("Modrinth::GetProjects"), APPLICATION->network());
+ auto netJob = makeShared<NetJob>(QString("Modrinth::GetProjects"), APPLICATION->network());
auto searchUrl = getMultipleModInfoURL(addonIds);
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
- QObject::connect(netJob, &NetJob::finished, [response, netJob] { delete response; netJob->deleteLater(); });
+ QObject::connect(netJob.get(), &NetJob::finished, [response, netJob] {
+ delete response;
+ });
return netJob;
}
+
+// https://docs.modrinth.com/api-spec/#tag/projects/operation/searchProjects
+static QList<ResourceAPI::SortingMethod> s_sorts = { { 1, "relevance", QObject::tr("Sort by Relevance") },
+ { 2, "downloads", QObject::tr("Sort by Downloads") },
+ { 3, "follows", QObject::tr("Sort by Follows") },
+ { 4, "newest", QObject::tr("Sort by Last Updated") },
+ { 5, "updated", QObject::tr("Sort by Newest") } };
+
+QList<ResourceAPI::SortingMethod> ModrinthAPI::getSortingMethods() const
+{
+ return s_sorts;
+}
diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h
index e1a18681..b91ac5c1 100644
--- a/launcher/modplatform/modrinth/ModrinthAPI.h
+++ b/launcher/modplatform/modrinth/ModrinthAPI.h
@@ -1,69 +1,54 @@
+// SPDX-FileCopyrightText: 2022-2023 flowln <flowlnlnln@gmail.com>
+//
// SPDX-License-Identifier: GPL-3.0-only
-/*
- * PolyMC - Minecraft Launcher
- * Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
#pragma once
#include "BuildConfig.h"
-#include "modplatform/ModAPI.h"
#include "modplatform/ModIndex.h"
-#include "modplatform/helpers/NetworkModAPI.h"
+#include "modplatform/helpers/NetworkResourceAPI.h"
#include <QDebug>
-class ModrinthAPI : public NetworkModAPI {
+class ModrinthAPI : public NetworkResourceAPI {
public:
auto currentVersion(QString hash,
QString hash_format,
- QByteArray* response) -> NetJob::Ptr;
+ QByteArray* response) -> Task::Ptr;
auto currentVersions(const QStringList& hashes,
QString hash_format,
- QByteArray* response) -> NetJob::Ptr;
+ QByteArray* response) -> Task::Ptr;
auto latestVersion(QString hash,
QString hash_format,
- std::list<Version> mcVersions,
- ModLoaderTypes loaders,
- QByteArray* response) -> NetJob::Ptr;
+ std::optional<std::list<Version>> mcVersions,
+ std::optional<ModLoaderTypes> loaders,
+ QByteArray* response) -> Task::Ptr;
auto latestVersions(const QStringList& hashes,
QString hash_format,
- std::list<Version> mcVersions,
- ModLoaderTypes loaders,
- QByteArray* response) -> NetJob::Ptr;
+ std::optional<std::list<Version>> mcVersions,
+ std::optional<ModLoaderTypes> loaders,
+ QByteArray* response) -> Task::Ptr;
- auto getProjects(QStringList addonIds, QByteArray* response) const -> NetJob* override;
+ Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override;
public:
+ [[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override;
+
inline auto getAuthorURL(const QString& name) const -> QString { return "https://modrinth.com/user/" + name; };
static auto getModLoaderStrings(const ModLoaderTypes types) -> const QStringList
{
QStringList l;
- for (auto loader : {Forge, Fabric, Quilt})
- {
- if ((types & loader) || types == Unspecified)
- {
- l << ModAPI::getModLoaderString(loader);
+ for (auto loader : {Forge, Fabric, Quilt}) {
+ if (types & loader) {
+ l << getModLoaderString(loader);
}
}
if ((types & Quilt) && (~types & Fabric)) // Add Fabric if Quilt is in use, if Fabric isn't already there
- l << ModAPI::getModLoaderString(Fabric);
+ l << getModLoaderString(Fabric);
return l;
}
@@ -78,28 +63,58 @@ class ModrinthAPI : public NetworkModAPI {
}
private:
- inline auto getModSearchURL(SearchArgs& args) const -> QString override
+ [[nodiscard]] static QString resourceTypeParameter(ModPlatform::ResourceType type)
+ {
+ switch (type) {
+ case ModPlatform::ResourceType::MOD:
+ return "mod";
+ case ModPlatform::ResourceType::RESOURCE_PACK:
+ return "resourcepack";
+ case ModPlatform::ResourceType::SHADER_PACK:
+ return "shader";
+ default:
+ qWarning() << "Invalid resource type for Modrinth API!";
+ break;
+ }
+
+ return "";
+ }
+ [[nodiscard]] QString createFacets(SearchArgs const& args) const
+ {
+ QStringList facets_list;
+
+ if (args.loaders.has_value())
+ facets_list.append(QString("[%1]").arg(getModLoaderFilters(args.loaders.value())));
+ if (args.versions.has_value())
+ facets_list.append(QString("[%1]").arg(getGameVersionsArray(args.versions.value())));
+ facets_list.append(QString("[\"project_type:%1\"]").arg(resourceTypeParameter(args.type)));
+
+ return QString("[%1]").arg(facets_list.join(','));
+ }
+
+ public:
+ [[nodiscard]] inline auto getSearchURL(SearchArgs const& args) const -> std::optional<QString> override
{
- if (!validateModLoaders(args.loaders)) {
- qWarning() << "Modrinth only have Forge and Fabric-compatible mods!";
- return "";
+ if (args.loaders.has_value()) {
+ if (!validateModLoaders(args.loaders.value())) {
+ qWarning() << "Modrinth only have Forge and Fabric-compatible mods!";
+ return {};
+ }
}
- return QString(BuildConfig.MODRINTH_PROD_URL +
- "/search?"
- "offset=%1&"
- "limit=25&"
- "query=%2&"
- "index=%3&"
- "facets=[[%4],%5[\"project_type:mod\"]]")
- .arg(args.offset)
- .arg(args.search)
- .arg(args.sorting)
- .arg(getModLoaderFilters(args.loaders))
- .arg(getGameVersionsArray(args.versions));
+ QStringList get_arguments;
+ get_arguments.append(QString("offset=%1").arg(args.offset));
+ get_arguments.append(QString("limit=25"));
+ if (args.search.has_value())
+ get_arguments.append(QString("query=%1").arg(args.search.value()));
+ if (args.sorting.has_value())
+ get_arguments.append(QString("index=%1").arg(args.sorting.value().name));
+ get_arguments.append(QString("facets=%1").arg(createFacets(args)));
+
+ return BuildConfig.MODRINTH_PROD_URL + "/search?" + get_arguments.join('&');
};
- inline auto getModInfoURL(QString& id) const -> QString override
+ inline auto getInfoURL(QString const& id) const -> std::optional<QString> override
{
return BuildConfig.MODRINTH_PROD_URL + "/project/" + id;
};
@@ -109,15 +124,16 @@ class ModrinthAPI : public NetworkModAPI {
return BuildConfig.MODRINTH_PROD_URL + QString("/projects?ids=[\"%1\"]").arg(ids.join("\",\""));
};
- inline auto getVersionsURL(VersionSearchArgs& args) const -> QString override
+ inline auto getVersionsURL(VersionSearchArgs const& args) const -> std::optional<QString> override
{
- return QString(BuildConfig.MODRINTH_PROD_URL +
- "/project/%1/version?"
- "game_versions=[%2]&"
- "loaders=[\"%3\"]")
- .arg(args.addonId,
- getGameVersionsString(args.mcVersions),
- getModLoaderStrings(args.loaders).join("\",\""));
+ QStringList get_arguments;
+ if (args.mcVersions.has_value())
+ get_arguments.append(QString("game_versions=[%1]").arg(getGameVersionsString(args.mcVersions.value())));
+ if (args.loaders.has_value())
+ get_arguments.append(QString("loaders=[\"%1\"]").arg(getModLoaderStrings(args.loaders.value()).join("\",\"")));
+
+ return QString("%1/project/%2/version%3%4")
+ .arg(BuildConfig.MODRINTH_PROD_URL, args.pack.addonId.toString(), get_arguments.isEmpty() ? "" : "?", get_arguments.join('&'));
};
auto getGameVersionsArray(std::list<Version> mcVersions) const -> QString
@@ -127,12 +143,12 @@ class ModrinthAPI : public NetworkModAPI {
s += QString("\"versions:%1\",").arg(ver.toString());
}
s.remove(s.length() - 1, 1); //remove last comma
- return s.isEmpty() ? QString() : QString("[%1],").arg(s);
+ return s.isEmpty() ? QString() : s;
}
inline auto validateModLoaders(ModLoaderTypes loaders) const -> bool
{
- return (loaders == Unspecified) || (loaders & (Forge | Fabric | Quilt));
+ return loaders & (Forge | Fabric | Quilt);
}
};
diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
index e2d27547..d1be7209 100644
--- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
+++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
@@ -4,12 +4,15 @@
#include "Json.h"
-#include "ModDownloadTask.h"
+#include "ResourceDownloadTask.h"
#include "modplatform/helpers/HashUtils.h"
#include "tasks/ConcurrentTask.h"
+#include "minecraft/mod/ModFolderModel.h"
+#include "minecraft/mod/ResourceFolderModel.h"
+
static ModrinthAPI api;
static ModPlatform::ProviderCapabilities ProviderCaps;
@@ -34,7 +37,7 @@ void ModrinthCheckUpdate::executeTask()
// Create all hashes
QStringList hashes;
- auto best_hash_type = ProviderCaps.hashType(ModPlatform::Provider::MODRINTH).first();
+ auto best_hash_type = ProviderCaps.hashType(ModPlatform::ResourceProvider::MODRINTH).first();
ConcurrentTask hashing_task(this, "MakeModrinthHashesTask", 10);
for (auto* mod : m_mods) {
@@ -108,11 +111,13 @@ void ModrinthCheckUpdate::executeTask()
// Sometimes a version may have multiple files, one with "forge" and one with "fabric",
// so we may want to filter it
QString loader_filter;
- static auto flags = { ModAPI::ModLoaderType::Forge, ModAPI::ModLoaderType::Fabric, ModAPI::ModLoaderType::Quilt };
- for (auto flag : flags) {
- if (m_loaders.testFlag(flag)) {
- loader_filter = api.getModLoaderString(flag);
- break;
+ if (m_loaders.has_value()) {
+ static auto flags = { ResourceAPI::ModLoaderType::Forge, ResourceAPI::ModLoaderType::Fabric, ResourceAPI::ModLoaderType::Quilt };
+ for (auto flag : flags) {
+ if (m_loaders.value().testFlag(flag)) {
+ loader_filter = api.getModLoaderString(flag);
+ break;
+ }
}
}
@@ -152,12 +157,12 @@ void ModrinthCheckUpdate::executeTask()
for (auto& author : mod->authors())
pack.authors.append({ author });
pack.description = mod->description();
- pack.provider = ModPlatform::Provider::MODRINTH;
+ pack.provider = ModPlatform::ResourceProvider::MODRINTH;
- auto download_task = new ModDownloadTask(pack, project_ver, m_mods_folder);
+ auto download_task = makeShared<ResourceDownloadTask>(pack, project_ver, m_mods_folder);
m_updatable.emplace_back(pack.name, hash, mod->version(), project_ver.version_number, project_ver.changelog,
- ModPlatform::Provider::MODRINTH, download_task);
+ ModPlatform::ResourceProvider::MODRINTH, download_task);
}
}
} catch (Json::JsonException& e) {
@@ -170,7 +175,7 @@ void ModrinthCheckUpdate::executeTask()
setStatus(tr("Waiting for the API response from Modrinth..."));
setProgress(1, 3);
- m_net_job = job.get();
+ m_net_job = qSharedPointerObjectCast<NetJob, Task>(job);
job->start();
lock.exec();
diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h
index abf8ada1..88e1a675 100644
--- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h
+++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h
@@ -8,7 +8,7 @@ class ModrinthCheckUpdate : public CheckUpdateTask {
Q_OBJECT
public:
- ModrinthCheckUpdate(QList<Mod*>& mods, std::list<Version>& mcVersions, ModAPI::ModLoaderTypes loaders, std::shared_ptr<ModFolderModel> mods_folder)
+ ModrinthCheckUpdate(QList<Mod*>& mods, std::list<Version>& mcVersions, std::optional<ResourceAPI::ModLoaderTypes> loaders, std::shared_ptr<ModFolderModel> mods_folder)
: CheckUpdateTask(mods, mcVersions, loaders, mods_folder)
{}
@@ -19,5 +19,5 @@ class ModrinthCheckUpdate : public CheckUpdateTask {
void executeTask() override;
private:
- NetJob* m_net_job = nullptr;
+ NetJob::Ptr m_net_job = nullptr;
};
diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
index c5a27c9d..bb8227aa 100644
--- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
+++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
@@ -11,6 +11,7 @@
#include "net/ChecksumValidator.h"
+#include "net/NetJob.h"
#include "settings/INISettingsObject.h"
#include "ui/dialogs/CustomMessageBox.h"
@@ -223,12 +224,21 @@ bool ModrinthCreationTask::createInstance()
instance.setName(name());
instance.saveNow();
- m_files_job = new NetJob(tr("Mod download"), APPLICATION->network());
+ m_files_job.reset(new NetJob(tr("Mod Download Modrinth"), APPLICATION->network()));
+
+ auto root_modpack_path = FS::PathCombine(m_stagingPath, ".minecraft");
+ auto root_modpack_url = QUrl::fromLocalFile(root_modpack_path);
for (auto file : m_files) {
- auto path = FS::PathCombine(m_stagingPath, ".minecraft", file.path);
- qDebug() << "Will try to download" << file.downloads.front() << "to" << path;
- auto dl = Net::Download::makeFile(file.downloads.dequeue(), path);
+ auto file_path = FS::PathCombine(root_modpack_path, file.path);
+ if (!root_modpack_url.isParentOf(QUrl::fromLocalFile(file_path))) {
+ // This means we somehow got out of the root folder, so abort here to prevent exploits
+ setError(tr("One of the files has a path that leads to an arbitrary location (%1). This is a security risk and isn't allowed.").arg(file.path));
+ return false;
+ }
+
+ qDebug() << "Will try to download" << file.downloads.front() << "to" << file_path;
+ auto dl = Net::Download::makeFile(file.downloads.dequeue(), file_path);
dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash));
m_files_job->addNetAction(dl);
@@ -236,8 +246,8 @@ bool ModrinthCreationTask::createInstance()
// FIXME: This really needs to be put into a ConcurrentTask of
// MultipleOptionsTask's , once those exist :)
auto param = dl.toWeakRef();
- connect(dl.get(), &NetAction::failed, [this, &file, path, param] {
- auto ndl = Net::Download::makeFile(file.downloads.dequeue(), path);
+ connect(dl.get(), &NetAction::failed, [this, &file, file_path, param] {
+ auto ndl = Net::Download::makeFile(file.downloads.dequeue(), file_path);
ndl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash));
m_files_job->addNetAction(ndl);
if (auto shared = param.lock()) shared->succeeded();
@@ -253,7 +263,11 @@ bool ModrinthCreationTask::createInstance()
setError(reason);
});
connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit);
- connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) { setProgress(current, total); });
+ connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) {
+ setDetails(tr("%1 out of %2 complete").arg(current).arg(total));
+ setProgress(current, total);
+ });
+ connect(m_files_job.get(), &NetJob::stepProgress, this, &ModrinthCreationTask::propogateStepProgress);
setStatus(tr("Downloading mods..."));
m_files_job->start();
diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
index ae45e096..7ade131e 100644
--- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
@@ -27,13 +27,14 @@
static ModrinthAPI api;
static ModPlatform::ProviderCapabilities ProviderCaps;
+// https://docs.modrinth.com/api-spec/#tag/projects/operation/getProject
void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj)
{
pack.addonId = Json::ensureString(obj, "project_id");
if (pack.addonId.toString().isEmpty())
pack.addonId = Json::requireString(obj, "id");
- pack.provider = ModPlatform::Provider::MODRINTH;
+ pack.provider = ModPlatform::ResourceProvider::MODRINTH;
pack.name = Json::requireString(obj, "title");
pack.slug = Json::ensureString(obj, "slug", "");
@@ -44,7 +45,7 @@ void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj)
pack.description = Json::ensureString(obj, "description", "");
- pack.logoUrl = Json::requireString(obj, "icon_url");
+ pack.logoUrl = Json::ensureString(obj, "icon_url", "");
pack.logoName = pack.addonId.toString();
ModPlatform::ModpackAuthor modAuthor;
@@ -87,7 +88,7 @@ void Modrinth::loadExtraPackData(ModPlatform::IndexedPack& pack, QJsonObject& ob
pack.extraData.donate.append(donate);
}
- pack.extraData.body = Json::ensureString(obj, "body");
+ pack.extraData.body = Json::ensureString(obj, "body").remove("<br>");
pack.extraDataLoaded = true;
}
@@ -95,10 +96,10 @@ void Modrinth::loadExtraPackData(ModPlatform::IndexedPack& pack, QJsonObject& ob
void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
QJsonArray& arr,
const shared_qobject_ptr<QNetworkAccessManager>& network,
- BaseInstance* inst)
+ const BaseInstance* inst)
{
QVector<ModPlatform::IndexedVersion> unsortedVersions;
- QString mcVersion = (static_cast<MinecraftInstance*>(inst))->getPackProfile()->getComponentVersion("net.minecraft");
+ QString mcVersion = (static_cast<const MinecraftInstance*>(inst))->getPackProfile()->getComponentVersion("net.minecraft");
for (auto versionIter : arr) {
auto obj = versionIter.toObject();
@@ -179,7 +180,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
file.hash = Json::requireString(hash_list, preferred_hash_type);
file.hash_type = preferred_hash_type;
} else {
- auto hash_types = ProviderCaps.hashType(ModPlatform::Provider::MODRINTH);
+ auto hash_types = ProviderCaps.hashType(ModPlatform::ResourceProvider::MODRINTH);
for (auto& hash_type : hash_types) {
if (hash_list.contains(hash_type)) {
file.hash = Json::requireString(hash_list, hash_type);
diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.h b/launcher/modplatform/modrinth/ModrinthPackIndex.h
index 31881414..e73e4b18 100644
--- a/launcher/modplatform/modrinth/ModrinthPackIndex.h
+++ b/launcher/modplatform/modrinth/ModrinthPackIndex.h
@@ -29,7 +29,7 @@ void loadExtraPackData(ModPlatform::IndexedPack& m, QJsonObject& obj);
void loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
QJsonArray& arr,
const shared_qobject_ptr<QNetworkAccessManager>& network,
- BaseInstance* inst);
+ const BaseInstance* inst);
auto loadIndexedPackVersion(QJsonObject& obj, QString hash_type = "sha512", QString filename_prefer = "") -> ModPlatform::IndexedVersion;
} // namespace Modrinth