Search in sources :

Example 1 with ShowSimplified

use of se.michaelthelin.spotify.model_objects.specification.ShowSimplified in project aiode by robinfriedli.

the class Episode method initShow.

private void initShow(se.michaelthelin.spotify.model_objects.specification.Episode episode) {
    ShowSimplified show = episode.getShow();
    if (show != null) {
        showId = show.getId();
        showName = show.getName();
    }
}
Also used : ShowSimplified(se.michaelthelin.spotify.model_objects.specification.ShowSimplified)

Example 2 with ShowSimplified

use of se.michaelthelin.spotify.model_objects.specification.ShowSimplified in project aiode by robinfriedli.

the class AbstractPlayableLoadingCommand method loadSpotifyShow.

private void loadSpotifyShow(AudioManager audioManager) throws Exception {
    int limit = getArgumentValueWithTypeOrElse("select", Integer.class, 20);
    Callable<List<ShowSimplified>> albumLoadCallable = () -> getSpotifyService().searchShow(getCommandInput(), argumentSet("own"), limit);
    List<ShowSimplified> shows;
    if (argumentSet("own")) {
        shows = runWithLogin(albumLoadCallable);
    } else {
        shows = runWithCredentials(albumLoadCallable);
    }
    if (shows.size() == 1) {
        ShowSimplified show = shows.get(0);
        List<Episode> episodes = runWithCredentials(() -> getSpotifyService().getShowEpisodes(show.getId()));
        PlayableFactory playableFactory = audioManager.createPlayableFactory(getSpotifyService(), trackLoadingExecutor);
        List<Playable> playables = playableFactory.createPlayables(shouldRedirectSpotify(), episodes);
        handleResults(playables);
        loadedShow = show;
    } else if (shows.isEmpty()) {
        throw new NoSpotifyResultsFoundException(String.format("No shows found for '%s'", getCommandInput()));
    } else {
        askQuestion(shows, ShowSimplified::getName, ShowSimplified::getPublisher);
    }
}
Also used : Episode(se.michaelthelin.spotify.model_objects.specification.Episode) PlayableFactory(net.robinfriedli.aiode.audio.PlayableFactory) ShowSimplified(se.michaelthelin.spotify.model_objects.specification.ShowSimplified) UrlPlayable(net.robinfriedli.aiode.audio.UrlPlayable) Playable(net.robinfriedli.aiode.audio.Playable) StringList(net.robinfriedli.stringlist.StringList) List(java.util.List) NoSpotifyResultsFoundException(net.robinfriedli.aiode.exceptions.NoSpotifyResultsFoundException)

Example 3 with ShowSimplified

use of se.michaelthelin.spotify.model_objects.specification.ShowSimplified in project aiode by robinfriedli.

the class QueueCommand method getPlayablesForOption.

private List<Playable> getPlayablesForOption(Object chosenOption, PlayableFactory playableFactory) throws Exception {
    if (chosenOption instanceof Track || chosenOption instanceof YouTubeVideo || chosenOption instanceof Episode) {
        Playable track = playableFactory.createPlayable(shouldRedirectSpotify(), chosenOption);
        loadedTrack = track;
        return Collections.singletonList(track);
    } else if (chosenOption instanceof PlaylistSimplified) {
        PlaylistSimplified playlist = (PlaylistSimplified) chosenOption;
        List<SpotifyTrack> tracks = runWithCredentials(() -> getSpotifyService().getPlaylistTracks(playlist));
        List<Playable> playables = playableFactory.createPlayables(shouldRedirectSpotify(), tracks);
        loadedSpotifyPlaylist = playlist;
        return playables;
    } else if (chosenOption instanceof YouTubePlaylist) {
        YouTubePlaylist youTubePlaylist = (YouTubePlaylist) chosenOption;
        List<Playable> playables = playableFactory.createPlayables(youTubePlaylist);
        loadedYouTubePlaylist = youTubePlaylist;
        return playables;
    } else if (chosenOption instanceof AlbumSimplified) {
        AlbumSimplified album = (AlbumSimplified) chosenOption;
        List<Track> tracks = runWithCredentials(() -> getSpotifyService().getAlbumTracks(album.getId()));
        List<Playable> playables = playableFactory.createPlayables(shouldRedirectSpotify(), tracks);
        loadedAlbum = album;
        return playables;
    } else if (chosenOption instanceof AudioTrack) {
        Playable playable = playableFactory.createPlayable(shouldRedirectSpotify(), chosenOption);
        loadedAudioTrack = (AudioTrack) chosenOption;
        return Collections.singletonList(playable);
    } else if (chosenOption instanceof AudioPlaylist) {
        List<Playable> playables = playableFactory.createPlayables(shouldRedirectSpotify(), chosenOption);
        loadedAudioPlaylist = (AudioPlaylist) chosenOption;
        return playables;
    } else if (chosenOption instanceof ShowSimplified) {
        ShowSimplified show = (ShowSimplified) chosenOption;
        List<Episode> episodes = runWithCredentials(() -> getSpotifyService().getShowEpisodes(show.getId()));
        List<Playable> playables = playableFactory.createPlayables(shouldRedirectSpotify(), episodes);
        loadedShow = show;
        return playables;
    }
    throw new UnsupportedOperationException("Unsupported chosen option type: " + chosenOption.getClass());
}
Also used : ShowSimplified(se.michaelthelin.spotify.model_objects.specification.ShowSimplified) Episode(se.michaelthelin.spotify.model_objects.specification.Episode) Playable(net.robinfriedli.aiode.audio.Playable) YouTubePlaylist(net.robinfriedli.aiode.audio.youtube.YouTubePlaylist) AlbumSimplified(se.michaelthelin.spotify.model_objects.specification.AlbumSimplified) List(java.util.List) AudioTrack(com.sedmelluq.discord.lavaplayer.track.AudioTrack) YouTubeVideo(net.robinfriedli.aiode.audio.youtube.YouTubeVideo) SpotifyTrack(net.robinfriedli.aiode.audio.spotify.SpotifyTrack) Track(se.michaelthelin.spotify.model_objects.specification.Track) AudioTrack(com.sedmelluq.discord.lavaplayer.track.AudioTrack) PlaylistSimplified(se.michaelthelin.spotify.model_objects.specification.PlaylistSimplified) AudioPlaylist(com.sedmelluq.discord.lavaplayer.track.AudioPlaylist)

Example 4 with ShowSimplified

use of se.michaelthelin.spotify.model_objects.specification.ShowSimplified in project aiode by robinfriedli.

the class SpotifyTrack method getDisplay.

public String getDisplay() {
    String name = getName();
    String artistString = exhaustiveMatch(track -> StringList.create(track.getArtists(), ArtistSimplified::getName).toSeparatedString(", "), episode -> {
        ShowSimplified show = episode.getShow();
        if (show != null) {
            return show.getName();
        }
        return null;
    });
    if (!Strings.isNullOrEmpty(artistString)) {
        return String.format("%s by %s", name, artistString);
    } else {
        return name;
    }
}
Also used : ShowSimplified(se.michaelthelin.spotify.model_objects.specification.ShowSimplified) ArtistSimplified(se.michaelthelin.spotify.model_objects.specification.ArtistSimplified)

Example 5 with ShowSimplified

use of se.michaelthelin.spotify.model_objects.specification.ShowSimplified in project aiode by robinfriedli.

the class YouTubeService method redirectSpotify.

/**
 * Workaround as Spotify does not allow full playback of tracks via third party APIs using the web api for licencing
 * reasons. Gets the metadata and searches the corresponding YouTube video. The only way to stream from Spotify
 * directly is by using the $preview argument with the {@link PlayCommand} or {@link QueueCommand} which plays the
 * provided mp3 preview.
 * <p>
 * However Spotify MIGHT release an SDK supporting full playback of songs across all devices, not just browsers in
 * which case this method and the corresponding block in {@link PlayableFactory#createPlayable(boolean, Object)} should
 * be removed.
 * For reference, see <a href="https://github.com/spotify/web-api/issues/57">Web playback of Full Tracks - Github</a>
 * <p>
 * This method searches 5 youtube videos using the Spotify track name + artist and then uses a combination of
 * levenshtein distance, whether or not the channel title matches the artist, the view count and the index in the
 * youtube response to determine the best match.
 * <p>
 * If the current YouTube API quota usage is beneath the threshold then this action
 * will use the YouTube API, costing {@link #QUOTA_COST_SEARCH} + {@link #QUOTA_COST_LIST} (this also applies
 * when searching with lavaplayer) quota. Else this uses lavaplayer to load the video metadata by scraping the HTML
 * page returned by YouTube.
 *
 * @param youTubeVideo the hollow youtube that has already been added to the queue and awaits to receive values
 */
public void redirectSpotify(HollowYouTubeVideo youTubeVideo) throws IOException {
    SpotifyTrack spotifyTrack = youTubeVideo.getRedirectedSpotifyTrack();
    if (spotifyTrack == null) {
        throw new IllegalArgumentException(youTubeVideo.toString() + " is not a placeholder for a redirected Spotify Track");
    }
    StringList artists = spotifyTrack.exhaustiveMatch(track -> StringList.create(track.getArtists(), ArtistSimplified::getName), episode -> {
        ShowSimplified show = episode.getShow();
        if (show != null) {
            return StringList.of(show.getName());
        }
        return StringList.create();
    });
    String searchTerm = spotifyTrack.getName() + " " + artists.toSeparatedString(" ");
    List<String> videoIds;
    if (currentQuota.get() < quotaThreshold) {
        YouTube.Search.List search = youTube.search().list(List.of("id", "snippet"));
        search.setKey(apiKey);
        search.setQ(searchTerm);
        // set topic to filter results to music video
        search.setTopicId("/m/04rlf");
        search.setType(List.of("video"));
        search.setFields("items(snippet/title,id/videoId)");
        search.setMaxResults((long) REDIRECT_SEARCH_AMOUNT);
        List<SearchResult> items = doWithQuota(QUOTA_COST_SEARCH, () -> search.execute().getItems());
        if (items.isEmpty()) {
            youTubeVideo.cancel();
            return;
        }
        videoIds = items.stream().map(item -> item.getId().getVideoId()).collect(Collectors.toList());
    } else {
        AudioTrackLoader audioTrackLoader = new AudioTrackLoader(Aiode.get().getAudioManager().getPlayerManager());
        AudioItem audioItem;
        try {
            audioItem = audioTrackLoader.loadByIdentifier("ytsearch:" + searchTerm);
        } catch (FriendlyException e) {
            youTubeVideo.cancel();
            return;
        }
        if (!(audioItem instanceof AudioPlaylist)) {
            youTubeVideo.cancel();
            return;
        }
        AudioPlaylist resultList = (AudioPlaylist) audioItem;
        List<AudioTrack> tracks = resultList.getTracks();
        if (tracks.isEmpty()) {
            youTubeVideo.cancel();
            return;
        }
        List<AudioTrack> audioTracks = tracks.subList(0, Math.min(tracks.size(), REDIRECT_SEARCH_AMOUNT));
        videoIds = audioTracks.stream().map(AudioTrack::getIdentifier).collect(Collectors.toList());
    }
    List<Video> videos = getAllVideos(videoIds);
    if (videos.isEmpty()) {
        youTubeVideo.cancel();
        return;
    }
    Video video = getBestMatch(videos, spotifyTrack, artists);
    String videoId = video.getId();
    long durationMillis = getDurationMillis(videoId);
    String artistString = artists.toSeparatedString(", ");
    String title = spotifyTrack.getName() + " by " + artistString;
    youTubeVideo.setTitle(title);
    youTubeVideo.setId(videoId);
    youTubeVideo.setDuration(durationMillis);
}
Also used : ShowSimplified(se.michaelthelin.spotify.model_objects.specification.ShowSimplified) StringList(net.robinfriedli.stringlist.StringList) AudioTrackLoader(net.robinfriedli.aiode.audio.AudioTrackLoader) SearchResult(com.google.api.services.youtube.model.SearchResult) AudioItem(com.sedmelluq.discord.lavaplayer.track.AudioItem) FriendlyException(com.sedmelluq.discord.lavaplayer.tools.FriendlyException) SpotifyTrack(net.robinfriedli.aiode.audio.spotify.SpotifyTrack) Video(com.google.api.services.youtube.model.Video) AudioTrack(com.sedmelluq.discord.lavaplayer.track.AudioTrack) AudioPlaylist(com.sedmelluq.discord.lavaplayer.track.AudioPlaylist)

Aggregations

ShowSimplified (se.michaelthelin.spotify.model_objects.specification.ShowSimplified)8 StringList (net.robinfriedli.stringlist.StringList)5 List (java.util.List)4 SpotifyTrack (net.robinfriedli.aiode.audio.spotify.SpotifyTrack)4 AudioPlaylist (com.sedmelluq.discord.lavaplayer.track.AudioPlaylist)2 AudioTrack (com.sedmelluq.discord.lavaplayer.track.AudioTrack)2 Objects (java.util.Objects)2 Playable (net.robinfriedli.aiode.audio.Playable)2 YouTubePlaylist (net.robinfriedli.aiode.audio.youtube.YouTubePlaylist)2 YouTubeVideo (net.robinfriedli.aiode.audio.youtube.YouTubeVideo)2 NoSpotifyResultsFoundException (net.robinfriedli.aiode.exceptions.NoSpotifyResultsFoundException)2 AlbumSimplified (se.michaelthelin.spotify.model_objects.specification.AlbumSimplified)2 ArtistSimplified (se.michaelthelin.spotify.model_objects.specification.ArtistSimplified)2 Episode (se.michaelthelin.spotify.model_objects.specification.Episode)2 PlaylistSimplified (se.michaelthelin.spotify.model_objects.specification.PlaylistSimplified)2 SearchResult (com.google.api.services.youtube.model.SearchResult)1 Video (com.google.api.services.youtube.model.Video)1 FriendlyException (com.sedmelluq.discord.lavaplayer.tools.FriendlyException)1 AudioItem (com.sedmelluq.discord.lavaplayer.track.AudioItem)1 BigInteger (java.math.BigInteger)1