diff --git a/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicAudioPlaylist.java b/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicAudioPlaylist.java index ff9b8d55..5f89dfb4 100644 --- a/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicAudioPlaylist.java +++ b/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicAudioPlaylist.java @@ -7,8 +7,8 @@ public class YandexMusicAudioPlaylist extends ExtendedAudioPlaylist { - public YandexMusicAudioPlaylist(String name, List tracks, ExtendedAudioPlaylist.Type type, String identifier, String artworkURL, String author) { - super(name, tracks, type, identifier, artworkURL, author, null); + public YandexMusicAudioPlaylist(String name, List tracks, ExtendedAudioPlaylist.Type type, String url, String artworkURL, String author, Integer totalTracks) { + super(name, tracks, type, url, artworkURL, author, totalTracks); } } diff --git a/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicAudioTrack.java b/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicAudioTrack.java index fafa2202..11450a27 100644 --- a/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicAudioTrack.java +++ b/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicAudioTrack.java @@ -1,11 +1,11 @@ package com.github.topi314.lavasrc.yandexmusic; +import com.github.topi314.lavasrc.ExtendedAudioTrack; import com.sedmelluq.discord.lavaplayer.container.mp3.Mp3AudioTrack; import com.sedmelluq.discord.lavaplayer.source.AudioSourceManager; import com.sedmelluq.discord.lavaplayer.tools.io.PersistentHttpStream; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo; -import com.sedmelluq.discord.lavaplayer.track.DelegatedAudioTrack; import com.sedmelluq.discord.lavaplayer.track.playback.LocalAudioTrackExecutor; import org.jsoup.Jsoup; import org.jsoup.parser.Parser; @@ -16,12 +16,17 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -public class YandexMusicAudioTrack extends DelegatedAudioTrack { +public class YandexMusicAudioTrack extends ExtendedAudioTrack { private final YandexMusicSourceManager sourceManager; public YandexMusicAudioTrack(AudioTrackInfo trackInfo, YandexMusicSourceManager sourceManager) { - super(trackInfo); + super(trackInfo, null, null, null, null, null, false); + this.sourceManager = sourceManager; + } + + public YandexMusicAudioTrack(AudioTrackInfo trackInfo, String albumName, String albumUrl, String artistUrl, String artistArtworkUrl, YandexMusicSourceManager sourceManager) { + super(trackInfo, albumName, albumUrl, artistUrl, artistArtworkUrl, null, false); this.sourceManager = sourceManager; } diff --git a/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicSourceManager.java b/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicSourceManager.java index 7e2ed2fa..e0de0371 100644 --- a/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicSourceManager.java +++ b/main/src/main/java/com/github/topi314/lavasrc/yandexmusic/YandexMusicSourceManager.java @@ -1,9 +1,9 @@ package com.github.topi314.lavasrc.yandexmusic; import com.github.topi314.lavasrc.ExtendedAudioPlaylist; +import com.github.topi314.lavasrc.ExtendedAudioSourceManager; import com.github.topi314.lavasrc.LavaSrcTools; import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; -import com.sedmelluq.discord.lavaplayer.source.AudioSourceManager; import com.sedmelluq.discord.lavaplayer.tools.JsonBrowser; import com.sedmelluq.discord.lavaplayer.tools.io.HttpClientTools; import com.sedmelluq.discord.lavaplayer.tools.io.HttpConfigurable; @@ -17,7 +17,6 @@ import org.slf4j.LoggerFactory; import java.io.DataInput; -import java.io.DataOutput; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -28,7 +27,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -public class YandexMusicSourceManager implements AudioSourceManager, HttpConfigurable { +public class YandexMusicSourceManager extends ExtendedAudioSourceManager implements HttpConfigurable { public static final Pattern URL_PATTERN = Pattern.compile("(https?://)?music\\.yandex\\.(ru|com)/(?artist|album|track)/(?[0-9]+)(/(?track)/(?[0-9]+))?/?"); public static final Pattern URL_PLAYLIST_PATTERN = Pattern.compile("(https?://)?music\\.yandex\\.(ru|com)/users/(?[0-9A-Za-z@.-]+)/playlists/(?[0-9]+)/?"); public static final String SEARCH_PREFIX = "ymsearch:"; @@ -122,7 +121,15 @@ private AudioItem getAlbum(String id) throws IOException { } var coverUri = json.get("result").get("coverUri").text(); var author = json.get("result").get("artists").values().get(0).get("name").text(); - return new YandexMusicAudioPlaylist(json.get("result").get("title").text(), tracks, ExtendedAudioPlaylist.Type.ALBUM, json.get("result").get("url").text(), this.formatCoverUri(coverUri), author); + return new YandexMusicAudioPlaylist( + json.get("result").get("title").text(), + tracks, + ExtendedAudioPlaylist.Type.ALBUM, + "https://music.yandex.ru/album/" + id, + this.formatCoverUri(coverUri), + author, + tracks.size() + ); } private AudioItem getTrack(String id) throws IOException { @@ -144,10 +151,27 @@ private AudioItem getArtist(String id) throws IOException { return AudioReference.NO_TRACK; } - var artistJson = this.getJson(PUBLIC_API_BASE + "/artists/" + id); - var coverUri = json.get("result").get("coverUri").text(); - var author = artistJson.get("result").get("artist").get("name").text(); - return new YandexMusicAudioPlaylist(author + "'s Top Tracks", tracks, ExtendedAudioPlaylist.Type.ARTIST, json.get("result").get("url").text(), this.formatCoverUri(coverUri), author); + var artistJsonResponse = this.getJson(PUBLIC_API_BASE + "/artists/" + id); + var artistJson = artistJsonResponse.get("result").get("artist"); + var author = artistJson.get("name").text(); + + String coverUri = null; + + if (!artistJson.get("ogImage").isNull()) { + coverUri = this.formatCoverUri(artistJson.get("ogImage").text()); + } else if (!artistJson.get("cover").isNull()) { + coverUri = this.formatCoverUri(artistJson.get("cover").get("uri").text()); + } + + return new YandexMusicAudioPlaylist( + author + "'s Top Tracks", + tracks, + ExtendedAudioPlaylist.Type.ARTIST, + "https://music.yandex.ru/artist/" + id, + coverUri, + author, + tracks.size() + ); } private AudioItem getPlaylist(String userString, String id) throws IOException { @@ -169,10 +193,25 @@ private AudioItem getPlaylist(String userString, String id) throws IOException { if (tracks.isEmpty()) { return AudioReference.NO_TRACK; } - var playlistTitle = json.get("result").get("kind").text().equals("3") ? "Liked songs" : json.get("result").get("title").text(); + String playlistTitle; + if (json.get("result").get("kind").text().equals("3")) { + var ownerJson = json.get("result").get("owner"); + var ownerName = ownerJson.get("name").isNull() ? ownerJson.get("login").text() : ownerJson.get("name").text(); + playlistTitle = ownerName + "'s liked songs"; + } else { + playlistTitle = json.get("result").get("title").text(); + } var coverUri = json.get("result").get("cover").get("uri").text(); var author = json.get("result").get("owner").get("name").text(); - return new YandexMusicAudioPlaylist(playlistTitle, tracks, ExtendedAudioPlaylist.Type.PLAYLIST, json.get("result").get("url").text(), this.formatCoverUri(coverUri), author); + return new YandexMusicAudioPlaylist( + playlistTitle, + tracks, + ExtendedAudioPlaylist.Type.PLAYLIST, + "https://music.yandex.ru/users/" + userString + "/playlists/" + id, + this.formatCoverUri(coverUri), + author, + tracks.size() + ); } private List getTracks(String trackIds) throws IOException { @@ -181,8 +220,8 @@ private List getTracks(String trackIds) throws IOException { private String getTrackIds(List tracksToParse) { return tracksToParse.stream() - .map(node -> node.get("id").text()) - .collect(Collectors.joining(",")); + .map(node -> node.get("id").text()) + .collect(Collectors.joining(",")); } public JsonBrowser getJson(String uri) throws IOException { @@ -217,18 +256,40 @@ private AudioTrack parseTrack(JsonBrowser json) { var id = json.get("id").text(); var artist = parseArtist(json); var coverUri = json.get("coverUri").text(); + + String albumName = null; + String albumUrl = null; + if (!json.get("albums").values().isEmpty()) { + var album = json.get("albums").values().get(0); + albumName = album.get("title").text(); + albumUrl = "https://music.yandex.ru/album/" + album.get("id").text(); + } + + String artistUrl = null; + String artistArtworkUrl = null; + if (!json.get("artists").values().isEmpty()) { + var firstArtist = json.get("artists").values().get(0); + artistUrl = "https://music.yandex.ru/artist/" + firstArtist.get("id").text(); + if (!firstArtist.get("cover").isNull()) { + artistArtworkUrl = this.formatCoverUri(firstArtist.get("cover").get("uri").text()); + } + } return new YandexMusicAudioTrack( - new AudioTrackInfo( - json.get("title").text(), - artist, - json.get("durationMs").as(Long.class), - id, - false, - "https://music.yandex.ru/track/" + id, - this.formatCoverUri(coverUri), - null - ), - this + new AudioTrackInfo( + json.get("title").text(), + artist, + json.get("durationMs").as(Long.class), + id, + false, + "https://music.yandex.ru/track/" + id, + this.formatCoverUri(coverUri), + null + ), + albumName, + albumUrl, + artistUrl, + artistArtworkUrl, + this ); } @@ -250,8 +311,8 @@ private String parseArtist(JsonBrowser json) { private String extractArtists(JsonBrowser artistNode) { return artistNode.values().stream() - .map(node -> node.get("name").text()) - .collect(Collectors.joining(", ")); + .map(node -> node.get("name").text()) + .collect(Collectors.joining(", ")); } private String formatCoverUri(String coverUri) { @@ -259,17 +320,15 @@ private String formatCoverUri(String coverUri) { } @Override - public boolean isTrackEncodable(AudioTrack track) { - return true; - } - - @Override - public void encodeTrack(AudioTrack track, DataOutput output) { - } - - @Override - public AudioTrack decodeTrack(AudioTrackInfo trackInfo, DataInput input) { - return new YandexMusicAudioTrack(trackInfo, this); + public AudioTrack decodeTrack(AudioTrackInfo trackInfo, DataInput input) throws IOException { + var extendedAudioTrackInfo = super.decodeTrack(input); + return new YandexMusicAudioTrack(trackInfo, + extendedAudioTrackInfo.albumName, + extendedAudioTrackInfo.albumUrl, + extendedAudioTrackInfo.artistUrl, + extendedAudioTrackInfo.artistArtworkUrl, + this + ); } @Override