summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSilarn <jrim@rimpo.org>2019-01-27 21:51:26 -0600
committerSilarn <jrim@rimpo.org>2019-02-18 21:28:06 -0600
commitb6498abaf39be52191dfaf4fcaa7bb91ece9edcf (patch)
tree4d8dd876c617982f25ec09793f84a1f56cd8f893 /src
parentfbbff08fb8774d8f6a22efe9532dc27ce7a1dae7 (diff)
Implement an API rate limiter
Diffstat (limited to 'src')
-rw-r--r--src/mainwindow.cpp8
-rw-r--r--src/mainwindow.h1
-rw-r--r--src/nexusinterface.cpp28
-rw-r--r--src/nexusinterface.h8
-rw-r--r--src/nxmaccessmanager.cpp3
5 files changed, 44 insertions, 4 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 9dbb8a86..e37ab150 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -396,6 +396,8 @@ MainWindow::MainWindow(QSettings &initSettings
connect(NexusInterface::instance(&pluginContainer)->getAccessManager(), SIGNAL(validateFailed(QString)), this, SLOT(validationFailed(QString)));
connect(NexusInterface::instance(&pluginContainer)->getAccessManager(), SIGNAL(credentialsReceived(const QString&, bool)),
this, SLOT(updateWindowTitle(const QString&, bool)));
+ connect(NexusInterface::instance(&pluginContainer)->getAccessManager(), SIGNAL(credentialsReceived(const QString&, bool)),
+ NexusInterface::instance(&m_PluginContainer), SLOT(setRateMax(const QString&, bool)));
connect(&TutorialManager::instance(), SIGNAL(windowTutorialFinished(QString)), this, SLOT(windowTutorialFinished(QString)));
connect(ui->tabWidget, SIGNAL(currentChanged(int)), &TutorialManager::instance(), SIGNAL(tabChanged(int)));
@@ -430,6 +432,11 @@ MainWindow::MainWindow(QSettings &initSettings
connect(&m_SaveMetaTimer, SIGNAL(timeout()), this, SLOT(saveModMetas()));
m_SaveMetaTimer.start(5000);
+ m_NexusLimitTimer.setTimerType(Qt::TimerType::PreciseTimer);
+ m_NexusLimitTimer.setSingleShot(false);
+ connect(&m_NexusLimitTimer, SIGNAL(timeout()), NexusInterface::instance(&m_PluginContainer), SLOT(calculateRequests()));
+ m_NexusLimitTimer.start(1000);
+
setCategoryListVisible(initSettings.value("categorylist_visible", true).toBool());
FileDialogMemory::restore(initSettings);
@@ -5526,6 +5533,7 @@ void MainWindow::nxmDescriptionAvailable(QString gameName, int modID, QVariant u
std::vector<ModInfo::Ptr> modsList = ModInfo::getByModID(gameName, modID);
for (auto mod : modsList) {
mod->setNexusDescription(result["description"].toString());
+ mod->setNewestVersion(result["version"].toString());
if ((mod->endorsedState() != ModInfo::ENDORSED_NEVER) && (result.contains("endorsement"))) {
QVariantMap endorsement = result["endorsement"].toMap();
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 077022db..bf475120 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -348,6 +348,7 @@ private:
QTimer m_CheckBSATimer;
QTimer m_SaveMetaTimer;
QTimer m_UpdateProblemsTimer;
+ QTimer m_NexusLimitTimer;
QFuture<void> m_MetaSave;
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp
index 19fc3af4..760af6a9 100644
--- a/src/nexusinterface.cpp
+++ b/src/nexusinterface.cpp
@@ -148,7 +148,7 @@ QAtomicInt NexusInterface::NXMRequestInfo::s_NextID(0);
NexusInterface::NexusInterface(PluginContainer *pluginContainer)
- : m_NMMVersion(), m_PluginContainer(pluginContainer)
+ : m_NMMVersion(), m_PluginContainer(pluginContainer), m_RemainingRequests(300), m_MaxRequests(300)
{
m_MOVersion = createVersionInfo();
@@ -190,6 +190,16 @@ void NexusInterface::loginCompleted()
nextRequest();
}
+void NexusInterface::setRateMax(const QString &userName, bool isPremium)
+{
+ if (isPremium) {
+ m_MaxRequests = 600;
+ m_RemainingRequests = 600;
+ } else {
+ m_MaxRequests = 300;
+ m_RemainingRequests = 300;
+ }
+}
void NexusInterface::interpretNexusFileName(const QString &fileName, QString &modName, int &modID, bool query)
{
@@ -459,6 +469,11 @@ void NexusInterface::nextRequest()
return;
}
+ if (m_RemainingRequests <= 0) {
+ qWarning() << tr("You've exceeded the Nexus API rate limit and requests are now being throttled.");
+ return;
+ }
+
if (requiresLogin(m_RequestQueue.head()) && !getAccessManager()->validated()) {
if (!getAccessManager()->validateAttempted()) {
emit needLogin();
@@ -468,6 +483,8 @@ void NexusInterface::nextRequest()
}
}
+ m_RemainingRequests--;
+
NXMRequestInfo info = m_RequestQueue.dequeue();
info.m_Timeout = new QTimer(this);
info.m_Timeout->setInterval(60000);
@@ -634,6 +651,12 @@ void NexusInterface::requestTimeout()
}
}
+void NexusInterface::calculateRequests()
+{
+ if (m_RemainingRequests < m_MaxRequests)
+ m_RemainingRequests++;
+}
+
namespace {
QString get_management_url(MOBase::IPluginGame const *game)
{
@@ -661,7 +684,8 @@ NexusInterface::NXMRequestInfo::NXMRequestInfo(int modID
, m_NexusGameID(game->nexusGameID())
, m_GameName(game->gameNexusName())
, m_Endorse(false)
-{}
+{
+}
NexusInterface::NXMRequestInfo::NXMRequestInfo(int modID
, QString modVersion
diff --git a/src/nexusinterface.h b/src/nexusinterface.h
index 56cdef47..022909ce 100644
--- a/src/nexusinterface.h
+++ b/src/nexusinterface.h
@@ -349,6 +349,11 @@ signals:
void nxmEndorsementToggled(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID);
void nxmRequestFailed(QString gameName, int modID, int fileID, QVariant userData, int requestID, QNetworkReply::NetworkError error, const QString &errorString);
+public slots:
+
+ void setRateMax(const QString &userName, bool isPremium);
+ void calculateRequests();
+
private slots:
void requestFinished();
@@ -418,6 +423,9 @@ private:
PluginContainer *m_PluginContainer;
+ int m_RemainingRequests;
+ int m_MaxRequests;
+
};
#endif // NEXUSINTERFACE_H
diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp
index 5da7b6a3..6847ba25 100644
--- a/src/nxmaccessmanager.cpp
+++ b/src/nxmaccessmanager.cpp
@@ -252,8 +252,7 @@ void NXMAccessManager::validateFinished()
QString test = jdoc.toJson();
QString name = credentialsData.value("name").toString();
bool premium = credentialsData.value("is_premium?").toBool();
- emit credentialsReceived(credentialsData.value("name").toString(),
- credentialsData.value("is_premium?").toBool());
+ emit credentialsReceived(name, premium);
m_ValidateReply->deleteLater();
m_ValidateReply = nullptr;