diff --git a/Webzine.Entity/Fixtures/SeedDataSpotify.cs b/Webzine.Entity/Fixtures/SeedDataSpotify.cs index c77d572..133777e 100644 --- a/Webzine.Entity/Fixtures/SeedDataSpotify.cs +++ b/Webzine.Entity/Fixtures/SeedDataSpotify.cs @@ -1,5 +1,337 @@ namespace Webzine.Entity.Fixtures; +using System.Globalization; +using System.Net.Http.Headers; +using System.Net.Http.Json; +using System.Text; +using System.Text.Json.Serialization; + +using Microsoft.Extensions.Options; + +public class SpotifySeederOptions +{ + public string ClientId { get; set; } = string.Empty; + + public string ClientSecret { get; set; } = string.Empty; + + public string Market { get; set; } = "FR"; + + public List Genres { get; set; } = + [ + "rock", + "pop", + "jazz", + "hip hop", + "electronic", + "metal", + ]; + + public int ArtistsPerGenre { get; set; } = 4; + + public int AlbumsPerArtist { get; set; } = 2; + + public int TracksPerAlbum { get; set; } = 4; + + public int MaxCommentsPerTrack { get; set; } = 3; +} + public class SeedDataSpotify { + private readonly HttpClient httpClient; + private readonly SpotifySeederOptions options; + + public SeedDataSpotify(HttpClient httpClient, IOptions optionsAccessor) + { + this.httpClient = httpClient; + this.options = optionsAccessor.Value; + } + + /// + /// + /// + /// + /// A representing the asynchronous operation. + /// + public async Task GenererJeuDeDonneesAsync(CancellationToken cancellationToken = default) + { + 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(StringComparer.OrdinalIgnoreCase); + 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.Where(g => !string.IsNullOrWhiteSpace(g))) + { + var artistesSpotify = await this.GetAsync( + $"https://api.spotify.com/v1/search?q={Uri.EscapeDataString($"genre:\"{genre}\"")}&type=artist&market={this.options.Market}&limit={Math.Clamp(this.options.ArtistsPerGenre, 1, 10)}", + 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 => this.GetOrCreateStyle(styles, NormalizeGenre(g), ref nextStyleId)) + .DistinctBy(s => s.IdStyle) + .ToList(); + + var artiste = new Artiste + { + IdArtiste = nextArtistId++, + Nom = Trim(artisteSpotify.Name, 50, "Artiste Spotify"), + Biographie = Trim( + $"{artisteSpotify.Name} est un artiste present sur Spotify, associe aux styles {string.Join(", ", stylesTitre.Select(s => s.Libelle))}.", + 4000, + "Artiste issu du catalogue Spotify."), + Titres = new List(), + }; + + 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 = new Titre + { + IdTitre = nextTitreId++, + IdArtiste = artiste.IdArtiste, + Artiste = artiste, + Libelle = Trim(track.Name, 200, "Titre Spotify"), + Chronique = Trim( + $"{track.Name} est un titre de {artiste.Nom}, issu de l'album {album.Name}. Cette fiche a ete generee depuis Spotify.", + 4000, + "Titre importe depuis Spotify."), + DateCreation = DateTime.UtcNow, + DateSortie = ParseDate(album.ReleaseDate), + Duree = Math.Max(1, track.DurationMs / 1000), + UrlJaquette = Trim(album.Images.FirstOrDefault()?.Url, 250, "https://placehold.co/640x640"), + UrlEcoute = Trim(track.ExternalUrls?.Spotify ?? $"https://open.spotify.com/track/{track.Id}", 250, string.Empty), + NbLectures = Random.Shared.Next(500, 50000), + NbLikes = Random.Shared.Next(50, 5000), + Album = Trim(album.Name, 200, "Album Spotify"), + Commentaires = new List(), + Styles = new List