<?php namespace App\Controller; use App\Service\SpotifyApiService; use App\Service\SpotifyPlaylistService; use SpotifyWebAPI\SpotifyWebAPI; use SpotifyWebAPI\SpotifyWebAPIException; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class PlaylistController extends AbstractController { private SpotifyWebAPI $spotifyApi; private SpotifyPlaylistService $spotifyPlaylistService; public function __construct(SpotifyApiService $spotifyApiService, SpotifyPlaylistService $spotifyPlaylistService) { // increase timeout limit set_time_limit(60); $this->spotifyApi = $spotifyApiService->createApi(); $this->spotifyPlaylistService = $spotifyPlaylistService; } /** * @Route("/playlist-generator", name="playlist-generator") */ public function playlistGeneratorIndex(): Response { try { $me = $this->spotifyApi->me(); } catch (SpotifyWebAPIException $e) { return $this->render('error.html.twig'); } return $this->render('playlist-generator/index.html.twig', [ 'user' => $me, ]); } /** * @Route("/playlists/user", name="get-user-playlists") */ public function getPlaylists(): JsonResponse { $me = $this->spotifyApi->me(); $rawPlaylists = $this->spotifyApi->getUserPlaylists( $me->id, [ 'limit' => SpotifyPlaylistService::PLAYLISTS_COUNT, ] )->items; $playlists = []; foreach ($rawPlaylists as $playlist) { $playlists[] = [ 'id' => $playlist->id, 'name' => $playlist->name, 'imageUrl' => $playlist->images[\count($playlist->images) - 1]->url, ]; } return new JsonResponse($playlists); } /** * @Route("/show-playlist-content/{playlistId}", name="show-playlist-content") */ public function showPlaylistContent(string $playlistId): Response { $this->spotifyPlaylistService->printLog('Get content of playlist'); $playlist = $this->spotifyApi->getPlaylist($playlistId); return $this->render('playlist-generator/view.html.twig', [ 'user' => $this->spotifyApi->me(), 'infos' => $this->spotifyPlaylistService->getPlaylistInformationMessage($playlist), 'playlist' => $this->spotifyPlaylistService->createDisplayablePlaylist($playlist), ]); } /** * @Route("/generate-playlist-from-playlists", name="generate-playlist-from-playlists") */ public function generatePlaylistFromPlaylists(Request $request): RedirectResponse { /** @var array */ $selectedPlaylists = $request->query->get('selected-playlist'); $this->spotifyPlaylistService->printLog('Will create new playlist with recommendations from playlists: ' . join(', ', $selectedPlaylists) . '".'); $recommendedTrackIds = []; $shouldFilterByArtists = (null !== $request->query->get('check-playlist-filter-artists')); $this->spotifyPlaylistService->printLog('Filter by artists in source playlists: ' . ($shouldFilterByArtists ? 'yes' : 'no')); $generateLongPlaylist = (null !== $request->query->get('check-playlist-long-playlist')); $this->spotifyPlaylistService->printLog('Generate long playlist: ' . ($generateLongPlaylist ? 'yes' : 'no')); $artistsInSourcePlaylists = []; foreach ($selectedPlaylists as $selectedPlaylistId) { $playlist = $this->spotifyApi->getPlaylist($selectedPlaylistId); $this->spotifyPlaylistService->printLog('Will get recommendations from tracks in playlist "' . $playlist->name . '".'); $playlistTracks = $playlist->tracks->items; $this->spotifyPlaylistService->printLog('Found ' . count($playlistTracks) . ' tracks.'); foreach ($playlistTracks as $track) { $artists = []; foreach ($track->track->artists as $artist) { $artists[] = $artist->name; $artistsInSourcePlaylists[$artist->id] = 1; } $this->spotifyPlaylistService->printLog('Track "' . $track->track->name . '" (' . join(', ', $artists) . ')'); $recommendations = $this->spotifyApi->getRecommendations([ 'seed_tracks' => [$track->track->id], 'limit' => ($generateLongPlaylist ? 50 : 30), ]); $this->spotifyPlaylistService->printLog(' -> Got ' . count($recommendations->tracks) . ' recommendatations.'); foreach ($recommendations->tracks as $recommendedTrack) { $recommendedTrackIds[$recommendedTrack->id] = $recommendedTrack; } } } if ($shouldFilterByArtists) { $artistsInSourcePlaylists = array_keys($artistsInSourcePlaylists); $this->spotifyPlaylistService->printLog('Filter by artists found in source playlists (' . count($artistsInSourcePlaylists) . ')'); $filteredTrackIds = []; foreach ($recommendedTrackIds as $track) { foreach ($track->artists as $trackArtist) { if (\in_array($trackArtist->id, $artistsInSourcePlaylists)) { $filteredTrackIds[$track->id] = 1; } } } $recommendedTrackIds = $filteredTrackIds; } $newPlaylist = $this->spotifyPlaylistService->createPlaylistWithRandomTracks( $this->spotifyApi, $recommendedTrackIds, $generateLongPlaylist ? SpotifyPlaylistService::TRACKS_COUNT_IN_LONG_PLAYLIST : SpotifyPlaylistService::TRACKS_COUNT_IN_SHORT_PLAYLIST, ); $this->addFlash('infos', $this->spotifyPlaylistService->getCreatedPlaylistInformationMessage($newPlaylist)); return new RedirectResponse($this->generateUrl('show-playlist-content', ['playlistId' => $newPlaylist->id])); } /** * @Route("/generate-playlist-from-top-artists", name="generate-playlist-from-top-artists") */ public function generatePlaylistFromTopArtists(Request $request): RedirectResponse { // Swith "random" or "selected" if (null !== $request->query->get('generate-playlist-random-top-artists')) { return $this->generatePlaylistFromRandomTopArtists($request); } elseif (null !== $request->query->get('generate-playlist-top-artists')) { return $this->generatePlaylistFromSelectedTopArtists($request); } return new RedirectResponse($this->generateUrl('playlist-generator')); } private function generatePlaylistFromSelectedTopArtists(Request $request): RedirectResponse { /** @var array */ $selectedArtists = $request->query->get('selected-artist'); $this->spotifyPlaylistService->printLog('Will create new playlist with filterted recommendations from artists: ' . join(', ', $selectedArtists) . '".'); $recommendedTrackIds = []; $shouldFilterByArtists = (null !== $request->query->get('check-top-artist-filter-artists')); $this->spotifyPlaylistService->printLog('Filter by artists in selection: ' . ($shouldFilterByArtists ? 'yes' : 'no')); $generateLongPlaylist = (null !== $request->query->get('check-top-artist-long-playlist')); $this->spotifyPlaylistService->printLog('Generate long playlist: ' . ($generateLongPlaylist ? 'yes' : 'no')); foreach ($selectedArtists as $selectedArtist) { $this->spotifyPlaylistService->printLog('Get recommendations for artist ' . $selectedArtist . ''); $recommendations = $this->spotifyApi->getRecommendations([ 'seed_artists' => $selectedArtist, 'limit' => 100 ]); $this->spotifyPlaylistService->printLog(' -> Got ' . count($recommendations->tracks) . ' recommendatations.'); // Filter by artist if requested, remove duplicates foreach ($recommendations->tracks as $recommendedTrack) { if ($shouldFilterByArtists) { foreach ($recommendedTrack->artists as $trackArtist) { if (\in_array($trackArtist->id, $selectedArtists)) { $recommendedTrackIds[$recommendedTrack->id] = 1; } } } else { $recommendedTrackIds[$recommendedTrack->id] = 1; } } } $newPlaylist = $this->spotifyPlaylistService->createPlaylistWithRandomTracks( $this->spotifyApi, $recommendedTrackIds, $generateLongPlaylist ? SpotifyPlaylistService::TRACKS_COUNT_IN_LONG_PLAYLIST : SpotifyPlaylistService::TRACKS_COUNT_IN_SHORT_PLAYLIST ); $this->addFlash('infos', $this->spotifyPlaylistService->getCreatedPlaylistInformationMessage($newPlaylist)); return new RedirectResponse($this->generateUrl('show-playlist-content', ['playlistId' => $newPlaylist->id])); } private function generatePlaylistFromRandomTopArtists(Request $request): RedirectResponse { $countInTopArtists = random_int(4, 6); $countInLessTopArtists = random_int(4, 6); $limitBetweenTopAndLessTop = SpotifyPlaylistService::TOP_ARTISTS_COUNT; $selectedArtists = $this->spotifyPlaylistService->getRandomArtistsFromTopArtists( $this->spotifyApi, $countInTopArtists, $countInLessTopArtists, $limitBetweenTopAndLessTop ); $this->spotifyPlaylistService->printLog('Will create new playlist with filterted recommendations from random artists: ' . join(', ', $selectedArtists) . '".'); $recommendedTrackIds = []; $shouldFilterByArtists = (null !== $request->query->get('check-top-artist-filter-artists')); $this->spotifyPlaylistService->printLog('Filter by artists in selection: ' . ($shouldFilterByArtists ? 'yes' : 'no')); $generateLongPlaylist = (null !== $request->query->get('check-top-artist-long-playlist')); $this->spotifyPlaylistService->printLog('Generate long playlist: ' . ($generateLongPlaylist ? 'yes' : 'no')); foreach ($selectedArtists as $selectedArtist) { $this->spotifyPlaylistService->printLog('Get recommendations for artist ' . $selectedArtist . ''); $recommendations = $this->spotifyApi->getRecommendations([ 'seed_artists' => $selectedArtist, 'limit' => 100 ]); $this->spotifyPlaylistService->printLog(' -> Got ' . count($recommendations->tracks) . ' recommendations.'); // Filter by artist if requested, remove duplicates foreach ($recommendations->tracks as $recommendedTrack) { if ($shouldFilterByArtists) { foreach ($recommendedTrack->artists as $trackArtist) { if (\in_array($trackArtist->id, $selectedArtists)) { $recommendedTrackIds[$recommendedTrack->id] = 1; } } } else { $recommendedTrackIds[$recommendedTrack->id] = 1; } } } $newPlaylist = $this->spotifyPlaylistService->createPlaylistWithRandomTracks( $this->spotifyApi, $recommendedTrackIds, $generateLongPlaylist ? SpotifyPlaylistService::TRACKS_COUNT_IN_LONG_PLAYLIST : SpotifyPlaylistService::TRACKS_COUNT_IN_SHORT_PLAYLIST ); $this->addFlash('infos', $this->spotifyPlaylistService->getCreatedPlaylistInformationMessage($newPlaylist)); return new RedirectResponse($this->generateUrl('show-playlist-content', ['playlistId' => $newPlaylist->id])); } /** * @Route("/generate-quick-playlist", name="generate-quick-playlist") */ public function generateQuickPlaylist(Request $request): RedirectResponse { // Swith between "daily mixes" or "tambouille" if (null !== $request->query->get('generate-quick-playlist-from-daily-mixes')) { return $this->generatePlaylistFromDailyMixes($request); } elseif (null !== $request->query->get('generate-quick-playlist-tambouille-mix')) { return $this->generateplaylistTambouilleMix($request); } return new RedirectResponse($this->generateUrl('playlist-generator')); } private function generatePlaylistFromDailyMixes(Request $request): RedirectResponse { $generateLongPlaylist = (null !== $request->query->get('check-quick-create-long-playlist')); $this->spotifyPlaylistService->printLog('Generate playlist from Daily Mixes (long playlist :' . ($generateLongPlaylist ? 'yes' : 'no') . ')'); $newPlaylist = $this->spotifyPlaylistService->createPlaylistFromDailyMixesTracks( $this->spotifyApi, $generateLongPlaylist ? SpotifyPlaylistService::TRACKS_COUNT_IN_LONG_PLAYLIST : SpotifyPlaylistService::TRACKS_COUNT_IN_SHORT_PLAYLIST ); $this->addFlash('infos', $this->spotifyPlaylistService->getCreatedPlaylistInformationMessage($newPlaylist)); return new RedirectResponse($this->generateUrl('show-playlist-content', ['playlistId' => $newPlaylist->id])); } private function generateplaylistTambouilleMix(Request $request): RedirectResponse { $generateLongPlaylist = (null !== $request->query->get('check-quick-create-long-playlist')); $this->spotifyPlaylistService->printLog('Generate tambouille mix playlist (long playlist :' . ($generateLongPlaylist ? 'yes' : 'no') . ')'); $newPlaylist = $this->spotifyPlaylistService->createPlaylistTambouilleMix( $this->spotifyApi, $generateLongPlaylist ? SpotifyPlaylistService::TRACKS_COUNT_IN_LONG_PLAYLIST : SpotifyPlaylistService::TRACKS_COUNT_IN_SHORT_PLAYLIST ); $this->addFlash('infos', $this->spotifyPlaylistService->getCreatedPlaylistInformationMessage($newPlaylist)); return new RedirectResponse($this->generateUrl('show-playlist-content', ['playlistId' => $newPlaylist->id])); } }