mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 17:43:32 +00:00
Added basic Subsonic interface
This commit is contained in:
parent
3fa634df39
commit
30ded0951b
5 changed files with 221 additions and 0 deletions
|
|
@ -0,0 +1,51 @@
|
|||
package com.cappielloantonio.play.subsonic;
|
||||
|
||||
import com.cappielloantonio.play.subsonic.base.Version;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Subsonic {
|
||||
private final SubsonicPreferences preferences;
|
||||
|
||||
private static final Version API_MIN_VERSION = Version.of("1.13.0");
|
||||
private static final Version API_MAX_VERSION = Version.of("1.15.0");
|
||||
|
||||
private Version apiVersion = API_MAX_VERSION;
|
||||
|
||||
public Subsonic(SubsonicPreferences preferences) {
|
||||
this.preferences = preferences;
|
||||
}
|
||||
|
||||
public SubsonicPreferences getPreferences() {
|
||||
return preferences;
|
||||
}
|
||||
|
||||
public static Version getApiMinVersion() {
|
||||
return API_MIN_VERSION;
|
||||
}
|
||||
|
||||
public static Version getApiMaxVersion() {
|
||||
return API_MAX_VERSION;
|
||||
}
|
||||
|
||||
public Version getApiVersion() {
|
||||
return apiVersion;
|
||||
}
|
||||
|
||||
public String createUrl(String path, Map<String, List<String>> params) {
|
||||
final StringBuilder sb = new StringBuilder(preferences.getServerUrl());
|
||||
|
||||
sb.append("/rest/").append(path);
|
||||
sb.append("?u=").append(preferences.getUsername());
|
||||
sb.append("&s=").append(preferences.getAuthentication().getSalt());
|
||||
sb.append("&t=").append(preferences.getAuthentication().getToken());
|
||||
sb.append("&v=").append(getApiVersion().getVersionString());
|
||||
sb.append("&c=").append(preferences.getClientName());
|
||||
sb.append("&f=").append("xml");
|
||||
|
||||
params.keySet().forEach(k -> params.get(k).forEach(v -> sb.append("&").append(k).append("=").append(v)));
|
||||
|
||||
return sb.toString().replace("//rest", "/rest");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.cappielloantonio.play.subsonic;
|
||||
|
||||
import com.cappielloantonio.play.subsonic.utils.StringUtil;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SubsonicPreferences {
|
||||
private String serverUrl;
|
||||
private String username;
|
||||
private String clientName = "SubsonicJavaClient";
|
||||
private int streamBitRate = 192;
|
||||
private String streamFormat = "mp3";
|
||||
|
||||
private final SubsonicAuthentication authentication;
|
||||
|
||||
public SubsonicPreferences(String serverUrl, String username, String password) {
|
||||
this.serverUrl = serverUrl;
|
||||
this.username = username;
|
||||
this.authentication = new SubsonicAuthentication(password);
|
||||
}
|
||||
|
||||
public String getServerUrl() {
|
||||
return serverUrl;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getClientName() {
|
||||
return clientName;
|
||||
}
|
||||
|
||||
public int getStreamBitRate() {
|
||||
return streamBitRate;
|
||||
}
|
||||
|
||||
public String getStreamFormat() {
|
||||
return streamFormat;
|
||||
}
|
||||
|
||||
public SubsonicAuthentication getAuthentication() {
|
||||
return authentication;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
authentication.update(password);
|
||||
}
|
||||
|
||||
public static class SubsonicAuthentication {
|
||||
private String salt;
|
||||
private String token;
|
||||
|
||||
public SubsonicAuthentication(String password) {
|
||||
update(password);
|
||||
}
|
||||
|
||||
public String getSalt() {
|
||||
return salt;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
void update(String password) {
|
||||
this.salt = UUID.randomUUID().toString();
|
||||
this.token = StringUtil.tokenize(password + salt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.cappielloantonio.play.subsonic.base;
|
||||
|
||||
public class SubsonicIncompatibilityException extends RuntimeException{
|
||||
private final Version serverApiVersion;
|
||||
private final Version minClientApiVersion;
|
||||
|
||||
public SubsonicIncompatibilityException(Version serverApiVersion, Version minClientApiVersion) {
|
||||
super(String.format("Server API version %s is lower than minimal supported API version %s.", serverApiVersion, minClientApiVersion));
|
||||
|
||||
this.serverApiVersion = serverApiVersion;
|
||||
this.minClientApiVersion = minClientApiVersion;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package com.cappielloantonio.play.subsonic.base;
|
||||
|
||||
public class Version implements Comparable<Version> {
|
||||
|
||||
private static final String VERSION_PATTERN = "[0-9]+(\\.[0-9]+)*";
|
||||
private final String versionString;
|
||||
|
||||
public static Version of(String versionString) {
|
||||
return new Version(versionString);
|
||||
}
|
||||
|
||||
private Version(String versionString) {
|
||||
if (versionString == null || !versionString.matches(VERSION_PATTERN)) {
|
||||
throw new IllegalArgumentException("Invalid version format");
|
||||
}
|
||||
this.versionString = versionString;
|
||||
}
|
||||
|
||||
public String getVersionString() {
|
||||
return versionString;
|
||||
}
|
||||
|
||||
public boolean isLowerThan(Version version) {
|
||||
return compareTo(version) < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Version that) {
|
||||
if (that == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
String[] thisParts = this.getVersionString().split("\\.");
|
||||
String[] thatParts = that.getVersionString().split("\\.");
|
||||
|
||||
int length = Math.max(thisParts.length, thatParts.length);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
int thisPart = i < thisParts.length ? Integer.parseInt(thisParts[i]) : 0;
|
||||
int thatPart = i < thatParts.length ? Integer.parseInt(thatParts[i]) : 0;
|
||||
|
||||
if (thisPart < thatPart) {
|
||||
return -1;
|
||||
}
|
||||
if (thisPart > thatPart) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return versionString;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.cappielloantonio.play.subsonic.utils;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class StringUtil {
|
||||
public static String tokenize(String s) {
|
||||
final String MD5 = "MD5";
|
||||
try {
|
||||
MessageDigest digest = java.security.MessageDigest.getInstance(MD5);
|
||||
digest.update(s.getBytes());
|
||||
byte messageDigest[] = digest.digest();
|
||||
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte aMessageDigest : messageDigest) {
|
||||
String h = Integer.toHexString(0xFF & aMessageDigest);
|
||||
while (h.length() < 2) {
|
||||
h = "0" + h;
|
||||
}
|
||||
hexString.append(h);
|
||||
}
|
||||
return hexString.toString();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue