|
a/notifications/audioscrobbler.cpp |
|
b/notifications/audioscrobbler.cpp |
|
... |
|
... |
26 |
#include "upadapt/md5.hxx"
|
26 |
#include "upadapt/md5.hxx"
|
27 |
#include "HelperStructs/Helper.h"
|
27 |
#include "HelperStructs/Helper.h"
|
28 |
|
28 |
|
29 |
using namespace UPnPP;
|
29 |
using namespace UPnPP;
|
30 |
|
30 |
|
31 |
static const QString rootUrl("http://ws.audioscrobbler.com/2.0/");
|
31 |
static const QString rootUrl("https://ws.audioscrobbler.com/2.0/");
|
32 |
// Values for upplay
|
32 |
// Values for upplay
|
33 |
static const string apiKey("48b8a81fe93a4532efb4b713c8ad8e00");
|
33 |
static const string apiKey("48b8a81fe93a4532efb4b713c8ad8e00");
|
34 |
static const string apiSecret("d5bb8eb0dafce36e20ab6d14deccb264");
|
34 |
static const string apiSecret("d5bb8eb0dafce36e20ab6d14deccb264");
|
35 |
|
35 |
|
36 |
AudioScrobbler::AudioScrobbler(QObject *parent)
|
36 |
AudioScrobbler::AudioScrobbler(QObject *parent)
|
37 |
: QObject(parent), m_curpos(0), m_starttime(0), m_sent(false),
|
37 |
: QObject(parent)
|
38 |
m_lastqfail(0), m_failcount(0), m_authed(false), m_netactive(false)
|
|
|
39 |
{
|
38 |
{
|
40 |
|
39 |
|
41 |
m_netman = new QNetworkAccessManager(this);
|
40 |
m_netman = new QNetworkAccessManager(this);
|
42 |
connect(m_netman, SIGNAL(finished(QNetworkReply*)),
|
41 |
connect(m_netman, SIGNAL(finished(QNetworkReply*)),
|
43 |
this, SLOT(replyFinished(QNetworkReply*)));
|
42 |
this, SLOT(replyFinished(QNetworkReply*)));
|
|
... |
|
... |
121 |
}
|
120 |
}
|
122 |
}
|
121 |
}
|
123 |
|
122 |
|
124 |
void AudioScrobbler::openURL(const QString& url, const char *data)
|
123 |
void AudioScrobbler::openURL(const QString& url, const char *data)
|
125 |
{
|
124 |
{
|
|
|
125 |
//qDebug() << "AudioScrobbler::openURL:" << url << " data " << data;
|
126 |
if (m_netman == 0 || m_netactive) {
|
126 |
if (m_netman == 0 || m_netactive) {
|
127 |
qDebug() << "AudioScrobbler::openURL: no netman or already active";
|
127 |
qDebug() << "AudioScrobbler::openURL: no netman or already active";
|
128 |
return;
|
128 |
return;
|
129 |
}
|
129 |
}
|
130 |
|
130 |
|
|
... |
|
... |
144 |
{
|
144 |
{
|
145 |
QNetworkReply::NetworkError error = reply->error();
|
145 |
QNetworkReply::NetworkError error = reply->error();
|
146 |
QByteArray qdata;
|
146 |
QByteArray qdata;
|
147 |
if (error == QNetworkReply::NoError) {
|
147 |
if (error == QNetworkReply::NoError) {
|
148 |
qdata = reply->readAll();
|
148 |
qdata = reply->readAll();
|
149 |
qDebug() << "Success: " << qdata;
|
149 |
//qDebug() << ""AudioScrobbler::replyFinished: Success: " << qdata;
|
150 |
} else {
|
150 |
} else {
|
151 |
qDebug() << "Failure: error: " << reply->errorString();
|
151 |
//qDebug() << ""AudioScrobbler::replyFinished: error: " <<
|
|
|
152 |
//reply->errorString();
|
152 |
reply->deleteLater();
|
153 |
reply->deleteLater();
|
153 |
m_netactive = false;
|
154 |
m_netactive = false;
|
154 |
return;
|
155 |
return;
|
155 |
}
|
156 |
}
|
156 |
reply->deleteLater();
|
157 |
reply->deleteLater();
|
|
... |
|
... |
252 |
string out;
|
253 |
string out;
|
253 |
string sigdata;
|
254 |
string sigdata;
|
254 |
static const string amp("&");
|
255 |
static const string amp("&");
|
255 |
static const string eq("=");
|
256 |
static const string eq("=");
|
256 |
|
257 |
|
257 |
for (map<string, string>::const_iterator it = vars.begin();
|
258 |
for (const auto& entry : vars) {
|
258 |
it != vars.end(); it++) {
|
259 |
if (!out.empty())
|
259 |
if (it != vars.begin())
|
|
|
260 |
out += amp;
|
260 |
out += amp;
|
261 |
out += it->first + eq + it->second;
|
261 |
out += entry.first + eq + entry.second;
|
262 |
sigdata += it->first + it->second;
|
262 |
sigdata += entry.first + entry.second;
|
263 |
}
|
263 |
}
|
264 |
sigdata += apiSecret;
|
264 |
sigdata += apiSecret;
|
265 |
|
265 |
|
266 |
string digest, sighash;
|
266 |
string digest, sighash;
|
267 |
MD5String(sigdata, digest);
|
267 |
MD5String(sigdata, digest);
|
268 |
MD5HexPrint(digest, sighash);
|
268 |
MD5HexPrint(digest, sighash);
|
269 |
|
269 |
|
270 |
out += "&api_sig=" + sighash;
|
270 |
out += "&api_sig=" + sighash;
|
271 |
|
271 |
|
272 |
//qDebug() << "Message: [" << out.c_str() << "]\n";
|
272 |
//qDebug() << "Message: [" << out.c_str() << "]";
|
273 |
return out;
|
273 |
return out;
|
274 |
}
|
274 |
}
|
275 |
|
275 |
|
276 |
string AudioScrobbler::createScrobbleMessage(const MetaData& meta)
|
276 |
string AudioScrobbler::createScrobbleMessage(const MetaData& meta)
|
277 |
{
|
277 |
{
|
|
... |
|
... |
289 |
return LFMMessage(vars);
|
289 |
return LFMMessage(vars);
|
290 |
}
|
290 |
}
|
291 |
|
291 |
|
292 |
bool AudioScrobbler::scrobble(const MetaData& meta)
|
292 |
bool AudioScrobbler::scrobble(const MetaData& meta)
|
293 |
{
|
293 |
{
|
|
|
294 |
//qDebug() << "AudioScrobbler::scrobble. m_authed " << m_authed;
|
294 |
if(!m_authed) {
|
295 |
if(!m_authed) {
|
295 |
//qDebug() << "AudioScrobbler::scrobble: handshake not done yet.";
|
296 |
//qDebug() << "AudioScrobbler::scrobble: handshake not done yet.";
|
296 |
handshake();
|
297 |
handshake();
|
297 |
return false;
|
298 |
return false;
|
298 |
}
|
299 |
}
|
299 |
|
300 |
|
300 |
qDebug() << "AudioScrobbler:scrobble: " << meta.title << " " << meta.artist;
|
301 |
//qDebug()<<"AudioScrobbler:scrobble: " << meta.title << " " << meta.artist;
|
301 |
|
302 |
|
302 |
openURL(rootUrl, createScrobbleMessage(meta).c_str());
|
303 |
openURL(rootUrl, createScrobbleMessage(meta).c_str());
|
303 |
|
304 |
|
304 |
return true;
|
305 |
return true;
|
305 |
}
|
306 |
}
|
306 |
|
307 |
|
307 |
bool AudioScrobbler::nowPlaying(const MetaData& meta)
|
308 |
bool AudioScrobbler::nowPlaying(const MetaData& meta)
|
308 |
{
|
309 |
{
|
|
|
310 |
//qDebug() << "AudioScrobbler::nowPlaying. m_authed " << m_authed;
|
|
|
311 |
if(!m_authed) {
|
|
|
312 |
//qDebug() << "AudioScrobbler::scrobble: handshake not done yet.";
|
|
|
313 |
handshake();
|
|
|
314 |
return false;
|
|
|
315 |
}
|
|
|
316 |
|
309 |
map<string, string> vars;
|
317 |
map<string, string> vars;
|
310 |
vars["method"] = "track.updateNowPlaying";
|
318 |
vars["method"] = "track.updateNowPlaying";
|
311 |
vars["track"] = Helper::escapeHtml(qs2utf8s(meta.title));
|
319 |
vars["track"] = Helper::escapeHtml(qs2utf8s(meta.title));
|
312 |
vars["artist"] = Helper::escapeHtml(qs2utf8s(meta.artist));
|
320 |
vars["artist"] = Helper::escapeHtml(qs2utf8s(meta.artist));
|
313 |
vars["album"] = Helper::escapeHtml(qs2utf8s(meta.album));
|
321 |
vars["album"] = Helper::escapeHtml(qs2utf8s(meta.album));
|
|
... |
|
... |
319 |
return true;
|
327 |
return true;
|
320 |
}
|
328 |
}
|
321 |
|
329 |
|
322 |
bool AudioScrobbler::loveTrack(const MetaData& meta)
|
330 |
bool AudioScrobbler::loveTrack(const MetaData& meta)
|
323 |
{
|
331 |
{
|
|
|
332 |
//qDebug() << "AudioScrobbler::loveTrack. m_authed " << m_authed;
|
|
|
333 |
if(!m_authed) {
|
|
|
334 |
//qDebug() << "AudioScrobbler::scrobble: handshake not done yet.";
|
|
|
335 |
handshake();
|
|
|
336 |
return false;
|
|
|
337 |
}
|
|
|
338 |
|
324 |
map<string, string> vars;
|
339 |
map<string, string> vars;
|
325 |
|
|
|
326 |
vars["method"] = "track.love";
|
340 |
vars["method"] = "track.love";
|
327 |
vars["track"] = Helper::escapeHtml(qs2utf8s(meta.title));
|
341 |
vars["track"] = Helper::escapeHtml(qs2utf8s(meta.title));
|
328 |
vars["artist"] = Helper::escapeHtml(qs2utf8s(meta.artist));
|
342 |
vars["artist"] = Helper::escapeHtml(qs2utf8s(meta.artist));
|
329 |
vars["api_key"] = apiKey;
|
343 |
vars["api_key"] = apiKey;
|
330 |
vars["sk"] = m_sessionid;
|
344 |
vars["sk"] = m_sessionid;
|
|
... |
|
... |
333 |
return true;
|
347 |
return true;
|
334 |
}
|
348 |
}
|
335 |
|
349 |
|
336 |
void AudioScrobbler::handshake()
|
350 |
void AudioScrobbler::handshake()
|
337 |
{
|
351 |
{
|
|
|
352 |
//qDebug() << "AudioScrobbler::handshake. m_authed " << m_authed;
|
338 |
QSettings settings;
|
353 |
QSettings settings;
|
339 |
string username = qs2utf8s(settings.value("lastfmusername").
|
354 |
string username = qs2utf8s(settings.value("lastfmusername").
|
340 |
toString().toLower());
|
355 |
toString().toLower());
|
341 |
string password = qs2utf8s(settings.value("lastfmpassword").toString());
|
356 |
string password = qs2utf8s(settings.value("lastfmpassword").toString());
|
342 |
|
357 |
|
343 |
string digest, authtoken;
|
|
|
344 |
MD5String(username + password, digest);
|
|
|
345 |
MD5HexPrint(digest, authtoken);
|
|
|
346 |
|
|
|
347 |
map<string, string> vars;
|
358 |
map<string, string> vars;
|
348 |
vars["method"] = "auth.getMobileSession";
|
359 |
vars["method"] = "auth.getMobileSession";
|
349 |
vars["username"] = username;
|
360 |
vars["username"] = username;
|
350 |
vars["authToken"] = authtoken;
|
361 |
vars["password"] = password;
|
351 |
vars["api_key"] = apiKey;
|
362 |
vars["api_key"] = apiKey;
|
352 |
|
363 |
|
353 |
openURL(rootUrl, LFMMessage(vars).c_str());
|
364 |
openURL(rootUrl, LFMMessage(vars).c_str());
|
354 |
}
|
365 |
}
|