diff --git a/PlaylistShared.Api/Controllers/YandexSearchController.cs b/PlaylistShared.Api/Controllers/YandexSearchController.cs index ff3511c..7171a38 100644 --- a/PlaylistShared.Api/Controllers/YandexSearchController.cs +++ b/PlaylistShared.Api/Controllers/YandexSearchController.cs @@ -28,13 +28,13 @@ public class YandexSearchController : ControllerBase [HttpGet("search")] public async Task>> SearchQuery( - [FromQuery] string query, - [FromQuery] int limit = 20, + [FromQuery] string query = "", + [FromQuery] int limit = 40, [FromQuery] TrackSearchType searchType = TrackSearchType.All, [FromQuery] bool byId = false, [FromQuery] string? shared_id = null) { - if (string.IsNullOrWhiteSpace(query)) + if (string.IsNullOrWhiteSpace(query) && searchType != TrackSearchType.MyPlaylists) return BadRequest(ApiResponse.Fail(new ErrorResponse { StatusCode = 400, @@ -46,6 +46,8 @@ public class YandexSearchController : ControllerBase if (userId.HasValue) user = await _userManager.FindByIdAsync(userId.Value.ToString()); + var byShareId = false; + // Если нет пользователя или у него нет токена, пробуем через shared_id if (user == null || string.IsNullOrEmpty(user.YandexAccessToken)) { @@ -61,6 +63,8 @@ public class YandexSearchController : ControllerBase var owner = await _userManager.FindByIdAsync(playlist.CreatorUserId.ToString()); if (owner == null) return StatusCode(500, "Не удалось найти владельца плейлиста."); user = owner; + + byShareId = true; } if (string.IsNullOrEmpty(user.YandexAccessToken)) @@ -74,7 +78,16 @@ public class YandexSearchController : ControllerBase if (byId) { - results = await _yandexService.SearchTracksByIdAsync(user, query, searchType, limit); + results = await _yandexService.SearchTracksByIdAsync(user, query, searchType); + } + else if (searchType == TrackSearchType.MyPlaylists) + { + if (byShareId) + { + return Unauthorized("Необходимо подключение профиля к яндекс музыке."); + } + + results = await _yandexService.SearchMyPlaylists(user); } else { diff --git a/PlaylistShared.Api/PlaylistShared.Api.csproj b/PlaylistShared.Api/PlaylistShared.Api.csproj index 4c5a891..6ae9dce 100644 --- a/PlaylistShared.Api/PlaylistShared.Api.csproj +++ b/PlaylistShared.Api/PlaylistShared.Api.csproj @@ -10,24 +10,24 @@ - - - - - - + + + + + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + diff --git a/PlaylistShared.Api/Services/Yandex/YandexMusicService.cs b/PlaylistShared.Api/Services/Yandex/YandexMusicService.cs index e539521..eef0547 100644 --- a/PlaylistShared.Api/Services/Yandex/YandexMusicService.cs +++ b/PlaylistShared.Api/Services/Yandex/YandexMusicService.cs @@ -161,11 +161,56 @@ public class YandexMusicService }; } + public async Task SearchMyPlaylists(ApplicationUser user) + { + YandexSearchResult result = new(); + + await AuthorizeIfNot(user); + + + var favoritesPlaylist = await Api.Playlist.FavoritesAsync(); + result.Playlists = favoritesPlaylist?.Select(t => new YandexPlaylist + { + Uuid = t.PlaylistUuid, + Kind = t.Kind, + OwnerUid = t.Owner?.Uid ?? string.Empty, + Title = t.Title, + Description = t.Description, + CoverUrl = t.Cover.GetUrl(), + TrackCount = t.TrackCount, + }).ToList(); + + var personalPlaylists = await Api.Playlist.GetPersonalPlaylistsAsync(); + result.PersonalPlaylists = personalPlaylists?.Select(t => new YandexPlaylist + { + Uuid = t.PlaylistUuid, + Kind = t.Kind, + OwnerUid = t.Owner?.Uid ?? string.Empty, + Title = t.Title, + Description = t.Description, + CoverUrl = t.Cover.GetUrl(), + TrackCount = t.TrackCount, + }).ToList(); + + var likedPlaylists = (await Api.Library.GetLikedPlaylistsAsync())?.Select(t => t.Playlist).ToList(); + result.LikedPlaylists = likedPlaylists?.Select(t => new YandexPlaylist + { + Uuid = t.PlaylistUuid, + Kind = t.Kind, + OwnerUid = t.Owner?.Uid ?? string.Empty, + Title = t.Title, + Description = t.Description, + CoverUrl = t.Cover.GetUrl(), + TrackCount = t.TrackCount, + }).ToList(); + + return result; + } + public async Task SearchTracksByIdAsync( ApplicationUser user, string id, - TrackSearchType searchType, - int limit = 20 + TrackSearchType searchType ) { YandexSearchResult result = new(); @@ -254,8 +299,8 @@ public class YandexMusicService TrackCount = p.TrackCount, }).ToList(); - - result.Tracks = artist.PopularTracks.Select(t => new YandexTrack + var allTraks = await artist.Artist.GetAllTracksAsync(); + result.Tracks = allTraks?.Select(t => new YandexTrack { TrackId = t.Id, Title = t.Title, diff --git a/PlaylistShared.Pwa/Pages/Login.razor b/PlaylistShared.Pwa/Pages/Login.razor index 53408c4..c2480f1 100644 --- a/PlaylistShared.Pwa/Pages/Login.razor +++ b/PlaylistShared.Pwa/Pages/Login.razor @@ -11,7 +11,7 @@ Вход в PlaylistShared - + @* Войдите через учётную запись Keycloak или используйте локальный аккаунт. @@ -22,7 +22,7 @@ или - + *@ diff --git a/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor b/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor index 169c4e4..5d81f93 100644 --- a/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor +++ b/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor @@ -8,6 +8,7 @@ @using PlaylistShared.Shared.DTO @using PlaylistShared.Shared.Enums @using PlaylistShared.Pwa.Services +@using PlaylistShared.Shared.Profile @using PlaylistShared.Shared.SharedPlaylist @using PlaylistShared.Shared.Yandex @inject HttpClient Http @@ -17,7 +18,6 @@ @inject IDialogService DialogService @inject IAudioPlayerService AudioPlayerService @inject IJSRuntime JS -@inject IDialogService DialogService @implements IDisposable @@ -254,6 +254,7 @@ + @@ -328,6 +329,34 @@ } + @* Секция персональных плейлистов *@ + @if (_searchResult?.PersonalPlaylists?.Any() == true) + { + Плейлисты (персональные) +
+ @foreach (var playlist in _searchResult.PersonalPlaylists) + { +
+ +
+ } +
+ } + + @* Секция лайкнутых плейлистов *@ + @if (_searchResult?.LikedPlaylists?.Any() == true) + { + Плейлисты (лайки) +
+ @foreach (var playlist in _searchResult.LikedPlaylists) + { +
+ +
+ } +
+ } + @* Секция треков *@ @if (_searchResult?.Tracks != null) { @@ -640,13 +669,50 @@ private async Task SearchTracks(bool byId = false, string? forcedQuery = null) { var query = forcedQuery ?? _searchQuery; - if (string.IsNullOrWhiteSpace(query)) + var type = _searchType; + + + //Если поиск в моих плейлистах + if (type == TrackSearchType.MyPlaylists) + { + var showMessage = true; + + if (_isAuthenticated) + { + var response = await Http.GetFromJsonAsync>("/api/yandexaccount/status"); + if (response?.Success == true) + { + var hasToken = response?.Data?.HasToken ?? false; + + if (hasToken) showMessage = false; + } + } + + if (showMessage) + { + var response = await DialogService.ShowMessageBoxAsync(new() + { + Title = "Необходимо авторизация", + Message = "Для использования \"Мои плейлисты\" необходима авторизация в яндекс музыке.", + YesText = "Авторизоваться", + CancelText = "Отмена", + }); + + if (response == true) + { + Navigation.NavigateTo("/login"); + } + + return; + } + } + //Если обычный поиск, нужен текст + else if (string.IsNullOrWhiteSpace(query)) { _searchResult = null; return; } - var type = _searchType; // Распознавание ссылки Яндекс.Музыки if (!byId && Uri.TryCreate(query, UriKind.Absolute, out var uri) && uri.Host == "music.yandex.ru") @@ -671,7 +737,7 @@ try { - var url = $"/api/yandexsearch/search?query={Uri.EscapeDataString(query)}&searchType={Uri.EscapeDataString(type.ToString())}&limit=20"; + var url = $"/api/yandexsearch/search?query={Uri.EscapeDataString(query)}&searchType={Uri.EscapeDataString(type.ToString())}"; if (byId) url += "&byId=true"; if (!string.IsNullOrEmpty(Token)) diff --git a/PlaylistShared.Shared/Enums/TrackSearchType.cs b/PlaylistShared.Shared/Enums/TrackSearchType.cs index 90e796a..4a75554 100644 --- a/PlaylistShared.Shared/Enums/TrackSearchType.cs +++ b/PlaylistShared.Shared/Enums/TrackSearchType.cs @@ -13,4 +13,5 @@ public enum TrackSearchType Album, Playlist, Track, + MyPlaylists, } diff --git a/PlaylistShared.Shared/Yandex/YandexSearchResult.cs b/PlaylistShared.Shared/Yandex/YandexSearchResult.cs index 1d38008..08a7412 100644 --- a/PlaylistShared.Shared/Yandex/YandexSearchResult.cs +++ b/PlaylistShared.Shared/Yandex/YandexSearchResult.cs @@ -17,6 +17,18 @@ public class YandexSearchResult [JsonPropertyName("playlists")] public List? Playlists { get; set; } = null; + /// + /// Персональные плейлисты. + /// + [JsonPropertyName("personalPlaylists")] + public List? PersonalPlaylists { get; set; } = null; + + /// + /// Плейлисты, которые понравились. + /// + [JsonPropertyName("likedPlaylists")] + public List? LikedPlaylists { get; set; } = null; + /// /// Найденные исполнители. ///