From f4429e8c4a659539baad56d177065e6a37e77d90 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Fri, 15 May 2020 22:53:21 +0200 Subject: [PATCH] Make Musicbrainz cover provider respect rate limiting --- src/covermanager/musicbrainzcoverprovider.cpp | 39 +++++++++++++++++-- src/covermanager/musicbrainzcoverprovider.h | 15 +++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/covermanager/musicbrainzcoverprovider.cpp b/src/covermanager/musicbrainzcoverprovider.cpp index cc501b725..887692688 100644 --- a/src/covermanager/musicbrainzcoverprovider.cpp +++ b/src/covermanager/musicbrainzcoverprovider.cpp @@ -23,11 +23,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -47,8 +49,15 @@ const char *MusicbrainzCoverProvider::kReleaseSearchUrl = "https://musicbrainz.org/ws/2/release/"; const char *MusicbrainzCoverProvider::kAlbumCoverUrl = "https://coverartarchive.org/release/%1/front"; const int MusicbrainzCoverProvider::kLimit = 8; +const int MusicbrainzCoverProvider::kRequestsDelay = 1000; -MusicbrainzCoverProvider::MusicbrainzCoverProvider(Application *app, QObject *parent): JsonCoverProvider("MusicBrainz", true, false, 1.5, true, false, app, parent), network_(new NetworkAccessManager(this)) {} +MusicbrainzCoverProvider::MusicbrainzCoverProvider(Application *app, QObject *parent): JsonCoverProvider("MusicBrainz", true, false, 1.5, true, false, app, parent), network_(new NetworkAccessManager(this)), timer_flush_requests_(new QTimer(this)) { + + timer_flush_requests_->setInterval(kRequestsDelay); + timer_flush_requests_->setSingleShot(false); + connect(timer_flush_requests_, SIGNAL(timeout()), this, SLOT(FlushRequests())); + +} MusicbrainzCoverProvider::~MusicbrainzCoverProvider() { @@ -65,7 +74,20 @@ bool MusicbrainzCoverProvider::StartSearch(const QString &artist, const QString Q_UNUSED(title); - QString query = QString("release:\"%1\" AND artist:\"%2\"").arg(album.trimmed().replace('"', "\\\"")).arg(artist.trimmed().replace('"', "\\\"")); + SearchRequest request(id, artist, album); + queue_search_requests_ << request; + + if (!timer_flush_requests_->isActive()) { + timer_flush_requests_->start(); + } + + return true; + +} + +void MusicbrainzCoverProvider::SendSearchRequest(const SearchRequest &request) { + + QString query = QString("release:\"%1\" AND artist:\"%2\"").arg(request.album.trimmed().replace('"', "\\\"")).arg(request.artist.trimmed().replace('"', "\\\"")); QUrlQuery url_query; url_query.addQueryItem("query", query); @@ -78,9 +100,18 @@ bool MusicbrainzCoverProvider::StartSearch(const QString &artist, const QString req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = network_->get(req); replies_ << reply; - connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id); }); + connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, request.id); }); - return true; +} + +void MusicbrainzCoverProvider::FlushRequests() { + + if (!queue_search_requests_.isEmpty()) { + SendSearchRequest(queue_search_requests_.dequeue()); + return; + } + + timer_flush_requests_->stop(); } diff --git a/src/covermanager/musicbrainzcoverprovider.h b/src/covermanager/musicbrainzcoverprovider.h index 1bf8fb3f5..2aceb8c53 100644 --- a/src/covermanager/musicbrainzcoverprovider.h +++ b/src/covermanager/musicbrainzcoverprovider.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -33,10 +34,12 @@ class QNetworkAccessManager; class QNetworkReply; +class QTimer; class Application; class MusicbrainzCoverProvider : public JsonCoverProvider { Q_OBJECT + public: explicit MusicbrainzCoverProvider(Application *app, QObject *parent = nullptr); ~MusicbrainzCoverProvider(); @@ -44,9 +47,18 @@ class MusicbrainzCoverProvider : public JsonCoverProvider { bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id); private slots: + void FlushRequests(); void HandleSearchReply(QNetworkReply *reply, const int search_id); private: + struct SearchRequest { + explicit SearchRequest(const int _id, const QString &_artist, const QString &_album) : id(_id), artist(_artist), album(_album) {} + int id; + QString artist; + QString album; + }; + + void SendSearchRequest(const SearchRequest &request); QByteArray GetReplyData(QNetworkReply *reply); void Error(const QString &error, const QVariant &debug = QVariant()); @@ -54,8 +66,11 @@ class MusicbrainzCoverProvider : public JsonCoverProvider { static const char *kReleaseSearchUrl; static const char *kAlbumCoverUrl; static const int kLimit; + static const int kRequestsDelay; QNetworkAccessManager *network_; + QTimer *timer_flush_requests_; + QQueue queue_search_requests_; QList replies_; };