Disable automatic conversions from 8-bit strings
This commit is contained in:
@@ -48,18 +48,18 @@ TidalBaseRequest::TidalBaseRequest(TidalService *service, SharedPtr<NetworkAcces
|
||||
QNetworkReply *TidalBaseRequest::CreateRequest(const QString &ressource_name, const ParamList ¶ms_provided) {
|
||||
|
||||
ParamList params = ParamList() << params_provided
|
||||
<< Param("countryCode", country_code());
|
||||
<< Param(QStringLiteral("countryCode"), country_code());
|
||||
|
||||
QUrlQuery url_query;
|
||||
for (const Param ¶m : params) {
|
||||
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
|
||||
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
|
||||
}
|
||||
|
||||
QUrl url(QString(TidalService::kApiUrl) + QStringLiteral("/") + ressource_name);
|
||||
QUrl url(QLatin1String(TidalService::kApiUrl) + QLatin1Char('/') + ressource_name);
|
||||
url.setQuery(url_query);
|
||||
QNetworkRequest req(url);
|
||||
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
|
||||
if (oauth() && !access_token().isEmpty()) req.setRawHeader("authorization", "Bearer " + access_token().toUtf8());
|
||||
else if (!session_id().isEmpty()) req.setRawHeader("X-Tidal-SessionId", session_id().toUtf8());
|
||||
|
||||
@@ -198,7 +198,7 @@ QString TidalBaseRequest::ErrorsToHTML(const QStringList &errors) {
|
||||
|
||||
QString error_html;
|
||||
for (const QString &error : errors) {
|
||||
error_html += error + "<br />";
|
||||
error_html += error + QStringLiteral("<br />");
|
||||
}
|
||||
return error_html;
|
||||
|
||||
|
||||
@@ -134,18 +134,18 @@ void TidalFavoriteRequest::AddFavorites(const FavoriteType type, const SongList
|
||||
|
||||
void TidalFavoriteRequest::AddFavoritesRequest(const FavoriteType type, const QStringList &id_list, const SongList &songs) {
|
||||
|
||||
ParamList params = ParamList() << Param("countryCode", country_code())
|
||||
<< Param(FavoriteMethod(type), id_list.join(','));
|
||||
ParamList params = ParamList() << Param(QStringLiteral("countryCode"), country_code())
|
||||
<< Param(FavoriteMethod(type), id_list.join(QLatin1Char(',')));
|
||||
|
||||
QUrlQuery url_query;
|
||||
for (const Param ¶m : params) {
|
||||
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
|
||||
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
|
||||
}
|
||||
|
||||
QUrl url(QString(TidalService::kApiUrl) + QStringLiteral("/") + "users/" + QString::number(service_->user_id()) + "/favorites/" + FavoriteText(type));
|
||||
QUrl url(QLatin1String(TidalService::kApiUrl) + QLatin1Char('/') + QStringLiteral("users/") + QString::number(service_->user_id()) + QStringLiteral("/favorites/") + FavoriteText(type));
|
||||
QNetworkRequest req(url);
|
||||
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
|
||||
if (oauth() && !access_token().isEmpty()) req.setRawHeader("authorization", "Bearer " + access_token().toUtf8());
|
||||
else if (!session_id().isEmpty()) req.setRawHeader("X-Tidal-SessionId", session_id().toUtf8());
|
||||
QByteArray query = url_query.toString(QUrl::FullyEncoded).toUtf8();
|
||||
@@ -244,18 +244,18 @@ void TidalFavoriteRequest::RemoveFavorites(const FavoriteType type, const SongLi
|
||||
|
||||
void TidalFavoriteRequest::RemoveFavoritesRequest(const FavoriteType type, const QString &id, const SongList &songs) {
|
||||
|
||||
ParamList params = ParamList() << Param("countryCode", country_code());
|
||||
ParamList params = ParamList() << Param(QStringLiteral("countryCode"), country_code());
|
||||
|
||||
QUrlQuery url_query;
|
||||
for (const Param ¶m : params) {
|
||||
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
|
||||
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
|
||||
}
|
||||
|
||||
QUrl url(QString(TidalService::kApiUrl) + QStringLiteral("/") + "users/" + QString::number(service_->user_id()) + "/favorites/" + FavoriteText(type) + QStringLiteral("/") + id);
|
||||
QUrl url(QLatin1String(TidalService::kApiUrl) + QStringLiteral("/users/") + QString::number(service_->user_id()) + QStringLiteral("/favorites/") + FavoriteText(type) + QStringLiteral("/") + id);
|
||||
url.setQuery(url_query);
|
||||
QNetworkRequest req(url);
|
||||
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
|
||||
if (oauth() && !access_token().isEmpty()) req.setRawHeader("authorization", "Bearer " + access_token().toUtf8());
|
||||
else if (!session_id().isEmpty()) req.setRawHeader("X-Tidal-SessionId", session_id().toUtf8());
|
||||
QNetworkReply *reply = network_->deleteResource(req);
|
||||
|
||||
@@ -47,14 +47,16 @@
|
||||
#include "tidalbaserequest.h"
|
||||
#include "tidalrequest.h"
|
||||
|
||||
constexpr char TidalRequest::kResourcesUrl[] = "https://resources.tidal.com";
|
||||
constexpr int TidalRequest::kMaxConcurrentArtistsRequests = 3;
|
||||
constexpr int TidalRequest::kMaxConcurrentAlbumsRequests = 3;
|
||||
constexpr int TidalRequest::kMaxConcurrentSongsRequests = 3;
|
||||
constexpr int TidalRequest::kMaxConcurrentArtistAlbumsRequests = 3;
|
||||
constexpr int TidalRequest::kMaxConcurrentAlbumSongsRequests = 3;
|
||||
constexpr int TidalRequest::kMaxConcurrentAlbumCoverRequests = 1;
|
||||
constexpr int TidalRequest::kFlushRequestsDelay = 200;
|
||||
namespace {
|
||||
constexpr char kResourcesUrl[] = "https://resources.tidal.com";
|
||||
constexpr int kMaxConcurrentArtistsRequests = 3;
|
||||
constexpr int kMaxConcurrentAlbumsRequests = 3;
|
||||
constexpr int kMaxConcurrentSongsRequests = 3;
|
||||
constexpr int kMaxConcurrentArtistAlbumsRequests = 3;
|
||||
constexpr int kMaxConcurrentAlbumSongsRequests = 3;
|
||||
constexpr int kMaxConcurrentAlbumCoverRequests = 1;
|
||||
constexpr int kFlushRequestsDelay = 200;
|
||||
} // namespace
|
||||
|
||||
TidalRequest::TidalRequest(TidalService *service, TidalUrlHandler *url_handler, Application *app, SharedPtr<NetworkAccessManager> network, QueryType query_type, QObject *parent)
|
||||
: TidalBaseRequest(service, network, parent),
|
||||
@@ -248,9 +250,9 @@ void TidalRequest::FlushArtistsRequests() {
|
||||
Request request = artists_requests_queue_.dequeue();
|
||||
|
||||
ParamList parameters;
|
||||
if (query_type_ == QueryType::SearchArtists) parameters << Param("query", search_text_);
|
||||
if (request.limit > 0) parameters << Param("limit", QString::number(request.limit));
|
||||
if (request.offset > 0) parameters << Param("offset", QString::number(request.offset));
|
||||
if (query_type_ == QueryType::SearchArtists) parameters << Param(QStringLiteral("query"), search_text_);
|
||||
if (request.limit > 0) parameters << Param(QStringLiteral("limit"), QString::number(request.limit));
|
||||
if (request.offset > 0) parameters << Param(QStringLiteral("offset"), QString::number(request.offset));
|
||||
QNetworkReply *reply = nullptr;
|
||||
if (query_type_ == QueryType::Artists) {
|
||||
reply = CreateRequest(QStringLiteral("users/%1/favorites/artists").arg(service_->user_id()), parameters);
|
||||
@@ -296,9 +298,9 @@ void TidalRequest::FlushAlbumsRequests() {
|
||||
Request request = albums_requests_queue_.dequeue();
|
||||
|
||||
ParamList parameters;
|
||||
if (query_type_ == QueryType::SearchAlbums) parameters << Param("query", search_text_);
|
||||
if (request.limit > 0) parameters << Param("limit", QString::number(request.limit));
|
||||
if (request.offset > 0) parameters << Param("offset", QString::number(request.offset));
|
||||
if (query_type_ == QueryType::SearchAlbums) parameters << Param(QStringLiteral("query"), search_text_);
|
||||
if (request.limit > 0) parameters << Param(QStringLiteral("limit"), QString::number(request.limit));
|
||||
if (request.offset > 0) parameters << Param(QStringLiteral("offset"), QString::number(request.offset));
|
||||
QNetworkReply *reply = nullptr;
|
||||
if (query_type_ == QueryType::Albums) {
|
||||
reply = CreateRequest(QStringLiteral("users/%1/favorites/albums").arg(service_->user_id()), parameters);
|
||||
@@ -344,9 +346,9 @@ void TidalRequest::FlushSongsRequests() {
|
||||
Request request = songs_requests_queue_.dequeue();
|
||||
|
||||
ParamList parameters;
|
||||
if (query_type_ == QueryType::SearchSongs) parameters << Param("query", search_text_);
|
||||
if (request.limit > 0) parameters << Param("limit", QString::number(request.limit));
|
||||
if (request.offset > 0) parameters << Param("offset", QString::number(request.offset));
|
||||
if (query_type_ == QueryType::SearchSongs) parameters << Param(QStringLiteral("query"), search_text_);
|
||||
if (request.limit > 0) parameters << Param(QStringLiteral("limit"), QString::number(request.limit));
|
||||
if (request.offset > 0) parameters << Param(QStringLiteral("offset"), QString::number(request.offset));
|
||||
QNetworkReply *reply = nullptr;
|
||||
if (query_type_ == QueryType::Songs) {
|
||||
reply = CreateRequest(QStringLiteral("users/%1/favorites/tracks").arg(service_->user_id()), parameters);
|
||||
@@ -584,7 +586,7 @@ void TidalRequest::FlushArtistAlbumsRequests() {
|
||||
const ArtistAlbumsRequest request = artist_albums_requests_queue_.dequeue();
|
||||
|
||||
ParamList parameters;
|
||||
if (request.offset > 0) parameters << Param("offset", QString::number(request.offset));
|
||||
if (request.offset > 0) parameters << Param(QStringLiteral("offset"), QString::number(request.offset));
|
||||
QNetworkReply *reply = CreateRequest(QStringLiteral("artists/%1/albums").arg(request.artist.artist_id), parameters);
|
||||
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, request]() { ArtistAlbumsReplyReceived(reply, request.artist, request.offset); });
|
||||
replies_ << reply;
|
||||
@@ -692,7 +694,7 @@ void TidalRequest::AlbumsReceived(QNetworkReply *reply, const Artist &artist_req
|
||||
if (service_->album_explicit() && obj_item.contains(QStringLiteral("explicit"))) {
|
||||
album.album_explicit = obj_item[QStringLiteral("explicit")].toVariant().toBool();
|
||||
if (album.album_explicit && !album.album.isEmpty()) {
|
||||
album.album.append(" (Explicit)");
|
||||
album.album.append(QStringLiteral(" (Explicit)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -717,7 +719,7 @@ void TidalRequest::AlbumsReceived(QNetworkReply *reply, const Artist &artist_req
|
||||
if (service_->album_explicit() && obj_album.contains(QStringLiteral("explicit"))) {
|
||||
album.album_explicit = obj_album[QStringLiteral("explicit")].toVariant().toBool();
|
||||
if (album.album_explicit && !album.album.isEmpty()) {
|
||||
album.album.append(" (Explicit)");
|
||||
album.album.append(QStringLiteral(" (Explicit)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -859,7 +861,7 @@ void TidalRequest::FlushAlbumSongsRequests() {
|
||||
|
||||
AlbumSongsRequest request = album_songs_requests_queue_.dequeue();
|
||||
ParamList parameters;
|
||||
if (request.offset > 0) parameters << Param("offset", QString::number(request.offset));
|
||||
if (request.offset > 0) parameters << Param(QStringLiteral("offset"), QString::number(request.offset));
|
||||
QNetworkReply *reply = CreateRequest(QStringLiteral("albums/%1/tracks").arg(request.album.album_id), parameters);
|
||||
replies_ << reply;
|
||||
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, request]() { AlbumSongsReplyReceived(reply, request.artist, request.album, request.offset); });
|
||||
@@ -1095,7 +1097,7 @@ void TidalRequest::ParseSong(Song &song, const QJsonObject &json_obj, const Arti
|
||||
return;
|
||||
}
|
||||
QString album_title = obj_album[QStringLiteral("title")].toString();
|
||||
if (album.album_explicit) album_title.append(" (Explicit)");
|
||||
if (album.album_explicit) album_title.append(QStringLiteral(" (Explicit)"));
|
||||
|
||||
if (!allow_streaming) {
|
||||
Warn(QStringLiteral("Song %1 %2 %3 is not allowStreaming").arg(artist, album_title, title));
|
||||
@@ -1125,7 +1127,7 @@ void TidalRequest::ParseSong(Song &song, const QJsonObject &json_obj, const Arti
|
||||
if (obj_album.contains(QStringLiteral("cover"))) {
|
||||
const QString cover = obj_album[QStringLiteral("cover")].toString().replace(QLatin1String("-"), QLatin1String("/"));
|
||||
if (!cover.isEmpty()) {
|
||||
cover_url.setUrl(QStringLiteral("%1/images/%2/%3.jpg").arg(kResourcesUrl, cover, coversize_));
|
||||
cover_url.setUrl(QStringLiteral("%1/images/%2/%3.jpg").arg(QLatin1String(kResourcesUrl), cover, coversize_));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1277,8 +1279,8 @@ void TidalRequest::AlbumCoverReceived(QNetworkReply *reply, const QString &album
|
||||
}
|
||||
|
||||
QString mimetype = reply->header(QNetworkRequest::ContentTypeHeader).toString();
|
||||
if (mimetype.contains(';')) {
|
||||
mimetype = mimetype.left(mimetype.indexOf(';'));
|
||||
if (mimetype.contains(QLatin1Char(';'))) {
|
||||
mimetype = mimetype.left(mimetype.indexOf(QLatin1Char(';')));
|
||||
}
|
||||
if (!ImageUtils::SupportedImageMimeTypes().contains(mimetype, Qt::CaseInsensitive) && !ImageUtils::SupportedImageFormats().contains(mimetype, Qt::CaseInsensitive)) {
|
||||
Error(QStringLiteral("Unsupported mimetype for image reader %1 for %2").arg(mimetype, url.toString()));
|
||||
@@ -1287,7 +1289,7 @@ void TidalRequest::AlbumCoverReceived(QNetworkReply *reply, const QString &album
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
const QByteArray data = reply->readAll();
|
||||
if (data.isEmpty()) {
|
||||
Error(QStringLiteral("Received empty image data for %1").arg(url.toString()));
|
||||
if (album_covers_requests_sent_.contains(album_id)) album_covers_requests_sent_.remove(album_id);
|
||||
|
||||
@@ -172,15 +172,6 @@ class TidalRequest : public TidalBaseRequest {
|
||||
static void Warn(const QString &error, const QVariant &debug = QVariant());
|
||||
void Error(const QString &error, const QVariant &debug = QVariant()) override;
|
||||
|
||||
static const char kResourcesUrl[];
|
||||
static const int kMaxConcurrentArtistsRequests;
|
||||
static const int kMaxConcurrentAlbumsRequests;
|
||||
static const int kMaxConcurrentSongsRequests;
|
||||
static const int kMaxConcurrentArtistAlbumsRequests;
|
||||
static const int kMaxConcurrentAlbumSongsRequests;
|
||||
static const int kMaxConcurrentAlbumCoverRequests;
|
||||
static const int kFlushRequestsDelay;
|
||||
|
||||
TidalService *service_;
|
||||
TidalUrlHandler *url_handler_;
|
||||
Application *app_;
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "core/networkaccessmanager.h"
|
||||
#include "core/database.h"
|
||||
#include "core/song.h"
|
||||
#include "core/settings.h"
|
||||
#include "utilities/randutils.h"
|
||||
#include "utilities/timeconstants.h"
|
||||
#include "internet/internetsearchview.h"
|
||||
@@ -69,25 +70,29 @@ const Song::Source TidalService::kSource = Song::Source::Tidal;
|
||||
|
||||
const char TidalService::kApiUrl[] = "https://api.tidalhifi.com/v1";
|
||||
const char TidalService::kResourcesUrl[] = "https://resources.tidal.com";
|
||||
|
||||
constexpr char TidalService::kOAuthUrl[] = "https://login.tidal.com/authorize";
|
||||
constexpr char TidalService::kOAuthAccessTokenUrl[] = "https://login.tidal.com/oauth2/token";
|
||||
constexpr char TidalService::kOAuthRedirectUrl[] = "tidal://login/auth";
|
||||
constexpr char TidalService::kAuthUrl[] = "https://api.tidalhifi.com/v1/login/username";
|
||||
|
||||
const int TidalService::kLoginAttempts = 2;
|
||||
constexpr int TidalService::kTimeResetLoginAttempts = 60000;
|
||||
|
||||
constexpr char TidalService::kArtistsSongsTable[] = "tidal_artists_songs";
|
||||
constexpr char TidalService::kAlbumsSongsTable[] = "tidal_albums_songs";
|
||||
constexpr char TidalService::kSongsTable[] = "tidal_songs";
|
||||
namespace {
|
||||
|
||||
constexpr char TidalService::kArtistsSongsFtsTable[] = "tidal_artists_songs_fts";
|
||||
constexpr char TidalService::kAlbumsSongsFtsTable[] = "tidal_albums_songs_fts";
|
||||
constexpr char TidalService::kSongsFtsTable[] = "tidal_songs_fts";
|
||||
constexpr char kOAuthUrl[] = "https://login.tidal.com/authorize";
|
||||
constexpr char kOAuthAccessTokenUrl[] = "https://login.tidal.com/oauth2/token";
|
||||
constexpr char kOAuthRedirectUrl[] = "tidal://login/auth";
|
||||
constexpr char kAuthUrl[] = "https://api.tidalhifi.com/v1/login/username";
|
||||
|
||||
constexpr int kTimeResetLoginAttempts = 60000;
|
||||
|
||||
constexpr char kArtistsSongsTable[] = "tidal_artists_songs";
|
||||
constexpr char kAlbumsSongsTable[] = "tidal_albums_songs";
|
||||
constexpr char kSongsTable[] = "tidal_songs";
|
||||
|
||||
constexpr char kArtistsSongsFtsTable[] = "tidal_artists_songs_fts";
|
||||
constexpr char kAlbumsSongsFtsTable[] = "tidal_albums_songs_fts";
|
||||
constexpr char kSongsFtsTable[] = "tidal_songs_fts";
|
||||
|
||||
} // namespace
|
||||
|
||||
TidalService::TidalService(Application *app, QObject *parent)
|
||||
: InternetService(Song::Source::Tidal, QStringLiteral("Tidal"), QStringLiteral("tidal"), TidalSettingsPage::kSettingsGroup, SettingsDialog::Page::Tidal, app, parent),
|
||||
: InternetService(Song::Source::Tidal, QStringLiteral("Tidal"), QStringLiteral("tidal"), QLatin1String(TidalSettingsPage::kSettingsGroup), SettingsDialog::Page::Tidal, app, parent),
|
||||
app_(app),
|
||||
network_(app->network()),
|
||||
url_handler_(new TidalUrlHandler(app, this)),
|
||||
@@ -130,15 +135,15 @@ TidalService::TidalService(Application *app, QObject *parent)
|
||||
|
||||
artists_collection_backend_ = make_shared<CollectionBackend>();
|
||||
artists_collection_backend_->moveToThread(app_->database()->thread());
|
||||
artists_collection_backend_->Init(app_->database(), app->task_manager(), Song::Source::Tidal, kArtistsSongsTable, kArtistsSongsFtsTable);
|
||||
artists_collection_backend_->Init(app_->database(), app->task_manager(), Song::Source::Tidal, QLatin1String(kArtistsSongsTable), QLatin1String(kArtistsSongsFtsTable));
|
||||
|
||||
albums_collection_backend_ = make_shared<CollectionBackend>();
|
||||
albums_collection_backend_->moveToThread(app_->database()->thread());
|
||||
albums_collection_backend_->Init(app_->database(), app->task_manager(), Song::Source::Tidal, kAlbumsSongsTable, kAlbumsSongsFtsTable);
|
||||
albums_collection_backend_->Init(app_->database(), app->task_manager(), Song::Source::Tidal, QLatin1String(kAlbumsSongsTable), QLatin1String(kAlbumsSongsFtsTable));
|
||||
|
||||
songs_collection_backend_ = make_shared<CollectionBackend>();
|
||||
songs_collection_backend_->moveToThread(app_->database()->thread());
|
||||
songs_collection_backend_->Init(app_->database(), app->task_manager(), Song::Source::Tidal, kSongsTable, kSongsFtsTable);
|
||||
songs_collection_backend_->Init(app_->database(), app->task_manager(), Song::Source::Tidal, QLatin1String(kSongsTable), QLatin1String(kSongsFtsTable));
|
||||
|
||||
artists_collection_model_ = new CollectionModel(artists_collection_backend_, app_, this);
|
||||
albums_collection_model_ = new CollectionModel(albums_collection_backend_, app_, this);
|
||||
@@ -247,10 +252,10 @@ void TidalService::ShowConfig() {
|
||||
|
||||
void TidalService::LoadSession() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(TidalSettingsPage::kSettingsGroup);
|
||||
user_id_ = s.value("user_id").toInt();
|
||||
country_code_ = s.value("country_code", "US").toString();
|
||||
country_code_ = s.value("country_code", QStringLiteral("US")).toString();
|
||||
access_token_ = s.value("access_token").toString();
|
||||
refresh_token_ = s.value("refresh_token").toString();
|
||||
session_id_ = s.value("session_id").toString();
|
||||
@@ -273,7 +278,7 @@ void TidalService::LoadSession() {
|
||||
|
||||
void TidalService::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(TidalSettingsPage::kSettingsGroup);
|
||||
|
||||
enabled_ = s.value("enabled", false).toBool();
|
||||
@@ -286,13 +291,13 @@ void TidalService::ReloadSettings() {
|
||||
if (password.isEmpty()) password_.clear();
|
||||
else password_ = QString::fromUtf8(QByteArray::fromBase64(password));
|
||||
|
||||
quality_ = s.value("quality", "LOSSLESS").toString();
|
||||
quality_ = s.value("quality", QStringLiteral("LOSSLESS")).toString();
|
||||
quint64 search_delay = s.value("searchdelay", 1500).toInt();
|
||||
artistssearchlimit_ = s.value("artistssearchlimit", 4).toInt();
|
||||
albumssearchlimit_ = s.value("albumssearchlimit", 10).toInt();
|
||||
songssearchlimit_ = s.value("songssearchlimit", 10).toInt();
|
||||
fetchalbums_ = s.value("fetchalbums", false).toBool();
|
||||
coversize_ = s.value("coversize", "640x640").toString();
|
||||
coversize_ = s.value("coversize", QStringLiteral("640x640")).toString();
|
||||
download_album_covers_ = s.value("downloadalbumcovers", true).toBool();
|
||||
stream_url_method_ = static_cast<TidalSettingsPage::StreamUrlMethod>(s.value("streamurl", static_cast<int>(TidalSettingsPage::StreamUrlMethod::StreamUrl)).toInt());
|
||||
album_explicit_ = s.value("album_explicit").toBool();
|
||||
@@ -307,25 +312,25 @@ void TidalService::StartAuthorization(const QString &client_id) {
|
||||
|
||||
client_id_ = client_id;
|
||||
code_verifier_ = Utilities::CryptographicRandomString(44);
|
||||
code_challenge_ = QString(QCryptographicHash::hash(code_verifier_.toUtf8(), QCryptographicHash::Sha256).toBase64(QByteArray::Base64UrlEncoding));
|
||||
code_challenge_ = QString::fromLatin1(QCryptographicHash::hash(code_verifier_.toUtf8(), QCryptographicHash::Sha256).toBase64(QByteArray::Base64UrlEncoding));
|
||||
|
||||
if (code_challenge_.lastIndexOf(QChar('=')) == code_challenge_.length() - 1) {
|
||||
if (code_challenge_.lastIndexOf(QLatin1Char('=')) == code_challenge_.length() - 1) {
|
||||
code_challenge_.chop(1);
|
||||
}
|
||||
|
||||
const ParamList params = ParamList() << Param("response_type", "code")
|
||||
<< Param("code_challenge", code_challenge_)
|
||||
<< Param("code_challenge_method", "S256")
|
||||
<< Param("redirect_uri", kOAuthRedirectUrl)
|
||||
<< Param("client_id", client_id_)
|
||||
<< Param("scope", "r_usr w_usr");
|
||||
const ParamList params = ParamList() << Param(QStringLiteral("response_type"), QStringLiteral("code"))
|
||||
<< Param(QStringLiteral("code_challenge"), code_challenge_)
|
||||
<< Param(QStringLiteral("code_challenge_method"), QStringLiteral("S256"))
|
||||
<< Param(QStringLiteral("redirect_uri"), QLatin1String(kOAuthRedirectUrl))
|
||||
<< Param(QStringLiteral("client_id"), client_id_)
|
||||
<< Param(QStringLiteral("scope"), QStringLiteral("r_usr w_usr"));
|
||||
|
||||
QUrlQuery url_query;
|
||||
for (const Param ¶m : params) {
|
||||
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
|
||||
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
|
||||
}
|
||||
|
||||
QUrl url = QUrl(kOAuthUrl);
|
||||
QUrl url = QUrl(QString::fromLatin1(kOAuthUrl));
|
||||
url.setQuery(url_query);
|
||||
QDesktopServices::openUrl(url);
|
||||
|
||||
@@ -339,15 +344,15 @@ void TidalService::AuthorizationUrlReceived(const QUrl &url) {
|
||||
|
||||
if (url_query.hasQueryItem(QStringLiteral("token_type")) && url_query.hasQueryItem(QStringLiteral("expires_in")) && url_query.hasQueryItem(QStringLiteral("access_token"))) {
|
||||
|
||||
access_token_ = url_query.queryItemValue(QStringLiteral("access_token")).toUtf8();
|
||||
access_token_ = url_query.queryItemValue(QStringLiteral("access_token"));
|
||||
if (url_query.hasQueryItem(QStringLiteral("refresh_token"))) {
|
||||
refresh_token_ = url_query.queryItemValue(QStringLiteral("refresh_token")).toUtf8();
|
||||
refresh_token_ = url_query.queryItemValue(QStringLiteral("refresh_token"));
|
||||
}
|
||||
expires_in_ = url_query.queryItemValue(QStringLiteral("expires_in")).toInt();
|
||||
login_time_ = QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
session_id_.clear();
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(TidalSettingsPage::kSettingsGroup);
|
||||
s.setValue("access_token", access_token_);
|
||||
s.setValue("refresh_token", refresh_token_);
|
||||
@@ -379,18 +384,18 @@ void TidalService::RequestAccessToken(const QString &code) {
|
||||
|
||||
timer_refresh_login_->stop();
|
||||
|
||||
ParamList params = ParamList() << Param("client_id", client_id_);
|
||||
ParamList params = ParamList() << Param(QStringLiteral("client_id"), client_id_);
|
||||
|
||||
if (!code.isEmpty()) {
|
||||
params << Param("grant_type", "authorization_code");
|
||||
params << Param("code", code);
|
||||
params << Param("code_verifier", code_verifier_);
|
||||
params << Param("redirect_uri", kOAuthRedirectUrl);
|
||||
params << Param("scope", "r_usr w_usr");
|
||||
params << Param(QStringLiteral("grant_type"), QStringLiteral("authorization_code"));
|
||||
params << Param(QStringLiteral("code"), code);
|
||||
params << Param(QStringLiteral("code_verifier"), code_verifier_);
|
||||
params << Param(QStringLiteral("redirect_uri"), QLatin1String(kOAuthRedirectUrl));
|
||||
params << Param(QStringLiteral("scope"), QStringLiteral("r_usr w_usr"));
|
||||
}
|
||||
else if (!refresh_token_.isEmpty() && enabled_ && oauth_) {
|
||||
params << Param("grant_type", "refresh_token");
|
||||
params << Param("refresh_token", refresh_token_);
|
||||
params << Param(QStringLiteral("grant_type"), QStringLiteral("refresh_token"));
|
||||
params << Param(QStringLiteral("refresh_token"), refresh_token_);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
@@ -398,13 +403,13 @@ void TidalService::RequestAccessToken(const QString &code) {
|
||||
|
||||
QUrlQuery url_query;
|
||||
for (const Param ¶m : params) {
|
||||
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
|
||||
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
|
||||
}
|
||||
|
||||
QUrl url(kOAuthAccessTokenUrl);
|
||||
QUrl url(QString::fromLatin1(kOAuthAccessTokenUrl));
|
||||
QNetworkRequest req(url);
|
||||
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
QByteArray query = url_query.toString(QUrl::FullyEncoded).toUtf8();
|
||||
const QByteArray query = url_query.toString(QUrl::FullyEncoded).toUtf8();
|
||||
|
||||
login_errors_.clear();
|
||||
QNetworkReply *reply = network_->post(req, query);
|
||||
@@ -462,7 +467,7 @@ void TidalService::AccessTokenRequestFinished(QNetworkReply *reply) {
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray data(reply->readAll());
|
||||
const QByteArray data = reply->readAll();
|
||||
QJsonParseError json_error;
|
||||
QJsonDocument json_doc = QJsonDocument::fromJson(data, &json_error);
|
||||
|
||||
@@ -509,7 +514,7 @@ void TidalService::AccessTokenRequestFinished(QNetworkReply *reply) {
|
||||
|
||||
session_id_.clear();
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(TidalSettingsPage::kSettingsGroup);
|
||||
s.setValue("access_token", access_token_);
|
||||
s.setValue("refresh_token", refresh_token_);
|
||||
@@ -543,20 +548,20 @@ void TidalService::SendLoginWithCredentials(const QString &api_token, const QStr
|
||||
timer_login_attempt_->start();
|
||||
timer_refresh_login_->stop();
|
||||
|
||||
const ParamList params = ParamList() << Param("token", (api_token.isEmpty() ? api_token_ : api_token))
|
||||
<< Param("username", username)
|
||||
<< Param("password", password)
|
||||
<< Param("clientVersion", "2.2.1--7");
|
||||
const ParamList params = ParamList() << Param(QStringLiteral("token"), (api_token.isEmpty() ? api_token_ : api_token))
|
||||
<< Param(QStringLiteral("username"), username)
|
||||
<< Param(QStringLiteral("password"), password)
|
||||
<< Param(QStringLiteral("clientVersion"), QStringLiteral("2.2.1--7"));
|
||||
|
||||
QUrlQuery url_query;
|
||||
for (const Param ¶m : params) {
|
||||
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
|
||||
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
|
||||
}
|
||||
|
||||
QUrl url(kAuthUrl);
|
||||
QUrl url(QString::fromLatin1(kAuthUrl));
|
||||
QNetworkRequest req(url);
|
||||
|
||||
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
|
||||
req.setRawHeader("X-Tidal-Token", (api_token.isEmpty() ? api_token_.toUtf8() : api_token.toUtf8()));
|
||||
|
||||
QByteArray query = url_query.toString(QUrl::FullyEncoded).toUtf8();
|
||||
@@ -615,7 +620,7 @@ void TidalService::HandleAuthReply(QNetworkReply *reply) {
|
||||
|
||||
login_errors_.clear();
|
||||
|
||||
QByteArray data(reply->readAll());
|
||||
const QByteArray data = reply->readAll();
|
||||
QJsonParseError json_error;
|
||||
QJsonDocument json_doc = QJsonDocument::fromJson(data, &json_error);
|
||||
|
||||
@@ -651,7 +656,7 @@ void TidalService::HandleAuthReply(QNetworkReply *reply) {
|
||||
access_token_.clear();
|
||||
refresh_token_.clear();
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(TidalSettingsPage::kSettingsGroup);
|
||||
s.remove("access_token");
|
||||
s.remove("refresh_token");
|
||||
@@ -681,7 +686,7 @@ void TidalService::Logout() {
|
||||
expires_in_ = 0;
|
||||
login_time_ = 0;
|
||||
|
||||
QSettings s;
|
||||
Settings s;
|
||||
s.beginGroup(TidalSettingsPage::kSettingsGroup);
|
||||
s.remove("user_id");
|
||||
s.remove("country_code");
|
||||
@@ -1026,7 +1031,7 @@ void TidalService::LoginError(const QString &error, const QVariant &debug) {
|
||||
QString error_html;
|
||||
for (const QString &e : login_errors_) {
|
||||
qLog(Error) << "Tidal:" << e;
|
||||
error_html += e + "<br />";
|
||||
error_html += e + QStringLiteral("<br />");
|
||||
}
|
||||
if (debug.isValid()) qLog(Debug) << debug;
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ class TidalService : public InternetService {
|
||||
static const Song::Source kSource;
|
||||
static const char kApiUrl[];
|
||||
static const char kResourcesUrl[];
|
||||
static const int kLoginAttempts;
|
||||
|
||||
void Exit() override;
|
||||
void ReloadSettings() override;
|
||||
@@ -159,22 +160,6 @@ class TidalService : public InternetService {
|
||||
void SendSearch();
|
||||
void LoginError(const QString &error = QString(), const QVariant &debug = QVariant());
|
||||
|
||||
static const char kOAuthUrl[];
|
||||
static const char kOAuthAccessTokenUrl[];
|
||||
static const char kOAuthRedirectUrl[];
|
||||
static const char kAuthUrl[];
|
||||
|
||||
static const int kLoginAttempts;
|
||||
static const int kTimeResetLoginAttempts;
|
||||
|
||||
static const char kArtistsSongsTable[];
|
||||
static const char kAlbumsSongsTable[];
|
||||
static const char kSongsTable[];
|
||||
|
||||
static const char kArtistsSongsFtsTable[];
|
||||
static const char kAlbumsSongsFtsTable[];
|
||||
static const char kSongsFtsTable[];
|
||||
|
||||
Application *app_;
|
||||
SharedPtr<NetworkAccessManager> network_;
|
||||
TidalUrlHandler *url_handler_;
|
||||
|
||||
@@ -121,22 +121,22 @@ void TidalStreamURLRequest::GetStreamURL() {
|
||||
|
||||
switch (stream_url_method()) {
|
||||
case TidalSettingsPage::StreamUrlMethod::StreamUrl:
|
||||
params << Param("soundQuality", quality());
|
||||
params << Param(QStringLiteral("soundQuality"), quality());
|
||||
reply_ = CreateRequest(QStringLiteral("tracks/%1/streamUrl").arg(song_id_), params);
|
||||
QObject::connect(reply_, &QNetworkReply::finished, this, &TidalStreamURLRequest::StreamURLReceived);
|
||||
break;
|
||||
case TidalSettingsPage::StreamUrlMethod::UrlPostPaywall:
|
||||
params << Param("audioquality", quality());
|
||||
params << Param("playbackmode", "STREAM");
|
||||
params << Param("assetpresentation", "FULL");
|
||||
params << Param("urlusagemode", "STREAM");
|
||||
params << Param(QStringLiteral("audioquality"), quality());
|
||||
params << Param(QStringLiteral("playbackmode"), QStringLiteral("STREAM"));
|
||||
params << Param(QStringLiteral("assetpresentation"), QStringLiteral("FULL"));
|
||||
params << Param(QStringLiteral("urlusagemode"), QStringLiteral("STREAM"));
|
||||
reply_ = CreateRequest(QStringLiteral("tracks/%1/urlpostpaywall").arg(song_id_), params);
|
||||
QObject::connect(reply_, &QNetworkReply::finished, this, &TidalStreamURLRequest::StreamURLReceived);
|
||||
break;
|
||||
case TidalSettingsPage::StreamUrlMethod::PlaybackInfoPostPaywall:
|
||||
params << Param("audioquality", quality());
|
||||
params << Param("playbackmode", "STREAM");
|
||||
params << Param("assetpresentation", "FULL");
|
||||
params << Param(QStringLiteral("audioquality"), quality());
|
||||
params << Param(QStringLiteral("playbackmode"), QStringLiteral("STREAM"));
|
||||
params << Param(QStringLiteral("assetpresentation"), QStringLiteral("FULL"));
|
||||
reply_ = CreateRequest(QStringLiteral("tracks/%1/playbackinfopostpaywall").arg(song_id_), params);
|
||||
QObject::connect(reply_, &QNetworkReply::finished, this, &TidalStreamURLRequest::StreamURLReceived);
|
||||
break;
|
||||
@@ -233,7 +233,7 @@ void TidalStreamURLRequest::StreamURLReceived() {
|
||||
|
||||
QString mimetype = json_obj[QStringLiteral("mimeType")].toString();
|
||||
QMimeDatabase mimedb;
|
||||
QStringList suffixes = mimedb.mimeTypeForName(mimetype.toUtf8()).suffixes();
|
||||
QStringList suffixes = mimedb.mimeTypeForName(mimetype).suffixes();
|
||||
for (const QString &suffix : suffixes) {
|
||||
filetype = Song::FiletypeByExtension(suffix);
|
||||
if (filetype != Song::FileType::Unknown) break;
|
||||
|
||||
Reference in New Issue
Block a user