using System.Net; using System.Text.Json; using System.Web; using Microsoft.Extensions.Options; using SWAD.API.Consts; using SWAD.API.Consts.Enums; using SWAD.API.Controllers.DTOs; using SWAD.API.Exceptions; using SWAD.API.Models.Config.ApiServices; using SWAD.API.Models.JsonStructures.MusicAPI.Yandex; using SWAD.API.Services.MusicAPI.Auth; namespace SWAD.API.Services.MusicAPI.Api; public class YandexService : ApiService { public YandexService(IOptions config, IEnumerable authServices) { ServiceType = MusicService.Yandex; var configServices = config.Value.ServicesData; Config = configServices.First(x => x.Name == ServiceType.ToString()); } public override async Task GetLinkByQuery(TrackDto query) { var searchUri = new Uri(new Uri(Config.Endpoints.Api), Config.ApiPaths.Search); using var client = new HttpClient(); var clientHeaders = client.DefaultRequestHeaders; var response = await client.PostAsync(searchUri, new FormUrlEncodedContent([ new("text", GetQuery(query)) ])); if (!response.IsSuccessStatusCode) { var requestDebugData = await response.Content.ReadAsStringAsync(); throw new HttpRequestException($"{ErrorResources.Unsuccessful}\n Service returned: {requestDebugData}"); } var json = await response.Content.ReadFromJsonAsync(); // ReSharper disable once NullableWarningSuppressionIsUsed if (json?.Entities.Count < 1) { throw new TrackNotFoundException($"Track is not found in {ServiceType}"); } var results = json?.Entities.FirstOrDefault(x => x.Type == "track")?.Results; /* * ВНИМАНИЕ * Yandex API писали шизы поэтому когда будешь добавлять поля в YandexSearchResponse и здесь их юзать * ПОМНИ: ID у артистов и альбомов в разных местах JSON в одних и тех же объектах то string то number * ЭТО ВЫЗОВЕТ ИСКЛЮЧЕНИЕ * Думой */ var resultTrack = results?.FirstOrDefault(x => x.Track.Title == query.Name) ?? results?[0]; return $"{Config.Endpoints.MusicLink[0]}{resultTrack?.Track.Id ?? throw new TrackNotFoundException($"Track is not found in {ServiceType}")}"; } public override async Task GetQueryObject(string link, string countryCode = "RU") { var url = new Uri(link); var id = url.Segments[^1]; //Prepare request using var client = new HttpClient(); var getTrackUrl = new UriBuilder(new Uri(new Uri(Config.Endpoints.Api), Config.ApiPaths.GetTrack)) { Port = -1 }; var urlQuery = HttpUtility.ParseQueryString(url.Query); urlQuery["track"] = id; getTrackUrl.Query = urlQuery.ToString(); //Get response var response = await client.GetAsync(getTrackUrl.Uri); if (!response.IsSuccessStatusCode) if (response.StatusCode == HttpStatusCode.NotFound) { throw new TrackNotFoundException("Ну, сори, яндекс кал"); } else throw new HttpRequestException(ErrorResources.Unsuccessful); try { var json = await response.Content.ReadFromJsonAsync(); // ReSharper disable once NullableWarningSuppressionIsUsed var artists = string.Join(", ", json!.Artists.ToList().ConvertAll(x => x.Name)); return new TrackDto(json.Track.Title, artists, json.Track.Albums[0].Title, ServiceType); } catch (JsonException ex) { throw new TooManyRequestsException("Яндекс, похоже, считает что мы робот, что по сути является правдой. Попробуйте позже."); } } }