From b529731c95bef7c63d4215e666bf3c62b9080249 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 25 Dec 2021 21:36:42 -0500 Subject: [PATCH] Song uploads Uploading songs is functional and does not use the song metadata for the filename or directory creation --- Controllers/Managers/CoverArtManager.cs | 18 ++++--- Controllers/Managers/DirectoryManager.cs | 48 +++++++---------- Controllers/Managers/SongManager.cs | 65 +++++++++++------------- Controllers/v1/SongDataController.cs | 10 ++-- Models/Album.cs | 3 ++ Models/Artist.cs | 1 + Models/CoverArt.cs | 23 ++++++++- Models/Genre.cs | 1 + Models/Song.cs | 13 +++++ 9 files changed, 105 insertions(+), 77 deletions(-) diff --git a/Controllers/Managers/CoverArtManager.cs b/Controllers/Managers/CoverArtManager.cs index 3fbe4cd..39bb612 100644 --- a/Controllers/Managers/CoverArtManager.cs +++ b/Controllers/Managers/CoverArtManager.cs @@ -37,9 +37,7 @@ namespace Icarus.Controllers.Managers { _logger.Info("Saving cover art record to the database"); _coverArtContext.Add(coverArt); - var songTitle = coverArt.SongTitle; - - coverArt = _coverArtContext.CoverArtImages.FirstOrDefault(cov => cov.SongTitle.Equals(songTitle)); + _coverArtContext.SaveChanges(); song.CoverArtID = coverArt.CoverArtID; } @@ -80,15 +78,19 @@ namespace Icarus.Controllers.Managers try { var dirMgr = new DirectoryManager(_rootCoverArtPath); + var defaultExtension = ".png"; dirMgr.CreateDirectory(song); - // TODO: Do not use metadata for file structure - var imagePath = dirMgr.SongDirectory + song.Title + ".png"; + var coverArt = new CoverArt { - SongTitle = song.Title, - ImagePath = imagePath + SongTitle = song.Title }; + var segment = coverArt.GenerateFilename(0); + var imagePath = dirMgr.SongDirectory + segment + defaultExtension; + + coverArt.ImagePath = imagePath; + var metaData = new MetadataRetriever(); var imgBytes = metaData.RetrieveCoverArtBytes(song); @@ -100,7 +102,7 @@ namespace Icarus.Controllers.Managers else { _logger.Info("Song has no cover art, applying stock cover art"); - coverArt.ImagePath = _rootCoverArtPath + "CoverArt.png"; + coverArt.ImagePath = _rootCoverArtPath + $"{segment}{defaultExtension}"; metaData.UpdateCoverArt(song, coverArt); File.WriteAllBytes(coverArt.ImagePath, _stockCoverArt); } diff --git a/Controllers/Managers/DirectoryManager.cs b/Controllers/Managers/DirectoryManager.cs index 94bb9a3..acf14fb 100644 --- a/Controllers/Managers/DirectoryManager.cs +++ b/Controllers/Managers/DirectoryManager.cs @@ -50,24 +50,7 @@ namespace Icarus.Controllers.Managers #region Methods public void CreateDirectory() { - try - { - _songDirectory = AlbumDirectory(); - - if (!Directory.Exists(_songDirectory)) - { - Directory.CreateDirectory(_songDirectory); - Console.WriteLine("The directory has been created"); - } - - - Console.WriteLine($"The song will be saved in the following" + - $" directory: {_songDirectory}"); - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred {ex.Message}"); - } + CreateDirectory(_song); } public void CreateDirectory(Song song) { @@ -209,34 +192,41 @@ namespace Icarus.Controllers.Managers private string AlbumDirectory() { - string directory = _rootSongDirectory; - directory += $@"{_song.Artist}/{_song.AlbumTitle}/"; - - return directory; + return AlbumDirectory(_song); } private string AlbumDirectory(Song song) { - var directory = _rootSongDirectory; - directory += $@"{song.Artist}/{song.AlbumTitle}/"; + var directory = ArtistDirectory(song); + var segment = SerializeValue(song.AlbumTitle); + directory += $@"{segment}/"; Console.WriteLine($"Album directory {directory}"); return directory; } private string ArtistDirectory() { - var directory = _rootSongDirectory; - directory += $@"{_song.Artist}/"; - - return directory; + return ArtistDirectory(_song); } private string ArtistDirectory(Song song) { var directory = _rootSongDirectory; - directory += $@"{song.Artist}/"; + var segment = SerializeValue(song.Artist); + directory += $@"{segment}/"; Console.WriteLine($"Artist directory {directory}"); return directory; } + + private string SerializeValue(string value) + { + const int length = 15; + const string chars = "ABCDEF0123456789"; + var random = new Random(); + var output = new string(Enumerable.Repeat(chars, length).Select(s => + s[random.Next(s.Length)]).ToArray()); + + return output; + } #endregion } } diff --git a/Controllers/Managers/SongManager.cs b/Controllers/Managers/SongManager.cs index 7ea7434..c670409 100644 --- a/Controllers/Managers/SongManager.cs +++ b/Controllers/Managers/SongManager.cs @@ -162,18 +162,15 @@ namespace Icarus.Controllers.Managers { _logger.Info("Starting the process of saving the song to the filesystem"); - var fileTempPath = Path.Combine(_tempDirectoryRoot, songFile.FileName); - var song = await SaveSongTemp(songFile, fileTempPath); - song.SongDirectory = _tempDirectoryRoot; - song.Filename = songFile.FileName; + var song = await SaveSongTemp(songFile); + System.IO.File.Delete(song.SongPath()); DirectoryManager dirMgr = new DirectoryManager(_config, song); dirMgr.CreateDirectory(); - System.IO.File.Delete(fileTempPath); - - var filePath = dirMgr.SongDirectory; - var songFilename = songFile.FileName; + var fileDir = dirMgr.SongDirectory; + var filePath = fileDir; + var songFilename = song.Filename; if (!songFilename.EndsWith(".mp3")) filePath += $"{songFilename}.mp3"; @@ -188,7 +185,6 @@ namespace Icarus.Controllers.Managers await (songFile.CopyToAsync(fileStream)); song.SongDirectory = dirMgr.SongDirectory; - _logger.Info("Song successfully saved to filesystem"); } @@ -209,7 +205,8 @@ namespace Icarus.Controllers.Managers public async Task RetrieveSong(Song songMetaData) { - SongData song = new SongData(); + var song = new SongData(); + try { Console.WriteLine("Fetching song from filesystem"); @@ -235,9 +232,11 @@ namespace Icarus.Controllers.Managers Data = uncompressedSong }; } - private async Task SaveSongTemp(IFormFile songFile, string filePath) + private async Task SaveSongTemp(IFormFile songFile) { var song = new Song(); + var filename = song.GenerateFilename(); + var filePath = Path.Combine(_tempDirectoryRoot, filename); using (var filestream = new FileStream(filePath, FileMode.Create)) @@ -250,7 +249,8 @@ namespace Icarus.Controllers.Managers song = meta.RetrieveMetaData(filePath); _logger.Info("Assigning song filename"); - song.Filename = songFile.FileName; + song.Filename = filename; + song.SongDirectory = _tempDirectoryRoot; song.DateCreated = DateTime.Now; return song; @@ -300,14 +300,15 @@ namespace Icarus.Controllers.Managers { _logger.Info("Starting process to save the song to the database"); - SaveAlbumToDatabase(ref song);//, albumStore); - SaveArtistToDatabase(ref song);//, artistStore); - SaveGenreToDatabase(ref song);//, genreStore); + SaveAlbumToDatabase(ref song); + SaveArtistToDatabase(ref song); + SaveGenreToDatabase(ref song); var info = "Saving Song to DB"; Console.WriteLine(info); _logger.Info(info); _songContext.Add(song); + _songContext.SaveChanges(); } private void SaveAlbumToDatabase(ref Song song) { @@ -318,22 +319,22 @@ namespace Icarus.Controllers.Managers album.Title = song.AlbumTitle; album.AlbumArtist = song.Artist; var albumTitle = song.AlbumTitle; + var albumArtist = song.Artist; AlbumContext albumContext = new AlbumContext(_connectionString); - if (!(albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(albumTitle)) != null)) + var albumRetrieved = albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(albumTitle) && alb.AlbumArtist.Equals(albumArtist)); + + if (albumRetrieved == null) { album.SongCount = 1; albumContext.Add(album); - album = albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(albumTitle)); + albumContext.SaveChanges(); + Console.WriteLine($"Album Id {album.AlbumID}"); } else { - var albumRetrieved = albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(albumTitle)); album.AlbumID = albumRetrieved.AlbumID; - album.SongCount = albumRetrieved.SongCount + 1; - - albumContext.Update(album); } song.AlbumID = album.AlbumID; @@ -349,20 +350,17 @@ namespace Icarus.Controllers.Managers var artistTitle = artist.Name; ArtistContext artistContext = new ArtistContext(_connectionString); - if (!(artistContext.Artists.FirstOrDefault(art => art.Name.Equals(artistTitle)) != null)) + var artistRetrieved = artistContext.Artists.FirstOrDefault(art => art.Name.Equals(artistTitle)); + + if (artistRetrieved == null) { artist.SongCount = 1; artistContext.Add(artist); - artist = artistContext.Artists.FirstOrDefault(art => art.Name.Equals(artistTitle)); + artistContext.SaveChanges(); } else { - var artistRetrieved = artistContext.Artists.FirstOrDefault(art => art.Name.Equals(artistTitle)); artist.ArtistID = artistRetrieved.ArtistID; - artist.SongCount = artistRetrieved.SongCount + 1; - - artistContext.Update(artist); - artistContext.SaveChanges(); } song.ArtistID = artist.ArtistID; @@ -379,12 +377,14 @@ namespace Icarus.Controllers.Managers var genreName = song.Genre; var genreContext = new GenreContext(_connectionString); + var genreRetrieved = genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(genreName)); - if (! (genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(genreName)) != null)) + if (genreRetrieved == null) { genreContext.Add(genre); + genreContext.SaveChanges(); Console.WriteLine("Going to find genre"); - genre = genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(genreName)); + var genreDump = $"Genre ID {genre.GenreID} GenreName {genre.GenreName}" + $" Genre song Count {genre.SongCount}"; Console.WriteLine(genreDump); @@ -392,12 +392,7 @@ namespace Icarus.Controllers.Managers } else { - var genreRetrieved = genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(genreName)); genre.GenreID = genreRetrieved.GenreID; - genre.SongCount = genreRetrieved.SongCount + 1; - - genreContext.Update(genre); - genreContext.SaveChanges(); } song.GenreID = genre.GenreID; diff --git a/Controllers/v1/SongDataController.cs b/Controllers/v1/SongDataController.cs index a5f6f34..f70a16e 100644 --- a/Controllers/v1/SongDataController.cs +++ b/Controllers/v1/SongDataController.cs @@ -55,15 +55,15 @@ namespace Icarus.Controllers.V1 var songContext = new SongContext(_connectionString); var songMetaData = songContext.RetrieveRecord(new Song { SongID = id}); - SongData song = await _songMgr.RetrieveSong(songMetaData); + var song = await _songMgr.RetrieveSong(songMetaData); return File(song.Data, "application/x-msdownload", songMetaData.Filename); } - [HttpPost] + [HttpPost("upload"), DisableRequestSizeLimit] [Route("private-scoped")] [Authorize("upload:songs")] - public async Task Post([FromForm(Name = "file")] List songData) + public async Task Post([FromForm(Name = "file")] List songData) { try { @@ -81,12 +81,16 @@ namespace Icarus.Controllers.V1 await _songMgr.SaveSongToFileSystem(sng); } + + return Ok(); } catch (Exception ex) { var msg = ex.Message; _logger.LogError(msg, "An error occurred"); } + + return NotFound(); } [HttpDelete("{id}")] diff --git a/Models/Album.cs b/Models/Album.cs index 41dfa47..72386b7 100644 --- a/Models/Album.cs +++ b/Models/Album.cs @@ -13,10 +13,13 @@ namespace Icarus.Models [JsonProperty("title")] public string Title { get; set; } [JsonProperty("album_artist")] + [Column("Artist")] public string AlbumArtist { get; set; } [JsonProperty("song_count")] [NotMapped] public int SongCount { get; set; } + [JsonProperty("year")] + public int Year { get; set; } [JsonIgnore] [NotMapped] diff --git a/Models/Artist.cs b/Models/Artist.cs index d5d5364..5863fa1 100644 --- a/Models/Artist.cs +++ b/Models/Artist.cs @@ -11,6 +11,7 @@ namespace Icarus.Models [JsonProperty("artist_id")] public int ArtistID { get; set; } [JsonProperty("name")] + [Column("Artist")] public string Name { get; set; } [JsonProperty("song_count")] [NotMapped] diff --git a/Models/CoverArt.cs b/Models/CoverArt.cs index d97907d..4a6891f 100644 --- a/Models/CoverArt.cs +++ b/Models/CoverArt.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; using System.Text; using Newtonsoft.Json; @@ -9,16 +10,34 @@ namespace Icarus.Models { public class CoverArt { + #region Properties [JsonProperty("cover_art_id")] public int CoverArtID { get; set; } [JsonProperty("title")] public string SongTitle { get; set; } [JsonIgnore] public string ImagePath { get; set; } - [JsonProperty("song_id")] - public int SongId { get; set; } + [JsonIgnore] + [NotMapped] + public int SongID { get; set; } [JsonIgnore] [NotMapped] public List Songs { get; set; } + #endregion + + + #region Methods + public string GenerateFilename(int flag) + { + const int length = 25; + const string chars = "ABCDEF0123456789"; + var random = new Random(); + var filename = new string(Enumerable.Repeat(chars, length).Select(s => + s[random.Next(s.Length)]).ToArray()); + var extension = ".mp3"; + + return (flag == 0) ? filename : $"{filename}{extension}"; + } + #endregion } } diff --git a/Models/Genre.cs b/Models/Genre.cs index 5ba2377..4d53466 100644 --- a/Models/Genre.cs +++ b/Models/Genre.cs @@ -11,6 +11,7 @@ namespace Icarus.Models [JsonProperty("genre_id")] public int GenreID { get; set; } [JsonProperty("genre")] + [Column("Category")] public string GenreName { get; set; } [JsonProperty("song_count")] [NotMapped] diff --git a/Models/Song.cs b/Models/Song.cs index 7ff55af..ff52872 100644 --- a/Models/Song.cs +++ b/Models/Song.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; using Newtonsoft.Json; @@ -58,6 +59,18 @@ namespace Icarus.Models return fullPath; } + + public string GenerateFilename() + { + const int length = 25; + const string chars = "ABCDEF0123456789"; + var random = new Random(); + var filename = new string(Enumerable.Repeat(chars, length).Select(s => + s[random.Next(s.Length)]).ToArray()); + var extension = ".mp3"; + + return $"{filename}{extension}"; + } #endregion } }