/* * Cantata * * Copyright (c) 2011-2017 Craig Drummond * * ---- * * 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 "config.h" #include #include #include #include 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; } urlQuery.addQueryItem("api_key", Covers::constLastFmApiKey); 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; foreach (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", "
"); text=text.simplified(); text.replace("
", "
"); // Remove last.fm read more link (as we add our own!!) int end=text.lastIndexOf(QLatin1String("on Last.fm")); if (-1!=end) { int start=text.lastIndexOf(QLatin1String("
")+constLinkPlaceholder+QLatin1String(""); text.replace("




", "

"); text.replace("



", "

"); text.replace("


", "

"); } 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(); }