223 lines
9.3 KiB
C++
223 lines
9.3 KiB
C++
#include "./groovesharksearcher.h"
|
|
|
|
#include "../groovesharkdownload.h"
|
|
|
|
#include <c++utilities/conversion/binaryconversion.h>
|
|
|
|
#include <QJsonArray>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QJsonValue>
|
|
|
|
using namespace CppUtilities;
|
|
|
|
namespace Network {
|
|
|
|
/*!
|
|
* \class GroovesharkSearcher
|
|
* \brief The GroovesharkSearcher class searches for albums or playlists on Grooveshark.
|
|
*/
|
|
|
|
/*!
|
|
* \brief Constructs a new grooveshark searcher with the specified \a searchTerm and \a searchType.
|
|
* \param searchTerm Specifies the search term.
|
|
* \param searchTermRole Specifies the role of the search term.
|
|
* \param verified Indicates whether the search should be limited to verified songs.
|
|
* \param parent Specifies the parent object.
|
|
*/
|
|
GroovesharkSearcher::GroovesharkSearcher(const QString &searchTerm, GroovesharkSearchTermRole searchTermRole, bool verified, QObject *parent)
|
|
: DownloadFinder(parent)
|
|
, m_searchTerm(searchTerm)
|
|
, m_searchType(searchTermRole)
|
|
, m_currentId(0)
|
|
, m_verified(verified)
|
|
{
|
|
switch (searchTermRole) {
|
|
case GroovesharkSearchTermRole::AlbumId:
|
|
case GroovesharkSearchTermRole::PlaylistId:
|
|
m_ids << searchTerm;
|
|
break;
|
|
case GroovesharkSearchTermRole::AlbumName:
|
|
reportCollectionTitle(searchTerm);
|
|
break;
|
|
case GroovesharkSearchTermRole::PlaylistName:
|
|
reportCollectionTitle(searchTerm);
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
|
|
Download *GroovesharkSearcher::createRequest(QString &reasonForFail)
|
|
{
|
|
Download *res = nullptr;
|
|
switch (m_searchType) {
|
|
case GroovesharkSearchTermRole::AlbumId:
|
|
case GroovesharkSearchTermRole::AlbumName:
|
|
if (!m_ids.isEmpty()) {
|
|
if (m_currentId >= m_ids.size()) {
|
|
reasonForFail = tr("Given id index is out of range.");
|
|
} else {
|
|
GroovesharkGetSongsRequestData requestData;
|
|
requestData.id = m_ids.at(m_currentId);
|
|
requestData.verified = m_verified;
|
|
res = new GroovesharkDownload(GroovesharkRequestType::AlbumGetSongs, QVariant::fromValue(requestData));
|
|
}
|
|
} else if (!m_searchTerm.isEmpty()) {
|
|
res = new GroovesharkDownload(GroovesharkRequestType::SearchForAlbum, QVariant::fromValue(m_searchTerm));
|
|
}
|
|
break;
|
|
case GroovesharkSearchTermRole::PlaylistId:
|
|
case GroovesharkSearchTermRole::PlaylistName:
|
|
if (!m_ids.isEmpty()) {
|
|
if (m_currentId >= m_ids.size()) {
|
|
reasonForFail = tr("Given id index is out of range.");
|
|
} else {
|
|
res = new GroovesharkDownload(GroovesharkRequestType::PlaylistGetSongs, QVariant::fromValue(m_ids.at(m_currentId)));
|
|
}
|
|
} else if (!m_searchTerm.isEmpty()) {
|
|
res = new GroovesharkDownload(GroovesharkRequestType::SearchForPlaylist, QVariant::fromValue(m_searchTerm));
|
|
}
|
|
break;
|
|
default:
|
|
reasonForFail = tr("Given search type isn't supported.");
|
|
}
|
|
return res;
|
|
}
|
|
|
|
DownloadFinder::ParsingResult GroovesharkSearcher::parseResults(const QByteArray &data, QString &reasonForFail)
|
|
{
|
|
QJsonParseError error;
|
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
|
if (!jsonDoc.isObject()) {
|
|
reasonForFail = tr("The response of Grooveshark is no valid Json object (%1).").arg(error.errorString());
|
|
return (++m_currentId) < m_ids.size() ? ParsingResult::AnotherRequestRequired : ParsingResult::Error;
|
|
}
|
|
QJsonObject mainObj = jsonDoc.object();
|
|
QJsonValue resVal = mainObj.value(QStringLiteral("result"));
|
|
if (!resVal.isObject() && !resVal.isArray()) {
|
|
reasonForFail = tr("No results found (no results array/object found).");
|
|
return (++m_currentId) < m_ids.size() ? ParsingResult::AnotherRequestRequired : ParsingResult::Error;
|
|
}
|
|
if (m_ids.isEmpty()) { // read albums/playlists
|
|
if (resVal.isObject()) {
|
|
QJsonValue subResVal = resVal.toObject().value("result");
|
|
if (subResVal.isObject()) {
|
|
resVal = subResVal;
|
|
}
|
|
}
|
|
QJsonValue collectionsVal;
|
|
QString collectionObjName;
|
|
QString idValName;
|
|
switch (m_searchType) {
|
|
case GroovesharkSearchTermRole::AlbumId:
|
|
case GroovesharkSearchTermRole::AlbumName:
|
|
collectionObjName = QStringLiteral("Albums");
|
|
idValName = QStringLiteral("AlbumID");
|
|
break;
|
|
case GroovesharkSearchTermRole::PlaylistId:
|
|
case GroovesharkSearchTermRole::PlaylistName:
|
|
collectionObjName = QStringLiteral("Playlists");
|
|
idValName = QStringLiteral("PlaylistID");
|
|
break;
|
|
default:
|
|
reasonForFail = tr("The response can't be parsed because the given search type isn't supported.");
|
|
return ParsingResult::Error;
|
|
}
|
|
collectionsVal = resVal.isObject() ? resVal.toObject().value(collectionObjName) : resVal.toArray();
|
|
if (!collectionsVal.isArray()) {
|
|
reasonForFail = tr("No collections found (relevant json value is no array).");
|
|
return ParsingResult::Error;
|
|
}
|
|
QJsonArray collectionArray = collectionsVal.toArray();
|
|
QJsonObject itemObj;
|
|
QJsonValue idVal;
|
|
QJsonValue verifiedVal;
|
|
for (const QJsonValue &itemVal : collectionArray) {
|
|
if (itemVal.isObject()) {
|
|
itemObj = itemVal.toObject();
|
|
if (m_verified) { // skip unverified items if verified option used
|
|
verifiedVal = itemObj.value(QStringLiteral("IsVerified"));
|
|
if (verifiedVal.isString() && verifiedVal.toString() == "0")
|
|
continue;
|
|
}
|
|
idVal = itemObj.value(idValName);
|
|
if (idVal.isString()) {
|
|
m_ids << idVal.toString();
|
|
}
|
|
}
|
|
}
|
|
m_currentId = 0;
|
|
if (!m_ids.isEmpty()) {
|
|
return ParsingResult::AnotherRequestRequired;
|
|
}
|
|
reasonForFail = tr("No collections found (relevant json array contains no parsable items).");
|
|
return ParsingResult::Error;
|
|
} else { // read songs
|
|
QJsonValue songsVal;
|
|
if (resVal.isObject()) {
|
|
switch (m_searchType) {
|
|
case GroovesharkSearchTermRole::AlbumId:
|
|
case GroovesharkSearchTermRole::AlbumName:
|
|
songsVal = resVal.toObject().value(QStringLiteral("songs"));
|
|
break;
|
|
case GroovesharkSearchTermRole::PlaylistId:
|
|
case GroovesharkSearchTermRole::PlaylistName:
|
|
songsVal = resVal.toObject().value(QStringLiteral("Songs"));
|
|
break;
|
|
default:
|
|
reasonForFail = tr("The response can't be parsed because the given search type isn't supported.");
|
|
return (++m_currentId) < m_ids.size() ? ParsingResult::AnotherRequestRequired : ParsingResult::Error;
|
|
}
|
|
} else {
|
|
songsVal = resVal;
|
|
}
|
|
if (!songsVal.isArray()) {
|
|
reasonForFail = tr("No songs found (no songs object found).");
|
|
return (++m_currentId) < m_ids.size() ? ParsingResult::AnotherRequestRequired : ParsingResult::Error;
|
|
}
|
|
GroovesharkDownload *res = nullptr;
|
|
QJsonArray songsArray = songsVal.toArray();
|
|
QJsonObject songObj;
|
|
QJsonValue albumNameVal;
|
|
QJsonValue artistNameVal;
|
|
QJsonValue idVal;
|
|
QJsonValue titleVal;
|
|
QJsonValue durationVal;
|
|
QJsonValue trackNumVal;
|
|
for (const QJsonValue songVal : songsArray) {
|
|
if (songVal.isObject()) {
|
|
songObj = songVal.toObject();
|
|
idVal = songObj.value(QStringLiteral("SongID"));
|
|
if (idVal.isString()) {
|
|
titleVal = songObj.value(QStringLiteral("Name"));
|
|
if (titleVal.isString()) {
|
|
durationVal = songObj.value(QStringLiteral("EstimateDuration"));
|
|
trackNumVal = songObj.value(QStringLiteral("TrackNum"));
|
|
albumNameVal = songObj.value(QStringLiteral("AlbumName"));
|
|
artistNameVal = songObj.value(QStringLiteral("ArtistName"));
|
|
res = new GroovesharkDownload(idVal.toString());
|
|
res->provideMetaData(titleVal.toString(), artistNameVal.toString(),
|
|
durationVal.isString() ? TimeSpan::fromString(durationVal.toString().toStdString()) : TimeSpan(), albumNameVal.toString(),
|
|
trackNumVal.isString() ? trackNumVal.toString().toInt() : 0);
|
|
reportResult(res);
|
|
}
|
|
if ((collectionTitle().isEmpty() || collectionTitle().compare(tr("Unknown Album"), Qt::CaseInsensitive) == 0)
|
|
&& albumNameVal.isString()) {
|
|
reportCollectionTitle(albumNameVal.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((++m_currentId) < m_ids.size()) {
|
|
return ParsingResult::AnotherRequestRequired;
|
|
} else {
|
|
if (!results().isEmpty()) {
|
|
return ParsingResult::Success;
|
|
}
|
|
}
|
|
reasonForFail = tr("No songs found (relevant json array contains no parsable items).");
|
|
return ParsingResult::Error;
|
|
}
|
|
}
|
|
} // namespace Network
|