2020-05-08 18:35:36 +02:00
/*
* Strawberry Music Player
2022-10-17 20:29:44 +02:00
* Copyright 2020 - 2022 , Jonas Kvinge < jonas @ jkvinge . net >
2020-05-08 18:35:36 +02:00
*
* Strawberry 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 3 of the License , or
* ( at your option ) any later version .
*
* Strawberry 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 Strawberry . If not , see < http : //www.gnu.org/licenses/>.
*
*/
# include "config.h"
2022-10-17 20:29:44 +02:00
# include <memory>
2020-05-08 18:35:36 +02:00
# include <QObject>
# include <QByteArray>
# include <QVariant>
# include <QString>
# include <QUrl>
# include <QUrlQuery>
2020-07-18 04:14:51 +02:00
# include <QRegularExpression>
2020-05-08 18:35:36 +02:00
# include <QNetworkRequest>
# include <QNetworkReply>
# include <QJsonObject>
2022-10-17 20:29:44 +02:00
# include <QJsonArray>
2020-05-08 18:35:36 +02:00
# include "core/logging.h"
2023-07-21 05:55:24 +02:00
# include "core/shared_ptr.h"
2021-01-11 16:48:46 +01:00
# include "core/networkaccessmanager.h"
2022-12-28 03:12:00 +01:00
# include "utilities/strutils.h"
2020-05-08 18:35:36 +02:00
# include "jsonlyricsprovider.h"
2023-03-06 21:42:59 +01:00
# include "lyricssearchrequest.h"
# include "lyricssearchresult.h"
2020-05-08 18:35:36 +02:00
# include "musixmatchlyricsprovider.h"
2022-10-18 22:49:15 +02:00
# include "providers/musixmatchprovider.h"
2022-10-17 20:29:44 +02:00
2023-07-21 05:55:24 +02:00
using std : : make_shared ;
2024-04-09 23:20:26 +02:00
MusixmatchLyricsProvider : : MusixmatchLyricsProvider ( SharedPtr < NetworkAccessManager > network , QObject * parent ) : JsonLyricsProvider ( QStringLiteral ( " Musixmatch " ) , true , false , network , parent ) , use_api_ ( true ) { }
2020-05-08 18:35:36 +02:00
2020-05-12 21:28:42 +02:00
MusixmatchLyricsProvider : : ~ MusixmatchLyricsProvider ( ) {
while ( ! replies_ . isEmpty ( ) ) {
QNetworkReply * reply = replies_ . takeFirst ( ) ;
2021-01-26 16:48:04 +01:00
QObject : : disconnect ( reply , nullptr , this , nullptr ) ;
2020-05-12 21:28:42 +02:00
reply - > abort ( ) ;
reply - > deleteLater ( ) ;
}
}
2023-03-06 21:42:59 +01:00
bool MusixmatchLyricsProvider : : StartSearch ( const int id , const LyricsSearchRequest & request ) {
2020-05-08 18:35:36 +02:00
2023-07-21 05:55:24 +02:00
LyricsSearchContextPtr search = make_shared < LyricsSearchContext > ( ) ;
2022-10-17 20:29:44 +02:00
search - > id = id ;
2023-03-06 21:42:59 +01:00
search - > request = request ;
2022-10-17 20:29:44 +02:00
requests_search_ . append ( search ) ;
2023-03-06 21:42:59 +01:00
if ( use_api_ ) {
return SendSearchRequest ( search ) ;
2022-10-17 20:29:44 +02:00
}
else {
2023-03-06 21:42:59 +01:00
return CreateLyricsRequest ( search ) ;
2022-10-17 20:29:44 +02:00
}
}
2020-05-08 18:35:36 +02:00
2022-10-17 20:29:44 +02:00
void MusixmatchLyricsProvider : : CancelSearch ( const int id ) { Q_UNUSED ( id ) ; }
2021-07-13 23:18:12 +02:00
2022-10-17 20:29:44 +02:00
bool MusixmatchLyricsProvider : : SendSearchRequest ( LyricsSearchContextPtr search ) {
2020-05-08 18:35:36 +02:00
2022-10-17 20:29:44 +02:00
QUrlQuery url_query ;
2024-04-11 02:56:01 +02:00
url_query . addQueryItem ( QStringLiteral ( " apikey " ) , QString : : fromLatin1 ( QByteArray : : fromBase64 ( kApiKey ) ) ) ;
url_query . addQueryItem ( QStringLiteral ( " q_artist " ) , QString : : fromLatin1 ( QUrl : : toPercentEncoding ( search - > request . artist ) ) ) ;
url_query . addQueryItem ( QStringLiteral ( " q_track " ) , QString : : fromLatin1 ( QUrl : : toPercentEncoding ( search - > request . title ) ) ) ;
2024-04-09 23:20:26 +02:00
url_query . addQueryItem ( QStringLiteral ( " f_has_lyrics " ) , QStringLiteral ( " 1 " ) ) ;
2022-10-17 20:29:44 +02:00
2024-04-11 02:56:01 +02:00
QUrl url ( QString : : fromLatin1 ( kApiUrl ) + QStringLiteral ( " /track.search " ) ) ;
2022-10-17 20:29:44 +02:00
url . setQuery ( url_query ) ;
2020-05-08 18:35:36 +02:00
QNetworkRequest req ( url ) ;
2020-08-14 20:20:41 +02:00
req . setAttribute ( QNetworkRequest : : RedirectPolicyAttribute , QNetworkRequest : : NoLessSafeRedirectPolicy ) ;
2020-05-08 18:35:36 +02:00
QNetworkReply * reply = network_ - > get ( req ) ;
2020-05-12 21:28:42 +02:00
replies_ < < reply ;
2022-10-17 20:29:44 +02:00
QObject : : connect ( reply , & QNetworkReply : : finished , this , [ this , reply , search ] ( ) { HandleSearchReply ( reply , search ) ; } ) ;
2020-05-08 18:35:36 +02:00
2022-10-17 20:29:44 +02:00
qLog ( Debug ) < < " MusixmatchLyrics: Sending request for " < < url ;
2020-05-08 18:35:36 +02:00
return true ;
}
2022-10-17 20:29:44 +02:00
void MusixmatchLyricsProvider : : HandleSearchReply ( QNetworkReply * reply , LyricsSearchContextPtr search ) {
if ( ! replies_ . contains ( reply ) ) return ;
replies_ . removeAll ( reply ) ;
QObject : : disconnect ( reply , nullptr , this , nullptr ) ;
reply - > deleteLater ( ) ;
if ( reply - > error ( ) ! = QNetworkReply : : NoError ) {
2023-03-06 21:42:59 +01:00
if ( reply - > error ( ) = = 401 | | reply - > error ( ) = = 402 ) {
2024-04-09 23:20:26 +02:00
Error ( QStringLiteral ( " Error %1 (%2) using API, switching to URL based lookup. " ) . arg ( reply - > errorString ( ) ) . arg ( reply - > error ( ) ) ) ;
2023-03-06 21:42:59 +01:00
use_api_ = false ;
2022-10-17 20:29:44 +02:00
CreateLyricsRequest ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
Error ( QStringLiteral ( " %1 (%2) " ) . arg ( reply - > errorString ( ) ) . arg ( reply - > error ( ) ) ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search ) ;
return ;
}
if ( reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) . toInt ( ) ! = 200 ) {
2023-03-06 21:42:59 +01:00
if ( reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) . toInt ( ) = = 401 | | reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) . toInt ( ) = = 402 ) {
2024-04-09 23:20:26 +02:00
Error ( QStringLiteral ( " Received HTTP code %1 using API, switching to URL based lookup. " ) . arg ( reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) . toInt ( ) ) ) ;
2023-03-06 21:42:59 +01:00
use_api_ = false ;
2022-10-17 20:29:44 +02:00
CreateLyricsRequest ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
Error ( QStringLiteral ( " Received HTTP code %1 " ) . arg ( reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) . toInt ( ) ) ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search ) ;
return ;
}
QByteArray data = reply - > readAll ( ) ;
QJsonObject json_obj = ExtractJsonObj ( data ) ;
if ( json_obj . isEmpty ( ) ) {
EndSearch ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
if ( ! json_obj . contains ( QStringLiteral ( " message " ) ) ) {
Error ( QStringLiteral ( " Json reply is missing message object. " ) , json_obj ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
if ( ! json_obj [ QStringLiteral ( " message " ) ] . isObject ( ) ) {
Error ( QStringLiteral ( " Json reply message is not an object. " ) , json_obj ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
QJsonObject obj_message = json_obj [ QStringLiteral ( " message " ) ] . toObject ( ) ;
2022-10-17 20:29:44 +02:00
2024-04-09 23:20:26 +02:00
if ( ! obj_message . contains ( QStringLiteral ( " header " ) ) ) {
Error ( QStringLiteral ( " Json reply message object is missing header. " ) , obj_message ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
if ( ! obj_message [ QStringLiteral ( " header " ) ] . isObject ( ) ) {
Error ( QStringLiteral ( " Json reply message header is not an object. " ) , obj_message ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
QJsonObject obj_header = obj_message [ QStringLiteral ( " header " ) ] . toObject ( ) ;
2022-10-17 20:29:44 +02:00
2024-04-09 23:20:26 +02:00
int status_code = obj_header [ QStringLiteral ( " status_code " ) ] . toInt ( ) ;
2022-10-17 20:29:44 +02:00
if ( status_code ! = 200 ) {
2024-04-09 23:20:26 +02:00
Error ( QStringLiteral ( " Received status code %1, switching to URL based lookup. " ) . arg ( status_code ) ) ;
2023-03-06 21:42:59 +01:00
use_api_ = false ;
CreateLyricsRequest ( search ) ;
2022-10-17 20:29:44 +02:00
return ;
}
2024-04-09 23:20:26 +02:00
if ( ! obj_message . contains ( QStringLiteral ( " body " ) ) ) {
Error ( QStringLiteral ( " Json reply is missing body. " ) , json_obj ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
if ( ! obj_message [ QStringLiteral ( " body " ) ] . isObject ( ) ) {
Error ( QStringLiteral ( " Json body is not an object. " ) , json_obj ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
QJsonObject obj_body = obj_message [ QStringLiteral ( " body " ) ] . toObject ( ) ;
2022-10-17 20:29:44 +02:00
2024-04-09 23:20:26 +02:00
if ( ! obj_body . contains ( QStringLiteral ( " track_list " ) ) ) {
Error ( QStringLiteral ( " Json response is missing body. " ) , obj_body ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
if ( ! obj_body [ QStringLiteral ( " track_list " ) ] . isArray ( ) ) {
Error ( QStringLiteral ( " Json hits is not an array. " ) , obj_body ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search ) ;
return ;
}
2024-04-09 23:20:26 +02:00
QJsonArray array_tracklist = obj_body [ QStringLiteral ( " track_list " ) ] . toArray ( ) ;
2022-10-17 20:29:44 +02:00
for ( const QJsonValueRef value_track : array_tracklist ) {
if ( ! value_track . isObject ( ) ) {
continue ;
}
QJsonObject obj_track = value_track . toObject ( ) ;
2024-04-09 23:20:26 +02:00
if ( ! obj_track . contains ( QStringLiteral ( " track " ) ) | | ! obj_track [ QStringLiteral ( " track " ) ] . isObject ( ) ) {
2022-10-17 20:29:44 +02:00
continue ;
}
2024-04-09 23:20:26 +02:00
obj_track = obj_track [ QStringLiteral ( " track " ) ] . toObject ( ) ;
if ( ! obj_track . contains ( QStringLiteral ( " artist_name " ) ) | |
! obj_track . contains ( QStringLiteral ( " album_name " ) ) | |
! obj_track . contains ( QStringLiteral ( " track_name " ) ) | |
! obj_track . contains ( QStringLiteral ( " track_share_url " ) ) ) {
Error ( QStringLiteral ( " Missing one or more values in result object " ) , obj_track ) ;
2022-10-17 20:29:44 +02:00
continue ;
}
2024-04-09 23:20:26 +02:00
QString artist_name = obj_track [ QStringLiteral ( " artist_name " ) ] . toString ( ) ;
QString album_name = obj_track [ QStringLiteral ( " album_name " ) ] . toString ( ) ;
QString track_name = obj_track [ QStringLiteral ( " track_name " ) ] . toString ( ) ;
QUrl track_share_url ( obj_track [ QStringLiteral ( " track_share_url " ) ] . toString ( ) ) ;
2022-10-17 20:29:44 +02:00
// Ignore results where both the artist, album and title don't match.
2023-03-06 21:42:59 +01:00
if ( use_api_ & &
artist_name . compare ( search - > request . albumartist , Qt : : CaseInsensitive ) ! = 0 & &
artist_name . compare ( search - > request . artist , Qt : : CaseInsensitive ) ! = 0 & &
album_name . compare ( search - > request . album , Qt : : CaseInsensitive ) ! = 0 & &
track_name . compare ( search - > request . title , Qt : : CaseInsensitive ) ! = 0 ) {
2022-10-17 20:29:44 +02:00
continue ;
}
if ( ! track_share_url . isValid ( ) ) continue ;
if ( search - > requests_lyrics_ . contains ( track_share_url ) ) continue ;
search - > requests_lyrics_ . append ( track_share_url ) ;
}
if ( search - > requests_lyrics_ . isEmpty ( ) ) {
EndSearch ( search ) ;
}
else {
for ( const QUrl & url : search - > requests_lyrics_ ) {
SendLyricsRequest ( search , url ) ;
}
}
}
bool MusixmatchLyricsProvider : : CreateLyricsRequest ( LyricsSearchContextPtr search ) {
2023-03-06 21:42:59 +01:00
QString artist_stripped = StringFixup ( search - > request . artist ) ;
QString title_stripped = StringFixup ( search - > request . title ) ;
2022-10-17 20:29:44 +02:00
if ( artist_stripped . isEmpty ( ) | | title_stripped . isEmpty ( ) ) {
EndSearch ( search ) ;
return false ;
}
2024-04-09 23:20:26 +02:00
QUrl url ( QStringLiteral ( " https://www.musixmatch.com/lyrics/%1/%2 " ) . arg ( artist_stripped , title_stripped ) ) ;
2022-10-17 20:29:44 +02:00
search - > requests_lyrics_ . append ( url ) ;
return SendLyricsRequest ( search , url ) ;
}
bool MusixmatchLyricsProvider : : SendLyricsRequest ( LyricsSearchContextPtr search , const QUrl & url ) {
QNetworkRequest req ( url ) ;
req . setAttribute ( QNetworkRequest : : RedirectPolicyAttribute , QNetworkRequest : : NoLessSafeRedirectPolicy ) ;
QNetworkReply * reply = network_ - > get ( req ) ;
replies_ < < reply ;
QObject : : connect ( reply , & QNetworkReply : : finished , this , [ this , reply , search , url ] ( ) { HandleLyricsReply ( reply , search , url ) ; } ) ;
qLog ( Debug ) < < " MusixmatchLyrics: Sending request for " < < url ;
return true ;
}
void MusixmatchLyricsProvider : : HandleLyricsReply ( QNetworkReply * reply , LyricsSearchContextPtr search , const QUrl & url ) {
2020-05-08 18:35:36 +02:00
2020-05-12 21:28:42 +02:00
if ( ! replies_ . contains ( reply ) ) return ;
replies_ . removeAll ( reply ) ;
2021-01-26 16:48:04 +01:00
QObject : : disconnect ( reply , nullptr , this , nullptr ) ;
2020-05-08 18:35:36 +02:00
reply - > deleteLater ( ) ;
if ( reply - > error ( ) ! = QNetworkReply : : NoError ) {
2024-04-09 23:20:26 +02:00
Error ( QStringLiteral ( " %1 (%2) " ) . arg ( reply - > errorString ( ) ) . arg ( reply - > error ( ) ) ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-10 12:48:48 +02:00
return ;
2020-05-08 18:35:36 +02:00
}
else if ( reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) . toInt ( ) ! = 200 ) {
2024-04-09 23:20:26 +02:00
Error ( QStringLiteral ( " Received HTTP code %1 " ) . arg ( reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) . toInt ( ) ) ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-08 18:35:36 +02:00
return ;
}
2024-04-11 02:56:01 +02:00
const QByteArray data = reply - > readAll ( ) ;
2020-05-08 18:35:36 +02:00
if ( data . isEmpty ( ) ) {
2024-04-09 23:20:26 +02:00
Error ( QStringLiteral ( " Empty reply received from server. " ) ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-08 18:35:36 +02:00
return ;
}
2024-04-11 02:56:01 +02:00
const QString content = QString : : fromUtf8 ( data ) ;
const QString data_begin = QStringLiteral ( " <script id= \" __NEXT_DATA__ \" type= \" application/json \" > " ) ;
const QString data_end = QStringLiteral ( " </script> " ) ;
2021-10-30 02:21:29 +02:00
qint64 begin_idx = content . indexOf ( data_begin ) ;
2020-05-08 18:35:36 +02:00
QString content_json ;
if ( begin_idx > 0 ) {
begin_idx + = data_begin . length ( ) ;
2021-10-30 02:21:29 +02:00
qint64 end_idx = content . indexOf ( data_end , begin_idx ) ;
2020-05-08 18:35:36 +02:00
if ( end_idx > begin_idx ) {
content_json = content . mid ( begin_idx , end_idx - begin_idx ) ;
}
}
if ( content_json . isEmpty ( ) ) {
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-08 18:35:36 +02:00
return ;
}
2024-04-09 23:20:26 +02:00
if ( content_json . contains ( QRegularExpression ( QStringLiteral ( " <[^>]*> " ) ) ) ) { // Make sure it's not HTML code.
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-08 18:35:36 +02:00
return ;
}
2024-03-17 23:41:05 +01:00
QJsonObject obj_data = ExtractJsonObj ( content_json . toUtf8 ( ) ) ;
if ( obj_data . isEmpty ( ) ) {
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-08 18:35:36 +02:00
return ;
}
2024-04-09 23:20:26 +02:00
if ( ! obj_data . contains ( QStringLiteral ( " props " ) ) | | ! obj_data [ QStringLiteral ( " props " ) ] . isObject ( ) ) {
Error ( QStringLiteral ( " Json reply is missing props. " ) , obj_data ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-08 18:35:36 +02:00
return ;
}
2024-04-09 23:20:26 +02:00
obj_data = obj_data [ QStringLiteral ( " props " ) ] . toObject ( ) ;
2020-05-08 18:35:36 +02:00
2024-04-09 23:20:26 +02:00
if ( ! obj_data . contains ( QStringLiteral ( " pageProps " ) ) | | ! obj_data [ QStringLiteral ( " pageProps " ) ] . isObject ( ) ) {
Error ( QStringLiteral ( " Json props is missing pageProps. " ) , obj_data ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-08 18:35:36 +02:00
return ;
}
2024-04-09 23:20:26 +02:00
obj_data = obj_data [ QStringLiteral ( " pageProps " ) ] . toObject ( ) ;
2020-05-08 18:35:36 +02:00
2024-04-09 23:20:26 +02:00
if ( ! obj_data . contains ( QStringLiteral ( " data " ) ) | | ! obj_data [ QStringLiteral ( " data " ) ] . isObject ( ) ) {
Error ( QStringLiteral ( " Json pageProps is missing data. " ) , obj_data ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-08 18:35:36 +02:00
return ;
}
2024-04-09 23:20:26 +02:00
obj_data = obj_data [ QStringLiteral ( " data " ) ] . toObject ( ) ;
2020-05-08 18:35:36 +02:00
2024-03-16 22:46:45 +01:00
2024-04-09 23:20:26 +02:00
if ( ! obj_data . contains ( QStringLiteral ( " trackInfo " ) ) | | ! obj_data [ QStringLiteral ( " trackInfo " ) ] . isObject ( ) ) {
Error ( QStringLiteral ( " Json data is missing trackInfo. " ) , obj_data ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-08 18:35:36 +02:00
return ;
}
2024-04-09 23:20:26 +02:00
obj_data = obj_data [ QStringLiteral ( " trackInfo " ) ] . toObject ( ) ;
2020-05-08 18:35:36 +02:00
2024-04-09 23:20:26 +02:00
if ( ! obj_data . contains ( QStringLiteral ( " data " ) ) | | ! obj_data [ QStringLiteral ( " data " ) ] . isObject ( ) ) {
Error ( QStringLiteral ( " Json trackInfo reply is missing data. " ) , obj_data ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
2020-05-08 18:35:36 +02:00
return ;
}
2024-04-09 23:20:26 +02:00
obj_data = obj_data [ QStringLiteral ( " data " ) ] . toObject ( ) ;
2020-05-08 18:35:36 +02:00
2024-04-09 23:20:26 +02:00
if ( ! obj_data . contains ( QStringLiteral ( " track " ) ) | | ! obj_data [ QStringLiteral ( " track " ) ] . isObject ( ) ) {
Error ( QStringLiteral ( " Json data is missing track. " ) , obj_data ) ;
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
return ;
2020-05-08 18:35:36 +02:00
}
2024-04-09 23:20:26 +02:00
const QJsonObject obj_track = obj_data [ QStringLiteral ( " track " ) ] . toObject ( ) ;
2024-03-17 23:41:05 +01:00
2024-04-09 23:20:26 +02:00
if ( ! obj_track . contains ( QStringLiteral ( " hasLyrics " ) ) | | ! obj_track [ QStringLiteral ( " hasLyrics " ) ] . isBool ( ) ) {
Error ( QStringLiteral ( " Json track is missing hasLyrics. " ) , obj_track ) ;
2024-03-17 23:41:05 +01:00
EndSearch ( search , url ) ;
return ;
}
2024-04-09 23:20:26 +02:00
const bool has_lyrics = obj_track [ QStringLiteral ( " hasLyrics " ) ] . toBool ( ) ;
2024-03-17 23:41:05 +01:00
if ( ! has_lyrics ) {
EndSearch ( search , url ) ;
return ;
}
LyricsSearchResult result ;
2024-04-09 23:20:26 +02:00
if ( obj_track . contains ( QStringLiteral ( " artistName " ) ) & & obj_track [ QStringLiteral ( " artistName " ) ] . isString ( ) ) {
result . artist = obj_track [ QStringLiteral ( " artistName " ) ] . toString ( ) ;
2024-03-17 23:41:05 +01:00
}
2024-04-09 23:20:26 +02:00
if ( obj_track . contains ( QStringLiteral ( " albumName " ) ) & & obj_track [ QStringLiteral ( " albumName " ) ] . isString ( ) ) {
result . album = obj_track [ QStringLiteral ( " albumName " ) ] . toString ( ) ;
2024-03-17 23:41:05 +01:00
}
2024-04-09 23:20:26 +02:00
if ( obj_track . contains ( QStringLiteral ( " name " ) ) & & obj_track [ QStringLiteral ( " name " ) ] . isString ( ) ) {
result . title = obj_track [ QStringLiteral ( " name " ) ] . toString ( ) ;
2024-03-17 23:41:05 +01:00
}
2024-04-09 23:20:26 +02:00
if ( ! obj_data . contains ( QStringLiteral ( " lyrics " ) ) | | ! obj_data [ QStringLiteral ( " lyrics " ) ] . isObject ( ) ) {
Error ( QStringLiteral ( " Json data is missing lyrics. " ) , obj_data ) ;
2024-03-17 23:41:05 +01:00
EndSearch ( search , url ) ;
return ;
}
2024-04-09 23:20:26 +02:00
QJsonObject obj_lyrics = obj_data [ QStringLiteral ( " lyrics " ) ] . toObject ( ) ;
2024-03-17 23:41:05 +01:00
2024-04-09 23:20:26 +02:00
if ( ! obj_lyrics . contains ( QStringLiteral ( " body " ) ) | | ! obj_lyrics [ QStringLiteral ( " body " ) ] . isString ( ) ) {
Error ( QStringLiteral ( " Json lyrics reply is missing body. " ) , obj_lyrics ) ;
2024-03-16 22:46:45 +01:00
EndSearch ( search , url ) ;
return ;
}
2024-04-09 23:20:26 +02:00
result . lyrics = obj_lyrics [ QStringLiteral ( " body " ) ] . toString ( ) ;
2020-05-08 18:35:36 +02:00
2024-03-17 23:41:05 +01:00
if ( ! result . lyrics . isEmpty ( ) ) {
result . lyrics = Utilities : : DecodeHtmlEntities ( result . lyrics ) ;
2022-10-17 20:29:44 +02:00
search - > results . append ( result ) ;
2020-05-08 18:35:36 +02:00
}
2022-10-17 20:29:44 +02:00
EndSearch ( search , url ) ;
}
void MusixmatchLyricsProvider : : EndSearch ( LyricsSearchContextPtr search , const QUrl & url ) {
if ( search - > requests_lyrics_ . contains ( url ) ) {
search - > requests_lyrics_ . removeAll ( url ) ;
2020-05-08 18:35:36 +02:00
}
2022-10-17 20:29:44 +02:00
if ( search - > requests_lyrics_ . count ( ) = = 0 ) {
requests_search_ . removeAll ( search ) ;
if ( search - > results . isEmpty ( ) ) {
2023-03-06 21:42:59 +01:00
qLog ( Debug ) < < " MusixmatchLyrics: No lyrics for " < < search - > request . artist < < search - > request . title ;
2022-10-17 20:29:44 +02:00
}
else {
2023-03-06 21:42:59 +01:00
qLog ( Debug ) < < " MusixmatchLyrics: Got lyrics for " < < search - > request . artist < < search - > request . title ;
2022-10-17 20:29:44 +02:00
}
emit SearchFinished ( search - > id , search - > results ) ;
}
2020-05-08 18:35:36 +02:00
}
void MusixmatchLyricsProvider : : Error ( const QString & error , const QVariant & debug ) {
qLog ( Error ) < < " MusixmatchLyrics: " < < error ;
if ( debug . isValid ( ) ) qLog ( Debug ) < < debug ;
}