Files
cantata/context/lastfmengine.cpp
Craig Drummond b6bd94c236 Update (c) year
2022-01-08 21:24:07 +00:00

190 lines
5.9 KiB
C++

/*
* Cantata
*
* Copyright (c) 2011-2022 Craig Drummond <craig.p.drummond@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; either version 2 of the License, or
* (at your option) any later version.
*
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "lastfmengine.h"
#include "network/networkaccessmanager.h"
#include "gui/covers.h"
#include "gui/apikeys.h"
#include "config.h"
#include <QUrlQuery>
#include <QXmlStreamReader>
#include <QRegExp>
#include <QDebug>
static bool debugEnabled=false;
#define DBUG if (debugEnabled) qWarning() << metaObject()->className() << __FUNCTION__
void LastFmEngine::enableDebug()
{
debugEnabled=true;
}
const QLatin1String LastFmEngine::constLang("lastfm");
const QLatin1String LastFmEngine::constLinkPlaceholder("XXX_CONTEXT_READ_MORE_ON_LASTFM_XXX");
static const char * constModeProperty="mode";
static const char * constQuery="query";
LastFmEngine::LastFmEngine(QObject *p)
: ContextEngine(p)
{
}
QStringList LastFmEngine::getLangs() const
{
QStringList langs;
langs.append(constLang);
return langs;
}
QString LastFmEngine::translateLinks(QString text) const
{
text=text.replace(constLinkPlaceholder, tr("Read more on last.fm"));
return text;
}
void LastFmEngine::search(const QStringList &query, Mode mode)
{
QStringList fixedQuery=fixQuery(query);
QUrl url("https://ws.audioscrobbler.com/2.0/");
QUrlQuery urlQuery;
switch (mode) {
case Artist:
urlQuery.addQueryItem("method", "artist.getInfo");
break;
case Album:
urlQuery.addQueryItem("method", "album.getInfo");
urlQuery.addQueryItem("album", fixedQuery.at(1));
break;
case Track:
urlQuery.addQueryItem("method", "track.getInfo");
urlQuery.addQueryItem("track", fixedQuery.at(1));
break;
}
ApiKeys::self()->addKey(urlQuery, ApiKeys::LastFm);
urlQuery.addQueryItem("autocorrect", "1");
urlQuery.addQueryItem("artist", Covers::fixArtist(fixedQuery.at(0)));
url.setQuery(urlQuery);
job=NetworkAccessManager::self()->get(url);
job->setProperty(constModeProperty, (int)mode);
QStringList queryString;
for (QString q: fixedQuery) {
q=q.replace("/", "%2F");
q=q.replace(" ", "+");
queryString.append(q);
}
job->setProperty(constQuery, queryString.join("/"));
DBUG << url.toString();
connect(job, SIGNAL(finished()), this, SLOT(parseResponse()));
}
void LastFmEngine::parseResponse()
{
DBUG << __FUNCTION__;
NetworkJob *reply = getReply(sender());
if (!reply) {
return;
}
QByteArray data=reply->readAll();
if (!reply->ok() || data.isEmpty()) {
DBUG << "Empty/error";
emit searchResult(QString(), QString());
return;
}
Mode mode=(Mode)reply->property(constModeProperty).toInt();
QString text;
switch (mode) {
case Artist:
text=parseResponse(data, QLatin1String("artist"), QLatin1String("bio"));
break;
case Album:
text=parseResponse(data, QLatin1String("album"), QLatin1String("wiki"));
break;
case Track:
text=parseResponse(data, QLatin1String("track"), QLatin1String("wiki"));
break;
}
if (!text.isEmpty()) {
static const QRegExp constLicense("User-contributed text is available.*");
text.remove(constLicense);
text.replace("\n", "<br>");
text=text.simplified();
text.replace(" <br>", "<br>");
// Remove last.fm read more link (as we add our own!!)
int end=text.lastIndexOf(QLatin1String("on Last.fm</a>"));
if (-1!=end) {
int start=text.lastIndexOf(QLatin1String("<a href=\"https://www.last.fm/music/"), end);
if (-1==start) {
start=text.lastIndexOf(QLatin1String("<a href=\"http://www.last.fm/music/"), end);
}
if (-1!=start) {
if (text.indexOf(QLatin1String("Read more about"), start)<end) {
text=text.left(start);
}
}
}
text += QLatin1String("<br><br><a href='http://www.last.fm/music/")+reply->property(constQuery).toString()+QLatin1String("/+wiki'>")+constLinkPlaceholder+QLatin1String("</a>");
text.replace("<br><br><br><br><br>", "<br><br>");
text.replace("<br><br><br><br>", "<br><br>");
text.replace("<br><br><br>", "<br><br>");
}
emit searchResult(text, text.isEmpty() ? QString() : constLang);
}
QString LastFmEngine::parseResponse(const QByteArray &data, const QString &firstTag, const QString &secondTag)
{
DBUG << __FUNCTION__ << data;
QXmlStreamReader xml(data);
xml.setNamespaceProcessing(false);
while (xml.readNextStartElement()) {
if (firstTag==xml.name()) {
while (xml.readNextStartElement()) {
if (secondTag==xml.name()) {
while (xml.readNextStartElement()) {
if (QLatin1String("content")==xml.name()) {
return xml.readElementText().trimmed();
} else {
xml.skipCurrentElement();
}
}
} else {
xml.skipCurrentElement();
}
}
}
}
return QString();
}
#include "moc_lastfmengine.cpp"