use of net.robinfriedli.aiode.audio.spotify.SpotifyTrack in project aiode by robinfriedli.
the class Playlist method asTrackList.
/**
* returns all Songs as Spotify tracks including all videos that are redirected Spotify tracks i.e. the attribute
* redirectedSpotifyId is set. Mind that this method has to be invoked with client credentials
*/
public List<SpotifyTrack> asTrackList(SpotifyApi spotifyApi) {
SpotifyTrackBulkLoadingService service = new SpotifyTrackBulkLoadingService(spotifyApi);
List<SpotifyTrack> tracks = Lists.newArrayList();
for (PlaylistItem item : getItemsSorted()) {
if (item instanceof Song) {
String id = ((Song) item).getId();
service.add(createItem(id, TRACK), tracks::add);
} else if (item instanceof Episode) {
String id = ((Episode) item).getId();
service.add(createItem(id, EPISODE), tracks::add);
} else if (item instanceof Video && ((Video) item).getRedirectedSpotifyId() != null) {
Video video = (Video) item;
String redirectedSpotifyId = video.getRedirectedSpotifyId();
SpotifyItemKind kindEntity = video.getRedirectedSpotifyKind();
SpotifyTrackKind kind = kindEntity != null ? kindEntity.asEnum() : TRACK;
service.add(createItem(redirectedSpotifyId, kind), tracks::add);
}
}
service.perform();
return tracks;
}
use of net.robinfriedli.aiode.audio.spotify.SpotifyTrack in project aiode by robinfriedli.
the class ChartsCommand method getTrackForRecord.
private Playable getTrackForRecord(Object[] record, Session session) throws Exception {
long sourceEntityPk = (Long) record[0];
PlaybackHistorySource sourceEntity = session.load(PlaybackHistorySource.class, sourceEntityPk);
Playable.Source source = sourceEntity.asEnum();
String id = (String) record[1];
Long spotifyItemKindPk = (Long) record[3];
SpotifyItemKind spotifyItemKind = spotifyItemKindPk != null ? session.load(SpotifyItemKind.class, spotifyItemKindPk) : null;
switch(source) {
case SPOTIFY:
return runWithCredentials(() -> {
if (spotifyItemKind == null) {
throw new IllegalStateException("spotifyItemKind cannot be null for PlaybackHistory entries of source SPOTIFY");
}
SpotifyTrackKind kind = spotifyItemKind.asEnum();
SpotifyService spotifyService = getSpotifyService();
SpotifyTrack track = kind.loadSingleItem(spotifyService, id);
if (track == null) {
return null;
}
return new PlayableTrackWrapper(track);
});
case YOUTUBE:
YouTubeService youTubeService = Aiode.get().getAudioManager().getYouTubeService();
try {
return youTubeService.getVideoForId(id);
} catch (FriendlyException e) {
return null;
}
case URL:
return playableFactory.createPlayable(id, getContext().getSpotifyApi(), false);
}
throw new UnsupportedOperationException("Unsupported source " + sourceEntity);
}
use of net.robinfriedli.aiode.audio.spotify.SpotifyTrack in project aiode by robinfriedli.
the class UploadCommand method doRun.
@Override
public void doRun() throws Exception {
SpotifyApi spotifyApi = getContext().getSpotifyApi();
Playlist playlist = SearchEngine.searchLocalList(getContext().getSession(), getCommandInput());
if (playlist == null) {
throw new InvalidCommandException(String.format("No local list found for '%s'", getCommandInput()));
}
runWithLogin(() -> {
List<SpotifyTrack> tracks = playlist.asTrackList(spotifyApi);
String name = playlist.getName();
if (tracks.isEmpty()) {
throw new InvalidCommandException("Playlist " + name + " has no Spotify tracks.");
}
String userId = spotifyApi.getCurrentUsersProfile().build().execute().getId();
se.michaelthelin.spotify.model_objects.specification.Playlist spotifyPlaylist = spotifyApi.createPlaylist(userId, name).build().execute();
uploadedPlaylistName = spotifyPlaylist.getName();
String playlistId = spotifyPlaylist.getId();
List<String> trackUris = tracks.stream().map(SpotifyTrack::getUri).collect(Collectors.toList());
List<List<String>> sequences = Lists.partition(trackUris, 90);
for (List<String> sequence : sequences) {
spotifyApi.addItemsToPlaylist(playlistId, sequence.toArray(new String[0])).build().execute();
}
return null;
});
}
use of net.robinfriedli.aiode.audio.spotify.SpotifyTrack 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());
}
use of net.robinfriedli.aiode.audio.spotify.SpotifyTrack in project aiode by robinfriedli.
the class YouTubeService method getBestMatch.
private Video getBestMatch(List<Video> videos, SpotifyTrack spotifyTrack, StringList artists) {
Video video;
int size = videos.size();
if (size == 1) {
video = videos.get(0);
} else {
Map<Integer, Video> videosByScore = new HashMap<>();
Map<Video, Integer> editDistanceMap = new HashMap<>();
long[] viewCounts = new long[size];
for (int i = 0; i < size; i++) {
Video v = videos.get(i);
viewCounts[i] = getViewCount(v);
editDistanceMap.put(v, getBestEditDistance(spotifyTrack, v));
}
int index = 0;
for (Video v : videos) {
int artistMatchScore = 0;
if (artists.stream().anyMatch(a -> {
String artist = a.toLowerCase();
String artistNoSpace = artist.replaceAll(" ", "");
VideoSnippet snippet = v.getSnippet();
if (snippet == null) {
return false;
}
String channelTitle = snippet.getChannelTitle();
if (channelTitle == null) {
return false;
}
String channel = channelTitle.toLowerCase();
String channelNoSpace = channel.replace(" ", "");
return channel.contains(artist) || artist.contains(channel) || channelNoSpace.contains(artistNoSpace) || artistNoSpace.contains(channelNoSpace);
})) {
artistMatchScore = ARTIST_MATCH_SCORE_MULTIPLIER * size;
}
long viewCount = getViewCount(v);
int editDistance = editDistanceMap.get(v);
long viewRank = Arrays.stream(viewCounts).filter(c -> viewCount < c).count();
long editDistanceRank = editDistanceMap.values().stream().filter(d -> d < editDistance).count();
int viewScore = VIEW_SCORE_MULTIPLIER * (int) (size - viewRank);
int editDistanceScore = EDIT_DISTANCE_SCORE_MULTIPLIER * (int) (size - editDistanceRank);
int indexScore = INDEX_SCORE_MULTIPLIER * (size - index);
int totalScore = artistMatchScore + viewScore + editDistanceScore + indexScore;
videosByScore.putIfAbsent(totalScore, v);
++index;
}
@SuppressWarnings("OptionalGetWithoutIsPresent") int bestScore = videosByScore.keySet().stream().mapToInt(k -> k).max().getAsInt();
video = videosByScore.get(bestScore);
}
return video;
}
Aggregations