Skip to content

Instantly share code, notes, and snippets.

@guymac
Last active October 24, 2023 19:55
Show Gist options
  • Save guymac/1a41a9ff0dca1ded4f42f0f33315ee8c to your computer and use it in GitHub Desktop.
Save guymac/1a41a9ff0dca1ded4f42f0f33315ee8c to your computer and use it in GitHub Desktop.
Given a Spotify playlist URL, prints out a track listing.
import java.io.*;
import java.net.*;
import java.net.http.*;
import java.nio.charset.*;
import java.util.*;
import javax.swing.text.html.parser.*;
import javax.swing.text.html.*;
import javax.swing.text.*;
/**
* The playlist contains meta tags with name attributes of "music:song", each is a URL
* to a song page where the meta og:title is the track title and og:description contains
* the artist
*/
public class SpotLister extends HTMLEditorKit.ParserCallback
{
private List <String> tracks = new ArrayList <> ();
private String title, artist;
static HttpClient client = HttpClient.newHttpClient();
public SpotLister(String uri)
{
list(uri);
for (var it = tracks.listIterator() ; it.hasNext() ;)
{
list(it.next());
System.out.format("%d. %s / %s%n", it.nextIndex(), title, artist);
}
}
private void list(String uri)
{
try
{
var req = HttpRequest.newBuilder(new URI(uri)).build();
var res = HttpResponse.BodyHandlers.ofInputStream();
new ParserDelegator().parse(new InputStreamReader(client.send(req, res).body(), StandardCharsets.UTF_8), this, true);
}
catch (IOException ex)
{
System.err.format("HTML parsing failed due to %s", ex.getMessage());
}
catch (URISyntaxException ex)
{
System.err.format("Invalid URI %s", uri);
}
catch (Exception ex)
{
System.err.format("HTTP request failed due to %s", ex.getMessage());
}
}
@Override
public void handleSimpleTag(HTML.Tag t, MutableAttributeSet s, int pos)
{
if (!(t.equals(HTML.Tag.META) && s.isDefined(HTML.Attribute.CONTENT))) return;
var content = s.getAttribute(HTML.Attribute.CONTENT).toString();
if (s.isDefined(HTML.Attribute.NAME) && "music:song".equals(s.getAttribute(HTML.Attribute.NAME).toString()))
{
tracks.add(content);
return;
}
if (!s.isDefined("property")) return;
var property = s.getAttribute("property").toString();
if ("og:description".equals(property)) artist = content.replaceFirst(" ·.*", "");
else if ("og:title".equals(property)) title = content;
}
public static void main(String[] args)
{
Arrays.stream(args).forEach(SpotLister::new);
}
}
@guymac
Copy link
Author

guymac commented Dec 7, 2022

Updated for latest Spotify html output, Dec 2022

@guymac
Copy link
Author

guymac commented Jul 27, 2023

Rewritten for new Spotify, July 2023

@guymac
Copy link
Author

guymac commented Oct 23, 2023

Updated, October 2023.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment