use of net.robinfriedli.aiode.audio.spotify.SpotifyTrackBulkLoadingService in project aiode by robinfriedli.
the class HibernatePlaylistMigrator method perform.
@Override
public Map<Playlist, List<PlaylistItem>> perform() throws Exception {
ShardManager shardManager = Aiode.get().getShardManager();
SpotifyTrackBulkLoadingService spotifyBulkLoadingService = new SpotifyTrackBulkLoadingService(spotifyApi);
List<XmlElement> playlists = context.query(tagName("playlist")).collect();
Map<Playlist, List<PlaylistItem>> playlistMap = new HashMap<>();
for (XmlElement playlist : playlists) {
Playlist newPlaylist = new Playlist();
newPlaylist.setName(playlist.getAttribute("name").getValue());
newPlaylist.setCreatedUser(playlist.getAttribute("createdUser").getValue());
newPlaylist.setCreatedUserId(playlist.getAttribute("createdUserId").getValue());
newPlaylist.setGuild(guild.getName());
newPlaylist.setGuildId(guild.getId());
List<XmlElement> items = playlist.getSubElements();
Map<PlaylistItem, Integer> itemsWithIndex = new HashMap<>();
for (int i = 0; i < items.size(); i++) {
XmlElement item = items.get(i);
switch(item.getTagName()) {
case "song":
loadSpotifyItem(item, i, spotifyBulkLoadingService, shardManager, newPlaylist, itemsWithIndex, TRACK);
break;
case "episode":
loadSpotifyItem(item, i, spotifyBulkLoadingService, shardManager, newPlaylist, itemsWithIndex, EPISODE);
break;
case "video":
Video video = new Video();
video.setId(item.getAttribute("id").getValue());
video.setTitle(item.getAttribute("title").getValue());
if (item.hasAttribute("redirectedSpotifyId")) {
video.setRedirectedSpotifyId(item.getAttribute("redirectedSpotifyId").getValue());
}
if (item.hasAttribute("spotifyTrackName")) {
video.setSpotifyTrackName(item.getAttribute("spotifyTrackName").getValue());
}
video.setPlaylist(newPlaylist);
video.setDuration(item.getAttribute("duration").getLong());
video.setAddedUser(item.getAttribute("addedUser").getValue());
video.setAddedUserId(item.getAttribute("addedUserId").getValue());
newPlaylist.getVideos().add(video);
itemsWithIndex.put(video, i);
break;
case "urlTrack":
UrlTrack urlTrack = new UrlTrack();
urlTrack.setUrl(item.getAttribute("url").getValue());
urlTrack.setTitle(item.getAttribute("title").getValue());
urlTrack.setDuration(item.getAttribute("duration").getLong());
urlTrack.setAddedUser(item.getAttribute("addedUser").getValue());
urlTrack.setAddedUserId(item.getAttribute("addedUserId").getValue());
urlTrack.setPlaylist(newPlaylist);
newPlaylist.getUrlTracks().add(urlTrack);
itemsWithIndex.put(urlTrack, i);
break;
}
}
SpotifyInvoker.create(spotifyApi).invoke(() -> {
spotifyBulkLoadingService.perform();
return null;
});
List<PlaylistItem> playlistItems = itemsWithIndex.keySet().stream().sorted(Comparator.comparing(itemsWithIndex::get)).collect(Collectors.toList());
playlistMap.put(newPlaylist, playlistItems);
}
return playlistMap;
}
use of net.robinfriedli.aiode.audio.spotify.SpotifyTrackBulkLoadingService 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.SpotifyTrackBulkLoadingService in project aiode by robinfriedli.
the class Playlist method getTracks.
/**
* Returns the items in this playlist as objects supported by the {@link PlayableFactory} class. Note that getting the
* Spotify track for a Song requires this method to be invoked with client credentials
*/
public List<Object> getTracks(SpotifyApi spotifyApi) {
List<PlaylistItem> playlistItems = getItemsSorted();
SpotifyTrackBulkLoadingService service = new SpotifyTrackBulkLoadingService(spotifyApi);
Map<Object, Integer> itemsWithIndex = new HashMap<>();
for (int i = 0; i < playlistItems.size(); i++) {
PlaylistItem item = playlistItems.get(i);
if (item instanceof Song) {
String id = ((Song) item).getId();
int finalI = i;
service.add(createItem(id, TRACK), track -> itemsWithIndex.put(track, finalI));
} else if (item instanceof Episode) {
String id = ((Episode) item).getId();
int finalI = i;
service.add(createItem(id, EPISODE), track -> itemsWithIndex.put(track, finalI));
} else if (item instanceof Video) {
Video video = (Video) item;
YouTubeVideo youtubeVideo = video.asYouTubeVideo();
itemsWithIndex.put(youtubeVideo, i);
String spotifyId = video.getRedirectedSpotifyId();
if (!Strings.isNullOrEmpty(spotifyId)) {
SpotifyItemKind kindEntity = video.getRedirectedSpotifyKind();
SpotifyTrackKind kind = kindEntity != null ? kindEntity.asEnum() : TRACK;
service.add(createItem(spotifyId, kind), youtubeVideo::setRedirectedSpotifyTrack);
}
} else if (item instanceof UrlTrack) {
itemsWithIndex.put(item, i);
}
}
service.perform();
return itemsWithIndex.keySet().stream().sorted(Comparator.comparing(itemsWithIndex::get)).collect(Collectors.toList());
}
use of net.robinfriedli.aiode.audio.spotify.SpotifyTrackBulkLoadingService in project aiode by robinfriedli.
the class RefreshSpotifyRedirectIndicesTask method run.
@Override
protected void run(JobExecutionContext jobExecutionContext) {
logger.info("Starting SpotifyRedirectIndex refresh");
SessionFactory sessionFactory = StaticSessionProvider.getSessionFactory();
SpotifyRedirectIndexModificationLock spotifyRedirectIndexModificationLock = new SpotifyRedirectIndexModificationLock();
spotifyRedirectIndexModificationLock.setCreationTimeStamp(LocalDateTime.now());
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
session.persist(spotifyRedirectIndexModificationLock);
transaction.commit();
}
try {
Aiode aiode = Aiode.get();
Stopwatch stopwatch = Stopwatch.createStarted();
YouTubeService youTubeService = aiode.getAudioManager().getYouTubeService();
SpotifyTrackBulkLoadingService spotifyTrackBulkLoadingService = new SpotifyTrackBulkLoadingService(spotifyApi, true);
LocalDate currentDate = LocalDate.now();
LocalDate date4WeeksAgo = currentDate.minusDays(28);
StaticSessionProvider.consumeSession(session -> {
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<SpotifyRedirectIndex> query = cb.createQuery(SpotifyRedirectIndex.class);
Root<SpotifyRedirectIndex> root = query.from(SpotifyRedirectIndex.class);
query.where(cb.lessThan(root.get("lastUpdated"), date4WeeksAgo));
query.orderBy(cb.asc(root.get("lastUpdated")));
List<SpotifyRedirectIndex> indices = session.createQuery(query).setLockOptions(new LockOptions(LockMode.PESSIMISTIC_WRITE)).getResultList();
if (indices.isEmpty()) {
return;
}
BigDecimal averageDailyIndices = (BigDecimal) session.createSQLQuery("select avg(count) from (select count(*) as count from spotify_redirect_index group by last_updated) as sub").uniqueResult();
int average = averageDailyIndices.setScale(0, RoundingMode.CEILING).intValue();
int updateCount = 0;
for (SpotifyRedirectIndex index : indices) {
SpotifyTrackKind kind = index.getSpotifyItemKind().asEnum();
RefreshTrackIndexTask task = new RefreshTrackIndexTask(session, index, youTubeService);
String spotifyId = index.getSpotifyId();
if (!Strings.isNullOrEmpty(spotifyId)) {
spotifyTrackBulkLoadingService.add(createItem(spotifyId, kind), task);
} else {
session.delete(index);
}
++updateCount;
if (updateCount == average) {
break;
}
}
spotifyTrackBulkLoadingService.perform();
stopwatch.stop();
logger.info(String.format("Regenerated %d spotify redirect indices in %d seconds", updateCount, stopwatch.elapsed(TimeUnit.SECONDS)));
});
} finally {
Transaction transaction = null;
try (Session session = sessionFactory.openSession()) {
transaction = session.beginTransaction();
// since hibernate is now bootstrapped by JPA rather than native after implementing spring boot
// the entity has the be merged because JPA does not allow the deletion of detached entities
Object merge = session.merge(spotifyRedirectIndexModificationLock);
session.delete(merge);
transaction.commit();
} catch (Throwable e) {
// catch exceptions thrown in the finally block so as to not override exceptions thrown in the try block
logger.error("Exception thrown while deleting SpotifyRedirectIndexModificationLock", e);
if (transaction != null) {
transaction.rollback();
}
}
}
}
Aggregations