From 16bfafa29e2cb54e1553c813cab0fff5203f8c60 Mon Sep 17 00:00:00 2001
From: flow <thiagodonato300@gmail.com>
Date: Mon, 7 Mar 2022 16:46:08 -0300
Subject: [PATCH] refactor: de-duplicate common code in network mod APIs

---
 launcher/CMakeLists.txt                       | 11 +++
 launcher/modplatform/ModAPI.h                 |  5 +-
 launcher/modplatform/flame/FlameAPI.h         | 65 +---------------
 .../modplatform/helpers/NetworkModAPI.cpp     | 60 +++++++++++++++
 launcher/modplatform/helpers/NetworkModAPI.h  | 13 ++++
 launcher/modplatform/modrinth/ModrinthAPI.h   | 74 +++----------------
 launcher/ui/pages/modplatform/ModModel.cpp    | 10 ++-
 launcher/ui/pages/modplatform/ModModel.h      |  4 +-
 8 files changed, 109 insertions(+), 133 deletions(-)
 create mode 100644 launcher/modplatform/helpers/NetworkModAPI.cpp
 create mode 100644 launcher/modplatform/helpers/NetworkModAPI.h

diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 0dcda925..48370c96 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -492,6 +492,16 @@ set(META_SOURCES
     meta/Index.h
 )
 
+set(API_SOURCES
+    modplatform/ModAPI.h
+
+    modplatform/flame/FlameAPI.h
+    modplatform/modrinth/ModrinthAPI.h
+    
+    modplatform/helpers/NetworkModAPI.h
+    modplatform/helpers/NetworkModAPI.cpp
+)
+
 set(FTB_SOURCES
     modplatform/legacy_ftb/PackFetchTask.h
     modplatform/legacy_ftb/PackFetchTask.cpp
@@ -572,6 +582,7 @@ set(LOGIC_SOURCES
     ${TOOLS_SOURCES}
     ${META_SOURCES}
     ${ICONS_SOURCES}
+    ${API_SOURCES}
     ${FTB_SOURCES}
     ${FLAME_SOURCES}
     ${MODRINTH_SOURCES}
diff --git a/launcher/modplatform/ModAPI.h b/launcher/modplatform/ModAPI.h
index 8503d7fc..5c7c6349 100644
--- a/launcher/modplatform/ModAPI.h
+++ b/launcher/modplatform/ModAPI.h
@@ -1,6 +1,5 @@
 #pragma once
 
-#include <QJsonDocument>
 #include <QString>
 
 namespace ModPlatform {
@@ -25,6 +24,6 @@ class ModAPI {
         QString version;
     };
 
-    inline virtual void searchMods(CallerType* caller, SearchArgs&& args) const {};
-    inline virtual void getVersions(CallerType* caller, const QString& addonId, const QString& debugName = "") const {};
+    virtual void searchMods(CallerType* caller, SearchArgs&& args) const = 0;
+    virtual void getVersions(CallerType* caller, const QString& addonId) const = 0;
 };
diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h
index be88df65..f7f993d7 100644
--- a/launcher/modplatform/flame/FlameAPI.h
+++ b/launcher/modplatform/flame/FlameAPI.h
@@ -1,67 +1,8 @@
 #pragma once
 
-#include "modplatform/ModAPI.h"
-#include "ui/pages/modplatform/ModModel.h"
-
-#include "Application.h"
-#include "net/NetJob.h"
-
-class FlameAPI : public ModAPI {
-   public:
-    inline void searchMods(CallerType* caller, SearchArgs&& args) const override
-    {
-        auto netJob = new NetJob(QString("Flame::Search"), APPLICATION->network());
-        auto searchUrl = getModSearchURL(args);
-
-        auto response = new QByteArray();
-        netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
-
-        QObject::connect(netJob, &NetJob::started, caller, [caller, netJob]{ caller->setActiveJob(netJob); });
-        QObject::connect(netJob, &NetJob::failed, caller, &CallerType::searchRequestFailed);
-        QObject::connect(netJob, &NetJob::succeeded, caller, [caller, response] {
-            QJsonParseError parse_error;
-            QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
-            if (parse_error.error != QJsonParseError::NoError) {
-                qWarning() << "Error while parsing JSON response from Modrinth at " << parse_error.offset
-                           << " reason: " << parse_error.errorString();
-                qWarning() << *response;
-                return;
-            }
-
-            caller->searchRequestFinished(doc);
-        });
-
-        netJob->start();
-    };
-
-    inline void getVersions(CallerType* caller, const QString& addonId, const QString& debugName = "Flame") const override
-    {
-        auto netJob = new NetJob(QString("%1::ModVersions(%2)").arg(debugName).arg(addonId), APPLICATION->network());
-        auto response = new QByteArray();
-
-        netJob->addNetAction(Net::Download::makeByteArray(getVersionsURL(addonId), response));
-
-        QObject::connect(netJob, &NetJob::succeeded, caller, [response, debugName, caller, addonId] {
-            QJsonParseError parse_error;
-            QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
-            if (parse_error.error != QJsonParseError::NoError) {
-                qWarning() << "Error while parsing JSON response from " << debugName << " at " << parse_error.offset
-                           << " reason: " << parse_error.errorString();
-                qWarning() << *response;
-                return;
-            }
-
-            caller->versionRequestSucceeded(doc, addonId);
-        });
-
-        QObject::connect(netJob, &NetJob::finished, caller, [response, netJob] {
-            netJob->deleteLater();
-            delete response;
-        });
-
-        netJob->start();
-    };
+#include "modplatform/helpers/NetworkModAPI.h"
 
+class FlameAPI : public NetworkModAPI {
    private:
     inline QString getModSearchURL(SearchArgs& args) const
     {
@@ -88,6 +29,4 @@ class FlameAPI : public ModAPI {
     {
         return QString("https://addons-ecs.forgesvc.net/api/v2/addon/%1/files").arg(addonId);
     };
-
-    inline QString getAuthorURL(const QString& name) const { return ""; };
 };
diff --git a/launcher/modplatform/helpers/NetworkModAPI.cpp b/launcher/modplatform/helpers/NetworkModAPI.cpp
new file mode 100644
index 00000000..4b066102
--- /dev/null
+++ b/launcher/modplatform/helpers/NetworkModAPI.cpp
@@ -0,0 +1,60 @@
+#include "NetworkModAPI.h"
+
+#include "ui/pages/modplatform/ModModel.h"
+
+#include "Application.h"
+#include "net/NetJob.h"
+
+void NetworkModAPI::searchMods(CallerType* caller, SearchArgs&& args) const
+{
+    auto netJob = new NetJob(QString("Modrinth::Search"), APPLICATION->network());
+    auto searchUrl = getModSearchURL(args);
+
+    auto response = new QByteArray();
+    netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
+
+    QObject::connect(netJob, &NetJob::started, caller, [caller, netJob] { caller->setActiveJob(netJob); });
+    QObject::connect(netJob, &NetJob::failed, caller, &CallerType::searchRequestFailed);
+    QObject::connect(netJob, &NetJob::succeeded, caller, [caller, response] {
+        QJsonParseError parse_error;
+        QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
+        if (parse_error.error != QJsonParseError::NoError) {
+            qWarning() << "Error while parsing JSON response from " << caller->debugName() << " at " << parse_error.offset
+                       << " reason: " << parse_error.errorString();
+            qWarning() << *response;
+            return;
+        }
+
+        caller->searchRequestFinished(doc);
+    });
+
+    netJob->start();
+};
+
+void NetworkModAPI::getVersions(CallerType* caller, const QString& addonId) const
+{
+    auto netJob = new NetJob(QString("%1::ModVersions(%2)").arg(caller->debugName()).arg(addonId), APPLICATION->network());
+    auto response = new QByteArray();
+
+    netJob->addNetAction(Net::Download::makeByteArray(getVersionsURL(addonId), response));
+
+    QObject::connect(netJob, &NetJob::succeeded, caller, [response, caller, addonId] {
+        QJsonParseError parse_error;
+        QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
+        if (parse_error.error != QJsonParseError::NoError) {
+            qWarning() << "Error while parsing JSON response from " << caller->debugName() << " at " << parse_error.offset
+                       << " reason: " << parse_error.errorString();
+            qWarning() << *response;
+            return;
+        }
+
+        caller->versionRequestSucceeded(doc, addonId);
+    });
+
+    QObject::connect(netJob, &NetJob::finished, caller, [response, netJob] {
+        netJob->deleteLater();
+        delete response;
+    });
+
+    netJob->start();
+};
diff --git a/launcher/modplatform/helpers/NetworkModAPI.h b/launcher/modplatform/helpers/NetworkModAPI.h
new file mode 100644
index 00000000..65192046
--- /dev/null
+++ b/launcher/modplatform/helpers/NetworkModAPI.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "modplatform/ModAPI.h"
+
+class NetworkModAPI : public ModAPI {
+   public:
+    void searchMods(CallerType* caller, SearchArgs&& args) const override;
+    void getVersions(CallerType* caller, const QString& addonId) const override;
+
+   protected:
+    virtual QString getModSearchURL(SearchArgs& args) const = 0;
+    virtual QString getVersionsURL(const QString& addonId) const = 0;
+};
diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h
index 84cc561b..1cc51ff2 100644
--- a/launcher/modplatform/modrinth/ModrinthAPI.h
+++ b/launcher/modplatform/modrinth/ModrinthAPI.h
@@ -1,73 +1,15 @@
 #pragma once
 
-#include "modplatform/ModAPI.h"
-#include "ui/pages/modplatform/ModModel.h"
-
-#include "Application.h"
-#include "net/NetJob.h"
+#include "modplatform/helpers/NetworkModAPI.h"
 
 #include <QDebug>
 
-class ModrinthAPI : public ModAPI {
+class ModrinthAPI : public NetworkModAPI {
    public:
-    inline void searchMods(CallerType* caller, SearchArgs&& args) const override
-    {
-        auto netJob = new NetJob(QString("Modrinth::Search"), APPLICATION->network());
-        auto searchUrl = getModSearchURL(args);
-
-        auto response = new QByteArray();
-        netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
-
-        QObject::connect(netJob, &NetJob::started, caller, [caller, netJob]{ caller->setActiveJob(netJob); });
-        QObject::connect(netJob, &NetJob::failed, caller, &CallerType::searchRequestFailed);
-        QObject::connect(netJob, &NetJob::succeeded, caller, [caller, response] {
-            QJsonParseError parse_error;
-            QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
-            if (parse_error.error != QJsonParseError::NoError) {
-                qWarning() << "Error while parsing JSON response from Modrinth at " << parse_error.offset
-                           << " reason: " << parse_error.errorString();
-                qWarning() << *response;
-                return;
-            }
-
-            caller->searchRequestFinished(doc);
-        });
-
-        netJob->start();
-    };
-
-    inline void getVersions(CallerType* caller, const QString& addonId, const QString& debugName = "Modrinth") const override
-    {
-        auto netJob = new NetJob(QString("%1::ModVersions(%2)").arg(debugName).arg(addonId), APPLICATION->network());
-        auto response = new QByteArray();
-
-        netJob->addNetAction(Net::Download::makeByteArray(getVersionsURL(addonId), response));
-
-        QObject::connect(netJob, &NetJob::succeeded, caller, [response, debugName, caller, addonId] {
-            QJsonParseError parse_error;
-            QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
-            if (parse_error.error != QJsonParseError::NoError) {
-                qWarning() << "Error while parsing JSON response from " << debugName << " at " << parse_error.offset
-                           << " reason: " << parse_error.errorString();
-                qWarning() << *response;
-                return;
-            }
-
-            caller->versionRequestSucceeded(doc, addonId);
-        });
-
-        QObject::connect(netJob, &NetJob::finished, caller, [response, netJob] {
-            netJob->deleteLater();
-            delete response;
-        });
-
-        netJob->start();
-    };
-
     inline QString getAuthorURL(const QString& name) const { return "https://modrinth.com/user/" + name; };
 
    private:
-    inline QString getModSearchURL(SearchArgs& args) const
+    inline QString getModSearchURL(SearchArgs& args) const override
     {
         if (!validateModLoader(args.mod_loader)) {
             qWarning() << "Modrinth only have Forge and Fabric-compatible mods!";
@@ -88,13 +30,11 @@ class ModrinthAPI : public ModAPI {
             .arg(args.version);
     };
 
-    inline QString getVersionsURL(const QString& addonId) const
+    inline QString getVersionsURL(const QString& addonId) const override
     {
         return QString("https://api.modrinth.com/v2/project/%1/version").arg(addonId);
     };
 
-    inline bool validateModLoader(ModLoaderType modLoader) const { return modLoader == Any || modLoader == Forge || modLoader == Fabric; }
-
     inline QString getModLoaderString(ModLoaderType modLoader) const
     {
         switch (modLoader) {
@@ -108,4 +48,10 @@ class ModrinthAPI : public ModAPI {
                 return "";
         }
     }
+
+    inline bool validateModLoader(ModLoaderType modLoader) const
+    {
+        return modLoader == Any || modLoader == Forge || modLoader == Fabric;
+    }
+
 };
diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp
index 705f384e..015fcf7d 100644
--- a/launcher/ui/pages/modplatform/ModModel.cpp
+++ b/launcher/ui/pages/modplatform/ModModel.cpp
@@ -53,6 +53,11 @@ QVariant ListModel::data(const QModelIndex& index, int role) const
     return QVariant();
 }
 
+QString ListModel::debugName() const
+{
+    return m_parent->debugName();
+}
+
 void ListModel::logoLoaded(QString logo, QIcon out)
 {
     m_loadingLogos.removeAll(logo);
@@ -99,8 +104,9 @@ void ListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallbac
     }
 }
 
-void ListModel::requestModVersions(ModPlatform::IndexedPack const& current) {
-    m_parent->apiProvider()->getVersions(this, current.addonId.toString(), m_parent->debugName());
+void ListModel::requestModVersions(ModPlatform::IndexedPack const& current)
+{
+    m_parent->apiProvider()->getVersions(this, current.addonId.toString());
 }
 
 void ListModel::performPaginatedSearch()
diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h
index 28bf05bb..e971149c 100644
--- a/launcher/ui/pages/modplatform/ModModel.h
+++ b/launcher/ui/pages/modplatform/ModModel.h
@@ -1,6 +1,5 @@
 #pragma once
 
-#include <qjsondocument.h>
 #include <QAbstractListModel>
 
 #include "modplatform/ModAPI.h"
@@ -24,6 +23,9 @@ class ListModel : public QAbstractListModel {
     int rowCount(const QModelIndex& parent) const override;
     int columnCount(const QModelIndex& parent) const override;
 
+    QString debugName() const;
+
+    /* Retrieve information from the model at a given index with the given role */
     QVariant data(const QModelIndex& index, int role) const override;
     Qt::ItemFlags flags(const QModelIndex& index) const override;