2015-09-08 17:05:59 +02:00
# include "./spotifydownload.h"
2015-04-22 19:32:04 +02:00
# include "../application/utils.h"
# include <QUrlQuery>
# include <QApplication>
# include <QClipboard>
# include <QJsonDocument>
# include <QJsonObject>
# include <QJsonArray>
# include <QJsonParseError>
using namespace Application ;
namespace Network {
const QUrl SpotifyDownload : : m_spotifyUrl = QUrl ( QStringLiteral ( " https://play.spotify.com/ " ) ) ;
bool SpotifyDownload : : m_authenticationCredentialsValidated = false ;
QString SpotifyDownload : : m_csrftoken = QString ( ) ;
QString SpotifyDownload : : m_trackingId = QString ( ) ;
QString SpotifyDownload : : m_referrer = QString ( ) ;
QString SpotifyDownload : : m_creationFlow = QString ( ) ;
QStringList SpotifyDownload : : m_supportedUseragents = QStringList ( )
< < QStringLiteral ( " Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:23.0) Gecko/20100101 Firefox/23.0 " ) ;
/*!
* \ class SpotifyDownload
* \ brief Download implementation for Spotify songs .
* \ remarks Under construction ( not even rudimental finished ) .
*/
/*!
* \ brief Constructs a new SpotifyDownload for the specified \ a songid .
*/
SpotifyDownload : : SpotifyDownload ( const QString & songid , QObject * parent ) :
HttpDownloadWithInfoRequst ( QUrl ( ) , parent ) ,
m_currentRequest ( SpotifyRequestType : : Invalid ) ,
m_triesToGetAuthenticationData ( 0 )
{
setId ( songid ) ;
}
QString SpotifyDownload : : typeName ( ) const
{
return tr ( " Spotify " ) ;
}
void SpotifyDownload : : resetSession ( )
{
m_authenticationCredentialsValidated = false ;
m_csrftoken . clear ( ) ;
m_trackingId . clear ( ) ;
m_referrer . clear ( ) ;
m_creationFlow . clear ( ) ;
}
Download * SpotifyDownload : : infoRequestDownload ( bool & sucess , QString & reasonForFail )
{
HttpDownload * download = nullptr ;
if ( m_csrftoken . isEmpty ( ) | | m_trackingId . isEmpty ( ) /* || creationFlow.isEmpty()*/ ) {
if ( m_triesToGetAuthenticationData < 2 ) {
download = new HttpDownload ( m_spotifyUrl ) ;
download - > setCustomUserAgent ( m_supportedUseragents . at ( 0 ) ) ;
sucess = true ;
+ + m_triesToGetAuthenticationData ;
m_currentRequest = SpotifyRequestType : : GetAuthenticationData ;
} else {
reasonForFail = tr ( " Unable to find data required for autentication. " ) ;
sucess = false ;
}
} else if ( ! m_authenticationCredentialsValidated ) {
if ( initialAuthenticationCredentials ( ) . isIncomplete ( ) ) {
reportAuthenticationRequired ( - 1 , tr ( " To download songs from Spotify authentication is required so you have to enter the credentials of your Spotify account. " ) ) ;
reasonForFail = tr ( " Authentication credentials not given. " ) ;
//networkError = QNetworkReply::AuthenticationRequiredError;
sucess = false ;
} else {
QUrl url ( m_spotifyUrl ) ;
url . setPath ( QStringLiteral ( " /xhr/json/auth.php " ) ) ;
download = new HttpDownload ( url ) ;
QByteArray postData ;
QUrlQuery query ;
query . addQueryItem ( QStringLiteral ( " type " ) , QStringLiteral ( " sp " ) ) ;
query . addQueryItem ( QStringLiteral ( " username " ) , initialAuthenticationCredentials ( ) . userName ( ) ) ;
query . addQueryItem ( QStringLiteral ( " password " ) , initialAuthenticationCredentials ( ) . password ( ) ) ;
query . addQueryItem ( QStringLiteral ( " secret " ) , m_csrftoken ) ;
query . addQueryItem ( QStringLiteral ( " trackingId " ) , m_trackingId ) ;
query . addQueryItem ( QStringLiteral ( " landingURL " ) , m_spotifyUrl . toString ( ) ) ;
query . addQueryItem ( QStringLiteral ( " cf " ) , m_creationFlow ) ;
postData . append ( query . toString ( QUrl : : FullyEncoded ) ) ;
download - > setMethod ( HttpDownloadMethod : : Post ) ;
download - > setPostData ( postData ) ;
download - > setCustomUserAgent ( m_supportedUseragents . at ( 0 ) ) ;
sucess = true ;
m_currentRequest = SpotifyRequestType : : Authenticate ;
}
}
return download ;
}
void SpotifyDownload : : evalVideoInformation ( Download * , QBuffer * videoInfoBuffer )
{
if ( m_currentRequest = = SpotifyRequestType : : Invalid )
reportInitiated ( false , tr ( " Interal error (current request type not set). " ) ) ;
else {
videoInfoBuffer - > seek ( 0 ) ;
switch ( m_currentRequest ) {
case SpotifyRequestType : : GetAuthenticationData : {
QString responseData ( videoInfoBuffer - > readAll ( ) ) ;
substring ( responseData , m_csrftoken , 0 , QStringLiteral ( " \" csrftoken \" : \" " ) , QStringLiteral ( " \" " ) ) ;
substring ( responseData , m_trackingId , 0 , QStringLiteral ( " \" trackingId \" : \" " ) , QStringLiteral ( " \" " ) ) ;
substring ( responseData , m_creationFlow , 0 , QStringLiteral ( " \" creationFlow \" : \" " ) , QStringLiteral ( " \" " ) ) ;
substring ( responseData , m_referrer , 0 , QStringLiteral ( " \" referrer \" : \" " ) , QStringLiteral ( " \" " ) ) ;
m_currentRequest = SpotifyRequestType : : Invalid ;
doInit ( ) ;
break ;
}
case SpotifyRequestType : : Authenticate : {
QByteArray responseData ( videoInfoBuffer - > readAll ( ) ) ;
QApplication : : clipboard ( ) - > setText ( QString ( responseData ) ) ;
QJsonParseError error ;
QJsonDocument document = QJsonDocument : : fromJson ( responseData , & error ) ;
if ( error . error = = QJsonParseError : : NoError ) {
QJsonObject obj = document . object ( ) ;
QJsonValue statusVal = obj . value ( QStringLiteral ( " status " ) ) ;
if ( statusVal . toString ( ) . compare ( QLatin1String ( " ok " ) , Qt : : CaseInsensitive ) = = 0 ) {
m_authenticationCredentialsValidated = true ;
reportInitiated ( true ) ;
} else {
QString error = obj . value ( QStringLiteral ( " error " ) ) . toString ( ) ;
QString message ;
if ( error . isEmpty ( ) ) {
message = tr ( " Authentication failed. Spotify returned no error message. " ) ;
} else if ( error . compare ( QLatin1String ( " invalid_credentials " ) , Qt : : CaseInsensitive ) = = 0 ) {
message = tr ( " Authentication failed because the entered credentials are invalid. " ) ;
} else {
message = tr ( " Authentication failed. Error message returned by Spotify: %1 " ) . arg ( error ) ;
}
reportInitiated ( false , message ) ;
}
} else {
reportInitiated ( false , tr ( " Authentication failed because the response by Spotify is no valid Json document (parse error: %1). " ) . arg ( error . errorString ( ) ) ) ;
}
break ;
}
case SpotifyRequestType : : Invalid :
;
}
}
}
}