SwapDude/SWAD.API/Services/MusicAPI/Api/SpotifyService.cs
Lisoveliy aebe654c38
Some checks are pending
Deploy / update (push) Waiting to run
Build Project .NET / build (push) Waiting to run
chore: init commit from GitHub
2025-05-12 19:44:33 +03:00

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);
}
}