/*
This file is part of Subsonic.
Subsonic 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.
Subsonic 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 Subsonic. If not, see
null
if not eligible for registration.
*/
private RegistrationData createRegistrationData(MediaFile mediaFile, String username, boolean submission) {
if (mediaFile == null || mediaFile.isVideo()) {
return null;
}
UserSettings userSettings = settingsService.getUserSettings(username);
if (!userSettings.isLastFmEnabled() || userSettings.getLastFmUsername() == null || userSettings.getLastFmPassword() == null) {
return null;
}
long now = System.currentTimeMillis();
// Don't register submissions more often than every 30 seconds.
if (submission) {
Long lastRegistrationTime = lastRegistrationTimes.get(username);
if (lastRegistrationTime != null && now - lastRegistrationTime < MIN_REGISTRATION_INTERVAL) {
return null;
}
lastRegistrationTimes.put(username, now);
}
RegistrationData reg = new RegistrationData();
reg.username = userSettings.getLastFmUsername();
reg.password = userSettings.getLastFmPassword();
reg.artist = mediaFile.getArtist();
reg.album = mediaFile.getAlbumName();
reg.title = mediaFile.getTitle();
reg.duration = mediaFile.getDurationSeconds() == null ? 0 : mediaFile.getDurationSeconds();
reg.time = new Date(now);
reg.submission = submission;
return reg;
}
/**
* Scrobbles the given song data at last.fm, using the protocol defined at http://www.last.fm/api/submissions.
*
* @param registrationData Registration data for the song.
*/
private void scrobble(RegistrationData registrationData) throws Exception {
if (registrationData == null) {
return;
}
String[] lines = authenticate(registrationData);
if (lines == null) {
return;
}
String sessionId = lines[1];
String nowPlayingUrl = lines[2];
String submissionUrl = lines[3];
if (registrationData.submission) {
lines = registerSubmission(registrationData, sessionId, submissionUrl);
} else {
lines = registerNowPlaying(registrationData, sessionId, nowPlayingUrl);
}
if (lines[0].startsWith("FAILED")) {
LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm: " + lines[0]);
} else if (lines[0].startsWith("BADSESSION")) {
LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm. Invalid session.");
} else if (lines[0].startsWith("OK")) {
LOG.debug("Successfully registered " + (registrationData.submission ? "submission" : "now playing") +
" for song '" + registrationData.title + "' for user " + registrationData.username + " at Last.fm.");
}
}
/**
* Returns the following lines if authentication succeeds:
*
* Line 0: Always "OK"
* Line 1: Session ID, e.g., "17E61E13454CDD8B68E8D7DEEEDF6170"
* Line 2: URL to use for now playing, e.g., "http://post.audioscrobbler.com:80/np_1.2"
* Line 3: URL to use for submissions, e.g., "http://post2.audioscrobbler.com:80/protocol_1.2"
*
* If authentication fails, null
is returned.
*/
private String[] authenticate(RegistrationData registrationData) throws Exception {
String clientId = "sub";
String clientVersion = "0.1";
long timestamp = System.currentTimeMillis() / 1000L;
String authToken = calculateAuthenticationToken(registrationData.password, timestamp);
String[] lines = executeGetRequest("http://post.audioscrobbler.com/?hs=true&p=1.2.1&c=" + clientId + "&v=" +
clientVersion + "&u=" + registrationData.username + "&t=" + timestamp + "&a=" + authToken);
if (lines[0].startsWith("BANNED")) {
LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm. Client version is banned.");
return null;
}
if (lines[0].startsWith("BADAUTH")) {
LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm. Wrong username or password.");
return null;
}
if (lines[0].startsWith("BADTIME")) {
LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm. Bad timestamp, please check local clock.");
return null;
}
if (lines[0].startsWith("FAILED")) {
LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm: " + lines[0]);
return null;
}
if (!lines[0].startsWith("OK")) {
LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm. Unknown response: " + lines[0]);
return null;
}
return lines;
}
private String[] registerSubmission(RegistrationData registrationData, String sessionId, String url) throws IOException {
Map