using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AutoMapper.Execution; using Flurl.Util; using MoreLinq; using Nancy; using Nancy.ModelBinding; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Sony.Filtr.AdminAPI.BusinessLogic; using Sony.Filtr.AdminAPI.Config; using Sony.Filtr.AdminAPI.ViewModels; using Sony.Filtr.Applications; using Sony.Filtr.Contracts.Definitions; using Sony.Filtr.Contracts.Entities; using Sony.Filtr.Core.EditorialPlaylists; using Sony.Filtr.Core.SonyMusic; using Sony.Filtr.Core.SpotifyCharts; using Sony.Filtr.Core.SpotifyCharts.Data; using Sony.Filtr.MusicServices; using Sony.Filtr.PlaylistContainer; using Sony.Filtr.Playlists; using Sony.Filtr.Playlists.Spotify; using Sony.Filtr.SpotifyWebAPI; using Sony.Filtr.Utility; namespace Sony.Filtr.AdminAPI.Modules.PlaylistContainer { public class PlaylistContainerModule : BaseModule { public PlaylistContainerModule(ApplicationInstanceManager applicationInstanceManager, PlaylistContainerManager playlistContainerManager, MusicServiceManager musicServiceManager, SpotifyPlaylistManager spotifyPlaylistManager, MusicServicePlaylistReferenceValidator musicServicePlaylistReferenceValidator, EditorialPlaylistManager editorialPlaylistManager) : base(applicationInstanceManager) { Get["GetLinkedPlaylists", "/PlaylistContainer/LinkedPlaylists", true] = async (parameters, cancellationToken) => { var playlistId = (string)Request.Query.playlistId; var musicServiceId = (int)Request.Query.musicServiceId; var linkedLists = await playlistContainerManager.GetLinkedPlaylistsAsync(playlistId, musicServiceId); var viewModel = new LinkedPlaylistsViewModel(); if (linkedLists.Any()) { viewModel.PlaylistContainerId = linkedLists.First().PlaylistContainerId; viewModel.LinkedPlaylists = linkedLists.Select(l => new LinkedPlaylist() { MusicServiceId = l.MusicServiceId, PlaylistId = l.PlaylistId }).ToList(); } return Response.AsJson(viewModel); }; Post["AddLinkedPlaylists", "/PlaylistContainer/LinkedPlaylists", true] = async (parameters, cancellationToken) => { var sourcePlaylistId = (string)Request.Query.sourcePlaylistId; var sourceMusicServiceId = (int)Request.Query.sourceMusicServiceId; var linkedPlaylistId = (string)Request.Query.linkedPlaylistId; var linkedMusicServiceId = (int)Request.Query.linkedMusicServiceId; try { await playlistContainerManager.AddPlaylistLinkAsync(sourcePlaylistId, sourceMusicServiceId, linkedPlaylistId, linkedMusicServiceId); } catch(Exception ex) { return new Response() { StatusCode = HttpStatusCode.Conflict, ReasonPhrase = ex.Message }; } return HttpStatusCode.Accepted; }; Delete["DeleteLinkedPlaylist", "/PlaylistContainer/LinkedPlaylists", true] = async (parameters, cancellationToken) => { var playlistContainerId = (int?)Request.Query.playlistContainerId; var playlistId = (string)Request.Query.playlistId; var musicServiceId = (int?)Request.Query.musicServiceId; if (!playlistContainerId.HasValue) return new Response() { StatusCode = HttpStatusCode.BadRequest, ReasonPhrase = "No playlist container id" }; if (!musicServiceId.HasValue) return new Response() { StatusCode = HttpStatusCode.BadRequest, ReasonPhrase = "No music service id" }; if (string.IsNullOrWhiteSpace(playlistId)) return new Response() { StatusCode = HttpStatusCode.BadRequest, ReasonPhrase = "No playlist id" }; try { await playlistContainerManager.DeleteLinkedPlaylistAsync(playlistContainerId.Value, playlistId, musicServiceId.Value); } catch (Exception ex) { return new Response() { StatusCode = HttpStatusCode.Conflict, ReasonPhrase = ex.Message }; } return HttpStatusCode.Accepted; }; Put["UpdatePlaylistContainer", "/PlaylistContainer/{id}", true] = async (parameters, cancellationToken) => { int containerId; if (!int.TryParse((string)parameters.id, out containerId)) return HttpStatusCode.BadRequest; var playlistContainer = this.Bind("id"); if (playlistContainer == null) return HttpStatusCode.BadRequest; playlistContainer.Id = containerId; const int spotifyServiceId = 1; try { await playlistContainerManager.UpdatePlaylistContainerAsync(playlistContainer); var linkedLists = await playlistContainerManager.GetLinkedPlaylistsAsync(containerId); var spotifyList = linkedLists?.FirstOrDefault(l => l.MusicServiceId == spotifyServiceId); if (spotifyList != null) { var list = spotifyPlaylistManager.GetPlaylist(spotifyList.PlaylistId); list.CountryCode = playlistContainer.Market; spotifyPlaylistManager.UpdatePlaylist(list); } } catch (Exception ex) { return new Response() { StatusCode = HttpStatusCode.Conflict, ReasonPhrase = ex.Message }; } return HttpStatusCode.Accepted; }; Get["GetOrCreatePlaylistContainer", "/PlaylistContainer", true] = async (parameters, cancellationToken) => { var playlistId = (string)Request.Query.playlistId; var musicServiceId = (int?)Request.Query.musicServiceId; if (!musicServiceId.HasValue) return new Response() { StatusCode = HttpStatusCode.BadRequest, ReasonPhrase = "No music service id" }; if (string.IsNullOrWhiteSpace(playlistId)) return new Response() { StatusCode = HttpStatusCode.BadRequest, ReasonPhrase = "No playlist id" }; var playlistContainer = await playlistContainerManager.GetOrCreatePlaylistContainer(playlistId, musicServiceId.Value); return Response.AsJson(playlistContainer); }; Put["SetPlaylistMarket", "/playlistMarket", true] = async (parameter, token) => { var playlistWithMarket = this.Bind(); if (string.IsNullOrWhiteSpace(playlistWithMarket?.MarketCode)) throw new NancyStatusException(HttpStatusCode.BadRequest, "Missing request body or market"); var playlistReference = new MusicServicePlaylistReference(playlistWithMarket.PlaylistId, playlistWithMarket.MusicServiceId); var valid = await musicServicePlaylistReferenceValidator.IsValidMusicServicePlaylistReferenceAsync(playlistReference); if (!valid) throw new NancyStatusException(HttpStatusCode.BadRequest, "Missing or invalid Playlist Id or Music Service Id"); playlistWithMarket = EnsureCorrectFormat(playlistWithMarket); await playlistContainerManager.SetPlaylistMarketAsync(playlistWithMarket.PlaylistId, (MusicService)playlistWithMarket.MusicServiceId, playlistWithMarket.MarketCode); // Update both new and old structure with new market. if (playlistWithMarket.MusicServiceId == (int)MusicService.Spotify) { var spotifyPlaylist = spotifyPlaylistManager.GetPlaylist(playlistWithMarket.PlaylistId); if (spotifyPlaylist != null) { spotifyPlaylist.CountryCode = playlistWithMarket.MarketCode; spotifyPlaylistManager.UpdatePlaylist(spotifyPlaylist); } var editorialPlaylists = await editorialPlaylistManager.GetEditorialPlaylistsByIdAsync(new List() { playlistWithMarket.PlaylistId }); if (editorialPlaylists != null) { foreach(var editorialPlaylist in editorialPlaylists) { editorialPlaylist.CountryCode = playlistWithMarket.MarketCode; await editorialPlaylistManager.UpdateSpotifyFieldsAsync(editorialPlaylist); } } } return Response.AsJson(playlistWithMarket); }; } private PlaylistMarketViewModel EnsureCorrectFormat(PlaylistMarketViewModel playlistWithMarket) { //We fix the value so we store and handle the playlist id for Spotify playlists even if we get in uri-format if (playlistWithMarket.MusicServiceId == (int)MusicService.Spotify) { if (playlistWithMarket.PlaylistId.StartsWith("spotify:")) { playlistWithMarket.PlaylistId = new SpotifyLink(playlistWithMarket.PlaylistId).ExtractPlaylistID(); } } return playlistWithMarket; } } }