Added categories filter

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97
2023-10-21 22:15:07 +03:00
parent 35d62cc5f2
commit 41c9ca4f8a
16 changed files with 230 additions and 6 deletions

View File

@ -191,6 +191,11 @@ constexpr bool hasSingleModLoaderSelected(ModLoaderTypes l) noexcept
return x && !(x & (x - 1));
}
struct Category {
QString name;
QString id;
};
} // namespace ModPlatform
Q_DECLARE_METATYPE(ModPlatform::IndexedPack)

View File

@ -74,6 +74,7 @@ class ResourceAPI {
std::optional<ModPlatform::ModLoaderTypes> loaders;
std::optional<std::list<Version> > versions;
std::optional<QString> side;
std::optional<QStringList> categoryIds;
};
struct SearchCallbacks {
std::function<void(QJsonDocument&)> on_succeed;

View File

@ -3,10 +3,12 @@
// SPDX-License-Identifier: GPL-3.0-only
#include "FlameAPI.h"
#include <memory>
#include "FlameModIndex.h"
#include "Application.h"
#include "Json.h"
#include "modplatform/ModIndex.h"
#include "net/ApiDownload.h"
#include "net/ApiUpload.h"
#include "net/NetJob.h"
@ -222,3 +224,42 @@ QList<ResourceAPI::SortingMethod> FlameAPI::getSortingMethods() const
{
return s_sorts;
}
Task::Ptr FlameAPI::getModCategories(std::shared_ptr<QByteArray> response)
{
auto netJob = makeShared<NetJob>(QString("Flame::GetCategories"), APPLICATION->network());
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl("https://api.curseforge.com/v1/categories?gameId=432&classId=6"), response));
QObject::connect(netJob.get(), &Task::failed, [](QString msg) { qDebug() << "Flame failed to get categories:" << msg; });
return netJob;
}
QList<ModPlatform::Category> FlameAPI::loadModCategories(std::shared_ptr<QByteArray> response)
{
QList<ModPlatform::Category> categories;
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from categories at " << parse_error.offset
<< " reason: " << parse_error.errorString();
qWarning() << *response;
return categories;
}
try {
auto obj = Json::requireObject(doc);
auto arr = Json::requireArray(obj, "data");
for (auto val : arr) {
auto cat = Json::requireObject(val);
auto id = Json::requireInteger(cat, "id");
auto name = Json::requireString(cat, "name");
categories.push_back({ name, QString::number(id) });
}
} catch (Json::JsonException& e) {
qCritical() << "Failed to parse response from a version request.";
qCritical() << e.what();
qDebug() << doc;
}
return categories;
};

View File

@ -4,6 +4,7 @@
#pragma once
#include <QList>
#include <algorithm>
#include <memory>
#include "modplatform/ModIndex.h"
@ -22,6 +23,9 @@ class FlameAPI : public NetworkResourceAPI {
Task::Ptr getFiles(const QStringList& fileIds, std::shared_ptr<QByteArray> response) const;
Task::Ptr getFile(const QString& addonId, const QString& fileId, std::shared_ptr<QByteArray> response) const;
static Task::Ptr getModCategories(std::shared_ptr<QByteArray> response);
static QList<ModPlatform::Category> loadModCategories(std::shared_ptr<QByteArray> response);
[[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override;
static inline auto validateModLoaders(ModPlatform::ModLoaderTypes loaders) -> bool
@ -96,6 +100,9 @@ class FlameAPI : public NetworkResourceAPI {
get_arguments.append("sortOrder=desc");
if (args.loaders.has_value())
get_arguments.append(QString("modLoaderTypes=%1").arg(getModLoaderFilters(args.loaders.value())));
if (args.categoryIds.has_value() && !args.categoryIds->empty())
get_arguments.append(QString("categoryIds=[%1]").arg(args.categoryIds->join(",")));
get_arguments.append(gameVersionStr);
return "https://api.curseforge.com/v1/mods/search?gameId=432&" + get_arguments.join('&');

View File

@ -122,3 +122,41 @@ QList<ResourceAPI::SortingMethod> ModrinthAPI::getSortingMethods() const
{
return s_sorts;
}
Task::Ptr ModrinthAPI::getModCategories(std::shared_ptr<QByteArray> response)
{
auto netJob = makeShared<NetJob>(QString("Modrinth::GetCategories"), APPLICATION->network());
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(BuildConfig.MODRINTH_PROD_URL + "/tag/category"), response));
QObject::connect(netJob.get(), &Task::failed, [](QString msg) { qDebug() << "Modrinth failed to get categories:" << msg; });
return netJob;
}
QList<ModPlatform::Category> ModrinthAPI::loadModCategories(std::shared_ptr<QByteArray> response)
{
QList<ModPlatform::Category> categories;
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from categories at " << parse_error.offset
<< " reason: " << parse_error.errorString();
qWarning() << *response;
return categories;
}
try {
auto arr = Json::requireArray(doc);
for (auto val : arr) {
auto cat = Json::requireObject(val);
auto name = Json::requireString(cat, "name");
if (Json::ensureString(cat, "project_type", "") == "mod")
categories.push_back({ name, name });
}
} catch (Json::JsonException& e) {
qCritical() << "Failed to parse response from a version request.";
qCritical() << e.what();
qDebug() << doc;
}
return categories;
};

View File

@ -30,6 +30,9 @@ class ModrinthAPI : public NetworkResourceAPI {
Task::Ptr getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const override;
static Task::Ptr getModCategories(std::shared_ptr<QByteArray> response);
static QList<ModPlatform::Category> loadModCategories(std::shared_ptr<QByteArray> response);
public:
[[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override;
@ -56,6 +59,15 @@ class ModrinthAPI : public NetworkResourceAPI {
return l.join(',');
}
static auto getCategoriesFilters(QStringList categories) -> const QString
{
QStringList l;
for (auto cat : categories) {
l << QString("\"categories:%1\"").arg(cat);
}
return l.join(',');
}
static auto getSideFilters(QString side) -> const QString
{
if (side.isEmpty() || side == "both") {
@ -99,6 +111,9 @@ class ModrinthAPI : public NetworkResourceAPI {
if (!side.isEmpty())
facets_list.append(QString("[%1]").arg(side));
}
if (args.categoryIds.has_value() && !args.categoryIds->empty())
facets_list.append(QString("[%1]").arg(getCategoriesFilters(args.categoryIds.value())));
facets_list.append(QString("[\"project_type:%1\"]").arg(resourceTypeParameter(args.type)));
return QString("[%1]").arg(facets_list.join(','));