Skip to content

Commit 6620880

Browse files
committed
Bump version to 1.3.0 and update JNA dependencies; introduce secret provider interface
1 parent d1762e2 commit 6620880

File tree

17 files changed

+281
-243
lines changed

17 files changed

+281
-243
lines changed

README.md

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,61 +47,76 @@ if (api.hasPosition()) {
4747

4848
Register a listener to get notified when the song changes:
4949
```java
50-
SpotifyAPI api = SpotifyAPIFactory.create();
51-
api.registerListener(new SpotifyListener() {
50+
SpotifyAPI localApi = SpotifyAPIFactory.create();
51+
localApi.registerListener(new SpotifyListener() {
5252
@Override
5353
public void onConnect() {
5454
System.out.println("Connected to Spotify!");
5555
}
56-
56+
5757
@Override
5858
public void onTrackChanged(Track track) {
5959
System.out.printf("Track changed: %s (%s)\n", track, formatDuration(track.getLength()));
60+
61+
// You could use the OpenSpotifyAPI to request the track cover image
62+
// try {
63+
// BufferedImage imageTrackCover = openApi.requestImage(track);
64+
// System.out.println("Loaded track cover: " + imageTrackCover.getWidth() + "x" + imageTrackCover.getHeight());
65+
// } catch (Exception e) {
66+
// System.out.println("Could not load track cover: " + e.getMessage());
67+
// }
6068
}
61-
69+
6270
@Override
6371
public void onPositionChanged(int position) {
64-
if (!api.hasTrack()) {
72+
if (!localApi.hasTrack()) {
6573
return;
6674
}
67-
68-
int length = api.getTrack().getLength();
75+
76+
int length = localApi.getTrack().getLength();
6977
float percentage = 100.0F / length * position;
70-
78+
7179
System.out.printf(
72-
"Position changed: %s of %s (%d%%)\n",
73-
formatDuration(position),
74-
formatDuration(length),
75-
(int) percentage
80+
"Position changed: %s of %s (%d%%)\n",
81+
formatDuration(position),
82+
formatDuration(length),
83+
(int) percentage
7684
);
7785
}
78-
86+
7987
@Override
8088
public void onPlayBackChanged(boolean isPlaying) {
8189
System.out.println(isPlaying ? "Song started playing" : "Song stopped playing");
8290
}
83-
91+
8492
@Override
8593
public void onSync() {
86-
94+
// System.out.println(formatDuration(api.getPosition()));
8795
}
88-
96+
8997
@Override
9098
public void onDisconnect(Exception exception) {
9199
System.out.println("Disconnected: " + exception.getMessage());
92-
100+
93101
// api.stop();
94102
}
95103
});
96104

97105
// Initialize the API
98-
api.initialize();
106+
localApi.initialize();
99107
```
100108

101109
Fetch an image of the current playing track:
102110
```java
103-
// Create an instance of the Open Spotify API (Or use SpotifyAPI#getOpenAPI)
104-
OpenSpotifyAPI openSpotifyAPI = new OpenSpotifyAPI();
111+
// Create a secret provider
112+
SecretProvider secretProvider = new DefaultSecretProvider(
113+
// Note: You have to update the secret with the latest TOTP secret from open.spotify.com
114+
// or find a way to retrieve it automatically from their website
115+
Secret.fromString("meZcB\\tlUFV1D6W2Hy4@9+$QaH5)N8", 9)
116+
);
117+
118+
// Create an instance of the Open Spotify API
119+
OpenSpotifyAPI openSpotifyAPI = new OpenSpotifyAPI(secretProvider);
105120

106121
// Download the cover art of the current song
107122
BufferedImage imageTrackCover = openSpotifyAPI.requestImage(track);

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
}
55

66
group 'de.labystudio'
7-
version '1.2.4'
7+
version '1.3.0'
88

99
compileJava {
1010
sourceCompatibility = '1.8'
@@ -21,8 +21,8 @@ repositories {
2121
}
2222

2323
dependencies {
24-
implementation group: 'net.java.dev.jna', name: 'jna', version: '4.5.0'
25-
implementation group: 'net.java.dev.jna', name: 'jna-platform', version: '4.5.0'
24+
implementation group: 'net.java.dev.jna', name: 'jna', version: '5.14.0'
25+
implementation group: 'net.java.dev.jna', name: 'jna-platform', version: '5.14.0'
2626
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.9'
2727
}
2828

src/main/java/de/labystudio/spotifyapi/SpotifyAPI.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import de.labystudio.spotifyapi.config.SpotifyConfiguration;
44
import de.labystudio.spotifyapi.model.MediaKey;
55
import de.labystudio.spotifyapi.model.Track;
6-
import de.labystudio.spotifyapi.open.OpenSpotifyAPI;
76

87
import java.util.concurrent.CompletableFuture;
98

@@ -145,8 +144,6 @@ default boolean hasTrack() {
145144
*/
146145
SpotifyConfiguration getConfiguration();
147146

148-
OpenSpotifyAPI getOpenAPI();
149-
150147
/**
151148
* Disconnect from the Spotify application and stop all background tasks.
152149
*/

src/main/java/de/labystudio/spotifyapi/open/OpenSpotifyAPI.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
package de.labystudio.spotifyapi.open;
22

33
import com.google.gson.Gson;
4+
import com.google.gson.GsonBuilder;
45
import com.google.gson.JsonObject;
56
import com.google.gson.stream.JsonReader;
67
import de.labystudio.spotifyapi.model.Track;
78
import de.labystudio.spotifyapi.open.model.AccessTokenResponse;
89
import de.labystudio.spotifyapi.open.model.track.OpenTrack;
9-
import de.labystudio.spotifyapi.open.totp.Secret;
10-
import de.labystudio.spotifyapi.open.totp.SecretFetcher;
1110
import de.labystudio.spotifyapi.open.totp.TOTP;
11+
import de.labystudio.spotifyapi.open.totp.gson.SecretDeserializer;
12+
import de.labystudio.spotifyapi.open.totp.model.Secret;
13+
import de.labystudio.spotifyapi.open.totp.provider.SecretProvider;
1214

1315
import javax.imageio.ImageIO;
1416
import javax.net.ssl.HttpsURLConnection;
@@ -32,7 +34,9 @@
3234
*/
3335
public class OpenSpotifyAPI {
3436

35-
public static final Gson GSON = new Gson();
37+
public static final Gson GSON = new GsonBuilder()
38+
.registerTypeAdapter(Secret.class, new SecretDeserializer())
39+
.create();
3640

3741
public static final String USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537." + (int) (Math.random() * 90);
3842
public static final String URL_API_GEN_ACCESS_TOKEN = "https://open.spotify.com/api/token?reason=%s&productType=web-player&totp=%s&totpServer=%s&totpVer=%s";
@@ -45,8 +49,14 @@ public class OpenSpotifyAPI {
4549
private final Cache<BufferedImage> imageCache = new Cache<>(10);
4650
private final Cache<OpenTrack> openTrackCache = new Cache<>(100);
4751

52+
private final SecretProvider secretProvider;
53+
4854
private AccessTokenResponse accessTokenResponse;
4955

56+
public OpenSpotifyAPI(SecretProvider secretProvider) {
57+
this.secretProvider = secretProvider;
58+
}
59+
5060
/**
5161
* Generate an access token asynchronously for the open spotify api
5262
*/
@@ -87,8 +97,8 @@ public long requestServerTime() throws IOException {
8797
* Generate an access token for the open spotify api
8898
*/
8999
private AccessTokenResponse generateAccessToken() throws IOException {
90-
SecretFetcher secretFetcher = new SecretFetcher();
91-
Secret secret = secretFetcher.fetchLatest();
100+
Secret secret = this.secretProvider.getSecret();
101+
92102
long serverTime = this.requestServerTime();
93103
String totp = TOTP.generateOtp(secret.toBytes(), serverTime, 30, 6);
94104

src/main/java/de/labystudio/spotifyapi/open/totp/SecretFetcher.java

Lines changed: 0 additions & 159 deletions
This file was deleted.

src/main/java/de/labystudio/spotifyapi/open/totp/TOTP.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
import java.security.InvalidKeyException;
88
import java.security.NoSuchAlgorithmException;
99

10+
/**
11+
* This class is used to generate a TOTP (Time-based One-Time Password) using the given secret, time, period, and number of digits.
12+
* It uses the HMAC-SHA1 algorithm to compute the TOTP based on the provided parameters.
13+
*
14+
* @author LabyStudio
15+
*/
1016
public class TOTP {
1117

1218
private static final String DEFAULT_ALGORITHM = "HmacSHA1";
@@ -23,7 +29,6 @@ public class TOTP {
2329
public static String generateOtp(byte[] secret, long time, int period, int digits) {
2430
long counter = time / period;
2531

26-
2732
// Convert counter to byte array (Big Endian)
2833
ByteBuffer buffer = ByteBuffer.allocate(8).order(ByteOrder.BIG_ENDIAN);
2934
buffer.putLong(counter);
@@ -52,6 +57,4 @@ public static String generateOtp(byte[] secret, long time, int period, int digit
5257
throw new IllegalStateException("Failed to generate TOTP", e);
5358
}
5459
}
55-
56-
5760
}

0 commit comments

Comments
 (0)