Implemented adding songs to playlist

\+ Creation of playlist with default name
\+ implemented track search (opens #2)
\+ Implemented adding tracks to list
\+ Implemented setting custom playlist cover

- Missing ability to select file to upload as cover (opens #3)
- Missing saving and retrieving auth tokens for use in chron jobs + flag to enable (opens #4)
- Known issue: some tracks cannot be found, although they were played on spotify to be scrobbled onto lastfm (see #2)
- Missing flag to set a custom playlist name (opens #5)
- missing flags to make playlists public and/or collaborative on creation. (opens #6)
This commit is contained in:
Alix von Schirp
2023-01-21 02:24:52 +01:00
parent 362ac0e4c3
commit 011cdc1481
2 changed files with 76 additions and 13 deletions

View File

@@ -1,15 +1,26 @@
package de.b00tload.tools.lastfmtospotifyplaylist;
import com.neovisionaries.i18n.CountryCode;
import de.b00tload.tools.lastfmtospotifyplaylist.arguments.ArgumentHandler;
import de.b00tload.tools.lastfmtospotifyplaylist.arguments.Arguments;
import de.b00tload.tools.lastfmtospotifyplaylist.util.PeriodHelper;
import de.b00tload.tools.lastfmtospotifyplaylist.util.TokenHelper;
import de.umass.lastfm.Caller;
import de.umass.lastfm.Track;
import de.umass.lastfm.User;
import io.javalin.Javalin;
import io.javalin.http.ContentType;
import se.michaelthelin.spotify.SpotifyApi;
import se.michaelthelin.spotify.model_objects.credentials.AuthorizationCodeCredentials;
import se.michaelthelin.spotify.model_objects.specification.Playlist;
import java.util.Collection;
import java.util.HashMap;
import java.net.URI;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import static de.b00tload.tools.lastfmtospotifyplaylist.util.Logger.logLn;
@@ -22,6 +33,7 @@ public class LastFMToSpotify {
// create hash map with user agent
configuration = new HashMap<>();
configuration.put("requests.useragent", "LastFMToSpotify/1.0-Snapshot (" + System.getProperty("os.name") + "; " + System.getProperty("os.arch") + ") Java/" + System.getProperty("java.version"));
configuration.put("playlist.name", "LastFMToSpotify@" + LocalDateTime.now(Clock.systemDefaultZone()).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
// parse arguments
for (int a = 0; a < args.length; a++) {
Arguments arg;
@@ -49,28 +61,60 @@ public class LastFMToSpotify {
// Start Progress Bar
try {
logLn("Authenticating with Spotify...", 1);
SpotifyApi.Builder build = SpotifyApi.builder();
build.setClientId(configuration.get("spotify.clientid"));
build.setClientSecret(configuration.get("spotify.secret"));
build.setRedirectUri(URI.create("http://localhost:9876/callback/spotify/"));
SpotifyApi api = build.build();
AtomicBoolean waiting = new AtomicBoolean(true);
try (Javalin webserver = Javalin.create().start(9876)) {
webserver.get("/callback/spotify", ctx -> {
if(ctx.queryParamMap().containsKey("code")) {
AuthorizationCodeCredentials cred = api.authorizationCode(ctx.queryParam("code")).build().execute();
configuration.put("spotify.access", cred.getAccessToken());
if(configuration.containsKey("spotify.saveaccess")) TokenHelper.saveTokens(cred);
ctx.result("success. <script>window.close()</script>").contentType(ContentType.TEXT_HTML);
waiting.set(false);
} else {
logLn("Error: Spotify authorization failed."+LINE_SEPERATOR+ctx.queryParam("error"), 1);
System.exit(500);
}
});
logLn("Waiting for Spotify authorization.", 1);
//TODO: Open auth page in Browser
while (waiting.get());
webserver.stop();
}
logLn("Authenticating with LastFM...", 1);
Caller.getInstance().setUserAgent(configuration.get("requests.useragent"));
logLn(User.getInfo(configuration.get("lastfm.user"), configuration.get("lastfm.apikey")).getName(), 1);
logLn("Reading from LastFM...", 1);
Collection<Track> tracks = User.getTopTracks(configuration.get("lastfm.user"), PeriodHelper.getPeriodByString(configuration.get("lastfm.period")), configuration.get("lastfm.apikey"));
for (Track track : tracks) {
logLn(track.getName() + " by " + track.getArtist(), 3);
}
logLn("Creating Playlist...", 1);
//SpotifyApi.Builder build = SpotifyApi.builder();
//build.setClientId(configuration.get("spotify.clientid"));
//build.setClientSecret(configuration.get("spotify.secret"));
//build.setRedirectUri(URI.create("http://localhost:9876/callback/spotify/"));
//SpotifyApi api = build.build();
//api.setAccessToken(configuration.get("spotify.access"));
//api.createPlaylist(api.getCurrentUsersProfile().build().execute().getId(), configuration.get("playlist.name")).setHeader("User-Agent", configuration.get("requests.useragent"));
api.setAccessToken(configuration.get("spotify.access"));
Playlist list = api.createPlaylist(api.getCurrentUsersProfile().build().execute().getId(), configuration.get("playlist.name")).public_(configuration.containsKey("playlist.public")||configuration.containsKey("playlist.collab")).collaborative(configuration.containsKey("playlist.collab")).setHeader("User-Agent", configuration.get("requests.useragent")).build().execute();
List<String> adders = new LinkedList<>();
for (Track track : tracks) {
logLn("Adding " + track.getName() + " by " + track.getArtist(), 3);
StringBuilder searchQuery = new StringBuilder();
searchQuery.append("track:").append(track.getName());
searchQuery.append(" artist:").append(track.getArtist());
if(track.getAlbum()!=null&&!track.getAlbum().equalsIgnoreCase("null")&&!track.getAlbum().isEmpty())
searchQuery.append(" album:").append(track.getAlbum());
logLn("Search query: " + searchQuery.toString(), 3);
se.michaelthelin.spotify.model_objects.specification.Track[] add = api.searchTracks(searchQuery.toString()).market(CountryCode.DE).setHeader("User-Agent", configuration.get("requests.useragent")).build().execute().getItems();
if(add.length!=0) {
adders.add(add[0].getUri());
logLn("Added " + add[0].getName() + " to " + configuration.get("playlist.name"), 3);
}
}
api.addItemsToPlaylist(list.getId(), adders.toArray(String[]::new)).build().execute();
if(configuration.containsKey(configuration.get("playlist.cover"))) api.uploadCustomPlaylistCoverImage(list.getId()).image_data(configuration.get("playlist.cover")).build().execute();
logLn("Done.", 1);
// } catch (IOException | ParseException | SpotifyWebApiException e) {
} catch (Exception e) {
throw new RuntimeException(e);
}
//TODO: Implement
}
}

View File

@@ -0,0 +1,19 @@
package de.b00tload.tools.lastfmtospotifyplaylist.util;
import se.michaelthelin.spotify.model_objects.credentials.AuthorizationCodeCredentials;
public class TokenHelper {
public static void saveTokens(AuthorizationCodeCredentials cred) {
//TODO: Save tokens
}
public static String getAccessToken(){
//TODO: Read AccessToken
return "";
}
public static String getRefreshToken(){
//TODO: Read RefreshToken
return "";
}
}