use of com.sedmelluq.discord.lavaplayer.track.BasicAudioPlaylist in project lavaplayer by sedmelluq.
the class BandcampAudioSourceManager method loadAlbum.
private AudioItem loadAlbum(String albumUrl) {
return extractFromPage(albumUrl, (httpClient, text) -> {
String bandUrl = readBandUrl(text);
JsonBrowser trackListInfo = readTrackListInformation(text);
String artist = trackListInfo.get("artist").text();
List<AudioTrack> tracks = new ArrayList<>();
for (JsonBrowser trackInfo : trackListInfo.get("trackinfo").values()) {
tracks.add(extractTrack(trackInfo, bandUrl, artist));
}
JsonBrowser albumInfo = readAlbumInformation(text);
return new BasicAudioPlaylist(albumInfo.get("album_title").text(), tracks, null, false);
});
}
use of com.sedmelluq.discord.lavaplayer.track.BasicAudioPlaylist in project lavaplayer by sedmelluq.
the class YoutubeMixProvider method load.
/**
* Loads tracks from mix in parallel into a playlist entry.
*
* @param mixId ID of the mix
* @param selectedVideoId Selected track, {@link AudioPlaylist#getSelectedTrack()} will return this.
* @return Playlist of the tracks in the mix.
*/
public AudioPlaylist load(HttpInterface httpInterface, String mixId, String selectedVideoId, Function<AudioTrackInfo, AudioTrack> trackFactory) {
String playlistTitle = "YouTube mix";
List<AudioTrack> tracks = new ArrayList<>();
String mixUrl = "https://www.youtube.com/watch?v=" + selectedVideoId + "&list=" + mixId + PBJ_PARAMETER;
try (CloseableHttpResponse response = httpInterface.execute(new HttpGet(mixUrl))) {
HttpClientTools.assertSuccessWithContent(response, "mix response");
JsonBrowser body = JsonBrowser.parse(response.getEntity().getContent());
JsonBrowser playlist = body.index(3).get("response").get("contents").get("twoColumnWatchNextResults").get("playlist").get("playlist");
JsonBrowser title = playlist.get("title");
if (!title.isNull()) {
playlistTitle = title.text();
}
extractPlaylistTracks(playlist.get("contents"), tracks, trackFactory);
} catch (IOException e) {
throw new FriendlyException("Could not read mix page.", SUSPICIOUS, e);
}
if (tracks.isEmpty()) {
throw new FriendlyException("Could not find tracks from mix.", SUSPICIOUS, null);
}
AudioTrack selectedTrack = findSelectedTrack(tracks, selectedVideoId);
return new BasicAudioPlaylist(playlistTitle, tracks, selectedTrack, false);
}
use of com.sedmelluq.discord.lavaplayer.track.BasicAudioPlaylist in project lavaplayer by sedmelluq.
the class DefaultYoutubePlaylistLoader method buildPlaylist.
private AudioPlaylist buildPlaylist(HttpInterface httpInterface, JsonBrowser json, String selectedVideoId, Function<AudioTrackInfo, AudioTrack> trackFactory) throws IOException {
JsonBrowser jsonResponse = json.index(1).get("response");
String errorAlertMessage = findErrorAlert(jsonResponse);
if (errorAlertMessage != null) {
throw new FriendlyException(errorAlertMessage, COMMON, null);
}
JsonBrowser info = jsonResponse.get("sidebar").get("playlistSidebarRenderer").get("items").index(0).get("playlistSidebarPrimaryInfoRenderer");
String playlistName = info.get("title").get("runs").index(0).get("text").text();
JsonBrowser playlistVideoList = jsonResponse.get("contents").get("twoColumnBrowseResultsRenderer").get("tabs").index(0).get("tabRenderer").get("content").get("sectionListRenderer").get("contents").index(0).get("itemSectionRenderer").get("contents").index(0).get("playlistVideoListRenderer").get("contents");
List<AudioTrack> tracks = new ArrayList<>();
String continuationsToken = extractPlaylistTracks(playlistVideoList, tracks, trackFactory);
int loadCount = 0;
int pageCount = playlistPageCount;
// Also load the next pages, each result gives us a JSON with separate values for list html and next page loader html
while (continuationsToken != null && ++loadCount < pageCount) {
HttpPost post = new HttpPost(REQUEST_URL);
StringEntity payload = new StringEntity(String.format(REQUEST_PAYLOAD, continuationsToken), "UTF-8");
post.setEntity(payload);
try (CloseableHttpResponse response = httpInterface.execute(post)) {
HttpClientTools.assertSuccessWithContent(response, "playlist response");
JsonBrowser continuationJson = JsonBrowser.parse(response.getEntity().getContent());
JsonBrowser playlistVideoListPage = continuationJson.index(1).get("response").get("continuationContents").get("playlistVideoListContinuation");
if (playlistVideoListPage.isNull()) {
playlistVideoListPage = continuationJson.get("onResponseReceivedActions").index(0).get("appendContinuationItemsAction").get("continuationItems");
}
continuationsToken = extractPlaylistTracks(playlistVideoListPage, tracks, trackFactory);
}
}
return new BasicAudioPlaylist(playlistName, tracks, findSelectedTrack(tracks, selectedVideoId), false);
}
use of com.sedmelluq.discord.lavaplayer.track.BasicAudioPlaylist in project FredBoat by Frederikam.
the class TrackSearcher method searchForTracks.
/**
* @param query The search term
* @param cacheMaxAge Age of acceptable results from cache.
* @param timeoutMillis How long to wait for each lavaplayer search to answer
* @param providers Providers that shall be used for the search. They will be used in the order they are provided, the
* result of the first successful one will be returned
* @return The result of the search, or an empty list.
* @throws SearchingException If none of the search providers could give us a result, and there was at least one SearchingException thrown by them
*/
public AudioPlaylist searchForTracks(String query, long cacheMaxAge, int timeoutMillis, List<SearchProvider> providers) throws SearchingException {
Metrics.searchRequests.inc();
List<SearchProvider> provs = new ArrayList<>();
if (providers == null || providers.isEmpty()) {
log.warn("No search provider provided, defaulting to youtube -> soundcloud.");
provs.add(SearchProvider.YOUTUBE);
provs.add(SearchProvider.SOUNDCLOUD);
} else {
provs.addAll(providers);
}
SearchingException searchingException = null;
for (SearchProvider provider : provs) {
// 1. cache
AudioPlaylist cacheResult = fromCache(provider, query, cacheMaxAge);
if (cacheResult != null && !cacheResult.getTracks().isEmpty()) {
log.debug("Loaded search result {} {} from cache", provider, query);
Metrics.searchHits.labels("cache").inc();
return cacheResult;
}
// 2. lavaplayer todo break up this beautiful construction of ifs and exception handling in a better readable one?
if (provider != SearchProvider.YOUTUBE || System.currentTimeMillis() > youtubeCooldownUntil) {
try {
AudioPlaylist lavaplayerResult = new SearchResultHandler().searchSync(audioPlayerManager, provider, query, timeoutMillis);
if (!lavaplayerResult.getTracks().isEmpty()) {
log.debug("Loaded search result {} {} from lavaplayer", provider, query);
// got a search result? cache and return it
executor.execute(() -> searchResultService.mergeSearchResult(new SearchResult(audioPlayerManager, provider, query, lavaplayerResult)));
Metrics.searchHits.labels("lavaplayer-" + provider.name().toLowerCase()).inc();
return lavaplayerResult;
}
} catch (Http503Exception e) {
if (provider == SearchProvider.YOUTUBE) {
log.warn("Got a 503 from Youtube. Not hitting it with searches it for {} minutes", TimeUnit.MILLISECONDS.toMinutes(DEFAULT_YOUTUBE_COOLDOWN));
youtubeCooldownUntil = System.currentTimeMillis() + DEFAULT_YOUTUBE_COOLDOWN;
}
searchingException = e;
} catch (SearchingException e) {
searchingException = e;
}
}
// 3. optional: youtube api
if (provider == SearchProvider.YOUTUBE && (appConfig.isPatronDistribution() || appConfig.isDevDistribution())) {
try {
AudioPlaylist youtubeApiResult = youtubeAPI.search(query, MAX_RESULTS, audioPlayerManager.source(YoutubeAudioSourceManager.class));
if (!youtubeApiResult.getTracks().isEmpty()) {
log.debug("Loaded search result {} {} from Youtube API", provider, query);
// got a search result? cache and return it
executor.execute(() -> searchResultService.mergeSearchResult(new SearchResult(audioPlayerManager, provider, query, youtubeApiResult)));
Metrics.searchHits.labels("youtube-api").inc();
return youtubeApiResult;
}
} catch (SearchingException e) {
searchingException = e;
}
}
}
// did we run into searching exceptions that made us end up here?
if (searchingException != null) {
Metrics.searchHits.labels("exception").inc();
throw searchingException;
}
// no result with any of the search providers
Metrics.searchHits.labels("empty").inc();
return new BasicAudioPlaylist("Search result for: " + query, Collections.emptyList(), null, true);
}
use of com.sedmelluq.discord.lavaplayer.track.BasicAudioPlaylist in project FredBoat by Frederikam.
the class YoutubeAPI method search.
/**
* @param query Search Youtube for this query
* @param maxResults Keep this as small as necessary, each of the videos needs to be looked up for more detailed info
* @param sourceManager The source manager may be used by the tracks to look further information up
* @return A playlist representing the search results; null if there was an exception
*/
// docs: https://developers.google.com/youtube/v3/docs/search/list
// theres a lot of room for tweaking the searches
public AudioPlaylist search(String query, int maxResults, YoutubeAudioSourceManager sourceManager) throws TrackSearcher.SearchingException {
JSONObject data;
String gkey = credentials.getRandomGoogleKey();
Http.SimpleRequest request = BotController.Companion.getHTTP().get(YOUTUBE_SEARCH, Http.Params.of("key", gkey, "type", "video", "maxResults", Integer.toString(maxResults), "q", query));
try {
data = request.asJson();
} catch (IOException e) {
throw new TrackSearcher.SearchingException("Youtube API search failed", e);
}
// The search contains all values we need, except for the duration :feelsbadman:
// so we need to do another query for each video.
List<String> ids = new ArrayList<>(maxResults);
try {
JSONArray items = data.getJSONArray("items");
for (int i = 0; i < items.length(); i++) {
JSONObject item = items.getJSONObject(i);
ids.add(item.getJSONObject("id").getString("videoId"));
}
} catch (JSONException e) {
String message = String.format("Youtube search with API key ending on %s for query %s returned unexpected JSON:\n%s", gkey.substring(20), query, data.toString());
throw new TrackSearcher.SearchingException(message, e);
}
List<AudioTrack> tracks = new ArrayList<>();
for (String id : ids) {
try {
YoutubeVideo vid = getVideoFromID(id, true);
tracks.add(sourceManager.buildTrackObject(id, vid.name, vid.channelTitle, vid.isStream, vid.getDurationInMillis()));
} catch (RuntimeException e) {
throw new TrackSearcher.SearchingException("Could not look up details for youtube video with id " + id, e);
}
}
return new BasicAudioPlaylist("Search results for: " + query, tracks, null, true);
}
Aggregations