Use desktopauth instead of mobileauth for last.fm
It now uses an oauth like authentication process so the user isn't required to enter the last.fm password in Clementine but rather authenticate through the last.fm website. Updates #5028 (cherry picked from commit 6c726e3e382bdd28fd00a5e68725980ef0da91e1)
This commit is contained in:
parent
641b597447
commit
8b02ae592f
@ -74,6 +74,7 @@ const char* LastFMService::kSettingsGroup = "Last.fm";
|
||||
const char* LastFMService::kAudioscrobblerClientId = "tng";
|
||||
const char* LastFMService::kApiKey = "75d20fb472be99275392aefa2760ea09";
|
||||
const char* LastFMService::kSecret = "d3072b60ae626be12be69448f5c46e70";
|
||||
const char* LastFMService::kAuthLoginUrl = "http://www.last.fm/api/auth/?api_key=%1&token=%2";
|
||||
|
||||
LastFMService::LastFMService(Application* app, QObject* parent)
|
||||
: Scrobbler(parent),
|
||||
@ -82,6 +83,8 @@ LastFMService::LastFMService(Application* app, QObject* parent)
|
||||
scrobbling_enabled_(false),
|
||||
connection_problems_(false),
|
||||
app_(app) {
|
||||
lastfm::ws::setScheme(lastfm::ws::Https);
|
||||
|
||||
ReloadSettings();
|
||||
|
||||
// we emit the signal the first time to be sure the buttons are in the right
|
||||
@ -127,13 +130,32 @@ bool LastFMService::IsSubscriber() const {
|
||||
return settings.value("Subscriber", false).toBool();
|
||||
}
|
||||
|
||||
void LastFMService::Authenticate(const QString& username,
|
||||
const QString& password) {
|
||||
void LastFMService::GetToken() {
|
||||
QMap<QString, QString> params;
|
||||
params["method"] = "auth.getMobileSession";
|
||||
params["username"] = username;
|
||||
params["authToken"] =
|
||||
lastfm::md5((username + lastfm::md5(password.toUtf8())).toUtf8());
|
||||
params["method"] = "auth.getToken";
|
||||
QNetworkReply* reply = lastfm::ws::post(params);
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
SLOT(GetTokenReplyFinished(QNetworkReply*)), reply);
|
||||
}
|
||||
|
||||
void LastFMService::GetTokenReplyFinished(QNetworkReply* reply) {
|
||||
reply->deleteLater();
|
||||
|
||||
// Parse the reply
|
||||
lastfm::XmlQuery lfm(lastfm::compat::EmptyXmlQuery());
|
||||
if (lastfm::compat::ParseQuery(reply->readAll(), &lfm)) {
|
||||
QString token = lfm["token"].text();
|
||||
|
||||
emit TokenReceived(true, token);
|
||||
} else {
|
||||
emit TokenReceived(false, lfm["error"].text().trimmed());
|
||||
}
|
||||
}
|
||||
|
||||
void LastFMService::Authenticate(const QString& token) {
|
||||
QMap<QString, QString> params;
|
||||
params["method"] = "auth.getSession";
|
||||
params["token"] = token;
|
||||
|
||||
QNetworkReply* reply = lastfm::ws::post(params);
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
@ -141,17 +163,6 @@ void LastFMService::Authenticate(const QString& username,
|
||||
// If we need more detailed error reporting, handle error(NetworkError) signal
|
||||
}
|
||||
|
||||
void LastFMService::SignOut() {
|
||||
lastfm::ws::Username.clear();
|
||||
lastfm::ws::SessionKey.clear();
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup(kSettingsGroup);
|
||||
|
||||
settings.setValue("Username", QString());
|
||||
settings.setValue("Session", QString());
|
||||
}
|
||||
|
||||
void LastFMService::AuthenticateReplyFinished(QNetworkReply* reply) {
|
||||
reply->deleteLater();
|
||||
|
||||
@ -181,6 +192,17 @@ void LastFMService::AuthenticateReplyFinished(QNetworkReply* reply) {
|
||||
emit AuthenticationComplete(true, QString());
|
||||
}
|
||||
|
||||
void LastFMService::SignOut() {
|
||||
lastfm::ws::Username.clear();
|
||||
lastfm::ws::SessionKey.clear();
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup(kSettingsGroup);
|
||||
|
||||
settings.setValue("Username", QString());
|
||||
settings.setValue("Session", QString());
|
||||
}
|
||||
|
||||
void LastFMService::UpdateSubscriberStatus() {
|
||||
QMap<QString, QString> params;
|
||||
params["method"] = "user.getInfo";
|
||||
|
@ -54,6 +54,7 @@ class LastFMService : public Scrobbler {
|
||||
static const char* kAudioscrobblerClientId;
|
||||
static const char* kApiKey;
|
||||
static const char* kSecret;
|
||||
static const char* kAuthLoginUrl;
|
||||
|
||||
void ReloadSettings();
|
||||
|
||||
@ -68,7 +69,8 @@ class LastFMService : public Scrobbler {
|
||||
bool PreferAlbumArtist() const { return prefer_albumartist_; }
|
||||
bool HasConnectionProblems() const { return connection_problems_; }
|
||||
|
||||
void Authenticate(const QString& username, const QString& password);
|
||||
void GetToken();
|
||||
void Authenticate(const QString& token);
|
||||
void SignOut();
|
||||
void UpdateSubscriberStatus();
|
||||
|
||||
@ -81,6 +83,7 @@ class LastFMService : public Scrobbler {
|
||||
void ToggleScrobbling();
|
||||
|
||||
signals:
|
||||
void TokenReceived(bool success, const QString& token);
|
||||
void AuthenticationComplete(bool success, const QString& error_message);
|
||||
void ScrobblingEnabledChanged(bool value);
|
||||
void ButtonVisibilityChanged(bool value);
|
||||
@ -94,6 +97,7 @@ class LastFMService : public Scrobbler {
|
||||
void SavedItemsChanged();
|
||||
|
||||
private slots:
|
||||
void GetTokenReplyFinished(QNetworkReply* reply);
|
||||
void AuthenticateReplyFinished(QNetworkReply* reply);
|
||||
void UpdateSubscriberStatusFinished(QNetworkReply* reply);
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <lastfm/ws.h>
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QSettings>
|
||||
|
||||
@ -42,17 +43,16 @@ LastFMSettingsPage::LastFMSettingsPage(SettingsDialog* dialog)
|
||||
// Icons
|
||||
setWindowIcon(IconLoader::Load("lastfm", IconLoader::Provider));
|
||||
|
||||
connect(service_, SIGNAL(TokenReceived(bool,QString)),
|
||||
SLOT(TokenReceived(bool,QString)));
|
||||
connect(service_, SIGNAL(AuthenticationComplete(bool, QString)),
|
||||
SLOT(AuthenticationComplete(bool, QString)));
|
||||
connect(ui_->login_state, SIGNAL(LogoutClicked()), SLOT(Logout()));
|
||||
connect(ui_->login_state, SIGNAL(LoginClicked()), SLOT(Login()));
|
||||
connect(ui_->login, SIGNAL(clicked()), SLOT(Login()));
|
||||
|
||||
ui_->login_state->AddCredentialField(ui_->username);
|
||||
ui_->login_state->AddCredentialField(ui_->password);
|
||||
ui_->login_state->AddCredentialGroup(ui_->groupBox);
|
||||
ui_->login_state->AddCredentialGroup(ui_->login_container);
|
||||
|
||||
ui_->username->setMinimumWidth(QFontMetrics(QFont()).width("WWWWWWWWWWWW"));
|
||||
resize(sizeHint());
|
||||
}
|
||||
|
||||
@ -62,7 +62,22 @@ void LastFMSettingsPage::Login() {
|
||||
waiting_for_auth_ = true;
|
||||
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress);
|
||||
service_->Authenticate(ui_->username->text(), ui_->password->text());
|
||||
service_->GetToken();
|
||||
}
|
||||
|
||||
void LastFMSettingsPage::TokenReceived(bool success, const QString &token) {
|
||||
if (!success) {
|
||||
QMessageBox::warning(this, tr("Last.fm authentication failed"), token);
|
||||
return;
|
||||
}
|
||||
|
||||
QString url = QString(LastFMService::kAuthLoginUrl).arg(LastFMService::kApiKey, token);
|
||||
QDesktopServices::openUrl(QUrl(url));
|
||||
|
||||
QMessageBox::information(this, tr("Last.fm authentication"),
|
||||
tr("Click Ok once you authenticated Clementine in your last.fm account."));
|
||||
|
||||
service_->Authenticate(token);
|
||||
}
|
||||
|
||||
void LastFMSettingsPage::AuthenticationComplete(bool success,
|
||||
@ -72,8 +87,6 @@ void LastFMSettingsPage::AuthenticationComplete(bool success,
|
||||
waiting_for_auth_ = false;
|
||||
|
||||
if (success) {
|
||||
// Clear password just to be sure
|
||||
ui_->password->clear();
|
||||
// Save settings
|
||||
Save();
|
||||
} else {
|
||||
@ -109,8 +122,6 @@ void LastFMSettingsPage::Save() {
|
||||
}
|
||||
|
||||
void LastFMSettingsPage::Logout() {
|
||||
ui_->username->clear();
|
||||
ui_->password->clear();
|
||||
RefreshControls(false);
|
||||
|
||||
service_->SignOut();
|
||||
|
@ -38,6 +38,7 @@ class LastFMSettingsPage : public SettingsPage {
|
||||
|
||||
private slots:
|
||||
void Login();
|
||||
void TokenReceived(bool success, const QString& token);
|
||||
void AuthenticationComplete(bool success, const QString& error_message);
|
||||
void Logout();
|
||||
|
||||
|
@ -18,26 +18,19 @@
|
||||
<widget class="LoginStateWidget" name="login_state" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Account details</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
<widget class="QWidget" name="login_container" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>28</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Last.fm username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="username"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="login">
|
||||
<property name="text">
|
||||
@ -45,19 +38,28 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Last.fm password</string>
|
||||
<string>Clicking the Login button will open a web browser. You should return to Clementine after you have logged in.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -112,6 +114,9 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
@ -131,9 +136,6 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>username</tabstop>
|
||||
<tabstop>password</tabstop>
|
||||
<tabstop>login</tabstop>
|
||||
<tabstop>scrobble</tabstop>
|
||||
<tabstop>love_ban_</tabstop>
|
||||
<tabstop>scrobble_button</tabstop>
|
||||
|
Loading…
x
Reference in New Issue
Block a user