109 lines
4.3 KiB
C#
109 lines
4.3 KiB
C#
using System.Net.Http.Headers;
|
|
using System.Text.Json;
|
|
using System.Web;
|
|
using Microsoft.AspNetCore.Authentication;
|
|
using Microsoft.Extensions.Options;
|
|
using SWAD.API.Consts.Enums;
|
|
using SWAD.API.Controllers.DTOs;
|
|
using SWAD.API.Models.Config.ApiServices;
|
|
using SWAD.API.Models.JsonStructures.MusicAPI.Spotify;
|
|
using SWAD.API.Services.MusicAPI.Auth;
|
|
|
|
namespace SWAD.API.Services.MusicAPI.Api;
|
|
|
|
public class SpotifyService : ApiService
|
|
{
|
|
private readonly SpotifyAuthService _authService;
|
|
private readonly Uri _searchUri;
|
|
private SpotifyAuthResponse? _token;
|
|
|
|
public SpotifyService(IOptions<ApiServicesConfig> config, IEnumerable<AbstractAuthService> authServices)
|
|
{
|
|
ServiceType = MusicService.Spotify;
|
|
var configServices = config.Value.ServicesData;
|
|
Config = configServices.First(x => x.Name == ServiceType.ToString());
|
|
_authService = (authServices.First(x => x.ServiceType == ServiceType) as SpotifyAuthService) ?? throw new ApplicationException("Auth service not found");
|
|
_searchUri = new Uri(new Uri(Config.Endpoints.Api), Config.ApiPaths.Search);
|
|
}
|
|
|
|
//Auto revoke on Expire
|
|
private SpotifyAuthResponse? Token
|
|
{
|
|
get => _token?.ExpireAt < DateTime.UtcNow ? null : _token;
|
|
set => _token = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get link to spotify by search query
|
|
/// </summary>
|
|
/// <param Name="query">DTO with search query</param>
|
|
/// <returns>link from spotify</returns>
|
|
/// <exception cref="AuthenticationFailureException">If token problems</exception>
|
|
/// <exception cref="HttpRequestException">If response is bad</exception>
|
|
public override async Task<string?> GetLinkByQuery(TrackDto query)
|
|
{
|
|
if (Token == null)
|
|
{
|
|
var newToken = await _authService.GetToken() as SpotifyAuthResponse;
|
|
Token = newToken ??
|
|
throw new AuthenticationFailureException(string.Format(Messages.AuthFailMessage, ServiceType));
|
|
}
|
|
|
|
using var client = new HttpClient();
|
|
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token.Token);
|
|
|
|
var url = new UriBuilder(_searchUri)
|
|
{
|
|
Port = -1
|
|
};
|
|
var urlQuery = HttpUtility.ParseQueryString(url.Query);
|
|
urlQuery["q"] = GetQuery(query);
|
|
urlQuery["type"] = "track";
|
|
urlQuery["limit"] = "1";
|
|
urlQuery["offset"] = "0";
|
|
url.Query = urlQuery.ToString();
|
|
|
|
var response = await client.GetAsync(url.Uri);
|
|
if (!response.IsSuccessStatusCode) throw new HttpRequestException("Request unsuccessful");
|
|
var json = await JsonSerializer.DeserializeAsync<SpotifySearchResponse>(
|
|
await response.Content.ReadAsStreamAsync());
|
|
|
|
// ReSharper disable once NullableWarningSuppressionIsUsed
|
|
return json!.Tracks.Items[0].ExternalUrls.Spotify;
|
|
}
|
|
|
|
public override async Task<TrackDto> GetQueryObject(string link, string countryCode = "US")
|
|
{
|
|
var url = new Uri(link);
|
|
var id = url.Segments[^1];
|
|
|
|
if (Token == null)
|
|
{
|
|
var newToken = await _authService.GetToken() as SpotifyAuthResponse;
|
|
Token = newToken ??
|
|
throw new AuthenticationFailureException(string.Format(Messages.AuthFailMessage, ServiceType));
|
|
}
|
|
using var client = new HttpClient();
|
|
//Prepare request
|
|
var clientHeaders = client.DefaultRequestHeaders;
|
|
clientHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token.Token);
|
|
|
|
var builder = new UriBuilder(Config.Endpoints.Api + Path.Combine(Config.ApiPaths.GetTrack, id))
|
|
{
|
|
Port = -1,
|
|
Query = $"market={countryCode}"
|
|
};
|
|
|
|
var httpRequest = new HttpRequestMessage(HttpMethod.Get, builder.Uri);
|
|
//Get response
|
|
var response = await client.SendAsync(httpRequest);
|
|
if (!response.IsSuccessStatusCode) throw new HttpRequestException("Request unsuccessful");
|
|
|
|
var json =
|
|
await JsonSerializer.DeserializeAsync<SpotifyTrackResponse>(await response.Content.ReadAsStreamAsync());
|
|
// ReSharper disable once NullableWarningSuppressionIsUsed
|
|
var artists = string.Join(", ", json!.Artists.ToList().ConvertAll(x => x.Name));
|
|
|
|
return new TrackDto(json.Name, artists, json.Albums.Name, ServiceType);
|
|
}
|
|
} |