diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000..8612f23 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "8.0.7", + "commands": [ + "dotnet-ef" + ], + "rollForward": false + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index e035641..1488bbd 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ /obj /obj/* /Icarus.txt +/appsettings.json +/appsettings.Development.json +appsettings.Development.json +appsettings.json diff --git a/Authorization/Handlers/HasScopeHandler.cs b/Authorization/Handlers/HasScopeHandler.cs index fa11cfa..3e4e06f 100644 --- a/Authorization/Handlers/HasScopeHandler.cs +++ b/Authorization/Handlers/HasScopeHandler.cs @@ -1,7 +1,3 @@ -using System; -using System.Linq; -using System.Threading.Tasks; - using Microsoft.AspNetCore.Authorization; using Icarus.Authorization; @@ -18,7 +14,7 @@ public class HasScopeHandler : AuthorizationHandler } var scopes = context.User.FindFirst(c => - c.Type == "scope" && c.Issuer == requirement.Issuer).Value.Split(' '); + c.Type == "scope" && c.Issuer == requirement.Issuer)!.Value.Split(' '); if (scopes.Any(s => s == requirement.Scope)) { diff --git a/Constants/FileExtensions.cs b/Constants/FileExtensions.cs index 2b20822..452aac7 100644 --- a/Constants/FileExtensions.cs +++ b/Constants/FileExtensions.cs @@ -2,6 +2,9 @@ namespace Icarus.Constants; public class FileExtensions { + // Contains the default audio file extension with period at the beginning + public static string DEFAULT_AUDIO_EXTENSION = WAV_EXTENSION!; + // Contains file extension with period at the beginning public static string MP3_EXTENSION = ".mp3"; @@ -11,6 +14,9 @@ public class FileExtensions // Contains file extension with period at the beginning public static string JPG_EXTENSION = ".jpg"; + // Contains file extension with period at the beginning + public static string FLAC_EXTENSION = ".flac"; + // Contains file extension with period at the beginning public static string ZIP_EXTENSION = ".zip"; } diff --git a/Controllers/Managers/AlbumManager.cs b/Controllers/Managers/AlbumManager.cs index 82b2603..e6a3642 100644 --- a/Controllers/Managers/AlbumManager.cs +++ b/Controllers/Managers/AlbumManager.cs @@ -6,7 +6,7 @@ namespace Icarus.Controllers.Managers; public class AlbumManager : BaseManager { #region Fields - private AlbumContext _albumContext; + private AlbumContext? _albumContext; #endregion @@ -19,7 +19,7 @@ public class AlbumManager : BaseManager { _config = config; _connectionString = _config.GetConnectionString("DefaultConnection"); - _albumContext = new AlbumContext(_connectionString); + _albumContext = new AlbumContext(_connectionString!); } #endregion @@ -33,11 +33,11 @@ public class AlbumManager : BaseManager album.Title = song.AlbumTitle; album.AlbumArtist = song.Artist; - album.Year = song.Year.Value; + album.Year = song.Year!.Value; var albumTitle = song.AlbumTitle; var albumArtist = song.Artist; - var albumRetrieved = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(albumTitle) && alb.AlbumArtist.Equals(albumArtist)); + var albumRetrieved = _albumContext!.Albums!.FirstOrDefault(alb => alb.Title!.Equals(albumTitle) && alb.AlbumArtist!.Equals(albumArtist)); if (albumRetrieved == null) { @@ -58,7 +58,7 @@ public class AlbumManager : BaseManager public void DeleteAlbumFromDatabase(Song song) { - var album = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(song.AlbumTitle)); + var album = _albumContext!.Albums!.FirstOrDefault(alb => alb.Title!.Equals(song.AlbumTitle)); if (album == null) { @@ -72,7 +72,7 @@ public class AlbumManager : BaseManager public Album UpdateAlbumInDatabase(Song oldSong, Song newSong) { - var albumRecord = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(oldSong.AlbumTitle)); + var albumRecord = _albumContext!.Albums!.FirstOrDefault(alb => alb.Title!.Equals(oldSong.AlbumTitle)); var oldAlbumTitle = oldSong.AlbumTitle; var oldAlbumArtist = oldSong.Artist; var newAlbumTitle = newSong.AlbumTitle; @@ -86,16 +86,16 @@ public class AlbumManager : BaseManager newAlbumTitle = oldAlbumTitle; if ((string.IsNullOrEmpty(newAlbumTitle) && string.IsNullOrEmpty(newAlbumArtist) || - oldAlbumTitle.Equals(newAlbumTitle) && oldAlbumArtist.Equals(newAlbumArtist))) + oldAlbumTitle!.Equals(newAlbumTitle) && oldAlbumArtist!.Equals(newAlbumArtist))) { _logger.Info("No change to the song's album"); - return albumRecord; + return albumRecord!; } info = "Change to the song's album"; _logger.Info(info); - var existingAlbumRecord = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(oldSong.AlbumTitle)); + var existingAlbumRecord = _albumContext.Albums!.FirstOrDefault(alb => alb.Title!.Equals(oldSong.AlbumTitle)); if (existingAlbumRecord == null) { _logger.Info("Creating new album record"); @@ -104,7 +104,7 @@ public class AlbumManager : BaseManager { Title = newAlbumTitle, AlbumArtist = newAlbumArtist, - Year = newSong.Year.Value + Year = newSong.Year!.Value }; _albumContext.Add(newAlbumRecord); @@ -116,8 +116,8 @@ public class AlbumManager : BaseManager { _logger.Info("Updating existing album record"); - existingAlbumRecord = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(newSong.AlbumTitle)); - existingAlbumRecord.AlbumArtist = newAlbumArtist; + existingAlbumRecord = _albumContext.Albums!.FirstOrDefault(alb => alb.Title!.Equals(newSong.AlbumTitle)); + existingAlbumRecord!.AlbumArtist = newAlbumArtist; _albumContext.Update(existingAlbumRecord); _albumContext.SaveChanges(); @@ -130,15 +130,15 @@ public class AlbumManager : BaseManager { if (SongsInAlbum(album) <= 1) { - _albumContext.Remove(album); + _albumContext!.Remove(album); _albumContext.SaveChanges(); } } private int SongsInAlbum(Album album) { - var sngContext = new SongContext(_connectionString); - var songs = sngContext.Songs.Where(sng => sng.AlbumId == album.Id).ToList(); + var sngContext = new SongContext(_connectionString!); + var songs = sngContext!.Songs!.Where(sng => sng.AlbumId == album.Id).ToList(); return songs.Count; } diff --git a/Controllers/Managers/ArtistManager.cs b/Controllers/Managers/ArtistManager.cs index de12592..8e7dcdb 100644 --- a/Controllers/Managers/ArtistManager.cs +++ b/Controllers/Managers/ArtistManager.cs @@ -6,7 +6,7 @@ namespace Icarus.Controllers.Managers; public class ArtistManager : BaseManager { #region Fields - private ArtistContext _artistContext; + private ArtistContext? _artistContext; #endregion @@ -19,7 +19,7 @@ public class ArtistManager : BaseManager { _config = config; _connectionString = _config.GetConnectionString("DefaultConnection"); - _artistContext = new ArtistContext(_connectionString); + _artistContext = new ArtistContext(_connectionString!); } #endregion @@ -35,7 +35,7 @@ public class ArtistManager : BaseManager SongCount = 1 }; - var artistRetrieved = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(artist.Name)); + var artistRetrieved = _artistContext!.Artists.FirstOrDefault(art => art.Name!.Equals(artist.Name)); if (artistRetrieved == null) { @@ -53,11 +53,11 @@ public class ArtistManager : BaseManager public Artist UpdateArtistInDatabase(Song oldSongRecord, Song newSongRecord) { - var oldArtistRecord = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(oldSongRecord.AlbumTitle)); - var oldArtistName = oldArtistRecord.Name; + var oldArtistRecord = _artistContext!.Artists.FirstOrDefault(art => art.Name!.Equals(oldSongRecord.AlbumTitle)); + var oldArtistName = oldArtistRecord!.Name; var newArtistName = newSongRecord.Artist; - if (string.IsNullOrEmpty(newArtistName) || oldArtistName.Equals(newArtistName)) + if (string.IsNullOrEmpty(newArtistName) || oldArtistName!.Equals(newArtistName)) { _logger.Info("No change to the song's Artist"); return oldArtistRecord; @@ -73,7 +73,7 @@ public class ArtistManager : BaseManager _artistContext.SaveChanges(); } - if (!(_artistContext.Artists.FirstOrDefault(art => art.Name.Equals(oldSongRecord.AlbumTitle)) != null)) + if (!(_artistContext.Artists.FirstOrDefault(art => art.Name!.Equals(oldSongRecord.AlbumTitle)) != null)) { _logger.Info("Creating new artist record"); @@ -91,36 +91,36 @@ public class ArtistManager : BaseManager { _logger.Info("Updating existing artist record"); - var existingArtistRecord = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(newSongRecord.AlbumTitle)); + var existingArtistRecord = _artistContext.Artists.FirstOrDefault(art => art.Name!.Equals(newSongRecord.AlbumTitle)); - _artistContext.Update(existingArtistRecord); + _artistContext.Update(existingArtistRecord!); _artistContext.SaveChanges(); - return existingArtistRecord; + return existingArtistRecord!; } } public void DeleteArtistFromDatabase(Song song) { - if (!(_artistContext.Artists.FirstOrDefault(art => art.Name.Equals(song.Artist)) != null)) + if (!(_artistContext!.Artists.FirstOrDefault(art => art.Name!.Equals(song.Artist)) != null)) { _logger.Info("Cannot delete the artist record because it does not exist"); return; } - var artist = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(song.Artist)); + var artist = _artistContext.Artists.FirstOrDefault(art => art.Name!.Equals(song.Artist)); - if (SongsOfArtist(artist) <= 1) + if (SongsOfArtist(artist!) <= 1) { - _artistContext.Remove(artist); + _artistContext!.Remove(artist!); _artistContext.SaveChanges(); } } private int SongsOfArtist(Artist artist) { - var sngContext = new SongContext(_connectionString); - var songs = sngContext.Songs.Where(sng => sng.ArtistId == artist.Id).ToList(); + var sngContext = new SongContext(_connectionString!); + var songs = sngContext.Songs!.Where(sng => sng.ArtistId == artist.Id).ToList(); return songs.Count; } diff --git a/Controllers/Managers/BaseManagers.cs b/Controllers/Managers/BaseManagers.cs index 93e6a5e..5b2ac4f 100644 --- a/Controllers/Managers/BaseManagers.cs +++ b/Controllers/Managers/BaseManagers.cs @@ -7,7 +7,7 @@ public class BaseManager { #region Fields protected static Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); - protected IConfiguration _config; - protected string _connectionString; + protected IConfiguration? _config; + protected string? _connectionString; #endregion } diff --git a/Controllers/Managers/CoverArtManager.cs b/Controllers/Managers/CoverArtManager.cs index ac54aa6..51b48c7 100644 --- a/Controllers/Managers/CoverArtManager.cs +++ b/Controllers/Managers/CoverArtManager.cs @@ -8,9 +8,10 @@ namespace Icarus.Controllers.Managers; public class CoverArtManager : BaseManager { #region Fields - private string _rootCoverArtPath; - private CoverArtContext _coverArtContext; - private byte[] _stockCoverArt = null; + private string? _rootCoverArtPath; + private CoverArtContext? _coverArtContext; + private byte[]? _stockCoverArt = null; + private const string? _filename = "CoverArt.png"; #endregion @@ -29,7 +30,7 @@ public class CoverArtManager : BaseManager public void SaveCoverArtToDatabase(ref Song song, ref CoverArt coverArt) { _logger.Info("Saving cover art record to the database"); - _coverArtContext.Add(coverArt); + _coverArtContext!.Add(coverArt); _coverArtContext.SaveChanges(); song.CoverArtId = coverArt.Id; @@ -38,7 +39,7 @@ public class CoverArtManager : BaseManager { _logger.Info("Attempting to delete cover art from the database"); - _coverArtContext.Attach(coverArt); + _coverArtContext!.Attach(coverArt); _coverArtContext.Remove(coverArt); _coverArtContext.SaveChanges(); } @@ -46,7 +47,7 @@ public class CoverArtManager : BaseManager { try { - var stockCoverArtPath = _rootCoverArtPath + "CoverArt.png"; + var stockCoverArtPath = _rootCoverArtPath + _filename; if (!string.Equals(stockCoverArtPath, coverArt.ImagePath(), StringComparison.CurrentCultureIgnoreCase)) { @@ -67,17 +68,17 @@ public class CoverArtManager : BaseManager } } - public CoverArt SaveCoverArt(Song song) + public CoverArt? SaveCoverArt(Song song) { try { - var dirMgr = new DirectoryManager(_rootCoverArtPath); + var dirMgr = new DirectoryManager(_rootCoverArtPath!); var defaultExtension = ".png"; dirMgr.CreateDirectory(song); var coverArt = new CoverArt { - SongTitle = song.Title + SongTitle = song.Title! }; var segment = coverArt.GenerateFilename(0); @@ -102,7 +103,7 @@ public class CoverArtManager : BaseManager metaData.UpdateCoverArt(song, coverArt); coverArt.Directory = this._rootCoverArtPath; coverArt.Filename = $"{segment}{defaultExtension}"; - File.WriteAllBytes(coverArt.ImagePath(), _stockCoverArt); + File.WriteAllBytes(coverArt.ImagePath(), _stockCoverArt!); } coverArt.Type = metaData.CoverArtFileExtensionType(coverArt); @@ -131,7 +132,7 @@ public class CoverArtManager : BaseManager try { MetadataRetriever metaData = new MetadataRetriever(); - var dirMgr = new DirectoryManager(_rootCoverArtPath); + var dirMgr = new DirectoryManager(_rootCoverArtPath!); cover.Type = metaData.FileExtensionType(data); var defaultExtension = "." + cover.Type; dirMgr.CreateDirectory(song); @@ -157,21 +158,23 @@ public class CoverArtManager : BaseManager public CoverArt GetCoverArt(Song song) { - return _coverArtContext.CoverArtImages.FirstOrDefault(cov => cov.SongTitle.Equals(song.Title)); + var title = song.Title; + var cov = _coverArtContext!.CoverArtImages!.FirstOrDefault(cov => cov.SongTitle!.Equals(title)); + return cov!; } private void Initialize() { - _coverArtContext = new CoverArtContext(_connectionString); + _coverArtContext = new CoverArtContext(_connectionString!); var path = DirectoryPaths.CoverArtDirectory + DirectoryPaths.CoverArtFilename; if (System.IO.File.Exists(path)) _stockCoverArt = File.ReadAllBytes(path); - if (!File.Exists(_rootCoverArtPath + "CoverArt.png")) + if (!File.Exists(_rootCoverArtPath + _filename)) { - File.WriteAllBytes(_rootCoverArtPath + "CoverArt.png", - _stockCoverArt); + File.WriteAllBytes(_rootCoverArtPath + _filename, + _stockCoverArt!); Console.WriteLine("Copied Stock Cover Art"); } } diff --git a/Controllers/Managers/DirectoryManager.cs b/Controllers/Managers/DirectoryManager.cs index 216c1c7..f1522a4 100644 --- a/Controllers/Managers/DirectoryManager.cs +++ b/Controllers/Managers/DirectoryManager.cs @@ -7,14 +7,14 @@ namespace Icarus.Controllers.Managers; public class DirectoryManager : BaseManager { #region Fields - private Song _song; - private string _rootSongDirectory; - private string _songDirectory; + private Song? _song; + private string? _rootSongDirectory; + private string? _songDirectory; #endregion #region Properties - public string SongDirectory + public string? SongDirectory { get => _songDirectory; set => _songDirectory = value; @@ -65,7 +65,7 @@ public class DirectoryManager : BaseManager public void CreateDirectory() { - this.CreateDirectory(_song); + this.CreateDirectory(_song!); } public void CreateDirectory(Song song) @@ -187,9 +187,9 @@ public class DirectoryManager : BaseManager private class DirEnt { - public string Pre { get; set;} - public string Path { get; set; } - public string Post { get; set; } + public string? Pre { get; set;} + public string? Path { get; set; } + public string? Post { get; set; } } private void GenerateDirectories(List dirs) @@ -197,7 +197,7 @@ public class DirectoryManager : BaseManager foreach (var di in dirs) { _logger.Info(di.Pre); - Directory.CreateDirectory(di.Path); + Directory.CreateDirectory(di.Path!); _logger.Info(di.Post); } } @@ -207,10 +207,10 @@ public class DirectoryManager : BaseManager switch (dirTypes) { case DirectoryType.Music: - _rootSongDirectory = _config.GetValue("RootMusicPath"); + _rootSongDirectory = _config!.GetValue("RootMusicPath")!; break; case DirectoryType.CoverArt: - _rootSongDirectory = _config.GetValue("CoverArtPath"); + _rootSongDirectory = _config!.GetValue("CoverArtPath")!; break; } } @@ -222,12 +222,12 @@ public class DirectoryManager : BaseManager private string AlbumDirectory() { - return AlbumDirectory(_song); + return AlbumDirectory(_song!); } private string AlbumDirectory(Song song) { var directory = ArtistDirectory(song); - var segment = SerializeValue(song.AlbumTitle); + var segment = SerializeValue(song.AlbumTitle!); directory += $@"{segment}/"; Console.WriteLine($"Album directory {directory}"); @@ -235,12 +235,12 @@ public class DirectoryManager : BaseManager } private string ArtistDirectory() { - return ArtistDirectory(_song); + return ArtistDirectory(_song!); } private string ArtistDirectory(Song song) { var directory = _rootSongDirectory; - var segment = SerializeValue(song.Artist); + var segment = SerializeValue(song.Artist!); directory += $@"{segment}/"; Console.WriteLine($"Artist directory {directory}"); diff --git a/Controllers/Managers/GenreManager.cs b/Controllers/Managers/GenreManager.cs index 0f2ecb7..c91be33 100644 --- a/Controllers/Managers/GenreManager.cs +++ b/Controllers/Managers/GenreManager.cs @@ -6,7 +6,7 @@ namespace Icarus.Controllers.Managers; public class GenreManager : BaseManager { #region Fields - private GenreContext _genreContext; + private GenreContext? _genreContext; #endregion @@ -19,7 +19,7 @@ public class GenreManager : BaseManager { _config = config; _connectionString = _config.GetConnectionString("DefaultConnection"); - _genreContext = new GenreContext(_connectionString); + _genreContext = new GenreContext(_connectionString!); } #endregion @@ -36,7 +36,7 @@ public class GenreManager : BaseManager }; var genreName = song.Genre; - var genreRetrieved = _genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(genreName)); + var genreRetrieved = _genreContext!.Genres!.FirstOrDefault(gnr => gnr.GenreName!.Equals(genreName)); if (genreRetrieved == null) { @@ -53,11 +53,11 @@ public class GenreManager : BaseManager public Genre UpdateGenreInDatabase(Song oldSongRecord, Song newSongRecord) { - var oldGenreRecord = _genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(oldSongRecord.Genre)); - var oldGenreName = oldGenreRecord.GenreName; + var oldGenreRecord = _genreContext!.Genres!.FirstOrDefault(gnr => gnr.GenreName!.Equals(oldSongRecord.Genre)); + var oldGenreName = oldGenreRecord!.GenreName; var newGenreName = newSongRecord.Genre; - if (string.IsNullOrEmpty(newGenreName) || oldGenreName.Equals(newGenreName)) + if (string.IsNullOrEmpty(newGenreName) || oldGenreName!.Equals(newGenreName)) { _logger.Info("No change to the song's Genre"); return oldGenreRecord; @@ -73,7 +73,7 @@ public class GenreManager : BaseManager _genreContext.SaveChanges(); } - if (!(_genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(oldSongRecord.Genre)) != null)) + if (!(_genreContext.Genres!.FirstOrDefault(gnr => gnr.GenreName!.Equals(oldSongRecord.Genre)) != null)) { _logger.Info("Creating new genre record"); @@ -91,36 +91,36 @@ public class GenreManager : BaseManager { _logger.Info("Updating existing genre record"); - var existingGenreRecord = _genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(oldGenreRecord.GenreName)); + var existingGenreRecord = _genreContext.Genres!.FirstOrDefault(gnr => gnr.GenreName!.Equals(oldGenreRecord.GenreName)); - _genreContext.Update(existingGenreRecord); + _genreContext.Update(existingGenreRecord!); _genreContext.SaveChanges(); - return existingGenreRecord; + return existingGenreRecord!; } } public void DeleteGenreFromDatabase(Song song) { - if (!(_genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(song.Genre)) != null)) + if (!(_genreContext!.Genres!.FirstOrDefault(gnr => gnr.GenreName!.Equals(song.Genre)) != null)) { _logger.Info("Cannot delete the genre record because it does not exist"); return; } - var genre = _genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(song.Genre)); + var genre = _genreContext.Genres!.FirstOrDefault(gnr => gnr.GenreName!.Equals(song.Genre)); - if (SongsInGenre(genre) <= 1) + if (SongsInGenre(genre!) <= 1) { - _genreContext.Remove(genre); + _genreContext.Remove(genre!); _genreContext.SaveChanges(); } } private int SongsInGenre(Genre genre) { - var sngContext = new SongContext(_connectionString); - var songs = sngContext.Songs.Where(sng => sng.GenreId == genre.Id).ToList(); + var sngContext = new SongContext(_connectionString!); + var songs = sngContext.Songs!.Where(sng => sng.GenreId == genre.Id).ToList(); return songs.Count; } diff --git a/Controllers/Managers/SongManager.cs b/Controllers/Managers/SongManager.cs index dc53f45..92b3ee6 100644 --- a/Controllers/Managers/SongManager.cs +++ b/Controllers/Managers/SongManager.cs @@ -9,26 +9,26 @@ namespace Icarus.Controllers.Managers; public class SongManager : BaseManager { #region Fields - private string _tempDirectoryRoot; - private string _archiveDirectoryRoot; - private string _compressedSongFilename; - private string _message; - private SongContext _songContext; + private string? _tempDirectoryRoot; + private string? _archiveDirectoryRoot; + private string? _compressedSongFilename; + private string? _message; + private SongContext? _songContext; #endregion #region Properties - public string ArchiveDirectoryRoot + public string? ArchiveDirectoryRoot { get => _archiveDirectoryRoot; set => _archiveDirectoryRoot = value; } - public string CompressedSongFilename + public string? CompressedSongFilename { get => _compressedSongFilename; set => _compressedSongFilename = value; } - public string Message + public string? Message { get => _message; set => _message = value; @@ -64,7 +64,7 @@ public class SongManager : BaseManager try { - var oldSongRecord = _songContext.RetrieveRecord(song); + var oldSongRecord = _songContext!.RetrieveRecord(song); song.Filename = oldSongRecord.Filename; song.SongDirectory = oldSongRecord.SongDirectory; @@ -73,19 +73,19 @@ public class SongManager : BaseManager var updatedSong = updateMetadata.UpdatedSongRecord; - var albMgr = new AlbumManager(_config); - var gnrMgr = new GenreManager(_config); - var artMgr = new ArtistManager(_config); - var updatedAlbum = albMgr.UpdateAlbumInDatabase(oldSongRecord, updatedSong); + var albMgr = new AlbumManager(_config!); + var gnrMgr = new GenreManager(_config!); + var artMgr = new ArtistManager(_config!); + var updatedAlbum = albMgr.UpdateAlbumInDatabase(oldSongRecord, updatedSong!); oldSongRecord.AlbumId = updatedAlbum.Id; - var updatedArtist = artMgr.UpdateArtistInDatabase(oldSongRecord, updatedSong); + var updatedArtist = artMgr.UpdateArtistInDatabase(oldSongRecord, updatedSong!); oldSongRecord.ArtistId = updatedArtist.Id; - var updatedGenre = gnrMgr.UpdateGenreInDatabase(oldSongRecord, updatedSong); + var updatedGenre = gnrMgr.UpdateGenreInDatabase(oldSongRecord, updatedSong!); oldSongRecord.GenreId = updatedGenre.Id; - UpdateSongInDatabase(ref oldSongRecord, ref updatedSong, ref result); + UpdateSongInDatabase(ref oldSongRecord, ref updatedSong!, ref result); DeleteEmptyDirectories(ref oldSongRecord, ref updatedSong); } @@ -109,7 +109,7 @@ public class SongManager : BaseManager var songPath = songMetaData.SongPath(); File.Delete(songPath); successful = true; - DirectoryManager dirMgr = new DirectoryManager(_config, songMetaData); + DirectoryManager dirMgr = new DirectoryManager(_config!, songMetaData); dirMgr.DeleteEmptyDirectories(); Console.WriteLine("Song successfully deleted"); } @@ -123,7 +123,7 @@ public class SongManager : BaseManager public bool DoesSongExist(Song song) { - if (!_songContext.DoesRecordExist(song)) + if (!_songContext!.DoesRecordExist(song)) { return false; } @@ -142,7 +142,7 @@ public class SongManager : BaseManager } _logger.Info("Song deleted from the filesystem"); - var coverMgr = new CoverArtManager(_config); + var coverMgr = new CoverArtManager(_config!); var coverArt = coverMgr.GetCoverArt(song); coverMgr.DeleteCoverArt(coverArt); @@ -166,11 +166,11 @@ public class SongManager : BaseManager var song = await SaveSongTemp(songFile); - DirectoryManager dirMgr = new DirectoryManager(_config, song); + DirectoryManager dirMgr = new DirectoryManager(_config!, song); dirMgr.CreateDirectory(); var tempPath = song.SongPath(); - song.Filename = song.GenerateFilename(1); + song.Filename = song.GenerateFilename(true, AudioFileExtensionsType.WAV); var filePath = $"{dirMgr.SongDirectory}{song.Filename}"; _logger.Info($"Absolute song path: {filePath}"); @@ -178,27 +178,15 @@ public class SongManager : BaseManager await Task.Run(() => { - using (var fileStream = new FileStream(filePath, FileMode.Create)) - { - var songBytes = System.IO.File.ReadAllBytes(tempPath); - - _logger.Info("Saving song to the filesystem"); - fileStream.Write(songBytes, 0, songBytes.Count()); - - System.IO.File.Delete(tempPath); - _logger.Info("Deleting temp file"); - - _logger.Info("Song successfully saved to filesystem"); - } + this.MoveSongToFinalDestination(tempPath, filePath); }); song.SongDirectory = dirMgr.SongDirectory; - var coverMgr = new CoverArtManager(_config); + var coverMgr = new CoverArtManager(_config!); var coverArt = coverMgr.SaveCoverArt(song); - coverMgr.SaveCoverArtToDatabase(ref song, ref coverArt); - SaveSongToDatabase(song); + SaveSongToDatabase(song, coverArt); } catch (Exception ex) { @@ -207,14 +195,28 @@ public class SongManager : BaseManager } } - public void SaveSongToFileSystem(IFormFile songFile, IFormFile coverArtData, Song song) + // Change the name of this method to only focus on wav files + public Song SaveSongToFileSystem(IFormFile songFile, IFormFile coverArtData, Song song) { - song.SongDirectory = _tempDirectoryRoot; - song.DateCreated = DateTime.Now; + if (string.IsNullOrEmpty(song.SongDirectory)) + { + song.SongDirectory = _tempDirectoryRoot; + } if (string.IsNullOrEmpty(song.Filename)) { - song.Filename = song.GenerateFilename(1); + switch (song.AudioType) + { + case "wav": + song.Filename = song.GenerateFilename(true, AudioFileExtensionsType.WAV); + break; + case "flac": + song.Filename = song.GenerateFilename(true, AudioFileExtensionsType.FLAC); + break; + default: + song.Filename = song.GenerateFilename(true, AudioFileExtensionsType.Default); + break; + } } _logger.Info($"Temporary directory: {_tempDirectoryRoot}"); @@ -223,16 +225,19 @@ public class SongManager : BaseManager _logger.Info("Temporary song path: {0}", tempPath); - using (var filestream = new FileStream(tempPath, FileMode.Create)) + if (!System.IO.File.Exists(tempPath)) { - _logger.Info("Saving song to temporary directory"); - songFile.CopyTo(filestream); + using (var filestream = new FileStream(tempPath, FileMode.Create)) + { + _logger.Info("Saving song to temporary directory"); + songFile.CopyTo(filestream); + } } - var coverMgr = new CoverArtManager(_config); + var coverMgr = new CoverArtManager(_config!); var coverArt = coverMgr.SaveCoverArt(coverArtData, song); - DirectoryManager dirMgr = new DirectoryManager(_config, song); + DirectoryManager dirMgr = new DirectoryManager(_config!, song); dirMgr.CreateDirectory(); song.SongDirectory = dirMgr.SongDirectory; @@ -240,24 +245,66 @@ public class SongManager : BaseManager var filePath = song.SongPath(); _logger.Info($"Absolute song path: {filePath}"); - using (var fileStream = new FileStream(filePath, FileMode.Create)) + this.MoveSongToFinalDestination(tempPath, filePath); + + SaveSongToDatabase(song, coverArt); + + return song; + } + + public Song SaveFlacSongToFileSystem(IFormFile songFile, IFormFile coverArtData, Song song) + { + // Save temp song (Should already be saved to the filesystem by the time it gets to this method) + // Save cover art + // Update the song's metadata with the song object + // Save song to its final directory + // Save cover art to the database + // Save song to the database + + var coverMgr = new CoverArtManager(_config!); + var coverArt = coverMgr.SaveCoverArt(coverArtData, song); + + var meta = new Utilities.MetadataRetriever(); + meta.UpdateMetadata(song, song); + + DirectoryManager dirMgr = new DirectoryManager(_config!, song); + dirMgr.CreateDirectory(); + + var tempPath = song.SongPath(); + + song.SongDirectory = dirMgr.SongDirectory; + song.Filename = song.GenerateFilename(true, AudioFileExtensionsType.FLAC); + + var filePath = song.SongPath(); + _logger.Info($"Absolute song path: {filePath}"); + + this.MoveSongToFinalDestination(tempPath, filePath); + + SaveSongToDatabase(song, coverArt); + + return song; + } + + private void MoveSongToFinalDestination(string sourcePath, string targetPath) + { + using (var fileStream = new FileStream(targetPath, FileMode.Create)) { - var songBytes = System.IO.File.ReadAllBytes(tempPath); + var songBytes = System.IO.File.ReadAllBytes(sourcePath); try { - if (System.IO.File.Exists(filePath) && System.IO.File.Exists(tempPath) && fileStream.Length > 0) + if (System.IO.File.Exists(sourcePath) && System.IO.File.Exists(sourcePath) && fileStream.Length > 0) { - System.IO.File.Delete(tempPath); - _logger.Info("Deleted temp song from filesystem: {0}", tempPath); + System.IO.File.Delete(sourcePath); + _logger.Info("Deleted temp song from filesystem: {0}", sourcePath); } else { fileStream.Write(songBytes, 0, songBytes.Count()); - _logger.Info("Saved song to filesystem: {0}", filePath); + _logger.Info("Saved song to filesystem: {0}", targetPath); - System.IO.File.Delete(tempPath); - _logger.Info("Deleted temp song from filesystem: {0}", tempPath); + System.IO.File.Delete(sourcePath); + _logger.Info("Deleted temp song from filesystem: {0}", sourcePath); } } catch (Exception ex) @@ -268,12 +315,7 @@ public class SongManager : BaseManager _logger.Info("Song successfully saved to filesystem"); } - - coverMgr.SaveCoverArtToDatabase(ref song, ref coverArt); - SaveSongToDatabase(song); - } - - + } public async Task RetrieveSong(Song songMetaData) { @@ -304,28 +346,21 @@ public class SongManager : BaseManager Data = uncompressedSong }; } - private async Task SaveSongTemp(IFormFile songFile) + public async Task SaveSongTemp(IFormFile songFile) { - var song = new Song(); _logger.Info("Assigning song filename"); - song.SongDirectory = _tempDirectoryRoot; - var filename = song.GenerateFilename(1); + var song = new Song { SongDirectory = this._tempDirectoryRoot! }; + var filename = await song.GenerateFilenameAsync(false) + "-" + songFile.FileName; song.Filename = filename; + var songPath = song.SongPath(); - using (var filestream = new FileStream(song.SongPath(), FileMode.Create)) + using (var filestream = new FileStream(songPath, FileMode.Create)) { - _logger.Info("Saving temp song: {0}", song.SongPath()); + _logger.Info("Saving temp song: {0}", songPath); await songFile.CopyToAsync(filestream); } - await Task.Run(() => - { - MetadataRetriever meta = new MetadataRetriever(); - song = meta.RetrieveMetaData(song.SongPath()); - }); - song.SongDirectory = _tempDirectoryRoot; song.DateCreated = DateTime.Now; - song.Filename = filename; return song; } @@ -339,9 +374,9 @@ public class SongManager : BaseManager var currentGenre = currentSong.Genre; var currentYear = currentSong.Year; - if (!currentTitle.Equals(songUpdates.Title) || !currentArtist.Equals(songUpdates.Artist) || - !currentAlbum.Equals(songUpdates.AlbumTitle) || - !currentGenre.Equals(songUpdates.Genre) || currentYear != songUpdates.Year) + if (!currentTitle!.Equals(songUpdates.Title) || !currentArtist!.Equals(songUpdates.Artist) || + !currentAlbum!.Equals(songUpdates.AlbumTitle) || + !currentGenre!.Equals(songUpdates.Genre) || currentYear != songUpdates.Year) return true; return false; @@ -349,7 +384,7 @@ public class SongManager : BaseManager private void DeleteEmptyDirectories(ref Song oldSong, ref Song updatedSong) { - DirectoryManager mgr = new DirectoryManager(_config); + DirectoryManager mgr = new DirectoryManager(_config!); _logger.Info("Checking to see if there are any directories to delete"); mgr.DeleteEmptyDirectories(oldSong); @@ -359,8 +394,8 @@ public class SongManager : BaseManager { try { - _connectionString = _config.GetConnectionString("DefaultConnection"); - _songContext = new SongContext(_connectionString); + _connectionString = _config!.GetConnectionString("DefaultConnection"); + _songContext = new SongContext(_connectionString!); } catch (Exception ex) { @@ -370,13 +405,14 @@ public class SongManager : BaseManager - private void SaveSongToDatabase(Song song) + private void SaveSongToDatabase(Song song, CoverArt? cover) { _logger.Info("Starting process to save the song to the database"); - var albumMgr = new AlbumManager(_config); - var artistMgr = new ArtistManager(_config); - var genreMgr = new GenreManager(_config); + var albumMgr = new AlbumManager(_config!); + var artistMgr = new ArtistManager(_config!); + var genreMgr = new GenreManager(_config!); + var coverMgr = new CoverArtManager(_config!); albumMgr.SaveAlbumToDatabase(ref song); artistMgr.SaveArtistToDatabase(ref song); genreMgr.SaveGenreToDatabase(ref song); @@ -384,8 +420,10 @@ public class SongManager : BaseManager var info = "Saving Song to DB"; _logger.Info(info); - _songContext.Add(song); - _songContext.SaveChanges(); + _songContext!.Add(song); + _songContext!.SaveChanges(); + + coverMgr.SaveCoverArtToDatabase(ref song, ref cover!); } @@ -430,7 +468,7 @@ public class SongManager : BaseManager { var updatedSongRecord = oldSongRecord; - var songContext = new SongContext(_connectionString); + var songContext = new SongContext(_connectionString!); if (!SongRecordChanged(oldSongRecord, newSongRecord)) { @@ -470,18 +508,18 @@ public class SongManager : BaseManager newSongRecord = updatedSongRecord; result.Message = "Successfully updated song"; - result.SongTitle = updatedSongRecord.Title; + result.SongTitle = updatedSongRecord.Title!; } private void DeleteSongFromDatabase(Song song) { _logger.Info("Starting process to delete records related to the song from the database"); - var albumMgr = new AlbumManager(_config); - var artistMgr = new ArtistManager(_config); - var genreMgr = new GenreManager(_config); - var sngContext = new SongContext(_connectionString); - sngContext.Songs.Remove(song); + var albumMgr = new AlbumManager(_config!); + var artistMgr = new ArtistManager(_config!); + var genreMgr = new GenreManager(_config!); + var sngContext = new SongContext(_connectionString!); + sngContext.Songs!.Remove(song); sngContext.SaveChanges(); artistMgr.DeleteArtistFromDatabase(song); albumMgr.DeleteAlbumFromDatabase(song); diff --git a/Controllers/Managers/TokenManager.cs b/Controllers/Managers/TokenManager.cs index 96fecfe..8db8dc7 100644 --- a/Controllers/Managers/TokenManager.cs +++ b/Controllers/Managers/TokenManager.cs @@ -15,16 +15,16 @@ namespace Icarus.Controllers.Managers; public class TokenManager : BaseManager { #region Fields - private string _clientId; - private string _clientSecret; - private string _privateKeyPath = string.Empty; - private string _privateKey = string.Empty; - private string _publicKeyPath = string.Empty; - private string _publicKey = string.Empty; - private string _audience; - private string _grantType; - private string _url; - private string SUCCESSFUL_TOKEN_MESSAGE = "Successfully retrieved token"; + private string? _clientId; + private string? _clientSecret; + private string? _privateKeyPath = string.Empty; + private string? _privateKey = string.Empty; + private string? _publicKeyPath = string.Empty; + private string? _publicKey = string.Empty; + private string? _audience; + private string? _grantType; + private string? _url; + private string? SUCCESSFUL_TOKEN_MESSAGE = "Successfully retrieved token"; #endregion @@ -46,7 +46,7 @@ public class TokenManager : BaseManager { _logger.Info("Preparing Auth0 API request"); - var client = new RestClient(_url); + var client = new RestClient(_url!); var request = new RestRequest("oauth/token", Method.POST); var tokenRequest = RetrieveTokenRequest(); @@ -68,7 +68,7 @@ public class TokenManager : BaseManager .DeserializeObject(response.Content); _logger.Info("Response deserialized"); - return this.InitializeLoginResult(user, tokenResult); + return this.InitializeLoginResult(user, tokenResult!); } @@ -80,7 +80,7 @@ public class TokenManager : BaseManager payload.Add(new Claim("user_id", user.Id.ToString(), ClaimValueTypes.Integer)); var tokenHandler = new JwtSecurityTokenHandler(); - var key = Encoding.ASCII.GetBytes(_config["JWT:Secret"]); + var key = Encoding.ASCII.GetBytes(_config!["JWT:Secret"]!); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new Claim[] @@ -101,7 +101,7 @@ public class TokenManager : BaseManager return cl.Type.Equals("exp"); }); - var expiredDate = DateTime.Parse(expClaim.Value); + var expiredDate = DateTime.Parse(expClaim!.Value); var exp = Math.Floor((expiredDate - DateTime.UnixEpoch).TotalSeconds); tokenResult.Expiration = Convert.ToInt32(exp); @@ -197,7 +197,7 @@ public class TokenManager : BaseManager var expiredDate = currentDate.AddMinutes(expLimit); var issuer = "http://localhost:5002"; var audience = "http://localhost:5002"; - var subject = _config["JWT:Subject"]; + var subject = _config!["JWT:Subject"]; var claim = new List() { @@ -205,7 +205,7 @@ public class TokenManager : BaseManager new Claim(JwtRegisteredClaimNames.Exp, expiredDate.ToString()), new Claim(JwtRegisteredClaimNames.Aud, audience), new Claim(JwtRegisteredClaimNames.Iss, issuer), - new Claim(JwtRegisteredClaimNames.Sub, subject), + new Claim(JwtRegisteredClaimNames.Sub, subject!), new Claim(JwtRegisteredClaimNames.Iat, currentDate.ToString()) }; @@ -233,7 +233,7 @@ public class TokenManager : BaseManager { _logger.Info("Analyzing Auth0 information"); - _clientId = _config["Auth0:ClientId"]; + _clientId = _config!["Auth0:ClientId"]; _clientSecret = _config["Auth0:ClientSecret"]; _audience = _config["Auth0:ApiIdentifier"]; _grantType = "client_credentials"; @@ -258,23 +258,23 @@ public class TokenManager : BaseManager private class TokenRequest { [JsonProperty("client_id")] - public string ClientId { get; set; } + public string? ClientId { get; set; } [JsonProperty("client_secret")] - public string ClientSecret { get; set; } + public string? ClientSecret { get; set; } [JsonProperty("audience")] - public string Audience { get; set; } + public string? Audience { get; set; } [JsonProperty("grant_type")] - public string GrantType { get; set; } + public string? GrantType { get; set; } } private class TokenTierOne { [JsonProperty("access_token")] - public string AccessToken { get; set; } + public string? AccessToken { get; set; } [JsonProperty("expires_in")] public int Expiration { get; set; } [JsonProperty("token_type")] - public string TokenType { get; set; } + public string? TokenType { get; set; } } #endregion } diff --git a/Controllers/Utilities/MetadataRetriever.cs b/Controllers/Utilities/MetadataRetriever.cs index 1862226..6ebe2da 100644 --- a/Controllers/Utilities/MetadataRetriever.cs +++ b/Controllers/Utilities/MetadataRetriever.cs @@ -8,25 +8,27 @@ namespace Icarus.Controllers.Utilities; public class MetadataRetriever { #region Fields - private static NLog.Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); - private Song _updatedSong; - private string _message; - private string _title; - private string _artist; - private string _album; - private string _genre; + private static NLog.Logger? _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); + private List? _supportedAudioFileTypes = new List {"wav", "flac"}; + private List? _supportedImageFileTypes = new List {"jpeg", "jpg", "png"}; + private Song? _updatedSong; + private string? _message; + private string? _title; + private string? _artist; + private string? _album; + private string? _genre; private int _year; private int _duration; #endregion #region Properties - public Song UpdatedSongRecord + public Song? UpdatedSongRecord { get => _updatedSong; set => _updatedSong = value; } - public string Message + public string? Message { get => _message; set => _message = value; @@ -39,32 +41,6 @@ public class MetadataRetriever #region Methods - public static void PrintMetadata(Song song) - { - Console.WriteLine("\n\nMetadata of the song:"); - Console.WriteLine($"ID: {song.Id}"); - Console.WriteLine($"Title: {song.Title}"); - Console.WriteLine($"Artist: {song.Artist}"); - Console.WriteLine($"Album: {song.AlbumTitle}"); - Console.WriteLine($"Genre: {song.Genre}"); - Console.WriteLine($"Year: {song.Year}"); - Console.WriteLine($"Duration: {song.Duration}"); - Console.WriteLine($"AlbumID: {song.AlbumId}"); - Console.WriteLine($"ArtistID: {song.ArtistId}"); - Console.WriteLine($"GenreID: {song.GenreId}"); - Console.WriteLine($"Song Path: {song.SongPath()}"); - Console.WriteLine($"Filename: {song.Filename}"); - Console.WriteLine("\n"); - - _logger.Info("Metadata of the song"); - _logger.Info($"Title: {song.Title}"); - _logger.Info($"Artist: {song.Artist}"); - _logger.Info($"Album: {song.AlbumTitle}"); - _logger.Info($"Genre: {song.Genre}"); - _logger.Info($"Year: {song.Year}"); - _logger.Info($"Duration: {song.Duration}"); - } - public string CoverArtFileExtensionType(CoverArt cover) { Console.WriteLine("Retrieving CoverArt file extension type"); @@ -106,6 +82,52 @@ public class MetadataRetriever } } + public string FileExtensionType(string path) + { + var extensionRaw = System.IO.Path.GetExtension(path); + + if (extensionRaw[0] == '.') + { + return extensionRaw.Substring(1); + } + else + { + return extensionRaw; + } + } + + public bool IsSupportedFile(IFormFile file) + { + var supportedTypes = this._supportedAudioFileTypes; + this._supportedImageFileTypes!.ForEach(t => + { + if (!supportedTypes!.Contains(t)) + { + supportedTypes.Add(t); + } + }); + + var extensionType = this.FileExtensionType(file).ToLower(); + + return supportedTypes!.Contains(extensionType); + } + + public bool IsSupportedFile(string path) + { + var supportedTypes = this._supportedAudioFileTypes; + this._supportedImageFileTypes!.ForEach(t => + { + if (!supportedTypes!.Contains(t)) + { + supportedTypes.Add(t); + } + }); + + var extensionType = this.FileExtensionType(path).ToLower(); + + return supportedTypes!.Contains(extensionType); + } + public Song RetrieveMetaData(string filePath) { Song song = new Song(); @@ -140,7 +162,7 @@ public class MetadataRetriever var msg = ex.Message; Console.WriteLine("An error occurred in MetadataRetriever"); Console.WriteLine(msg); - _logger.Error(msg, "An error occurred in MetadataRetriever"); + _logger!.Error(msg, "An error occurred in MetadataRetriever"); } return song; @@ -148,9 +170,8 @@ public class MetadataRetriever public int RetrieveSongDuration(string filepath) { - var duration = 0; var fileTag = TagLib.File.Create(filepath); - duration = (int)fileTag.Properties.Duration.TotalSeconds; + var duration = (int)fileTag.Properties.Duration.TotalSeconds; return duration; } @@ -161,17 +182,21 @@ public class MetadataRetriever { Console.WriteLine("Fetching image"); var tag = TagLib.File.Create(song.SongPath()); - byte[] imgBytes = tag.Tag.Pictures[0].Data.Data; - - return imgBytes; + + if (tag.Tag.Pictures.Count() == 0) + { + return []; + } + + return tag.Tag.Pictures[0].Data.Data; } catch (Exception ex) { var msg = ex.Message; - _logger.Error(msg, "An error occurred in MetadataRetriever"); + _logger!.Error(msg, "An error occurred in MetadataRetriever"); } - return null; + return []; } @@ -188,7 +213,7 @@ public class MetadataRetriever { var msg = ex.Message; Console.WriteLine($"An error occurred: {msg}"); - _logger.Error(msg, "An error occurred"); + _logger!.Error(msg, "An error occurred"); Message = "Failed to update metadata"; } } @@ -227,7 +252,7 @@ public class MetadataRetriever try { Console.WriteLine($"Updating metadata of {title}"); - _logger.Info($"Updating metadata of {title}"); + _logger!.Info($"Updating metadata of {title}"); foreach (var key in checkedValues.Keys) { @@ -237,43 +262,43 @@ public class MetadataRetriever switch (key.ToLower()) { case "title": - _updatedSong.Title = title; + _updatedSong!.Title = title; fileTag.Tag.Title = title; break; case "artists": - _updatedSong.Artist = artist; + _updatedSong!.Artist = artist; fileTag.Tag.Performers = new []{artist}; break; case "album": - _updatedSong.AlbumTitle = album; + _updatedSong!.AlbumTitle = album; fileTag.Tag.Album = album; break; case "genre": - _updatedSong.Genre = genre; + _updatedSong!.Genre = genre; fileTag.Tag.Genres = new []{genre}; break; case "year": - _updatedSong.Year = year; - fileTag.Tag.Year = (uint)year; + _updatedSong!.Year = year; + fileTag.Tag.Year = (uint)year!; break; case "albumartist": - _updatedSong.AlbumArtist = albumArtist; + _updatedSong!.AlbumArtist = albumArtist; fileTag.Tag.AlbumArtists = new []{albumArtist}; break; case "track": - _updatedSong.Track = track; + _updatedSong!.Track = track; fileTag.Tag.Track = (uint)(track); break; case "trackcount": - _updatedSong.TrackCount = trackCount; + _updatedSong!.TrackCount = trackCount; fileTag.Tag.TrackCount = (uint)(trackCount); break; case "disc": - _updatedSong.Disc = disc; + _updatedSong!.Disc = disc; fileTag.Tag.Disc = (uint)(disc); break; case "disccount": - _updatedSong.DiscCount = discCount; + _updatedSong!.DiscCount = discCount; fileTag.Tag.DiscCount = (uint)(discCount); break; } @@ -288,55 +313,19 @@ public class MetadataRetriever { var msg = ex.Message; Console.WriteLine($"An error occurred:\n{msg}"); - _logger.Error(msg, "An error occurred"); + _logger!.Error(msg, "An error occurred"); } } private void InitializeUpdatedSong(Song song) { _updatedSong = song; } - private void PrintMetadata() - { - Console.WriteLine("\n\nMetadata of the song:"); - Console.WriteLine($"Title: {_title}"); - Console.WriteLine($"Artist: {_artist}"); - Console.WriteLine($"Album: {_album}"); - Console.WriteLine($"Genre: {_genre}"); - Console.WriteLine($"Year: {_year}"); - Console.WriteLine($"Duration: {_duration}\n\n"); - - _logger.Info("Metadata of the song"); - _logger.Info($"Title: {_title}"); - _logger.Info($"Artist: {_artist}"); - _logger.Info($"Album: {_album}"); - _logger.Info($"Genre: {_genre}"); - _logger.Info($"Year: {_year}"); - _logger.Info($"Duration: {_duration}"); - } - private void PrintMetadata(Song song, string message) - { - Console.WriteLine($"\n\n{message}"); - Console.WriteLine($"Title: {song.Title}"); - Console.WriteLine($"Artist: {song.Artist}"); - Console.WriteLine($"Album: {song.AlbumTitle}"); - Console.WriteLine($"Genre: {song.Genre}"); - Console.WriteLine($"Year: {song.Year}"); - Console.WriteLine($"Duration: {song.Duration}\n\n"); - - _logger.Info(message); - _logger.Info($"Title: {_title}"); - _logger.Info($"Artist: {_artist}"); - _logger.Info($"Album: {_album}"); - _logger.Info($"Genre: {_genre}"); - _logger.Info($"Year: {_year}"); - _logger.Info($"Duration: {_duration}"); - } private SortedDictionary CheckSongValues(Song song) { var songValues = new SortedDictionary(); Console.WriteLine("Checking for null data"); - _logger.Info("Checking for null data"); + _logger!.Info("Checking for null data"); try { diff --git a/Controllers/Utilities/PasswordEncryption.cs b/Controllers/Utilities/PasswordEncryption.cs index 9984ae0..f09374e 100644 --- a/Controllers/Utilities/PasswordEncryption.cs +++ b/Controllers/Utilities/PasswordEncryption.cs @@ -60,7 +60,7 @@ public class PasswordEncryption _logger.Error(exMsg, "An error occurred"); } - return null; + return string.Empty; } string GenerateHash(string password, byte[] salt) diff --git a/Controllers/Utilities/SongCompression.cs b/Controllers/Utilities/SongCompression.cs index ef7035a..ea72b2c 100644 --- a/Controllers/Utilities/SongCompression.cs +++ b/Controllers/Utilities/SongCompression.cs @@ -1,5 +1,3 @@ -using Ionic.Zip; - using Icarus.Models; namespace Icarus.Controllers.Utilities; @@ -7,14 +5,14 @@ namespace Icarus.Controllers.Utilities; public class SongCompression { #region Fields - string _compressedSongFilename; - string _tempDirectory; - byte[] _uncompressedSong; + string? _compressedSongFilename; + string? _tempDirectory; + byte[]? _uncompressedSong; #endregion #region Propterties - public string CompressedSongFilename + public string? CompressedSongFilename { get => _compressedSongFilename; set => _compressedSongFilename = value; @@ -63,10 +61,15 @@ public class SongCompression try { - using (ZipFile zip = new ZipFile()) + using (var fi = new FileStream(songDetails.SongPath(), FileMode.Open)) { - zip.AddFile(songDetails.SongPath()); - zip.Save(tmpZipFilePath); + using (var z = new Ionic.Zlib.ZlibStream(fi, Ionic.Zlib.CompressionMode.Compress)) + { + using (var tr = new FileStream(tmpZipFilePath, FileMode.CreateNew)) + { + z.CopyTo(tr); + } + } } Console.WriteLine("Successfully compressed"); @@ -78,7 +81,7 @@ public class SongCompression Console.WriteLine(exMsg); } - if (songDetails.Filename.Contains(Constants.FileExtensions.WAV_EXTENSION)) + if (songDetails.Filename!.Contains(Constants.FileExtensions.WAV_EXTENSION)) { _compressedSongFilename = StripExtension(songDetails.Filename); } @@ -89,7 +92,7 @@ public class SongCompression // Method not being used public byte[] CompressedSong(byte[] uncompressedSong) { - byte[] compressedSong = null; + byte[]? compressedSong = null; try { Console.WriteLine("Song has been successfully compressed"); @@ -101,7 +104,7 @@ public class SongCompression Console.WriteLine(exMsg); } - return compressedSong; + return compressedSong!; } diff --git a/Controllers/v1/AlbumController.cs b/Controllers/v1/AlbumController.cs index eb5bbc6..2956ffb 100644 --- a/Controllers/v1/AlbumController.cs +++ b/Controllers/v1/AlbumController.cs @@ -12,8 +12,8 @@ namespace Icarus.Controllers.V1; public class AlbumController : BaseController { #region Fields - private readonly ILogger _logger; - private string _connectionString; + private readonly ILogger? _logger; + private string? _connectionString; #endregion @@ -35,9 +35,9 @@ public class AlbumController : BaseController [HttpGet] public IActionResult GetAlbums() { - var albumContext = new AlbumContext(_connectionString); + var albumContext = new AlbumContext(_connectionString!); - var albums = albumContext.Albums.ToList(); + var albums = albumContext.Albums!.ToList(); if (albums.Count > 0) return Ok(albums); @@ -50,7 +50,7 @@ public class AlbumController : BaseController { Album album = new Album{ Id = id }; - var albumContext = new AlbumContext(_connectionString); + var albumContext = new AlbumContext(_connectionString!); if (albumContext.DoesRecordExist(album)) { diff --git a/Controllers/v1/ArtistController.cs b/Controllers/v1/ArtistController.cs index 6bf41ce..7cc9be9 100644 --- a/Controllers/v1/ArtistController.cs +++ b/Controllers/v1/ArtistController.cs @@ -12,8 +12,8 @@ namespace Icarus.Controllers.V1; public class ArtistController : BaseController { #region Fields - private readonly ILogger _logger; - private string _connectionString; + private readonly ILogger? _logger; + private string? _connectionString; #endregion @@ -35,7 +35,7 @@ public class ArtistController : BaseController [HttpGet] public IActionResult GetArtists() { - var artistContext = new ArtistContext(_connectionString); + var artistContext = new ArtistContext(_connectionString!); var artists = artistContext.Artists.ToList(); @@ -50,7 +50,7 @@ public class ArtistController : BaseController { Artist artist = new Artist { Id = id }; - var artistContext = new ArtistContext(_connectionString); + var artistContext = new ArtistContext(_connectionString!); if (artistContext.DoesRecordExist(artist)) { diff --git a/Controllers/v1/BaseController.cs b/Controllers/v1/BaseController.cs index e04b9aa..03a3221 100644 --- a/Controllers/v1/BaseController.cs +++ b/Controllers/v1/BaseController.cs @@ -6,7 +6,7 @@ namespace Icarus.Controllers.V1; public class BaseController : ControllerBase { #region Fiends - protected IConfiguration _config; + protected IConfiguration? _config; #endregion diff --git a/Controllers/v1/CoverArtController.cs b/Controllers/v1/CoverArtController.cs index 0cc1523..199a9e3 100644 --- a/Controllers/v1/CoverArtController.cs +++ b/Controllers/v1/CoverArtController.cs @@ -13,8 +13,8 @@ namespace Icarus.Controllers.V1; public class CoverArtController : BaseController { #region Fields - private readonly ILogger _logger; - private string _connectionString; + private readonly ILogger? _logger; + private string? _connectionString; #endregion @@ -32,18 +32,18 @@ public class CoverArtController : BaseController [HttpGet] public IActionResult GetCoverArts() { - var coverArtContext = new CoverArtContext(_connectionString); + var coverArtContext = new CoverArtContext(_connectionString!); - var coverArtRecords = coverArtContext.CoverArtImages.ToList(); + var coverArtRecords = coverArtContext.CoverArtImages!.ToList(); if (coverArtRecords == null) { - _logger.LogInformation("No cover art records"); + _logger!.LogInformation("No cover art records"); return NotFound(); } else { - _logger.LogInformation("Found cover art records"); + _logger!.LogInformation("Found cover art records"); return Ok(coverArtRecords); } } @@ -53,13 +53,13 @@ public class CoverArtController : BaseController { var coverArt = new CoverArt { Id = id }; - var coverArtContext = new CoverArtContext(_connectionString); + var coverArtContext = new CoverArtContext(_connectionString!); coverArt = coverArtContext.RetrieveRecord(coverArt); if (coverArt != null) { - _logger.LogInformation("Found cover art record"); + _logger!.LogInformation("Found cover art record"); var coverArtBytes = System.IO.File.ReadAllBytes( coverArt.ImagePath()); @@ -68,7 +68,7 @@ public class CoverArtController : BaseController } else { - _logger.LogInformation("Cover art not found"); + _logger!.LogInformation("Cover art not found"); return NotFound(); } } @@ -76,13 +76,13 @@ public class CoverArtController : BaseController [HttpGet("data/download/{id}")] public async Task Download(int id, [FromQuery] bool? randomizeFilename) { - var songContext = new SongContext(_connectionString); - var covMgr = new CoverArtManager(this._config); + var songContext = new SongContext(_connectionString!); + var covMgr = new CoverArtManager(this._config!); var songMetaData = songContext.RetrieveRecord(new Song { Id = id}); var c = covMgr.GetCoverArt(songMetaData); - var filename = DirectoryManager.GenerateDownloadFilename(10, Constants.FileExtensions.JPG_EXTENSION, songMetaData.Title, randomizeFilename); + var filename = DirectoryManager.GenerateDownloadFilename(10, Constants.FileExtensions.JPG_EXTENSION, songMetaData.Title!, randomizeFilename); var data = await c.GetData(); diff --git a/Controllers/v1/GenreController.cs b/Controllers/v1/GenreController.cs index 534240e..47b4e13 100644 --- a/Controllers/v1/GenreController.cs +++ b/Controllers/v1/GenreController.cs @@ -12,8 +12,8 @@ namespace Icarus.Controllers.V1; public class GenreController : BaseController { #region Fields - private readonly ILogger _logger; - private string _connectionString; + private readonly ILogger? _logger; + private string? _connectionString; #endregion @@ -35,9 +35,9 @@ public class GenreController : BaseController [HttpGet] public IActionResult GetGenres() { - var genreStore = new GenreContext(_connectionString); + var genreStore = new GenreContext(_connectionString!); - var genres = genreStore.Genres.ToList(); + var genres = genreStore!.Genres!.ToList(); if (genres.Count > 0) { @@ -54,7 +54,7 @@ public class GenreController : BaseController { var genre = new Genre { Id = id }; - var genreStore = new GenreContext(_connectionString); + var genreStore = new GenreContext(_connectionString!); if (genreStore.DoesRecordExist(genre)) { diff --git a/Controllers/v1/LoginController.cs b/Controllers/v1/LoginController.cs index dfc917c..4834471 100644 --- a/Controllers/v1/LoginController.cs +++ b/Controllers/v1/LoginController.cs @@ -17,8 +17,8 @@ namespace Icarus.Controllers.V1; public class LoginController : ControllerBase { #region Fields - private string _connectionString; - private IConfiguration _config; + private string? _connectionString; + private IConfiguration? _config; private ILogger _logger; #endregion @@ -41,7 +41,7 @@ public class LoginController : ControllerBase [HttpPost] public IActionResult Login([FromBody] User user) { - var context = new UserContext(_connectionString); + var context = new UserContext(_connectionString!); _logger.LogInformation("Starting process of validating credentials"); @@ -55,12 +55,12 @@ public class LoginController : ControllerBase try { - if (context.Users.FirstOrDefault(usr => usr.Username.Equals(user.Username)) != null) + if (context.Users.FirstOrDefault(usr => usr.Username!.Equals(user.Username)) != null) { - user = context.Users.FirstOrDefault(usr => usr.Username.Equals(user.Username)); + user = context.Users.FirstOrDefault(usr => usr.Username!.Equals(user.Username))!; var validatePass = new PasswordEncryption(); - var validated = validatePass.VerifyPassword(user, password); + var validated = validatePass.VerifyPassword(user!, password!); if (!validated) { loginRes.Message = message; @@ -71,9 +71,9 @@ public class LoginController : ControllerBase _logger.LogInformation("Successfully validated user credentials"); - TokenManager tk = new TokenManager(_config); + TokenManager tk = new TokenManager(_config!); - loginRes = tk.LoginSymmetric(user); + loginRes = tk.LoginSymmetric(user!); return Ok(loginRes); } @@ -87,7 +87,7 @@ public class LoginController : ControllerBase catch (Exception ex) { _logger.LogError("An error occurred: {0}", ex.Message); - _logger.LogError("Inner Exception: {0}", ex.InnerException.Message); + _logger.LogError("Inner Exception: {0}", ex.InnerException!.Message); } return NotFound(loginRes); diff --git a/Controllers/v1/RegisterController.cs b/Controllers/v1/RegisterController.cs index 2bad355..d397c8c 100644 --- a/Controllers/v1/RegisterController.cs +++ b/Controllers/v1/RegisterController.cs @@ -11,7 +11,7 @@ namespace Icarus.Controllers.V1; public class RegisterController : ControllerBase { #region Fields - private IConfiguration _config; + private IConfiguration? _config; #endregion @@ -35,11 +35,12 @@ public class RegisterController : ControllerBase user.Status = "Registered"; user.DateCreated = DateTime.Now; - UserContext context = null; + UserContext? context = null; try { - context = new UserContext(_config.GetConnectionString("DefaultConnection")); + var connString = _config!.GetConnectionString("DefaultConnection"); + context = new UserContext(connString!); context.Add(user); context.SaveChanges(); } @@ -56,7 +57,7 @@ public class RegisterController : ControllerBase Username = user.Username }; - if (context.Users.FirstOrDefault(sng => sng.Username.Equals(user.Username)) != null) + if (context!.Users.FirstOrDefault(sng => sng.Username!.Equals(user.Username)) != null) { registerResult.Message = "Successful registration"; registerResult.SuccessfullyRegistered = true; diff --git a/Controllers/v1/SongCompressedDataControllers.cs b/Controllers/v1/SongCompressedDataControllers.cs index 12b5a2e..43a66b6 100644 --- a/Controllers/v1/SongCompressedDataControllers.cs +++ b/Controllers/v1/SongCompressedDataControllers.cs @@ -14,9 +14,9 @@ namespace Icarus.Controllers.V1; public class SongCompressedDataController : BaseController { #region Fields - private string _connectionString; - private string _songTempDir; - private string _archiveDir; + private string? _connectionString; + private string? _songTempDir; + private string? _archiveDir; #endregion @@ -39,9 +39,9 @@ public class SongCompressedDataController : BaseController [HttpGet("{id}")] public async Task DownloadCompressedSong(int id, [FromQuery] bool? randomizeFilename) { - var context = new SongContext(_connectionString); + var context = new SongContext(_connectionString!); - SongCompression cmp = new SongCompression(_archiveDir); + SongCompression cmp = new SongCompression(_archiveDir!); Console.WriteLine($"Archive directory root: {_archiveDir}"); @@ -49,9 +49,9 @@ public class SongCompressedDataController : BaseController var sng = context.RetrieveRecord(new Song{ Id = id }); SongData song = await cmp.RetrieveCompressedSong(sng); - var filename = DirectoryManager.GenerateDownloadFilename(10, Constants.FileExtensions.ZIP_EXTENSION, sng.Title, randomizeFilename); + var filename = DirectoryManager.GenerateDownloadFilename(10, Constants.FileExtensions.ZIP_EXTENSION, sng.Title!, randomizeFilename); - return File(song.Data, "application/x-msdownload", filename); + return File(song.Data!, "application/x-msdownload", filename); } #endregion } diff --git a/Controllers/v1/SongController.cs b/Controllers/v1/SongController.cs index 9ec26c3..622c877 100644 --- a/Controllers/v1/SongController.cs +++ b/Controllers/v1/SongController.cs @@ -13,9 +13,9 @@ namespace Icarus.Controllers.V1; public class SongController : BaseController { #region Fields - private readonly ILogger _logger; - private string _connectionString; - private SongManager _songMgr; + private readonly ILogger? _logger; + private string? _connectionString; + private SongManager? _songMgr; #endregion @@ -40,11 +40,11 @@ public class SongController : BaseController public IActionResult GetSongs() { Console.WriteLine("Attemtping to retrieve songs"); - _logger.LogInformation("Attempting to retrieve songs"); + _logger!.LogInformation("Attempting to retrieve songs"); - var context = new SongContext(_connectionString); + var context = new SongContext(_connectionString!); - var songs = context.Songs.ToList(); + var songs = context.Songs!.ToList(); if (songs.Count > 0) { @@ -59,7 +59,7 @@ public class SongController : BaseController [HttpGet("{id}")] public IActionResult GetSong(int id) { - var context = new SongContext(_connectionString); + var context = new SongContext(_connectionString!); var song = context.RetrieveRecord(new Song{ Id = id }); @@ -76,9 +76,9 @@ public class SongController : BaseController { song.Id = id; Console.WriteLine("Retrieving filepath of song"); - _logger.LogInformation("Retrieving filepath of song"); + _logger!.LogInformation("Retrieving filepath of song"); - if (!_songMgr.DoesSongExist(song)) + if (!_songMgr!.DoesSongExist(song)) { return NotFound(new SongResult { diff --git a/Controllers/v1/SongDataController.cs b/Controllers/v1/SongDataController.cs index fd97f3b..dd9e271 100644 --- a/Controllers/v1/SongDataController.cs +++ b/Controllers/v1/SongDataController.cs @@ -13,10 +13,10 @@ namespace Icarus.Controllers.V1; public class SongDataController : BaseController { #region Fields - private string _connectionString; - private ILogger _logger; - private SongManager _songMgr; - private string _songTempDir; + private string? _connectionString; + private ILogger? _logger; + private SongManager? _songMgr; + private string? _songTempDir; #endregion @@ -31,7 +31,7 @@ public class SongDataController : BaseController _connectionString = _config.GetConnectionString("DefaultConnection"); _logger = logger; _songTempDir = _config.GetValue("TemporaryMusicPath"); - _songMgr = new SongManager(config, _songTempDir); + _songMgr = new SongManager(config, _songTempDir!); } #endregion @@ -39,13 +39,29 @@ public class SongDataController : BaseController [HttpGet("download/{id}")] public IActionResult Download(int id, [FromQuery] bool? randomizeFilename) { - var songContext = new SongContext(_connectionString); + var songContext = new SongContext(_connectionString!); var songMetaData = songContext.RetrieveRecord(new Song { Id = id}); - var song = _songMgr.RetrieveSong(songMetaData).Result; - var filename = DirectoryManager.GenerateDownloadFilename(10, Constants.FileExtensions.WAV_EXTENSION, songMetaData.Title, randomizeFilename); + var song = _songMgr!.RetrieveSong(songMetaData).Result; + string filename; - return File(song.Data, "application/x-msdownload", filename); + switch (songMetaData.AudioType) + { + case "wav": + filename = DirectoryManager.GenerateDownloadFilename(10, Constants.FileExtensions.WAV_EXTENSION, + songMetaData.Title!, randomizeFilename); + break; + case "flac": + filename = DirectoryManager.GenerateDownloadFilename(10, Constants.FileExtensions.FLAC_EXTENSION, + songMetaData.Title!, randomizeFilename); + break; + default: + filename = DirectoryManager.GenerateDownloadFilename(10, Constants.FileExtensions.DEFAULT_AUDIO_EXTENSION, + songMetaData.Title!, randomizeFilename); + break; + } + + return File(song.Data!, "application/x-msdownload", filename); } // Assumes that the song already has metadata such as @@ -65,20 +81,17 @@ public class SongDataController : BaseController { try { - // Console.WriteLine("Uploading song..."); - _logger.LogInformation("Uploading song..."); + _logger!.LogInformation("Uploading song..."); var uploads = _songTempDir; - // Console.WriteLine($"Song Root Path {uploads}"); - _logger.LogInformation($"Song root path {uploads}"); + _logger!.LogInformation($"Song root path {uploads}"); foreach (var sng in songData) if (sng.Length > 0) { - // Console.WriteLine($"Song filename {sng.FileName}"); - _logger.LogInformation($"Song filename {sng.FileName}"); + _logger!.LogInformation($"Song filename {sng.FileName}"); - _songMgr.SaveSongToFileSystem(sng).Wait(); + _songMgr!.SaveSongToFileSystem(sng).Wait(); } return Ok(); @@ -86,7 +99,7 @@ public class SongDataController : BaseController catch (Exception ex) { var msg = ex.Message; - _logger.LogError(msg, "An error occurred"); + _logger!.LogError(msg, "An error occurred"); } return NotFound(); @@ -101,35 +114,67 @@ public class SongDataController : BaseController { try { - if (up.SongData.Length > 0 && up.CoverArtData.Length > 0 && !string.IsNullOrEmpty(up.SongFile)) + if (up.SongData!.Length > 0 && up.CoverArtData!.Length > 0 && !string.IsNullOrEmpty(up.SongFile)) { + var meta = new Utilities.MetadataRetriever(); + var tmpSong = this._songMgr!.SaveSongTemp(up.SongData).Result; + if (!meta.IsSupportedFile(tmpSong.SongPath()) && !meta.IsSupportedFile(up.CoverArtData)) + { + return BadRequest("Media is not supported"); + } + else if (!meta.IsSupportedFile(tmpSong.SongPath())) + { + return BadRequest("Song is not supported"); + } + else if (!meta.IsSupportedFile(up.CoverArtData)) + { + return BadRequest("Cover art is not supported"); + } + var song = Newtonsoft.Json.JsonConvert.DeserializeObject(up.SongFile); - var tokMgr = new TokenManager(this._config); + var tokMgr = new TokenManager(this._config!); var accessToken = Request.Headers["Authorization"]; - var userId = tokMgr.RetrieveUserIdFromToken(accessToken); + var userId = tokMgr.RetrieveUserIdFromToken(accessToken!); if (userId != -1) { - song.UserId = userId; + song!.UserId = userId; } - _logger.LogInformation($"Song title: {song.Title}"); + _logger!.LogInformation($"Song title: {song!.Title}"); - _songMgr.SaveSongToFileSystem(up.SongData, up.CoverArtData, song); + song.Filename = tmpSong.Filename; + song.SongDirectory = tmpSong.SongDirectory; + song.DateCreated = tmpSong.DateCreated; + song.AudioType = meta.FileExtensionType(tmpSong.SongPath()); + + switch (song.AudioType) + { + case "wav": + song = _songMgr.SaveSongToFileSystem(up.SongData, up.CoverArtData, song); + break; + case "flac": + song = _songMgr.SaveFlacSongToFileSystem(up.SongData, up.CoverArtData, song); + break; + default: + return BadRequest(); + } + + return Ok(song); } } catch (Exception ex) { - _logger.LogError(ex.Message, "An error occurred"); + _logger!.LogError(ex.Message, "An error occurred"); } - return Ok(); + return BadRequest(); } [HttpDelete("delete/{id}")] public IActionResult DeleteSong(int id) { - var songContext = new SongContext(_connectionString); + var songContext = new SongContext(_connectionString!); var songMetaData = new Song{ Id = id }; Console.WriteLine($"Id {songMetaData.Id}"); @@ -138,14 +183,14 @@ public class SongDataController : BaseController if (string.IsNullOrEmpty(songMetaData.Title)) { - _logger.LogInformation("Song does not exist"); + _logger!.LogInformation("Song does not exist"); return NotFound("Song does not exist"); } else { - _logger.LogInformation("Starting process of deleting song from the filesystem and database"); + _logger!.LogInformation("Starting process of deleting song from the filesystem and database"); - _songMgr.DeleteSong(songMetaData); + _songMgr!.DeleteSong(songMetaData); return Ok(songMetaData); } @@ -155,11 +200,11 @@ public class SongDataController : BaseController public class UploadSongWithDataForm { [FromForm(Name = "file")] - public IFormFile SongData { get; set; } + public IFormFile? SongData { get; set; } // NOTE: Think about making this optional and if it is not provided, use the stock cover art [FromForm(Name = "cover")] - public IFormFile CoverArtData { get; set; } + public IFormFile? CoverArtData { get; set; } [FromForm(Name = "metadata")] - public string SongFile { get; set; } + public string? SongFile { get; set; } } } diff --git a/Controllers/v1/SongStreamController.cs b/Controllers/v1/SongStreamController.cs index d72117b..45c2da6 100644 --- a/Controllers/v1/SongStreamController.cs +++ b/Controllers/v1/SongStreamController.cs @@ -11,7 +11,7 @@ namespace Icarus.Controllers.V1; public class SongStreamController : BaseController { #region Fields - private ILogger _logger; + private ILogger? _logger; #endregion @@ -32,11 +32,11 @@ public class SongStreamController : BaseController [HttpGet("{id}")] public async Task StreamSong(int id) { - var context = new SongContext(_config.GetConnectionString("DefaultConnection")); + var context = new SongContext(_config!.GetConnectionString("DefaultConnection")!); - var song = context.Songs.FirstOrDefault(sng => sng.Id == id); + var song = context.Songs!.FirstOrDefault(sng => sng.Id == id); - var stream = new FileStream(song.SongPath(), FileMode.Open, FileAccess.Read); + var stream = new FileStream(song!.SongPath(), FileMode.Open, FileAccess.Read); stream.Position = 0; var filename = song.Filename; @@ -45,7 +45,7 @@ public class SongStreamController : BaseController filename = song.GenerateFilename(); } - _logger.LogInformation("Starting to stream song...>"); + _logger!.LogInformation("Starting to stream song...>"); Console.WriteLine("Starting to streamsong..."); return await Task.Run(() => { diff --git a/Database/Contexts/AlbumContext.cs b/Database/Contexts/AlbumContext.cs index ecf0275..f78c37d 100644 --- a/Database/Contexts/AlbumContext.cs +++ b/Database/Contexts/AlbumContext.cs @@ -6,7 +6,7 @@ namespace Icarus.Database.Contexts; public class AlbumContext : DbContext { - public DbSet Albums { get; set; } + public DbSet? Albums { get; set; } public AlbumContext(DbContextOptions options) : base(options) { } public AlbumContext(string connString) : base(new DbContextOptionsBuilder() @@ -22,11 +22,12 @@ public class AlbumContext : DbContext public Album RetrieveRecord(Album album) { - return Albums.FirstOrDefault(alb => alb.Id == album.Id); + var albm = Albums!.FirstOrDefault(alb => alb.Id == album.Id); + return albm!; } public bool DoesRecordExist(Album album) { - return Albums.FirstOrDefault(alb => alb.Id == album.Id) != null ? true : false; + return Albums!.FirstOrDefault(alb => alb.Id == album.Id) != null ? true : false; } } diff --git a/Database/Contexts/ArtistContext.cs b/Database/Contexts/ArtistContext.cs index d34e52d..142a236 100644 --- a/Database/Contexts/ArtistContext.cs +++ b/Database/Contexts/ArtistContext.cs @@ -23,7 +23,7 @@ public class ArtistContext : DbContext public Artist RetrieveRecord(Artist artist) { - return Artists.FirstOrDefault(arst => arst.Id == artist.Id); + return Artists.FirstOrDefault(arst => arst.Id == artist.Id)!; } diff --git a/Database/Contexts/CoverArtContext.cs b/Database/Contexts/CoverArtContext.cs index 2f3dfe3..5ec75bd 100644 --- a/Database/Contexts/CoverArtContext.cs +++ b/Database/Contexts/CoverArtContext.cs @@ -6,7 +6,9 @@ namespace Icarus.Database.Contexts; public class CoverArtContext : DbContext { - public DbSet CoverArtImages { get; set; } + #region Properties + public DbSet? CoverArtImages { get; set; } + #endregion public CoverArtContext(DbContextOptions options) : base(options) { } public CoverArtContext(string connString) : base(new DbContextOptionsBuilder() @@ -22,11 +24,11 @@ public class CoverArtContext : DbContext public CoverArt RetrieveRecord(CoverArt cover) { - return CoverArtImages.FirstOrDefault(cov => cov.Id == cover.Id); + return CoverArtImages!.FirstOrDefault(cov => cov.Id == cover.Id)!; } public bool DoesRecordExist(CoverArt cover) { - return CoverArtImages.FirstOrDefault(cov => cov.Id == cover.Id) != null ? true : false; + return CoverArtImages!.FirstOrDefault(cov => cov.Id == cover.Id) != null ? true : false; } } diff --git a/Database/Contexts/GenreContext.cs b/Database/Contexts/GenreContext.cs index 37ffd53..77db307 100644 --- a/Database/Contexts/GenreContext.cs +++ b/Database/Contexts/GenreContext.cs @@ -6,7 +6,10 @@ namespace Icarus.Database.Contexts; public class GenreContext : DbContext { - public DbSet Genres { get; set; } + #region Properties + public DbSet? Genres { get; set; } + #endregion + public GenreContext(DbContextOptions options) : base(options) { } public GenreContext(string connString) : base(new DbContextOptionsBuilder() .UseMySQL(connString).Options) @@ -22,11 +25,12 @@ public class GenreContext : DbContext public Genre RetrieveRecord(Genre genre) { - return Genres.FirstOrDefault(gnr => gnr.Id == genre.Id); + var gnre = Genres!.FirstOrDefault(gnr => gnr.Id == genre.Id); + return gnre!; } public bool DoesRecordExist(Genre genre) { - return Genres.FirstOrDefault(gnr => gnr.Id == genre.Id) != null ? true : false; + return Genres!.FirstOrDefault(gnr => gnr.Id == genre.Id) != null ? true : false; } } diff --git a/Database/Contexts/SongContext.cs b/Database/Contexts/SongContext.cs index f65588e..bbab8c2 100644 --- a/Database/Contexts/SongContext.cs +++ b/Database/Contexts/SongContext.cs @@ -6,7 +6,7 @@ namespace Icarus.Database.Contexts; public class SongContext : DbContext { - public DbSet Songs { get; set; } + public DbSet? Songs { get; set; } public SongContext(string connString) : base(new DbContextOptionsBuilder() .UseMySQL(connString).Options) @@ -41,12 +41,13 @@ public class SongContext : DbContext public Song RetrieveRecord(Song song) { - return Songs.FirstOrDefault(sng => sng.Id == song.Id); + var sng = Songs!.FirstOrDefault(sng => sng.Id == song.Id); + return sng!; } public bool DoesRecordExist(Song song) { - return Songs.FirstOrDefault(sng => sng.Id == song.Id) != null ? true : false; + return Songs!.FirstOrDefault(sng => sng.Id == song.Id) != null ? true : false; } } diff --git a/Database/Contexts/UserContext.cs b/Database/Contexts/UserContext.cs index 987ade5..008aa49 100644 --- a/Database/Contexts/UserContext.cs +++ b/Database/Contexts/UserContext.cs @@ -32,7 +32,7 @@ public class UserContext : DbContext public User RetrieveRecord(User user) { - return Users.FirstOrDefault(usr => usr.Id == user.Id); + return Users.FirstOrDefault(usr => usr.Id == user.Id)!; } public bool DoesRecordExist(User user) diff --git a/Icarus.csproj b/Icarus.csproj index 4a7e949..0dbde29 100644 --- a/Icarus.csproj +++ b/Icarus.csproj @@ -3,6 +3,7 @@ net8.0 enable + enable InProcess 0.1.10 @@ -10,10 +11,9 @@ - - + diff --git a/Models/Album.cs b/Models/Album.cs index b8ec4b9..715f745 100644 --- a/Models/Album.cs +++ b/Models/Album.cs @@ -6,16 +6,18 @@ namespace Icarus.Models; public class Album { + #region Properties [JsonProperty("id")] public int Id { get; set; } [JsonProperty("title")] - public string Title { get; set; } + public string? Title { get; set; } [JsonProperty("album_artist")] [Column("Artist")] - public string AlbumArtist { get; set; } + public string? AlbumArtist { get; set; } [JsonProperty("song_count")] [NotMapped] public int SongCount { get; set; } [JsonProperty("year")] public int Year { get; set; } + #endregion } diff --git a/Models/Artist.cs b/Models/Artist.cs index 24f3cac..699930f 100644 --- a/Models/Artist.cs +++ b/Models/Artist.cs @@ -6,12 +6,14 @@ namespace Icarus.Models; public class Artist { + #region Properties [JsonProperty("id")] public int Id { get; set; } [JsonProperty("name")] [Column("Artist")] - public string Name { get; set; } + public string? Name { get; set; } [JsonProperty("song_count")] [NotMapped] public int SongCount { get; set; } + #endregion } diff --git a/Models/BaseResult.cs b/Models/BaseResult.cs index e86e495..2740123 100644 --- a/Models/BaseResult.cs +++ b/Models/BaseResult.cs @@ -5,5 +5,5 @@ namespace Icarus.Models; public class BaseResult { [JsonProperty("message")] - public string Message { get; set; } + public string? Message { get; set; } } diff --git a/Models/CoverArt.cs b/Models/CoverArt.cs index 65426ca..4692f95 100644 --- a/Models/CoverArt.cs +++ b/Models/CoverArt.cs @@ -8,13 +8,13 @@ public class CoverArt [JsonProperty("id")] public int Id { get; set; } [JsonProperty("title")] - public string SongTitle { get; set; } + public string? SongTitle { get; set; } [JsonIgnore] - public string Directory { get; set; } + public string? Directory { get; set; } [JsonProperty("filename")] - public string Filename { get; set; } + public string? Filename { get; set; } [JsonProperty("type")] - public string Type { get; set; } + public string? Type { get; set; } #endregion @@ -23,7 +23,7 @@ public class CoverArt { var fullPath = this.Directory; - if (fullPath[fullPath.Length -1] != '/') + if (fullPath![fullPath.Length -1] != '/') { fullPath += "/"; } diff --git a/Models/Genre.cs b/Models/Genre.cs index 97ba1b0..c1a4af1 100644 --- a/Models/Genre.cs +++ b/Models/Genre.cs @@ -6,12 +6,14 @@ namespace Icarus.Models; public class Genre { + #region Properties [JsonProperty("id")] public int Id { get; set; } [JsonProperty("genre")] [Column("Category")] - public string GenreName { get; set; } + public string? GenreName { get; set; } [JsonProperty("song_count")] [NotMapped] public int SongCount { get; set; } + #endregion } diff --git a/Models/LoginResult.cs b/Models/LoginResult.cs index dd28313..d8d4da7 100644 --- a/Models/LoginResult.cs +++ b/Models/LoginResult.cs @@ -4,14 +4,16 @@ namespace Icarus.Models; public class LoginResult : BaseResult { + #region Properties [JsonProperty("user_id")] public int UserId { get; set; } [JsonProperty("username")] - public string Username { get; set; } + public string? Username { get; set; } [JsonProperty("token")] - public string Token { get; set; } + public string? Token { get; set; } [JsonProperty("token_type")] - public string TokenType { get; set; } + public string? TokenType { get; set; } [JsonProperty("expiration")] public int Expiration { get; set; } + #endregion } diff --git a/Models/RegisterResult.cs b/Models/RegisterResult.cs index 96ec1ce..798942a 100644 --- a/Models/RegisterResult.cs +++ b/Models/RegisterResult.cs @@ -4,8 +4,10 @@ namespace Icarus.Models; public class RegisterResult : BaseResult { + #region Properties [JsonProperty("username")] - public string Username { get; set; } + public string? Username { get; set; } [JsonProperty("successfully_registered")] public bool SuccessfullyRegistered { get; set; } + #endregion } diff --git a/Models/Song.cs b/Models/Song.cs index 9d9ef5f..8ee4377 100644 --- a/Models/Song.cs +++ b/Models/Song.cs @@ -10,24 +10,26 @@ public class Song [JsonProperty("id")] public int Id { get; set; } [JsonProperty("title")] - public string Title { get; set; } + public string? Title { get; set; } [JsonProperty("album")] [Column("Album")] - public string AlbumTitle { get; set; } + public string? AlbumTitle { get; set; } [JsonProperty("artist")] - public string Artist { get; set; } + public string? Artist { get; set; } [JsonProperty("album_artist")] - public string AlbumArtist { get; set; } + public string? AlbumArtist { get; set; } [JsonProperty("year")] public int? Year { get; set; } [JsonProperty("genre")] - public string Genre { get; set; } + public string? Genre { get; set; } [JsonProperty("duration")] public int Duration { get; set; } [JsonProperty("filename")] - public string Filename { get; set; } + public string? Filename { get; set; } [JsonIgnore] - public string SongDirectory { get; set; } + public string? SongDirectory { get; set; } + [JsonProperty("audio_type")] + public string? AudioType { get; set; } [JsonProperty("track")] public int Track { get; set; } = 0; [JsonProperty("track_count")] @@ -56,11 +58,29 @@ public class Song #region Methods + public void PrintMetadata() + { + Console.WriteLine("\n\nMetadata of the song:"); + Console.WriteLine($"ID: {this.Id}"); + Console.WriteLine($"Title: {this.Title}"); + Console.WriteLine($"Artist: {this.Artist}"); + Console.WriteLine($"Album: {this.AlbumTitle}"); + Console.WriteLine($"Genre: {this.Genre}"); + Console.WriteLine($"Year: {this.Year}"); + Console.WriteLine($"Duration: {this.Duration}"); + Console.WriteLine($"AlbumID: {this.AlbumId}"); + Console.WriteLine($"ArtistID: {this.ArtistId}"); + Console.WriteLine($"GenreID: {this.GenreId}"); + Console.WriteLine($"Song Path: {this.SongPath()}"); + Console.WriteLine($"Filename: {this.Filename}"); + Console.WriteLine("\n"); + } + public string SongPath() { var fullPath = SongDirectory; - if (fullPath[fullPath.Length -1] != '/') + if (fullPath![fullPath.Length -1] != '/') { fullPath += "/"; } @@ -70,26 +90,41 @@ public class Song return fullPath; } - public string GenerateFilename(int flag = 0) + public string GenerateFilename(bool includeExtension = false, AudioFileExtensionsType flag = AudioFileExtensionsType.Default) { int length = Constants.DirectoryPaths.FILENAME_LENGTH; string chars = Constants.DirectoryPaths.FILENAME_CHARACTERS; var filename = this.Generate(length, chars); - var extension = Icarus.Constants.FileExtensions.WAV_EXTENSION; + var extension = this.DetermineFileExtension(flag); - return flag == 0 ? filename : $"{filename}{extension}"; + return includeExtension ? $"{filename}{extension}" : filename; } - public async Task GenerateFilenameAsync(int flag = 0) + public async Task GenerateFilenameAsync(bool includeExtension = false, AudioFileExtensionsType flag = AudioFileExtensionsType.Default) { int length = Constants.DirectoryPaths.FILENAME_LENGTH; string chars = Constants.DirectoryPaths.FILENAME_CHARACTERS; - var extension = Icarus.Constants.FileExtensions.WAV_EXTENSION; + var extension = this.DetermineFileExtension(flag); var filename = await Task.Run(() => { return this.Generate(length, chars); }); - return flag == 0 ? filename : $"{filename}{extension}"; + return includeExtension ? $"{filename}{extension}" : filename; + } + + private string DetermineFileExtension(AudioFileExtensionsType flag) + { + switch (flag) + { + case AudioFileExtensionsType.Default: + return Constants.FileExtensions.DEFAULT_AUDIO_EXTENSION; + case AudioFileExtensionsType.WAV: + return Constants.FileExtensions.WAV_EXTENSION; + case AudioFileExtensionsType.FLAC: + return Constants.FileExtensions.FLAC_EXTENSION; + default: + return ""; + } } private string Generate(int length, string chars) @@ -101,3 +136,10 @@ public class Song } #endregion } + +public enum AudioFileExtensionsType +{ + Default = 0, + WAV = 1, + FLAC = 2 +} diff --git a/Models/SongData.cs b/Models/SongData.cs index ad03c59..8600368 100644 --- a/Models/SongData.cs +++ b/Models/SongData.cs @@ -2,7 +2,9 @@ namespace Icarus.Models; public class SongData { + #region Properties public int ID { get; set; } - public byte[] Data { get; set; } + public byte[]? Data { get; set; } public int SongID { get; set; } + #endregion } diff --git a/Models/SongResult.cs b/Models/SongResult.cs index 266090c..dd8dbf9 100644 --- a/Models/SongResult.cs +++ b/Models/SongResult.cs @@ -4,8 +4,10 @@ namespace Icarus.Models; public class SongResult { + #region Properties [JsonProperty("message")] - public string Message { get; set; } + public string? Message { get; set; } [JsonProperty("song_title")] - public string SongTitle { get; set; } + public string? SongTitle { get; set; } + #endregion } diff --git a/Models/Token.cs b/Models/Token.cs index 146347a..aab8a50 100644 --- a/Models/Token.cs +++ b/Models/Token.cs @@ -1,6 +1,3 @@ -using System; -using System.Linq; - using Newtonsoft.Json; @@ -10,13 +7,13 @@ public class Token { #region Properties [JsonProperty("scope")] - public string Scope { get; set; } + public string? Scope { get; set; } [JsonProperty("exp")] public int Expiration { get; set; } [JsonProperty("aud")] - public string Audience { get; set; } + public string? Audience { get; set; } [JsonProperty("iss")] - public string Issuer { get; set; } + public string? Issuer { get; set; } [JsonProperty("iat")] public int Issued { get; set; } #endregion @@ -24,29 +21,24 @@ public class Token #region Methods public bool TokenExpired() { - var result = false; var currentDate = DateTime.Now; - var currentDateInSeconds = Math.Floor((currentDate - DateTime.UnixEpoch).TotalSeconds); - - result = (currentDateInSeconds >= Expiration) ? true : false; + var result = (currentDateInSeconds >= Expiration) ? true : false; return result; } public bool ContainsScope(string desiredScope) { - var result = false; - result = Scope.Contains(desiredScope); + var result = Scope!.Contains(desiredScope); return result; } public bool Erroneous() { - var result = true; Func isEmpty = a => string.IsNullOrEmpty(a); - result = (!isEmpty(Scope) && !isEmpty(Audience) && !isEmpty(Issuer) && + var result = (!isEmpty(Scope!) && !isEmpty(Audience!) && !isEmpty(Issuer!) && Expiration > 0 && Issued > 0) ? false : true; return result; diff --git a/Models/User.cs b/Models/User.cs index 4752c6c..95182f4 100644 --- a/Models/User.cs +++ b/Models/User.cs @@ -14,39 +14,39 @@ public class User [Key] public int Id { get; set; } [JsonProperty("username")] - public string Username { get; set; } + public string? Username { get; set; } [JsonProperty("password")] - public string Password { get; set; } + public string? Password { get; set; } [JsonProperty("email")] - public string Email { get; set; } + public string? Email { get; set; } [JsonProperty("phone")] [Column("Phone")] - public string Phone { get; set; } + public string? Phone { get; set; } [JsonProperty("firstname")] - public string Firstname { get; set; } + public string? Firstname { get; set; } [JsonProperty("lastname")] - public string Lastname { get; set; } + public string? Lastname { get; set; } [JsonProperty("email_verified")] [NotMapped] public bool EmailVerified { get; set; } [JsonProperty("date_created")] public DateTime DateCreated { get; set; } [JsonProperty("status")] - public string Status { get; set; } + public string? Status { get; set; } [JsonProperty("last_login")] public DateTime? LastLogin { get; set; } [JsonIgnore] [NotMapped] - public System.Collections.Generic.IEnumerable Roles { get; set; } + public System.Collections.Generic.IEnumerable? Roles { get; set; } #endregion #region Methods public System.Collections.Generic.IEnumerable Claims() { - var claims = new System.Collections.Generic.List { new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, Username) }; - claims.AddRange(Roles.Select(role => new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, role))); + var claims = new System.Collections.Generic.List { new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, Username!) }; + claims.AddRange(Roles!.Select(role => new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, role))); return claims; } diff --git a/Program.cs b/Program.cs index 2b5db35..4f015a5 100644 --- a/Program.cs +++ b/Program.cs @@ -64,16 +64,16 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJw ValidateLifetime = true, ValidAudience = Configuration["JWT:Audience"], ValidIssuer = Configuration["JWT:Issuer"], - IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["JWT:Secret"])) + IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["JWT:Secret"]!)) }; }); -builder.Services.AddDbContext(options => options.UseMySQL(connString)); -builder.Services.AddDbContext(options => options.UseMySQL(connString)); -builder.Services.AddDbContext(options => options.UseMySQL(connString)); -builder.Services.AddDbContext(options => options.UseMySQL(connString)); -builder.Services.AddDbContext(options => options.UseMySQL(connString)); -builder.Services.AddDbContext(options => options.UseMySQL(connString)); +builder.Services.AddDbContext(options => options.UseMySQL(connString!)); +builder.Services.AddDbContext(options => options.UseMySQL(connString!)); +builder.Services.AddDbContext(options => options.UseMySQL(connString!)); +builder.Services.AddDbContext(options => options.UseMySQL(connString!)); +builder.Services.AddDbContext(options => options.UseMySQL(connString!)); +builder.Services.AddDbContext(options => options.UseMySQL(connString!)); builder.Services.AddControllers() .AddNewtonsoftJson(); diff --git a/README.md b/README.md index 26fac34..9c93b5b 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,7 @@ One can interface with Icarus the music server either by: * [MySql](https://www.nuget.org/packages/MySql.Data/) * OpenSSL * BCrypt.Net-Next -* DotNetZip -* ID3 +* Iconic.Zlib.Netstandard * JWT * Microsoft.AspNetCore.Authentication.JwtBearer * Microsoft.AspNetCore.Mvc.NewtonsoftJson @@ -126,11 +125,11 @@ scripts/Migrations/Linux/AddUpdate.sh ``` Or you can manually add the migrations like so for each migration: ```shell -dotnet-ef migrations Add InitialCreate --context UserContext +dotnet dotnet-ef migrations Add InitialCreate --context UserContext ``` Then update the migrations to the database like so*: ```shell -dotnet-ef database update --context UserContext +dotnet dotnet-ef database update --context UserContext ``` All of the contexts can be found in Database/Contexts folder. diff --git a/Scripts/Migrations/Linux/AddUpdate.sh b/Scripts/Migrations/Linux/AddUpdate.sh index 493ceb5..ed4ba7b 100755 --- a/Scripts/Migrations/Linux/AddUpdate.sh +++ b/Scripts/Migrations/Linux/AddUpdate.sh @@ -1,28 +1,29 @@ echo "Adding migrations..." echo "Adding User migration" -~/.dotnet/tools/dotnet-ef migrations add User --context UserContext +dotnet dotnet-ef migrations add User --context UserContext echo "Adding Album migration" -~/.dotnet/tools/dotnet-ef migrations add Album --context AlbumContext +dotnet dotnet-ef migrations add Album --context AlbumContext echo "Adding Artist migration" -~/.dotnet/tools/dotnet-ef migrations add Artist --context ArtistContext +dotnet dotnet-ef migrations add Artist --context ArtistContext echo "Adding Genre migration" -~/.dotnet/tools/dotnet-ef migrations add Genre --context GenreContext +dotnet dotnet-ef migrations add Genre --context GenreContext echo "Adding Cover art migration" -~/.dotnet/tools/dotnet-ef migrations add CoverArt --context CoverArtContext +dotnet dotnet-ef migrations add CoverArt --context CoverArtContext echo "Adding Song migration" -~/.dotnet/tools/dotnet-ef migrations add Song --context SongContext +dotnet dotnet-ef migrations add Song --context SongContext echo "Updating migrations.." echo "Updating User migration" -~/.dotnet/tools/dotnet-ef database update --context UserContext +dotnet dotnet-ef database update --context UserContext echo "Updating Album migration" -~/.dotnet/tools/dotnet-ef database update --context AlbumContext +dotnet dotnet-ef database update --context AlbumContext echo "Updating Artist migration" -~/.dotnet/tools/dotnet-ef database update --context ArtistContext +dotnet dotnet-ef database update --context ArtistContext echo "Updating Genre migration" -~/.dotnet/tools/dotnet-ef database update --context GenreContext +dotnet dotnet-ef database update --context GenreContext echo "Updating Cover art migration" -~/.dotnet/tools/dotnet-ef database update --context CoverArtContext +dotnet dotnet-ef database update --context CoverArtContext echo "Updating Song migration" -~/.dotnet/tools/dotnet-ef database update --context SongContext +dotnet dotnet-ef database update --context SongContext + diff --git a/Scripts/MySQL/drop_and_create_database.sql b/Scripts/MySQL/drop_and_create_database.sql new file mode 100644 index 0000000..8d8a59c --- /dev/null +++ b/Scripts/MySQL/drop_and_create_database.sql @@ -0,0 +1,3 @@ +drop database Icarus; + +create database Icarus; diff --git a/Scripts/convert_wav_to_flac.zsh b/Scripts/convert_wav_to_flac.zsh new file mode 100755 index 0000000..a35e6e0 --- /dev/null +++ b/Scripts/convert_wav_to_flac.zsh @@ -0,0 +1,137 @@ +#!/usr/bin/zsh +# +# Working directory +# Output directory +# Folder name creation +# Sub-folder name creation +# +# Validation +# Check if WORK_DIR is an actual directory +# Check if OUTPUT_DIR exists +# Check if the Folder and Sub folder has been created +# Check if WORK_DIR contains .wav files +# +# Conversion +# Convert wav files to flac files +# Create folder and sub folder if it does not exist +# Move the converted flac files to the sub folder +# +# Final +# Check if OUTPUT_DIR has the folder structure. Delete if so +# Move the folder and sub folder to OUTPUT_DIR + +if [[ $# -eq 0 ]]; then + my_text="No arguments provided. Provide four arguments:\n" + my_text+="script.zsh \"working_dir\" \"output_dir\" \"folder_name\" \"sub_folder_name\"" + + echo "$my_text" + exit +fi + +if [[ ! -n "$2" ]]; then + echo "The \"output_dir\" has not been provided" + exit +fi + +if [[ ! -n "$3" ]]; then + echo "The \"folder_name\" has not been provided" + exit +fi + +if [[ ! -n "$4" ]]; then + echo "The \"sub_folder_name\" has not been provided" + exit +fi + +WORK_DIR=$1 +OUTPUT_DIR=$2 +FOLDER=$3 +SUB_FOLDER=$4 + +# Validation + +if [[ ! -d $WORK_DIR ]]; then + echo "$WORK_DIR is not a directory" + exit +fi + +if [[ ! -d $OUTPUT_DIR ]]; then + echo "$OUTPUT_DIR does not exist" + exit +fi + +FOLDER_DIR="$OUTPUT_DIR/$FOLDER" + +if [[ ! -d $FOLDER_DIR ]]; then + echo "$FOLDER_DIR directory does not exist. Creating directory" + mkdir $FOLDER_DIR + echo "Created $FOLDER_DIR directory" +fi + +FOLDER_DIR="$FOLDER_DIR/$SUB_FOLDER" + +if [[ ! -d $FOLDER_DIR ]]; then + echo "$FOLDER_DIR directory does not exist. Creating directory" + mkdir $FOLDER_DIR + echo "Created $FOLDER_DIR directory" +fi + +# Find all files matching the pattern in the directory +matched_files=( "$WORK_DIR"/*.wav ) + +# Check if any files were found +if [[ ${#matched_files[@]} -gt 0 ]]; then + echo "Files matching the pattern exist in the directory:" +else + echo "No files matching the pattern were found." + exit +fi + +echo "Working directory: $WORK_DIR" +echo "Output directory: $OUTPUT_DIR" +echo "Folder name: $FOLDER" +echo "Sub folder name: $SUB_FOLDER" + +# Conversion +i=1 + +for file in "${matched_files[@]}"; do + file_output="track" + + if [[ $i -lt 10 ]]; then + file_output="track0$i.flac" + else + file_output="track$i.flac" + fi + + echo "$i file: $file" + + output_file_path="$FOLDER_DIR/$file_output" + echo "Output file path: $output_file_path" + + echo "Converting wav file to flac" + flac --best $file -o $output_file_path + + ALBUM_FILE="$WORK_DIR/new-album.json" + TARGET_ALBUM_FILE="$FOLDER_DIR/album.json" + + if [[ -f $ALBUM_FILE ]]; then + echo "Copying album file" + cp -a $ALBUM_FILE $TARGET_ALBUM_FILE + fi + + matched_img_files=( "$WORK_DIR"/*.[j,J,p,P][p,P,n,N]* ) + + # Check if any files were found + if [[ ${#matched_img_files[@]} -gt 0 ]]; then + echo "Files matching the pattern exist in the directory:" + echo "Copying cover art file(s)" + + for img_file in "${matched_img_files[@]}"; do + cp -a $img_file $FOLDER_DIR + done + fi + + i=$((i + 1)) +done +