namespace Webzine.Business.Seeders; using System.Net.Http.Headers; using System.Net.Http.Json; using System.Text; using Microsoft.Extensions.Options; using Webzine.Business.DTOs.Spotify; using Webzine.Business.Mappers.Spotify; using Webzine.Entity; using Webzine.Entity.Fixtures; public class SeedDataSpotify { private readonly HttpClient httpClient; private readonly SpotifySeederOptions options; public SeedDataSpotify(HttpClient httpClient, IOptions optionsAccessor) { this.httpClient = httpClient; this.options = optionsAccessor.Value; } public async Task GenererJeuDeDonneesAsync(CancellationToken cancellationToken = default) { // Verification des parametres pour l'acces a Spotify. if (string.IsNullOrWhiteSpace(this.options.ClientId) || string.IsNullOrWhiteSpace(this.options.ClientSecret)) { throw new InvalidOperationException("Renseignez SpotifySeeder:ClientId et SpotifySeeder:ClientSecret."); } var token = await this.GetTokenAsync(cancellationToken); var styles = new Dictionary(); var artistes = new List(); var titres = new List(); var commentaires = new List(); var artistIds = new HashSet(StringComparer.OrdinalIgnoreCase); int nextArtistId = 1; int nextStyleId = 1; int nextTitreId = 1; int nextCommentaireId = 1; foreach (var genre in this.options.Genres) { var artistesSpotify = await this.GetAsync( $"https://api.spotify.com/v1/search?q={Uri.EscapeDataString($"genre:\"{genre}\"")}&type=artist&market={this.options.Market}&limit={this.options.ArtistsPerGenre}", token, cancellationToken); foreach (var artisteSpotify in artistesSpotify?.Artists?.Items ??[]) { if (string.IsNullOrWhiteSpace(artisteSpotify.Id) || !artistIds.Add(artisteSpotify.Id)) { continue; } var stylesTitre = (artisteSpotify.Genres.Count > 0 ? artisteSpotify.Genres :[genre]) .Select(g => SpotifyMapper.GetOrCreateStyle(styles, g, ref nextStyleId)) .DistinctBy(s => s.IdStyle) .ToList(); var artiste = SpotifyMapper.ToArtiste(artisteSpotify, stylesTitre, nextArtistId++); artistes.Add(artiste); var albums = await this.GetAsync( $"https://api.spotify.com/v1/artists/{artisteSpotify.Id}/albums?include_groups=album,single&market={this.options.Market}", token, cancellationToken); foreach (var album in albums?.Items.GroupBy(a => a.Name, StringComparer.OrdinalIgnoreCase).Select(g => g.First()) ??[]) { var tracks = await this.GetAsync( $"https://api.spotify.com/v1/albums/{album.Id}/tracks?market={this.options.Market}&limit={Math.Clamp(this.options.TracksPerAlbum, 1, 10)}", token, cancellationToken); foreach (var track in tracks?.Items ??[]) { var titre = SpotifyMapper.ToTitre(track, album, artiste, stylesTitre, nextTitreId++); var commentairesTitre = SeedDataLocal.GenererListeCommentaire( titre, 0, Math.Clamp(this.options.MaxCommentsPerTrack, 0, 10), nextCommentaireId); nextCommentaireId += commentairesTitre.Count; titre.Commentaires.AddRange(commentairesTitre); commentaires.AddRange(commentairesTitre); titres.Add(titre); artiste.Titres.Add(titre); foreach (var style in titre.Styles) { style.Titres.Add(titre); } } } } } return new SeedDataSet { Artistes = artistes, Styles = styles.Values.OrderBy(s => s.IdStyle).ToList(), Titres = titres, Commentaires = commentaires, }; } /// /// Recuperation du token d'access a Spotify. /// /// Permet d'annuler la requete HTTP en cas de probleme. /// Le token d'acces a spotify. /// Le token spotify est introuvable. private async Task GetTokenAsync(CancellationToken cancellationToken) { using var request = new HttpRequestMessage(HttpMethod.Post, "https://accounts.spotify.com/api/token"); request.Content = new FormUrlEncodedContent( [ new KeyValuePair("grant_type", "client_credentials"), ]); var basic = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{this.options.ClientId}:{this.options.ClientSecret}")); request.Headers.Authorization = new AuthenticationHeaderValue("Basic", basic); using var response = await this.httpClient.SendAsync(request, cancellationToken); response.EnsureSuccessStatusCode(); var payload = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); return payload?.AccessToken ?? throw new InvalidOperationException("Token Spotify introuvable."); } /// /// Recuperation d'information depuis spotify, en formattant /// la requete avec le Bearer Token. /// /// DTOs Spotify. /// URL Spotify. /// Token Bearer pour authorisation d'acces a l'api. /// Permet d'annuler la requete. /// Reponse Spotify deserialiser. private async Task GetAsync(string url, string token, CancellationToken cancellationToken) { // Formattage de la requete HTTP avec le Bearer token. using var request = new HttpRequestMessage(HttpMethod.Get, url); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); using var response = await this.httpClient.SendAsync(request, cancellationToken); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); } }