#93: Add flac support #101

Merged
kdeng00 merged 25 commits from tsk-93 into master 2024-07-27 13:19:12 -04:00
50 changed files with 787 additions and 493 deletions
+13
View File
@@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "8.0.7",
"commands": [
"dotnet-ef"
],
"rollForward": false
}
}
}
+4
View File
@@ -9,3 +9,7 @@
/obj /obj
/obj/* /obj/*
/Icarus.txt /Icarus.txt
/appsettings.json
/appsettings.Development.json
appsettings.Development.json
appsettings.json
+1 -5
View File
@@ -1,7 +1,3 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Icarus.Authorization; using Icarus.Authorization;
@@ -18,7 +14,7 @@ public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
} }
var scopes = context.User.FindFirst(c => 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)) if (scopes.Any(s => s == requirement.Scope))
{ {
+6
View File
@@ -2,6 +2,9 @@ namespace Icarus.Constants;
public class FileExtensions 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 // Contains file extension with period at the beginning
public static string MP3_EXTENSION = ".mp3"; public static string MP3_EXTENSION = ".mp3";
@@ -11,6 +14,9 @@ public class FileExtensions
// Contains file extension with period at the beginning // Contains file extension with period at the beginning
public static string JPG_EXTENSION = ".jpg"; 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 // Contains file extension with period at the beginning
public static string ZIP_EXTENSION = ".zip"; public static string ZIP_EXTENSION = ".zip";
} }
+15 -15
View File
@@ -6,7 +6,7 @@ namespace Icarus.Controllers.Managers;
public class AlbumManager : BaseManager public class AlbumManager : BaseManager
{ {
#region Fields #region Fields
private AlbumContext _albumContext; private AlbumContext? _albumContext;
#endregion #endregion
@@ -19,7 +19,7 @@ public class AlbumManager : BaseManager
{ {
_config = config; _config = config;
_connectionString = _config.GetConnectionString("DefaultConnection"); _connectionString = _config.GetConnectionString("DefaultConnection");
_albumContext = new AlbumContext(_connectionString); _albumContext = new AlbumContext(_connectionString!);
} }
#endregion #endregion
@@ -33,11 +33,11 @@ public class AlbumManager : BaseManager
album.Title = song.AlbumTitle; album.Title = song.AlbumTitle;
album.AlbumArtist = song.Artist; album.AlbumArtist = song.Artist;
album.Year = song.Year.Value; album.Year = song.Year!.Value;
var albumTitle = song.AlbumTitle; var albumTitle = song.AlbumTitle;
var albumArtist = song.Artist; 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) if (albumRetrieved == null)
{ {
@@ -58,7 +58,7 @@ public class AlbumManager : BaseManager
public void DeleteAlbumFromDatabase(Song song) 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) if (album == null)
{ {
@@ -72,7 +72,7 @@ public class AlbumManager : BaseManager
public Album UpdateAlbumInDatabase(Song oldSong, Song newSong) 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 oldAlbumTitle = oldSong.AlbumTitle;
var oldAlbumArtist = oldSong.Artist; var oldAlbumArtist = oldSong.Artist;
var newAlbumTitle = newSong.AlbumTitle; var newAlbumTitle = newSong.AlbumTitle;
@@ -86,16 +86,16 @@ public class AlbumManager : BaseManager
newAlbumTitle = oldAlbumTitle; newAlbumTitle = oldAlbumTitle;
if ((string.IsNullOrEmpty(newAlbumTitle) && string.IsNullOrEmpty(newAlbumArtist) || 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"); _logger.Info("No change to the song's album");
return albumRecord; return albumRecord!;
} }
info = "Change to the song's album"; info = "Change to the song's album";
_logger.Info(info); _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) if (existingAlbumRecord == null)
{ {
_logger.Info("Creating new album record"); _logger.Info("Creating new album record");
@@ -104,7 +104,7 @@ public class AlbumManager : BaseManager
{ {
Title = newAlbumTitle, Title = newAlbumTitle,
AlbumArtist = newAlbumArtist, AlbumArtist = newAlbumArtist,
Year = newSong.Year.Value Year = newSong.Year!.Value
}; };
_albumContext.Add(newAlbumRecord); _albumContext.Add(newAlbumRecord);
@@ -116,8 +116,8 @@ public class AlbumManager : BaseManager
{ {
_logger.Info("Updating existing album record"); _logger.Info("Updating existing album record");
existingAlbumRecord = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(newSong.AlbumTitle)); existingAlbumRecord = _albumContext.Albums!.FirstOrDefault(alb => alb.Title!.Equals(newSong.AlbumTitle));
existingAlbumRecord.AlbumArtist = newAlbumArtist; existingAlbumRecord!.AlbumArtist = newAlbumArtist;
_albumContext.Update(existingAlbumRecord); _albumContext.Update(existingAlbumRecord);
_albumContext.SaveChanges(); _albumContext.SaveChanges();
@@ -130,15 +130,15 @@ public class AlbumManager : BaseManager
{ {
if (SongsInAlbum(album) <= 1) if (SongsInAlbum(album) <= 1)
{ {
_albumContext.Remove(album); _albumContext!.Remove(album);
_albumContext.SaveChanges(); _albumContext.SaveChanges();
} }
} }
private int SongsInAlbum(Album album) private int SongsInAlbum(Album album)
{ {
var sngContext = new SongContext(_connectionString); var sngContext = new SongContext(_connectionString!);
var songs = sngContext.Songs.Where(sng => sng.AlbumId == album.Id).ToList(); var songs = sngContext!.Songs!.Where(sng => sng.AlbumId == album.Id).ToList();
return songs.Count; return songs.Count;
} }
+16 -16
View File
@@ -6,7 +6,7 @@ namespace Icarus.Controllers.Managers;
public class ArtistManager : BaseManager public class ArtistManager : BaseManager
{ {
#region Fields #region Fields
private ArtistContext _artistContext; private ArtistContext? _artistContext;
#endregion #endregion
@@ -19,7 +19,7 @@ public class ArtistManager : BaseManager
{ {
_config = config; _config = config;
_connectionString = _config.GetConnectionString("DefaultConnection"); _connectionString = _config.GetConnectionString("DefaultConnection");
_artistContext = new ArtistContext(_connectionString); _artistContext = new ArtistContext(_connectionString!);
} }
#endregion #endregion
@@ -35,7 +35,7 @@ public class ArtistManager : BaseManager
SongCount = 1 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) if (artistRetrieved == null)
{ {
@@ -53,11 +53,11 @@ public class ArtistManager : BaseManager
public Artist UpdateArtistInDatabase(Song oldSongRecord, Song newSongRecord) public Artist UpdateArtistInDatabase(Song oldSongRecord, Song newSongRecord)
{ {
var oldArtistRecord = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(oldSongRecord.AlbumTitle)); var oldArtistRecord = _artistContext!.Artists.FirstOrDefault(art => art.Name!.Equals(oldSongRecord.AlbumTitle));
var oldArtistName = oldArtistRecord.Name; var oldArtistName = oldArtistRecord!.Name;
var newArtistName = newSongRecord.Artist; 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"); _logger.Info("No change to the song's Artist");
return oldArtistRecord; return oldArtistRecord;
@@ -73,7 +73,7 @@ public class ArtistManager : BaseManager
_artistContext.SaveChanges(); _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"); _logger.Info("Creating new artist record");
@@ -91,36 +91,36 @@ public class ArtistManager : BaseManager
{ {
_logger.Info("Updating existing artist record"); _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(); _artistContext.SaveChanges();
return existingArtistRecord; return existingArtistRecord!;
} }
} }
public void DeleteArtistFromDatabase(Song song) 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"); _logger.Info("Cannot delete the artist record because it does not exist");
return; 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(); _artistContext.SaveChanges();
} }
} }
private int SongsOfArtist(Artist artist) private int SongsOfArtist(Artist artist)
{ {
var sngContext = new SongContext(_connectionString); var sngContext = new SongContext(_connectionString!);
var songs = sngContext.Songs.Where(sng => sng.ArtistId == artist.Id).ToList(); var songs = sngContext.Songs!.Where(sng => sng.ArtistId == artist.Id).ToList();
return songs.Count; return songs.Count;
} }
+2 -2
View File
@@ -7,7 +7,7 @@ public class BaseManager
{ {
#region Fields #region Fields
protected static Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); protected static Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
protected IConfiguration _config; protected IConfiguration? _config;
protected string _connectionString; protected string? _connectionString;
#endregion #endregion
} }
+19 -16
View File
@@ -8,9 +8,10 @@ namespace Icarus.Controllers.Managers;
public class CoverArtManager : BaseManager public class CoverArtManager : BaseManager
{ {
#region Fields #region Fields
private string _rootCoverArtPath; private string? _rootCoverArtPath;
private CoverArtContext _coverArtContext; private CoverArtContext? _coverArtContext;
private byte[] _stockCoverArt = null; private byte[]? _stockCoverArt = null;
private const string? _filename = "CoverArt.png";
#endregion #endregion
@@ -29,7 +30,7 @@ public class CoverArtManager : BaseManager
public void SaveCoverArtToDatabase(ref Song song, ref CoverArt coverArt) public void SaveCoverArtToDatabase(ref Song song, ref CoverArt coverArt)
{ {
_logger.Info("Saving cover art record to the database"); _logger.Info("Saving cover art record to the database");
_coverArtContext.Add(coverArt); _coverArtContext!.Add(coverArt);
_coverArtContext.SaveChanges(); _coverArtContext.SaveChanges();
song.CoverArtId = coverArt.Id; song.CoverArtId = coverArt.Id;
@@ -38,7 +39,7 @@ public class CoverArtManager : BaseManager
{ {
_logger.Info("Attempting to delete cover art from the database"); _logger.Info("Attempting to delete cover art from the database");
_coverArtContext.Attach(coverArt); _coverArtContext!.Attach(coverArt);
_coverArtContext.Remove(coverArt); _coverArtContext.Remove(coverArt);
_coverArtContext.SaveChanges(); _coverArtContext.SaveChanges();
} }
@@ -46,7 +47,7 @@ public class CoverArtManager : BaseManager
{ {
try try
{ {
var stockCoverArtPath = _rootCoverArtPath + "CoverArt.png"; var stockCoverArtPath = _rootCoverArtPath + _filename;
if (!string.Equals(stockCoverArtPath, coverArt.ImagePath(), if (!string.Equals(stockCoverArtPath, coverArt.ImagePath(),
StringComparison.CurrentCultureIgnoreCase)) StringComparison.CurrentCultureIgnoreCase))
{ {
@@ -67,17 +68,17 @@ public class CoverArtManager : BaseManager
} }
} }
public CoverArt SaveCoverArt(Song song) public CoverArt? SaveCoverArt(Song song)
{ {
try try
{ {
var dirMgr = new DirectoryManager(_rootCoverArtPath); var dirMgr = new DirectoryManager(_rootCoverArtPath!);
var defaultExtension = ".png"; var defaultExtension = ".png";
dirMgr.CreateDirectory(song); dirMgr.CreateDirectory(song);
var coverArt = new CoverArt var coverArt = new CoverArt
{ {
SongTitle = song.Title SongTitle = song.Title!
}; };
var segment = coverArt.GenerateFilename(0); var segment = coverArt.GenerateFilename(0);
@@ -102,7 +103,7 @@ public class CoverArtManager : BaseManager
metaData.UpdateCoverArt(song, coverArt); metaData.UpdateCoverArt(song, coverArt);
coverArt.Directory = this._rootCoverArtPath; coverArt.Directory = this._rootCoverArtPath;
coverArt.Filename = $"{segment}{defaultExtension}"; coverArt.Filename = $"{segment}{defaultExtension}";
File.WriteAllBytes(coverArt.ImagePath(), _stockCoverArt); File.WriteAllBytes(coverArt.ImagePath(), _stockCoverArt!);
} }
coverArt.Type = metaData.CoverArtFileExtensionType(coverArt); coverArt.Type = metaData.CoverArtFileExtensionType(coverArt);
@@ -131,7 +132,7 @@ public class CoverArtManager : BaseManager
try try
{ {
MetadataRetriever metaData = new MetadataRetriever(); MetadataRetriever metaData = new MetadataRetriever();
var dirMgr = new DirectoryManager(_rootCoverArtPath); var dirMgr = new DirectoryManager(_rootCoverArtPath!);
cover.Type = metaData.FileExtensionType(data); cover.Type = metaData.FileExtensionType(data);
var defaultExtension = "." + cover.Type; var defaultExtension = "." + cover.Type;
dirMgr.CreateDirectory(song); dirMgr.CreateDirectory(song);
@@ -157,21 +158,23 @@ public class CoverArtManager : BaseManager
public CoverArt GetCoverArt(Song song) 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() private void Initialize()
{ {
_coverArtContext = new CoverArtContext(_connectionString); _coverArtContext = new CoverArtContext(_connectionString!);
var path = DirectoryPaths.CoverArtDirectory + DirectoryPaths.CoverArtFilename; var path = DirectoryPaths.CoverArtDirectory + DirectoryPaths.CoverArtFilename;
if (System.IO.File.Exists(path)) if (System.IO.File.Exists(path))
_stockCoverArt = File.ReadAllBytes(path); _stockCoverArt = File.ReadAllBytes(path);
if (!File.Exists(_rootCoverArtPath + "CoverArt.png")) if (!File.Exists(_rootCoverArtPath + _filename))
{ {
File.WriteAllBytes(_rootCoverArtPath + "CoverArt.png", File.WriteAllBytes(_rootCoverArtPath + _filename,
_stockCoverArt); _stockCoverArt!);
Console.WriteLine("Copied Stock Cover Art"); Console.WriteLine("Copied Stock Cover Art");
} }
} }
+15 -15
View File
@@ -7,14 +7,14 @@ namespace Icarus.Controllers.Managers;
public class DirectoryManager : BaseManager public class DirectoryManager : BaseManager
{ {
#region Fields #region Fields
private Song _song; private Song? _song;
private string _rootSongDirectory; private string? _rootSongDirectory;
private string _songDirectory; private string? _songDirectory;
#endregion #endregion
#region Properties #region Properties
public string SongDirectory public string? SongDirectory
{ {
get => _songDirectory; get => _songDirectory;
set => _songDirectory = value; set => _songDirectory = value;
@@ -65,7 +65,7 @@ public class DirectoryManager : BaseManager
public void CreateDirectory() public void CreateDirectory()
{ {
this.CreateDirectory(_song); this.CreateDirectory(_song!);
} }
public void CreateDirectory(Song song) public void CreateDirectory(Song song)
@@ -187,9 +187,9 @@ public class DirectoryManager : BaseManager
private class DirEnt private class DirEnt
{ {
public string Pre { get; set;} public string? Pre { get; set;}
public string Path { get; set; } public string? Path { get; set; }
public string Post { get; set; } public string? Post { get; set; }
} }
private void GenerateDirectories(List<DirEnt> dirs) private void GenerateDirectories(List<DirEnt> dirs)
@@ -197,7 +197,7 @@ public class DirectoryManager : BaseManager
foreach (var di in dirs) foreach (var di in dirs)
{ {
_logger.Info(di.Pre); _logger.Info(di.Pre);
Directory.CreateDirectory(di.Path); Directory.CreateDirectory(di.Path!);
_logger.Info(di.Post); _logger.Info(di.Post);
} }
} }
@@ -207,10 +207,10 @@ public class DirectoryManager : BaseManager
switch (dirTypes) switch (dirTypes)
{ {
case DirectoryType.Music: case DirectoryType.Music:
_rootSongDirectory = _config.GetValue<string>("RootMusicPath"); _rootSongDirectory = _config!.GetValue<string>("RootMusicPath")!;
break; break;
case DirectoryType.CoverArt: case DirectoryType.CoverArt:
_rootSongDirectory = _config.GetValue<string>("CoverArtPath"); _rootSongDirectory = _config!.GetValue<string>("CoverArtPath")!;
break; break;
} }
} }
@@ -222,12 +222,12 @@ public class DirectoryManager : BaseManager
private string AlbumDirectory() private string AlbumDirectory()
{ {
return AlbumDirectory(_song); return AlbumDirectory(_song!);
} }
private string AlbumDirectory(Song song) private string AlbumDirectory(Song song)
{ {
var directory = ArtistDirectory(song); var directory = ArtistDirectory(song);
var segment = SerializeValue(song.AlbumTitle); var segment = SerializeValue(song.AlbumTitle!);
directory += $@"{segment}/"; directory += $@"{segment}/";
Console.WriteLine($"Album directory {directory}"); Console.WriteLine($"Album directory {directory}");
@@ -235,12 +235,12 @@ public class DirectoryManager : BaseManager
} }
private string ArtistDirectory() private string ArtistDirectory()
{ {
return ArtistDirectory(_song); return ArtistDirectory(_song!);
} }
private string ArtistDirectory(Song song) private string ArtistDirectory(Song song)
{ {
var directory = _rootSongDirectory; var directory = _rootSongDirectory;
var segment = SerializeValue(song.Artist); var segment = SerializeValue(song.Artist!);
directory += $@"{segment}/"; directory += $@"{segment}/";
Console.WriteLine($"Artist directory {directory}"); Console.WriteLine($"Artist directory {directory}");
+16 -16
View File
@@ -6,7 +6,7 @@ namespace Icarus.Controllers.Managers;
public class GenreManager : BaseManager public class GenreManager : BaseManager
{ {
#region Fields #region Fields
private GenreContext _genreContext; private GenreContext? _genreContext;
#endregion #endregion
@@ -19,7 +19,7 @@ public class GenreManager : BaseManager
{ {
_config = config; _config = config;
_connectionString = _config.GetConnectionString("DefaultConnection"); _connectionString = _config.GetConnectionString("DefaultConnection");
_genreContext = new GenreContext(_connectionString); _genreContext = new GenreContext(_connectionString!);
} }
#endregion #endregion
@@ -36,7 +36,7 @@ public class GenreManager : BaseManager
}; };
var genreName = song.Genre; 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) if (genreRetrieved == null)
{ {
@@ -53,11 +53,11 @@ public class GenreManager : BaseManager
public Genre UpdateGenreInDatabase(Song oldSongRecord, Song newSongRecord) public Genre UpdateGenreInDatabase(Song oldSongRecord, Song newSongRecord)
{ {
var oldGenreRecord = _genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(oldSongRecord.Genre)); var oldGenreRecord = _genreContext!.Genres!.FirstOrDefault(gnr => gnr.GenreName!.Equals(oldSongRecord.Genre));
var oldGenreName = oldGenreRecord.GenreName; var oldGenreName = oldGenreRecord!.GenreName;
var newGenreName = newSongRecord.Genre; 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"); _logger.Info("No change to the song's Genre");
return oldGenreRecord; return oldGenreRecord;
@@ -73,7 +73,7 @@ public class GenreManager : BaseManager
_genreContext.SaveChanges(); _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"); _logger.Info("Creating new genre record");
@@ -91,36 +91,36 @@ public class GenreManager : BaseManager
{ {
_logger.Info("Updating existing genre record"); _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(); _genreContext.SaveChanges();
return existingGenreRecord; return existingGenreRecord!;
} }
} }
public void DeleteGenreFromDatabase(Song song) 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"); _logger.Info("Cannot delete the genre record because it does not exist");
return; 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(); _genreContext.SaveChanges();
} }
} }
private int SongsInGenre(Genre genre) private int SongsInGenre(Genre genre)
{ {
var sngContext = new SongContext(_connectionString); var sngContext = new SongContext(_connectionString!);
var songs = sngContext.Songs.Where(sng => sng.GenreId == genre.Id).ToList(); var songs = sngContext.Songs!.Where(sng => sng.GenreId == genre.Id).ToList();
return songs.Count; return songs.Count;
} }
+124 -86
View File
@@ -9,26 +9,26 @@ namespace Icarus.Controllers.Managers;
public class SongManager : BaseManager public class SongManager : BaseManager
{ {
#region Fields #region Fields
private string _tempDirectoryRoot; private string? _tempDirectoryRoot;
private string _archiveDirectoryRoot; private string? _archiveDirectoryRoot;
private string _compressedSongFilename; private string? _compressedSongFilename;
private string _message; private string? _message;
private SongContext _songContext; private SongContext? _songContext;
#endregion #endregion
#region Properties #region Properties
public string ArchiveDirectoryRoot public string? ArchiveDirectoryRoot
{ {
get => _archiveDirectoryRoot; get => _archiveDirectoryRoot;
set => _archiveDirectoryRoot = value; set => _archiveDirectoryRoot = value;
} }
public string CompressedSongFilename public string? CompressedSongFilename
{ {
get => _compressedSongFilename; get => _compressedSongFilename;
set => _compressedSongFilename = value; set => _compressedSongFilename = value;
} }
public string Message public string? Message
{ {
get => _message; get => _message;
set => _message = value; set => _message = value;
@@ -64,7 +64,7 @@ public class SongManager : BaseManager
try try
{ {
var oldSongRecord = _songContext.RetrieveRecord(song); var oldSongRecord = _songContext!.RetrieveRecord(song);
song.Filename = oldSongRecord.Filename; song.Filename = oldSongRecord.Filename;
song.SongDirectory = oldSongRecord.SongDirectory; song.SongDirectory = oldSongRecord.SongDirectory;
@@ -73,19 +73,19 @@ public class SongManager : BaseManager
var updatedSong = updateMetadata.UpdatedSongRecord; var updatedSong = updateMetadata.UpdatedSongRecord;
var albMgr = new AlbumManager(_config); var albMgr = new AlbumManager(_config!);
var gnrMgr = new GenreManager(_config); var gnrMgr = new GenreManager(_config!);
var artMgr = new ArtistManager(_config); var artMgr = new ArtistManager(_config!);
var updatedAlbum = albMgr.UpdateAlbumInDatabase(oldSongRecord, updatedSong); var updatedAlbum = albMgr.UpdateAlbumInDatabase(oldSongRecord, updatedSong!);
oldSongRecord.AlbumId = updatedAlbum.Id; oldSongRecord.AlbumId = updatedAlbum.Id;
var updatedArtist = artMgr.UpdateArtistInDatabase(oldSongRecord, updatedSong); var updatedArtist = artMgr.UpdateArtistInDatabase(oldSongRecord, updatedSong!);
oldSongRecord.ArtistId = updatedArtist.Id; oldSongRecord.ArtistId = updatedArtist.Id;
var updatedGenre = gnrMgr.UpdateGenreInDatabase(oldSongRecord, updatedSong); var updatedGenre = gnrMgr.UpdateGenreInDatabase(oldSongRecord, updatedSong!);
oldSongRecord.GenreId = updatedGenre.Id; oldSongRecord.GenreId = updatedGenre.Id;
UpdateSongInDatabase(ref oldSongRecord, ref updatedSong, ref result); UpdateSongInDatabase(ref oldSongRecord, ref updatedSong!, ref result);
DeleteEmptyDirectories(ref oldSongRecord, ref updatedSong); DeleteEmptyDirectories(ref oldSongRecord, ref updatedSong);
} }
@@ -109,7 +109,7 @@ public class SongManager : BaseManager
var songPath = songMetaData.SongPath(); var songPath = songMetaData.SongPath();
File.Delete(songPath); File.Delete(songPath);
successful = true; successful = true;
DirectoryManager dirMgr = new DirectoryManager(_config, songMetaData); DirectoryManager dirMgr = new DirectoryManager(_config!, songMetaData);
dirMgr.DeleteEmptyDirectories(); dirMgr.DeleteEmptyDirectories();
Console.WriteLine("Song successfully deleted"); Console.WriteLine("Song successfully deleted");
} }
@@ -123,7 +123,7 @@ public class SongManager : BaseManager
public bool DoesSongExist(Song song) public bool DoesSongExist(Song song)
{ {
if (!_songContext.DoesRecordExist(song)) if (!_songContext!.DoesRecordExist(song))
{ {
return false; return false;
} }
@@ -142,7 +142,7 @@ public class SongManager : BaseManager
} }
_logger.Info("Song deleted from the filesystem"); _logger.Info("Song deleted from the filesystem");
var coverMgr = new CoverArtManager(_config); var coverMgr = new CoverArtManager(_config!);
var coverArt = coverMgr.GetCoverArt(song); var coverArt = coverMgr.GetCoverArt(song);
coverMgr.DeleteCoverArt(coverArt); coverMgr.DeleteCoverArt(coverArt);
@@ -166,11 +166,11 @@ public class SongManager : BaseManager
var song = await SaveSongTemp(songFile); var song = await SaveSongTemp(songFile);
DirectoryManager dirMgr = new DirectoryManager(_config, song); DirectoryManager dirMgr = new DirectoryManager(_config!, song);
dirMgr.CreateDirectory(); dirMgr.CreateDirectory();
var tempPath = song.SongPath(); var tempPath = song.SongPath();
song.Filename = song.GenerateFilename(1); song.Filename = song.GenerateFilename(true, AudioFileExtensionsType.WAV);
var filePath = $"{dirMgr.SongDirectory}{song.Filename}"; var filePath = $"{dirMgr.SongDirectory}{song.Filename}";
_logger.Info($"Absolute song path: {filePath}"); _logger.Info($"Absolute song path: {filePath}");
@@ -178,27 +178,15 @@ public class SongManager : BaseManager
await Task.Run(() => await Task.Run(() =>
{ {
using (var fileStream = new FileStream(filePath, FileMode.Create)) this.MoveSongToFinalDestination(tempPath, filePath);
{
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");
}
}); });
song.SongDirectory = dirMgr.SongDirectory; song.SongDirectory = dirMgr.SongDirectory;
var coverMgr = new CoverArtManager(_config); var coverMgr = new CoverArtManager(_config!);
var coverArt = coverMgr.SaveCoverArt(song); var coverArt = coverMgr.SaveCoverArt(song);
coverMgr.SaveCoverArtToDatabase(ref song, ref coverArt); SaveSongToDatabase(song, coverArt);
SaveSongToDatabase(song);
} }
catch (Exception ex) 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)
{
if (string.IsNullOrEmpty(song.SongDirectory))
{ {
song.SongDirectory = _tempDirectoryRoot; song.SongDirectory = _tempDirectoryRoot;
song.DateCreated = DateTime.Now; }
if (string.IsNullOrEmpty(song.Filename)) 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}"); _logger.Info($"Temporary directory: {_tempDirectoryRoot}");
@@ -223,16 +225,19 @@ public class SongManager : BaseManager
_logger.Info("Temporary song path: {0}", tempPath); _logger.Info("Temporary song path: {0}", tempPath);
if (!System.IO.File.Exists(tempPath))
{
using (var filestream = new FileStream(tempPath, FileMode.Create)) using (var filestream = new FileStream(tempPath, FileMode.Create))
{ {
_logger.Info("Saving song to temporary directory"); _logger.Info("Saving song to temporary directory");
songFile.CopyTo(filestream); songFile.CopyTo(filestream);
} }
}
var coverMgr = new CoverArtManager(_config); var coverMgr = new CoverArtManager(_config!);
var coverArt = coverMgr.SaveCoverArt(coverArtData, song); var coverArt = coverMgr.SaveCoverArt(coverArtData, song);
DirectoryManager dirMgr = new DirectoryManager(_config, song); DirectoryManager dirMgr = new DirectoryManager(_config!, song);
dirMgr.CreateDirectory(); dirMgr.CreateDirectory();
song.SongDirectory = dirMgr.SongDirectory; song.SongDirectory = dirMgr.SongDirectory;
@@ -240,24 +245,66 @@ public class SongManager : BaseManager
var filePath = song.SongPath(); var filePath = song.SongPath();
_logger.Info($"Absolute song path: {filePath}"); _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)
{ {
var songBytes = System.IO.File.ReadAllBytes(tempPath); // 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(sourcePath);
try 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); System.IO.File.Delete(sourcePath);
_logger.Info("Deleted temp song from filesystem: {0}", tempPath); _logger.Info("Deleted temp song from filesystem: {0}", sourcePath);
} }
else else
{ {
fileStream.Write(songBytes, 0, songBytes.Count()); 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); System.IO.File.Delete(sourcePath);
_logger.Info("Deleted temp song from filesystem: {0}", tempPath); _logger.Info("Deleted temp song from filesystem: {0}", sourcePath);
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -268,13 +315,8 @@ public class SongManager : BaseManager
_logger.Info("Song successfully saved to filesystem"); _logger.Info("Song successfully saved to filesystem");
} }
coverMgr.SaveCoverArtToDatabase(ref song, ref coverArt);
SaveSongToDatabase(song);
} }
public async Task<SongData> RetrieveSong(Song songMetaData) public async Task<SongData> RetrieveSong(Song songMetaData)
{ {
var song = new SongData(); var song = new SongData();
@@ -304,28 +346,21 @@ public class SongManager : BaseManager
Data = uncompressedSong Data = uncompressedSong
}; };
} }
private async Task<Song> SaveSongTemp(IFormFile songFile) public async Task<Song> SaveSongTemp(IFormFile songFile)
{ {
var song = new Song();
_logger.Info("Assigning song filename"); _logger.Info("Assigning song filename");
song.SongDirectory = _tempDirectoryRoot; var song = new Song { SongDirectory = this._tempDirectoryRoot! };
var filename = song.GenerateFilename(1); var filename = await song.GenerateFilenameAsync(false) + "-" + songFile.FileName;
song.Filename = 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 songFile.CopyToAsync(filestream);
} }
await Task.Run(() =>
{
MetadataRetriever meta = new MetadataRetriever();
song = meta.RetrieveMetaData(song.SongPath());
});
song.SongDirectory = _tempDirectoryRoot;
song.DateCreated = DateTime.Now; song.DateCreated = DateTime.Now;
song.Filename = filename;
return song; return song;
} }
@@ -339,9 +374,9 @@ public class SongManager : BaseManager
var currentGenre = currentSong.Genre; var currentGenre = currentSong.Genre;
var currentYear = currentSong.Year; var currentYear = currentSong.Year;
if (!currentTitle.Equals(songUpdates.Title) || !currentArtist.Equals(songUpdates.Artist) || if (!currentTitle!.Equals(songUpdates.Title) || !currentArtist!.Equals(songUpdates.Artist) ||
!currentAlbum.Equals(songUpdates.AlbumTitle) || !currentAlbum!.Equals(songUpdates.AlbumTitle) ||
!currentGenre.Equals(songUpdates.Genre) || currentYear != songUpdates.Year) !currentGenre!.Equals(songUpdates.Genre) || currentYear != songUpdates.Year)
return true; return true;
return false; return false;
@@ -349,7 +384,7 @@ public class SongManager : BaseManager
private void DeleteEmptyDirectories(ref Song oldSong, ref Song updatedSong) 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"); _logger.Info("Checking to see if there are any directories to delete");
mgr.DeleteEmptyDirectories(oldSong); mgr.DeleteEmptyDirectories(oldSong);
@@ -359,8 +394,8 @@ public class SongManager : BaseManager
{ {
try try
{ {
_connectionString = _config.GetConnectionString("DefaultConnection"); _connectionString = _config!.GetConnectionString("DefaultConnection");
_songContext = new SongContext(_connectionString); _songContext = new SongContext(_connectionString!);
} }
catch (Exception ex) 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"); _logger.Info("Starting process to save the song to the database");
var albumMgr = new AlbumManager(_config); var albumMgr = new AlbumManager(_config!);
var artistMgr = new ArtistManager(_config); var artistMgr = new ArtistManager(_config!);
var genreMgr = new GenreManager(_config); var genreMgr = new GenreManager(_config!);
var coverMgr = new CoverArtManager(_config!);
albumMgr.SaveAlbumToDatabase(ref song); albumMgr.SaveAlbumToDatabase(ref song);
artistMgr.SaveArtistToDatabase(ref song); artistMgr.SaveArtistToDatabase(ref song);
genreMgr.SaveGenreToDatabase(ref song); genreMgr.SaveGenreToDatabase(ref song);
@@ -384,8 +420,10 @@ public class SongManager : BaseManager
var info = "Saving Song to DB"; var info = "Saving Song to DB";
_logger.Info(info); _logger.Info(info);
_songContext.Add(song); _songContext!.Add(song);
_songContext.SaveChanges(); _songContext!.SaveChanges();
coverMgr.SaveCoverArtToDatabase(ref song, ref cover!);
} }
@@ -430,7 +468,7 @@ public class SongManager : BaseManager
{ {
var updatedSongRecord = oldSongRecord; var updatedSongRecord = oldSongRecord;
var songContext = new SongContext(_connectionString); var songContext = new SongContext(_connectionString!);
if (!SongRecordChanged(oldSongRecord, newSongRecord)) if (!SongRecordChanged(oldSongRecord, newSongRecord))
{ {
@@ -470,18 +508,18 @@ public class SongManager : BaseManager
newSongRecord = updatedSongRecord; newSongRecord = updatedSongRecord;
result.Message = "Successfully updated song"; result.Message = "Successfully updated song";
result.SongTitle = updatedSongRecord.Title; result.SongTitle = updatedSongRecord.Title!;
} }
private void DeleteSongFromDatabase(Song song) private void DeleteSongFromDatabase(Song song)
{ {
_logger.Info("Starting process to delete records related to the song from the database"); _logger.Info("Starting process to delete records related to the song from the database");
var albumMgr = new AlbumManager(_config); var albumMgr = new AlbumManager(_config!);
var artistMgr = new ArtistManager(_config); var artistMgr = new ArtistManager(_config!);
var genreMgr = new GenreManager(_config); var genreMgr = new GenreManager(_config!);
var sngContext = new SongContext(_connectionString); var sngContext = new SongContext(_connectionString!);
sngContext.Songs.Remove(song); sngContext.Songs!.Remove(song);
sngContext.SaveChanges(); sngContext.SaveChanges();
artistMgr.DeleteArtistFromDatabase(song); artistMgr.DeleteArtistFromDatabase(song);
albumMgr.DeleteAlbumFromDatabase(song); albumMgr.DeleteAlbumFromDatabase(song);
+23 -23
View File
@@ -15,16 +15,16 @@ namespace Icarus.Controllers.Managers;
public class TokenManager : BaseManager public class TokenManager : BaseManager
{ {
#region Fields #region Fields
private string _clientId; private string? _clientId;
private string _clientSecret; private string? _clientSecret;
private string _privateKeyPath = string.Empty; private string? _privateKeyPath = string.Empty;
private string _privateKey = string.Empty; private string? _privateKey = string.Empty;
private string _publicKeyPath = string.Empty; private string? _publicKeyPath = string.Empty;
private string _publicKey = string.Empty; private string? _publicKey = string.Empty;
private string _audience; private string? _audience;
private string _grantType; private string? _grantType;
private string _url; private string? _url;
private string SUCCESSFUL_TOKEN_MESSAGE = "Successfully retrieved token"; private string? SUCCESSFUL_TOKEN_MESSAGE = "Successfully retrieved token";
#endregion #endregion
@@ -46,7 +46,7 @@ public class TokenManager : BaseManager
{ {
_logger.Info("Preparing Auth0 API request"); _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 request = new RestRequest("oauth/token", Method.POST);
var tokenRequest = RetrieveTokenRequest(); var tokenRequest = RetrieveTokenRequest();
@@ -68,7 +68,7 @@ public class TokenManager : BaseManager
.DeserializeObject<TokenTierOne>(response.Content); .DeserializeObject<TokenTierOne>(response.Content);
_logger.Info("Response deserialized"); _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)); payload.Add(new Claim("user_id", user.Id.ToString(), ClaimValueTypes.Integer));
var tokenHandler = new JwtSecurityTokenHandler(); var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_config["JWT:Secret"]); var key = Encoding.ASCII.GetBytes(_config!["JWT:Secret"]!);
var tokenDescriptor = new SecurityTokenDescriptor var tokenDescriptor = new SecurityTokenDescriptor
{ {
Subject = new ClaimsIdentity(new Claim[] Subject = new ClaimsIdentity(new Claim[]
@@ -101,7 +101,7 @@ public class TokenManager : BaseManager
return cl.Type.Equals("exp"); 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); var exp = Math.Floor((expiredDate - DateTime.UnixEpoch).TotalSeconds);
tokenResult.Expiration = Convert.ToInt32(exp); tokenResult.Expiration = Convert.ToInt32(exp);
@@ -197,7 +197,7 @@ public class TokenManager : BaseManager
var expiredDate = currentDate.AddMinutes(expLimit); var expiredDate = currentDate.AddMinutes(expLimit);
var issuer = "http://localhost:5002"; var issuer = "http://localhost:5002";
var audience = "http://localhost:5002"; var audience = "http://localhost:5002";
var subject = _config["JWT:Subject"]; var subject = _config!["JWT:Subject"];
var claim = new List<System.Security.Claims.Claim>() var claim = new List<System.Security.Claims.Claim>()
{ {
@@ -205,7 +205,7 @@ public class TokenManager : BaseManager
new Claim(JwtRegisteredClaimNames.Exp, expiredDate.ToString()), new Claim(JwtRegisteredClaimNames.Exp, expiredDate.ToString()),
new Claim(JwtRegisteredClaimNames.Aud, audience), new Claim(JwtRegisteredClaimNames.Aud, audience),
new Claim(JwtRegisteredClaimNames.Iss, issuer), new Claim(JwtRegisteredClaimNames.Iss, issuer),
new Claim(JwtRegisteredClaimNames.Sub, subject), new Claim(JwtRegisteredClaimNames.Sub, subject!),
new Claim(JwtRegisteredClaimNames.Iat, currentDate.ToString()) new Claim(JwtRegisteredClaimNames.Iat, currentDate.ToString())
}; };
@@ -233,7 +233,7 @@ public class TokenManager : BaseManager
{ {
_logger.Info("Analyzing Auth0 information"); _logger.Info("Analyzing Auth0 information");
_clientId = _config["Auth0:ClientId"]; _clientId = _config!["Auth0:ClientId"];
_clientSecret = _config["Auth0:ClientSecret"]; _clientSecret = _config["Auth0:ClientSecret"];
_audience = _config["Auth0:ApiIdentifier"]; _audience = _config["Auth0:ApiIdentifier"];
_grantType = "client_credentials"; _grantType = "client_credentials";
@@ -258,23 +258,23 @@ public class TokenManager : BaseManager
private class TokenRequest private class TokenRequest
{ {
[JsonProperty("client_id")] [JsonProperty("client_id")]
public string ClientId { get; set; } public string? ClientId { get; set; }
[JsonProperty("client_secret")] [JsonProperty("client_secret")]
public string ClientSecret { get; set; } public string? ClientSecret { get; set; }
[JsonProperty("audience")] [JsonProperty("audience")]
public string Audience { get; set; } public string? Audience { get; set; }
[JsonProperty("grant_type")] [JsonProperty("grant_type")]
public string GrantType { get; set; } public string? GrantType { get; set; }
} }
private class TokenTierOne private class TokenTierOne
{ {
[JsonProperty("access_token")] [JsonProperty("access_token")]
public string AccessToken { get; set; } public string? AccessToken { get; set; }
[JsonProperty("expires_in")] [JsonProperty("expires_in")]
public int Expiration { get; set; } public int Expiration { get; set; }
[JsonProperty("token_type")] [JsonProperty("token_type")]
public string TokenType { get; set; } public string? TokenType { get; set; }
} }
#endregion #endregion
} }
+82 -93
View File
@@ -8,25 +8,27 @@ namespace Icarus.Controllers.Utilities;
public class MetadataRetriever public class MetadataRetriever
{ {
#region Fields #region Fields
private static NLog.Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); private static NLog.Logger? _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
private Song _updatedSong; private List<string>? _supportedAudioFileTypes = new List<string> {"wav", "flac"};
private string _message; private List<string>? _supportedImageFileTypes = new List<string> {"jpeg", "jpg", "png"};
private string _title; private Song? _updatedSong;
private string _artist; private string? _message;
private string _album; private string? _title;
private string _genre; private string? _artist;
private string? _album;
private string? _genre;
private int _year; private int _year;
private int _duration; private int _duration;
#endregion #endregion
#region Properties #region Properties
public Song UpdatedSongRecord public Song? UpdatedSongRecord
{ {
get => _updatedSong; get => _updatedSong;
set => _updatedSong = value; set => _updatedSong = value;
} }
public string Message public string? Message
{ {
get => _message; get => _message;
set => _message = value; set => _message = value;
@@ -39,32 +41,6 @@ public class MetadataRetriever
#region Methods #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) public string CoverArtFileExtensionType(CoverArt cover)
{ {
Console.WriteLine("Retrieving CoverArt file extension type"); 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) public Song RetrieveMetaData(string filePath)
{ {
Song song = new Song(); Song song = new Song();
@@ -140,7 +162,7 @@ public class MetadataRetriever
var msg = ex.Message; var msg = ex.Message;
Console.WriteLine("An error occurred in MetadataRetriever"); Console.WriteLine("An error occurred in MetadataRetriever");
Console.WriteLine(msg); Console.WriteLine(msg);
_logger.Error(msg, "An error occurred in MetadataRetriever"); _logger!.Error(msg, "An error occurred in MetadataRetriever");
} }
return song; return song;
@@ -148,9 +170,8 @@ public class MetadataRetriever
public int RetrieveSongDuration(string filepath) public int RetrieveSongDuration(string filepath)
{ {
var duration = 0;
var fileTag = TagLib.File.Create(filepath); var fileTag = TagLib.File.Create(filepath);
duration = (int)fileTag.Properties.Duration.TotalSeconds; var duration = (int)fileTag.Properties.Duration.TotalSeconds;
return duration; return duration;
} }
@@ -161,17 +182,21 @@ public class MetadataRetriever
{ {
Console.WriteLine("Fetching image"); Console.WriteLine("Fetching image");
var tag = TagLib.File.Create(song.SongPath()); 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) catch (Exception ex)
{ {
var msg = ex.Message; 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; var msg = ex.Message;
Console.WriteLine($"An error occurred: {msg}"); Console.WriteLine($"An error occurred: {msg}");
_logger.Error(msg, "An error occurred"); _logger!.Error(msg, "An error occurred");
Message = "Failed to update metadata"; Message = "Failed to update metadata";
} }
} }
@@ -227,7 +252,7 @@ public class MetadataRetriever
try try
{ {
Console.WriteLine($"Updating metadata of {title}"); Console.WriteLine($"Updating metadata of {title}");
_logger.Info($"Updating metadata of {title}"); _logger!.Info($"Updating metadata of {title}");
foreach (var key in checkedValues.Keys) foreach (var key in checkedValues.Keys)
{ {
@@ -237,43 +262,43 @@ public class MetadataRetriever
switch (key.ToLower()) switch (key.ToLower())
{ {
case "title": case "title":
_updatedSong.Title = title; _updatedSong!.Title = title;
fileTag.Tag.Title = title; fileTag.Tag.Title = title;
break; break;
case "artists": case "artists":
_updatedSong.Artist = artist; _updatedSong!.Artist = artist;
fileTag.Tag.Performers = new []{artist}; fileTag.Tag.Performers = new []{artist};
break; break;
case "album": case "album":
_updatedSong.AlbumTitle = album; _updatedSong!.AlbumTitle = album;
fileTag.Tag.Album = album; fileTag.Tag.Album = album;
break; break;
case "genre": case "genre":
_updatedSong.Genre = genre; _updatedSong!.Genre = genre;
fileTag.Tag.Genres = new []{genre}; fileTag.Tag.Genres = new []{genre};
break; break;
case "year": case "year":
_updatedSong.Year = year; _updatedSong!.Year = year;
fileTag.Tag.Year = (uint)year; fileTag.Tag.Year = (uint)year!;
break; break;
case "albumartist": case "albumartist":
_updatedSong.AlbumArtist = albumArtist; _updatedSong!.AlbumArtist = albumArtist;
fileTag.Tag.AlbumArtists = new []{albumArtist}; fileTag.Tag.AlbumArtists = new []{albumArtist};
break; break;
case "track": case "track":
_updatedSong.Track = track; _updatedSong!.Track = track;
fileTag.Tag.Track = (uint)(track); fileTag.Tag.Track = (uint)(track);
break; break;
case "trackcount": case "trackcount":
_updatedSong.TrackCount = trackCount; _updatedSong!.TrackCount = trackCount;
fileTag.Tag.TrackCount = (uint)(trackCount); fileTag.Tag.TrackCount = (uint)(trackCount);
break; break;
case "disc": case "disc":
_updatedSong.Disc = disc; _updatedSong!.Disc = disc;
fileTag.Tag.Disc = (uint)(disc); fileTag.Tag.Disc = (uint)(disc);
break; break;
case "disccount": case "disccount":
_updatedSong.DiscCount = discCount; _updatedSong!.DiscCount = discCount;
fileTag.Tag.DiscCount = (uint)(discCount); fileTag.Tag.DiscCount = (uint)(discCount);
break; break;
} }
@@ -288,55 +313,19 @@ public class MetadataRetriever
{ {
var msg = ex.Message; var msg = ex.Message;
Console.WriteLine($"An error occurred:\n{msg}"); Console.WriteLine($"An error occurred:\n{msg}");
_logger.Error(msg, "An error occurred"); _logger!.Error(msg, "An error occurred");
} }
} }
private void InitializeUpdatedSong(Song song) private void InitializeUpdatedSong(Song song)
{ {
_updatedSong = 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<string, bool> CheckSongValues(Song song) private SortedDictionary<string, bool> CheckSongValues(Song song)
{ {
var songValues = new SortedDictionary<string, bool>(); var songValues = new SortedDictionary<string, bool>();
Console.WriteLine("Checking for null data"); Console.WriteLine("Checking for null data");
_logger.Info("Checking for null data"); _logger!.Info("Checking for null data");
try try
{ {
+1 -1
View File
@@ -60,7 +60,7 @@ public class PasswordEncryption
_logger.Error(exMsg, "An error occurred"); _logger.Error(exMsg, "An error occurred");
} }
return null; return string.Empty;
} }
string GenerateHash(string password, byte[] salt) string GenerateHash(string password, byte[] salt)
+15 -12
View File
@@ -1,5 +1,3 @@
using Ionic.Zip;
using Icarus.Models; using Icarus.Models;
namespace Icarus.Controllers.Utilities; namespace Icarus.Controllers.Utilities;
@@ -7,14 +5,14 @@ namespace Icarus.Controllers.Utilities;
public class SongCompression public class SongCompression
{ {
#region Fields #region Fields
string _compressedSongFilename; string? _compressedSongFilename;
string _tempDirectory; string? _tempDirectory;
byte[] _uncompressedSong; byte[]? _uncompressedSong;
#endregion #endregion
#region Propterties #region Propterties
public string CompressedSongFilename public string? CompressedSongFilename
{ {
get => _compressedSongFilename; get => _compressedSongFilename;
set => _compressedSongFilename = value; set => _compressedSongFilename = value;
@@ -63,10 +61,15 @@ public class SongCompression
try try
{ {
using (ZipFile zip = new ZipFile()) using (var fi = new FileStream(songDetails.SongPath(), FileMode.Open))
{ {
zip.AddFile(songDetails.SongPath()); using (var z = new Ionic.Zlib.ZlibStream(fi, Ionic.Zlib.CompressionMode.Compress))
zip.Save(tmpZipFilePath); {
using (var tr = new FileStream(tmpZipFilePath, FileMode.CreateNew))
{
z.CopyTo(tr);
}
}
} }
Console.WriteLine("Successfully compressed"); Console.WriteLine("Successfully compressed");
@@ -78,7 +81,7 @@ public class SongCompression
Console.WriteLine(exMsg); Console.WriteLine(exMsg);
} }
if (songDetails.Filename.Contains(Constants.FileExtensions.WAV_EXTENSION)) if (songDetails.Filename!.Contains(Constants.FileExtensions.WAV_EXTENSION))
{ {
_compressedSongFilename = StripExtension(songDetails.Filename); _compressedSongFilename = StripExtension(songDetails.Filename);
} }
@@ -89,7 +92,7 @@ public class SongCompression
// Method not being used // Method not being used
public byte[] CompressedSong(byte[] uncompressedSong) public byte[] CompressedSong(byte[] uncompressedSong)
{ {
byte[] compressedSong = null; byte[]? compressedSong = null;
try try
{ {
Console.WriteLine("Song has been successfully compressed"); Console.WriteLine("Song has been successfully compressed");
@@ -101,7 +104,7 @@ public class SongCompression
Console.WriteLine(exMsg); Console.WriteLine(exMsg);
} }
return compressedSong; return compressedSong!;
} }
+5 -5
View File
@@ -12,8 +12,8 @@ namespace Icarus.Controllers.V1;
public class AlbumController : BaseController public class AlbumController : BaseController
{ {
#region Fields #region Fields
private readonly ILogger<AlbumController> _logger; private readonly ILogger<AlbumController>? _logger;
private string _connectionString; private string? _connectionString;
#endregion #endregion
@@ -35,9 +35,9 @@ public class AlbumController : BaseController
[HttpGet] [HttpGet]
public IActionResult GetAlbums() 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) if (albums.Count > 0)
return Ok(albums); return Ok(albums);
@@ -50,7 +50,7 @@ public class AlbumController : BaseController
{ {
Album album = new Album{ Id = id }; Album album = new Album{ Id = id };
var albumContext = new AlbumContext(_connectionString); var albumContext = new AlbumContext(_connectionString!);
if (albumContext.DoesRecordExist(album)) if (albumContext.DoesRecordExist(album))
{ {
+4 -4
View File
@@ -12,8 +12,8 @@ namespace Icarus.Controllers.V1;
public class ArtistController : BaseController public class ArtistController : BaseController
{ {
#region Fields #region Fields
private readonly ILogger<ArtistController> _logger; private readonly ILogger<ArtistController>? _logger;
private string _connectionString; private string? _connectionString;
#endregion #endregion
@@ -35,7 +35,7 @@ public class ArtistController : BaseController
[HttpGet] [HttpGet]
public IActionResult GetArtists() public IActionResult GetArtists()
{ {
var artistContext = new ArtistContext(_connectionString); var artistContext = new ArtistContext(_connectionString!);
var artists = artistContext.Artists.ToList(); var artists = artistContext.Artists.ToList();
@@ -50,7 +50,7 @@ public class ArtistController : BaseController
{ {
Artist artist = new Artist { Id = id }; Artist artist = new Artist { Id = id };
var artistContext = new ArtistContext(_connectionString); var artistContext = new ArtistContext(_connectionString!);
if (artistContext.DoesRecordExist(artist)) if (artistContext.DoesRecordExist(artist))
{ {
+1 -1
View File
@@ -6,7 +6,7 @@ namespace Icarus.Controllers.V1;
public class BaseController : ControllerBase public class BaseController : ControllerBase
{ {
#region Fiends #region Fiends
protected IConfiguration _config; protected IConfiguration? _config;
#endregion #endregion
+12 -12
View File
@@ -13,8 +13,8 @@ namespace Icarus.Controllers.V1;
public class CoverArtController : BaseController public class CoverArtController : BaseController
{ {
#region Fields #region Fields
private readonly ILogger<CoverArtController> _logger; private readonly ILogger<CoverArtController>? _logger;
private string _connectionString; private string? _connectionString;
#endregion #endregion
@@ -32,18 +32,18 @@ public class CoverArtController : BaseController
[HttpGet] [HttpGet]
public IActionResult GetCoverArts() 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) if (coverArtRecords == null)
{ {
_logger.LogInformation("No cover art records"); _logger!.LogInformation("No cover art records");
return NotFound(); return NotFound();
} }
else else
{ {
_logger.LogInformation("Found cover art records"); _logger!.LogInformation("Found cover art records");
return Ok(coverArtRecords); return Ok(coverArtRecords);
} }
} }
@@ -53,13 +53,13 @@ public class CoverArtController : BaseController
{ {
var coverArt = new CoverArt { Id = id }; var coverArt = new CoverArt { Id = id };
var coverArtContext = new CoverArtContext(_connectionString); var coverArtContext = new CoverArtContext(_connectionString!);
coverArt = coverArtContext.RetrieveRecord(coverArt); coverArt = coverArtContext.RetrieveRecord(coverArt);
if (coverArt != null) if (coverArt != null)
{ {
_logger.LogInformation("Found cover art record"); _logger!.LogInformation("Found cover art record");
var coverArtBytes = System.IO.File.ReadAllBytes( var coverArtBytes = System.IO.File.ReadAllBytes(
coverArt.ImagePath()); coverArt.ImagePath());
@@ -68,7 +68,7 @@ public class CoverArtController : BaseController
} }
else else
{ {
_logger.LogInformation("Cover art not found"); _logger!.LogInformation("Cover art not found");
return NotFound(); return NotFound();
} }
} }
@@ -76,13 +76,13 @@ public class CoverArtController : BaseController
[HttpGet("data/download/{id}")] [HttpGet("data/download/{id}")]
public async Task<IActionResult> Download(int id, [FromQuery] bool? randomizeFilename) public async Task<IActionResult> Download(int id, [FromQuery] bool? randomizeFilename)
{ {
var songContext = new SongContext(_connectionString); var songContext = new SongContext(_connectionString!);
var covMgr = new CoverArtManager(this._config); var covMgr = new CoverArtManager(this._config!);
var songMetaData = songContext.RetrieveRecord(new Song { Id = id}); var songMetaData = songContext.RetrieveRecord(new Song { Id = id});
var c = covMgr.GetCoverArt(songMetaData); 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(); var data = await c.GetData();
+5 -5
View File
@@ -12,8 +12,8 @@ namespace Icarus.Controllers.V1;
public class GenreController : BaseController public class GenreController : BaseController
{ {
#region Fields #region Fields
private readonly ILogger<GenreController> _logger; private readonly ILogger<GenreController>? _logger;
private string _connectionString; private string? _connectionString;
#endregion #endregion
@@ -35,9 +35,9 @@ public class GenreController : BaseController
[HttpGet] [HttpGet]
public IActionResult GetGenres() 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) if (genres.Count > 0)
{ {
@@ -54,7 +54,7 @@ public class GenreController : BaseController
{ {
var genre = new Genre { Id = id }; var genre = new Genre { Id = id };
var genreStore = new GenreContext(_connectionString); var genreStore = new GenreContext(_connectionString!);
if (genreStore.DoesRecordExist(genre)) if (genreStore.DoesRecordExist(genre))
{ {
+9 -9
View File
@@ -17,8 +17,8 @@ namespace Icarus.Controllers.V1;
public class LoginController : ControllerBase public class LoginController : ControllerBase
{ {
#region Fields #region Fields
private string _connectionString; private string? _connectionString;
private IConfiguration _config; private IConfiguration? _config;
private ILogger<LoginController> _logger; private ILogger<LoginController> _logger;
#endregion #endregion
@@ -41,7 +41,7 @@ public class LoginController : ControllerBase
[HttpPost] [HttpPost]
public IActionResult Login([FromBody] User user) public IActionResult Login([FromBody] User user)
{ {
var context = new UserContext(_connectionString); var context = new UserContext(_connectionString!);
_logger.LogInformation("Starting process of validating credentials"); _logger.LogInformation("Starting process of validating credentials");
@@ -55,12 +55,12 @@ public class LoginController : ControllerBase
try 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 validatePass = new PasswordEncryption();
var validated = validatePass.VerifyPassword(user, password); var validated = validatePass.VerifyPassword(user!, password!);
if (!validated) if (!validated)
{ {
loginRes.Message = message; loginRes.Message = message;
@@ -71,9 +71,9 @@ public class LoginController : ControllerBase
_logger.LogInformation("Successfully validated user credentials"); _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); return Ok(loginRes);
} }
@@ -87,7 +87,7 @@ public class LoginController : ControllerBase
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError("An error occurred: {0}", ex.Message); _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); return NotFound(loginRes);
+5 -4
View File
@@ -11,7 +11,7 @@ namespace Icarus.Controllers.V1;
public class RegisterController : ControllerBase public class RegisterController : ControllerBase
{ {
#region Fields #region Fields
private IConfiguration _config; private IConfiguration? _config;
#endregion #endregion
@@ -35,11 +35,12 @@ public class RegisterController : ControllerBase
user.Status = "Registered"; user.Status = "Registered";
user.DateCreated = DateTime.Now; user.DateCreated = DateTime.Now;
UserContext context = null; UserContext? context = null;
try try
{ {
context = new UserContext(_config.GetConnectionString("DefaultConnection")); var connString = _config!.GetConnectionString("DefaultConnection");
context = new UserContext(connString!);
context.Add(user); context.Add(user);
context.SaveChanges(); context.SaveChanges();
} }
@@ -56,7 +57,7 @@ public class RegisterController : ControllerBase
Username = user.Username 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.Message = "Successful registration";
registerResult.SuccessfullyRegistered = true; registerResult.SuccessfullyRegistered = true;
@@ -14,9 +14,9 @@ namespace Icarus.Controllers.V1;
public class SongCompressedDataController : BaseController public class SongCompressedDataController : BaseController
{ {
#region Fields #region Fields
private string _connectionString; private string? _connectionString;
private string _songTempDir; private string? _songTempDir;
private string _archiveDir; private string? _archiveDir;
#endregion #endregion
@@ -39,9 +39,9 @@ public class SongCompressedDataController : BaseController
[HttpGet("{id}")] [HttpGet("{id}")]
public async Task<IActionResult> DownloadCompressedSong(int id, [FromQuery] bool? randomizeFilename) public async Task<IActionResult> 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}"); Console.WriteLine($"Archive directory root: {_archiveDir}");
@@ -49,9 +49,9 @@ public class SongCompressedDataController : BaseController
var sng = context.RetrieveRecord(new Song{ Id = id }); var sng = context.RetrieveRecord(new Song{ Id = id });
SongData song = await cmp.RetrieveCompressedSong(sng); 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 #endregion
} }
+9 -9
View File
@@ -13,9 +13,9 @@ namespace Icarus.Controllers.V1;
public class SongController : BaseController public class SongController : BaseController
{ {
#region Fields #region Fields
private readonly ILogger<SongController> _logger; private readonly ILogger<SongController>? _logger;
private string _connectionString; private string? _connectionString;
private SongManager _songMgr; private SongManager? _songMgr;
#endregion #endregion
@@ -40,11 +40,11 @@ public class SongController : BaseController
public IActionResult GetSongs() public IActionResult GetSongs()
{ {
Console.WriteLine("Attemtping to retrieve songs"); 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) if (songs.Count > 0)
{ {
@@ -59,7 +59,7 @@ public class SongController : BaseController
[HttpGet("{id}")] [HttpGet("{id}")]
public IActionResult GetSong(int id) public IActionResult GetSong(int id)
{ {
var context = new SongContext(_connectionString); var context = new SongContext(_connectionString!);
var song = context.RetrieveRecord(new Song{ Id = id }); var song = context.RetrieveRecord(new Song{ Id = id });
@@ -76,9 +76,9 @@ public class SongController : BaseController
{ {
song.Id = id; song.Id = id;
Console.WriteLine("Retrieving filepath of song"); 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 return NotFound(new SongResult
{ {
+77 -32
View File
@@ -13,10 +13,10 @@ namespace Icarus.Controllers.V1;
public class SongDataController : BaseController public class SongDataController : BaseController
{ {
#region Fields #region Fields
private string _connectionString; private string? _connectionString;
private ILogger<SongDataController> _logger; private ILogger<SongDataController>? _logger;
private SongManager _songMgr; private SongManager? _songMgr;
private string _songTempDir; private string? _songTempDir;
#endregion #endregion
@@ -31,7 +31,7 @@ public class SongDataController : BaseController
_connectionString = _config.GetConnectionString("DefaultConnection"); _connectionString = _config.GetConnectionString("DefaultConnection");
_logger = logger; _logger = logger;
_songTempDir = _config.GetValue<string>("TemporaryMusicPath"); _songTempDir = _config.GetValue<string>("TemporaryMusicPath");
_songMgr = new SongManager(config, _songTempDir); _songMgr = new SongManager(config, _songTempDir!);
} }
#endregion #endregion
@@ -39,13 +39,29 @@ public class SongDataController : BaseController
[HttpGet("download/{id}")] [HttpGet("download/{id}")]
public IActionResult Download(int id, [FromQuery] bool? randomizeFilename) 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 songMetaData = songContext.RetrieveRecord(new Song { Id = id});
var song = _songMgr.RetrieveSong(songMetaData).Result; var song = _songMgr!.RetrieveSong(songMetaData).Result;
var filename = DirectoryManager.GenerateDownloadFilename(10, Constants.FileExtensions.WAV_EXTENSION, songMetaData.Title, randomizeFilename); 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 // Assumes that the song already has metadata such as
@@ -65,20 +81,17 @@ public class SongDataController : BaseController
{ {
try try
{ {
// Console.WriteLine("Uploading song..."); _logger!.LogInformation("Uploading song...");
_logger.LogInformation("Uploading song...");
var uploads = _songTempDir; 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) foreach (var sng in songData)
if (sng.Length > 0) 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(); return Ok();
@@ -86,7 +99,7 @@ public class SongDataController : BaseController
catch (Exception ex) catch (Exception ex)
{ {
var msg = ex.Message; var msg = ex.Message;
_logger.LogError(msg, "An error occurred"); _logger!.LogError(msg, "An error occurred");
} }
return NotFound(); return NotFound();
@@ -101,35 +114,67 @@ public class SongDataController : BaseController
{ {
try 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<Song>(up.SongFile); var song = Newtonsoft.Json.JsonConvert.DeserializeObject<Song>(up.SongFile);
var tokMgr = new TokenManager(this._config); var tokMgr = new TokenManager(this._config!);
var accessToken = Request.Headers["Authorization"]; var accessToken = Request.Headers["Authorization"];
var userId = tokMgr.RetrieveUserIdFromToken(accessToken); var userId = tokMgr.RetrieveUserIdFromToken(accessToken!);
if (userId != -1) 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) catch (Exception ex)
{ {
_logger.LogError(ex.Message, "An error occurred"); _logger!.LogError(ex.Message, "An error occurred");
} }
return Ok(); return BadRequest();
} }
[HttpDelete("delete/{id}")] [HttpDelete("delete/{id}")]
public IActionResult DeleteSong(int id) public IActionResult DeleteSong(int id)
{ {
var songContext = new SongContext(_connectionString); var songContext = new SongContext(_connectionString!);
var songMetaData = new Song{ Id = id }; var songMetaData = new Song{ Id = id };
Console.WriteLine($"Id {songMetaData.Id}"); Console.WriteLine($"Id {songMetaData.Id}");
@@ -138,14 +183,14 @@ public class SongDataController : BaseController
if (string.IsNullOrEmpty(songMetaData.Title)) if (string.IsNullOrEmpty(songMetaData.Title))
{ {
_logger.LogInformation("Song does not exist"); _logger!.LogInformation("Song does not exist");
return NotFound("Song does not exist"); return NotFound("Song does not exist");
} }
else 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); return Ok(songMetaData);
} }
@@ -155,11 +200,11 @@ public class SongDataController : BaseController
public class UploadSongWithDataForm public class UploadSongWithDataForm
{ {
[FromForm(Name = "file")] [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 // NOTE: Think about making this optional and if it is not provided, use the stock cover art
[FromForm(Name = "cover")] [FromForm(Name = "cover")]
public IFormFile CoverArtData { get; set; } public IFormFile? CoverArtData { get; set; }
[FromForm(Name = "metadata")] [FromForm(Name = "metadata")]
public string SongFile { get; set; } public string? SongFile { get; set; }
} }
} }
+5 -5
View File
@@ -11,7 +11,7 @@ namespace Icarus.Controllers.V1;
public class SongStreamController : BaseController public class SongStreamController : BaseController
{ {
#region Fields #region Fields
private ILogger<SongStreamController> _logger; private ILogger<SongStreamController>? _logger;
#endregion #endregion
@@ -32,11 +32,11 @@ public class SongStreamController : BaseController
[HttpGet("{id}")] [HttpGet("{id}")]
public async Task<IActionResult> StreamSong(int id) public async Task<IActionResult> 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; stream.Position = 0;
var filename = song.Filename; var filename = song.Filename;
@@ -45,7 +45,7 @@ public class SongStreamController : BaseController
filename = song.GenerateFilename(); filename = song.GenerateFilename();
} }
_logger.LogInformation("Starting to stream song...>"); _logger!.LogInformation("Starting to stream song...>");
Console.WriteLine("Starting to streamsong..."); Console.WriteLine("Starting to streamsong...");
return await Task.Run(() => { return await Task.Run(() => {
+4 -3
View File
@@ -6,7 +6,7 @@ namespace Icarus.Database.Contexts;
public class AlbumContext : DbContext public class AlbumContext : DbContext
{ {
public DbSet<Album> Albums { get; set; } public DbSet<Album>? Albums { get; set; }
public AlbumContext(DbContextOptions<AlbumContext> options) : base(options) { } public AlbumContext(DbContextOptions<AlbumContext> options) : base(options) { }
public AlbumContext(string connString) : base(new DbContextOptionsBuilder<AlbumContext>() public AlbumContext(string connString) : base(new DbContextOptionsBuilder<AlbumContext>()
@@ -22,11 +22,12 @@ public class AlbumContext : DbContext
public Album RetrieveRecord(Album album) 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) 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;
} }
} }
+1 -1
View File
@@ -23,7 +23,7 @@ public class ArtistContext : DbContext
public Artist RetrieveRecord(Artist artist) public Artist RetrieveRecord(Artist artist)
{ {
return Artists.FirstOrDefault(arst => arst.Id == artist.Id); return Artists.FirstOrDefault(arst => arst.Id == artist.Id)!;
} }
+5 -3
View File
@@ -6,7 +6,9 @@ namespace Icarus.Database.Contexts;
public class CoverArtContext : DbContext public class CoverArtContext : DbContext
{ {
public DbSet<CoverArt> CoverArtImages { get; set; } #region Properties
public DbSet<CoverArt>? CoverArtImages { get; set; }
#endregion
public CoverArtContext(DbContextOptions<CoverArtContext> options) : base(options) { } public CoverArtContext(DbContextOptions<CoverArtContext> options) : base(options) { }
public CoverArtContext(string connString) : base(new DbContextOptionsBuilder<CoverArtContext>() public CoverArtContext(string connString) : base(new DbContextOptionsBuilder<CoverArtContext>()
@@ -22,11 +24,11 @@ public class CoverArtContext : DbContext
public CoverArt RetrieveRecord(CoverArt cover) 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) 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;
} }
} }
+7 -3
View File
@@ -6,7 +6,10 @@ namespace Icarus.Database.Contexts;
public class GenreContext : DbContext public class GenreContext : DbContext
{ {
public DbSet<Genre> Genres { get; set; } #region Properties
public DbSet<Genre>? Genres { get; set; }
#endregion
public GenreContext(DbContextOptions<GenreContext> options) : base(options) { } public GenreContext(DbContextOptions<GenreContext> options) : base(options) { }
public GenreContext(string connString) : base(new DbContextOptionsBuilder<GenreContext>() public GenreContext(string connString) : base(new DbContextOptionsBuilder<GenreContext>()
.UseMySQL(connString).Options) .UseMySQL(connString).Options)
@@ -22,11 +25,12 @@ public class GenreContext : DbContext
public Genre RetrieveRecord(Genre genre) 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) 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;
} }
} }
+4 -3
View File
@@ -6,7 +6,7 @@ namespace Icarus.Database.Contexts;
public class SongContext : DbContext public class SongContext : DbContext
{ {
public DbSet<Song> Songs { get; set; } public DbSet<Song>? Songs { get; set; }
public SongContext(string connString) : base(new DbContextOptionsBuilder<SongContext>() public SongContext(string connString) : base(new DbContextOptionsBuilder<SongContext>()
.UseMySQL(connString).Options) .UseMySQL(connString).Options)
@@ -41,12 +41,13 @@ public class SongContext : DbContext
public Song RetrieveRecord(Song song) 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) 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;
} }
} }
+1 -1
View File
@@ -32,7 +32,7 @@ public class UserContext : DbContext
public User RetrieveRecord(User user) 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) public bool DoesRecordExist(User user)
+2 -2
View File
@@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel> <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<Version>0.1.10</Version> <Version>0.1.10</Version>
</PropertyGroup> </PropertyGroup>
@@ -10,10 +11,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.2" /> <PackageReference Include="BCrypt.Net-Next" Version="4.0.2" />
<PackageReference Include="BouncyCastle.Cryptography" Version="2.4.0" /> <PackageReference Include="BouncyCastle.Cryptography" Version="2.4.0" />
<PackageReference Include="DotNetZip" Version="1.15.0" />
<PackageReference Include="EntityFramework" Version="6.4.4" /> <PackageReference Include="EntityFramework" Version="6.4.4" />
<PackageReference Include="File.TypeChecker" Version="4.1.1" /> <PackageReference Include="File.TypeChecker" Version="4.1.1" />
<PackageReference Include="ID3" Version="0.6.0" /> <PackageReference Include="Iconic.Zlib.Netstandard" Version="1.0.0" />
<PackageReference Include="JWT" Version="10.1.1" /> <PackageReference Include="JWT" Version="10.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.6" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.6" />
+4 -2
View File
@@ -6,16 +6,18 @@ namespace Icarus.Models;
public class Album public class Album
{ {
#region Properties
[JsonProperty("id")] [JsonProperty("id")]
public int Id { get; set; } public int Id { get; set; }
[JsonProperty("title")] [JsonProperty("title")]
public string Title { get; set; } public string? Title { get; set; }
[JsonProperty("album_artist")] [JsonProperty("album_artist")]
[Column("Artist")] [Column("Artist")]
public string AlbumArtist { get; set; } public string? AlbumArtist { get; set; }
[JsonProperty("song_count")] [JsonProperty("song_count")]
[NotMapped] [NotMapped]
public int SongCount { get; set; } public int SongCount { get; set; }
[JsonProperty("year")] [JsonProperty("year")]
public int Year { get; set; } public int Year { get; set; }
#endregion
} }
+3 -1
View File
@@ -6,12 +6,14 @@ namespace Icarus.Models;
public class Artist public class Artist
{ {
#region Properties
[JsonProperty("id")] [JsonProperty("id")]
public int Id { get; set; } public int Id { get; set; }
[JsonProperty("name")] [JsonProperty("name")]
[Column("Artist")] [Column("Artist")]
public string Name { get; set; } public string? Name { get; set; }
[JsonProperty("song_count")] [JsonProperty("song_count")]
[NotMapped] [NotMapped]
public int SongCount { get; set; } public int SongCount { get; set; }
#endregion
} }
+1 -1
View File
@@ -5,5 +5,5 @@ namespace Icarus.Models;
public class BaseResult public class BaseResult
{ {
[JsonProperty("message")] [JsonProperty("message")]
public string Message { get; set; } public string? Message { get; set; }
} }
+5 -5
View File
@@ -8,13 +8,13 @@ public class CoverArt
[JsonProperty("id")] [JsonProperty("id")]
public int Id { get; set; } public int Id { get; set; }
[JsonProperty("title")] [JsonProperty("title")]
public string SongTitle { get; set; } public string? SongTitle { get; set; }
[JsonIgnore] [JsonIgnore]
public string Directory { get; set; } public string? Directory { get; set; }
[JsonProperty("filename")] [JsonProperty("filename")]
public string Filename { get; set; } public string? Filename { get; set; }
[JsonProperty("type")] [JsonProperty("type")]
public string Type { get; set; } public string? Type { get; set; }
#endregion #endregion
@@ -23,7 +23,7 @@ public class CoverArt
{ {
var fullPath = this.Directory; var fullPath = this.Directory;
if (fullPath[fullPath.Length -1] != '/') if (fullPath![fullPath.Length -1] != '/')
{ {
fullPath += "/"; fullPath += "/";
} }
+3 -1
View File
@@ -6,12 +6,14 @@ namespace Icarus.Models;
public class Genre public class Genre
{ {
#region Properties
[JsonProperty("id")] [JsonProperty("id")]
public int Id { get; set; } public int Id { get; set; }
[JsonProperty("genre")] [JsonProperty("genre")]
[Column("Category")] [Column("Category")]
public string GenreName { get; set; } public string? GenreName { get; set; }
[JsonProperty("song_count")] [JsonProperty("song_count")]
[NotMapped] [NotMapped]
public int SongCount { get; set; } public int SongCount { get; set; }
#endregion
} }
+5 -3
View File
@@ -4,14 +4,16 @@ namespace Icarus.Models;
public class LoginResult : BaseResult public class LoginResult : BaseResult
{ {
#region Properties
[JsonProperty("user_id")] [JsonProperty("user_id")]
public int UserId { get; set; } public int UserId { get; set; }
[JsonProperty("username")] [JsonProperty("username")]
public string Username { get; set; } public string? Username { get; set; }
[JsonProperty("token")] [JsonProperty("token")]
public string Token { get; set; } public string? Token { get; set; }
[JsonProperty("token_type")] [JsonProperty("token_type")]
public string TokenType { get; set; } public string? TokenType { get; set; }
[JsonProperty("expiration")] [JsonProperty("expiration")]
public int Expiration { get; set; } public int Expiration { get; set; }
#endregion
} }
+3 -1
View File
@@ -4,8 +4,10 @@ namespace Icarus.Models;
public class RegisterResult : BaseResult public class RegisterResult : BaseResult
{ {
#region Properties
[JsonProperty("username")] [JsonProperty("username")]
public string Username { get; set; } public string? Username { get; set; }
[JsonProperty("successfully_registered")] [JsonProperty("successfully_registered")]
public bool SuccessfullyRegistered { get; set; } public bool SuccessfullyRegistered { get; set; }
#endregion
} }
+56 -14
View File
@@ -10,24 +10,26 @@ public class Song
[JsonProperty("id")] [JsonProperty("id")]
public int Id { get; set; } public int Id { get; set; }
[JsonProperty("title")] [JsonProperty("title")]
public string Title { get; set; } public string? Title { get; set; }
[JsonProperty("album")] [JsonProperty("album")]
[Column("Album")] [Column("Album")]
public string AlbumTitle { get; set; } public string? AlbumTitle { get; set; }
[JsonProperty("artist")] [JsonProperty("artist")]
public string Artist { get; set; } public string? Artist { get; set; }
[JsonProperty("album_artist")] [JsonProperty("album_artist")]
public string AlbumArtist { get; set; } public string? AlbumArtist { get; set; }
[JsonProperty("year")] [JsonProperty("year")]
public int? Year { get; set; } public int? Year { get; set; }
[JsonProperty("genre")] [JsonProperty("genre")]
public string Genre { get; set; } public string? Genre { get; set; }
[JsonProperty("duration")] [JsonProperty("duration")]
public int Duration { get; set; } public int Duration { get; set; }
[JsonProperty("filename")] [JsonProperty("filename")]
public string Filename { get; set; } public string? Filename { get; set; }
[JsonIgnore] [JsonIgnore]
public string SongDirectory { get; set; } public string? SongDirectory { get; set; }
[JsonProperty("audio_type")]
public string? AudioType { get; set; }
[JsonProperty("track")] [JsonProperty("track")]
public int Track { get; set; } = 0; public int Track { get; set; } = 0;
[JsonProperty("track_count")] [JsonProperty("track_count")]
@@ -56,11 +58,29 @@ public class Song
#region Methods #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() public string SongPath()
{ {
var fullPath = SongDirectory; var fullPath = SongDirectory;
if (fullPath[fullPath.Length -1] != '/') if (fullPath![fullPath.Length -1] != '/')
{ {
fullPath += "/"; fullPath += "/";
} }
@@ -70,26 +90,41 @@ public class Song
return fullPath; return fullPath;
} }
public string GenerateFilename(int flag = 0) public string GenerateFilename(bool includeExtension = false, AudioFileExtensionsType flag = AudioFileExtensionsType.Default)
{ {
int length = Constants.DirectoryPaths.FILENAME_LENGTH; int length = Constants.DirectoryPaths.FILENAME_LENGTH;
string chars = Constants.DirectoryPaths.FILENAME_CHARACTERS; string chars = Constants.DirectoryPaths.FILENAME_CHARACTERS;
var filename = this.Generate(length, chars); 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<string> GenerateFilenameAsync(int flag = 0) public async Task<string> GenerateFilenameAsync(bool includeExtension = false, AudioFileExtensionsType flag = AudioFileExtensionsType.Default)
{ {
int length = Constants.DirectoryPaths.FILENAME_LENGTH; int length = Constants.DirectoryPaths.FILENAME_LENGTH;
string chars = Constants.DirectoryPaths.FILENAME_CHARACTERS; string chars = Constants.DirectoryPaths.FILENAME_CHARACTERS;
var extension = Icarus.Constants.FileExtensions.WAV_EXTENSION; var extension = this.DetermineFileExtension(flag);
var filename = await Task.Run(() => var filename = await Task.Run(() =>
{ {
return this.Generate(length, chars); 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) private string Generate(int length, string chars)
@@ -101,3 +136,10 @@ public class Song
} }
#endregion #endregion
} }
public enum AudioFileExtensionsType
{
Default = 0,
WAV = 1,
FLAC = 2
}
+3 -1
View File
@@ -2,7 +2,9 @@ namespace Icarus.Models;
public class SongData public class SongData
{ {
#region Properties
public int ID { get; set; } public int ID { get; set; }
public byte[] Data { get; set; } public byte[]? Data { get; set; }
public int SongID { get; set; } public int SongID { get; set; }
#endregion
} }
+4 -2
View File
@@ -4,8 +4,10 @@ namespace Icarus.Models;
public class SongResult public class SongResult
{ {
#region Properties
[JsonProperty("message")] [JsonProperty("message")]
public string Message { get; set; } public string? Message { get; set; }
[JsonProperty("song_title")] [JsonProperty("song_title")]
public string SongTitle { get; set; } public string? SongTitle { get; set; }
#endregion
} }
+6 -14
View File
@@ -1,6 +1,3 @@
using System;
using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -10,13 +7,13 @@ public class Token
{ {
#region Properties #region Properties
[JsonProperty("scope")] [JsonProperty("scope")]
public string Scope { get; set; } public string? Scope { get; set; }
[JsonProperty("exp")] [JsonProperty("exp")]
public int Expiration { get; set; } public int Expiration { get; set; }
[JsonProperty("aud")] [JsonProperty("aud")]
public string Audience { get; set; } public string? Audience { get; set; }
[JsonProperty("iss")] [JsonProperty("iss")]
public string Issuer { get; set; } public string? Issuer { get; set; }
[JsonProperty("iat")] [JsonProperty("iat")]
public int Issued { get; set; } public int Issued { get; set; }
#endregion #endregion
@@ -24,29 +21,24 @@ public class Token
#region Methods #region Methods
public bool TokenExpired() public bool TokenExpired()
{ {
var result = false;
var currentDate = DateTime.Now; var currentDate = DateTime.Now;
var currentDateInSeconds = Math.Floor((currentDate - DateTime.UnixEpoch).TotalSeconds); var currentDateInSeconds = Math.Floor((currentDate - DateTime.UnixEpoch).TotalSeconds);
var result = (currentDateInSeconds >= Expiration) ? true : false;
result = (currentDateInSeconds >= Expiration) ? true : false;
return result; return result;
} }
public bool ContainsScope(string desiredScope) public bool ContainsScope(string desiredScope)
{ {
var result = false; var result = Scope!.Contains(desiredScope);
result = Scope.Contains(desiredScope);
return result; return result;
} }
public bool Erroneous() public bool Erroneous()
{ {
var result = true;
Func<string, bool> isEmpty = a => string.IsNullOrEmpty(a); Func<string, bool> 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; Expiration > 0 && Issued > 0) ? false : true;
return result; return result;
+10 -10
View File
@@ -14,39 +14,39 @@ public class User
[Key] [Key]
public int Id { get; set; } public int Id { get; set; }
[JsonProperty("username")] [JsonProperty("username")]
public string Username { get; set; } public string? Username { get; set; }
[JsonProperty("password")] [JsonProperty("password")]
public string Password { get; set; } public string? Password { get; set; }
[JsonProperty("email")] [JsonProperty("email")]
public string Email { get; set; } public string? Email { get; set; }
[JsonProperty("phone")] [JsonProperty("phone")]
[Column("Phone")] [Column("Phone")]
public string Phone { get; set; } public string? Phone { get; set; }
[JsonProperty("firstname")] [JsonProperty("firstname")]
public string Firstname { get; set; } public string? Firstname { get; set; }
[JsonProperty("lastname")] [JsonProperty("lastname")]
public string Lastname { get; set; } public string? Lastname { get; set; }
[JsonProperty("email_verified")] [JsonProperty("email_verified")]
[NotMapped] [NotMapped]
public bool EmailVerified { get; set; } public bool EmailVerified { get; set; }
[JsonProperty("date_created")] [JsonProperty("date_created")]
public DateTime DateCreated { get; set; } public DateTime DateCreated { get; set; }
[JsonProperty("status")] [JsonProperty("status")]
public string Status { get; set; } public string? Status { get; set; }
[JsonProperty("last_login")] [JsonProperty("last_login")]
public DateTime? LastLogin { get; set; } public DateTime? LastLogin { get; set; }
[JsonIgnore] [JsonIgnore]
[NotMapped] [NotMapped]
public System.Collections.Generic.IEnumerable<string> Roles { get; set; } public System.Collections.Generic.IEnumerable<string>? Roles { get; set; }
#endregion #endregion
#region Methods #region Methods
public System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> Claims() public System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> Claims()
{ {
var claims = new System.Collections.Generic.List<System.Security.Claims.Claim> { new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, Username) }; var claims = new System.Collections.Generic.List<System.Security.Claims.Claim> { 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))); claims.AddRange(Roles!.Select(role => new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, role)));
return claims; return claims;
} }
+7 -7
View File
@@ -64,16 +64,16 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJw
ValidateLifetime = true, ValidateLifetime = true,
ValidAudience = Configuration["JWT:Audience"], ValidAudience = Configuration["JWT:Audience"],
ValidIssuer = Configuration["JWT:Issuer"], 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<SongContext>(options => options.UseMySQL(connString)); builder.Services.AddDbContext<SongContext>(options => options.UseMySQL(connString!));
builder.Services.AddDbContext<AlbumContext>(options => options.UseMySQL(connString)); builder.Services.AddDbContext<AlbumContext>(options => options.UseMySQL(connString!));
builder.Services.AddDbContext<ArtistContext>(options => options.UseMySQL(connString)); builder.Services.AddDbContext<ArtistContext>(options => options.UseMySQL(connString!));
builder.Services.AddDbContext<UserContext>(options => options.UseMySQL(connString)); builder.Services.AddDbContext<UserContext>(options => options.UseMySQL(connString!));
builder.Services.AddDbContext<GenreContext>(options => options.UseMySQL(connString)); builder.Services.AddDbContext<GenreContext>(options => options.UseMySQL(connString!));
builder.Services.AddDbContext<CoverArtContext>(options => options.UseMySQL(connString)); builder.Services.AddDbContext<CoverArtContext>(options => options.UseMySQL(connString!));
builder.Services.AddControllers() builder.Services.AddControllers()
.AddNewtonsoftJson(); .AddNewtonsoftJson();
+3 -4
View File
@@ -16,8 +16,7 @@ One can interface with Icarus the music server either by:
* [MySql](https://www.nuget.org/packages/MySql.Data/) * [MySql](https://www.nuget.org/packages/MySql.Data/)
* OpenSSL * OpenSSL
* BCrypt.Net-Next * BCrypt.Net-Next
* DotNetZip * Iconic.Zlib.Netstandard
* ID3
* JWT * JWT
* Microsoft.AspNetCore.Authentication.JwtBearer * Microsoft.AspNetCore.Authentication.JwtBearer
* Microsoft.AspNetCore.Mvc.NewtonsoftJson * 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: Or you can manually add the migrations like so for each migration:
```shell ```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<sup>*</sup>: Then update the migrations to the database like so<sup>*</sup>:
```shell ```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. All of the contexts can be found in Database/Contexts folder.
+13 -12
View File
@@ -1,28 +1,29 @@
echo "Adding migrations..." echo "Adding migrations..."
echo "Adding User migration" 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" 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" 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" 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" 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" 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 migrations.."
echo "Updating User migration" echo "Updating User migration"
~/.dotnet/tools/dotnet-ef database update --context UserContext dotnet dotnet-ef database update --context UserContext
echo "Updating Album migration" echo "Updating Album migration"
~/.dotnet/tools/dotnet-ef database update --context AlbumContext dotnet dotnet-ef database update --context AlbumContext
echo "Updating Artist migration" echo "Updating Artist migration"
~/.dotnet/tools/dotnet-ef database update --context ArtistContext dotnet dotnet-ef database update --context ArtistContext
echo "Updating Genre migration" echo "Updating Genre migration"
~/.dotnet/tools/dotnet-ef database update --context GenreContext dotnet dotnet-ef database update --context GenreContext
echo "Updating Cover art migration" echo "Updating Cover art migration"
~/.dotnet/tools/dotnet-ef database update --context CoverArtContext dotnet dotnet-ef database update --context CoverArtContext
echo "Updating Song migration" echo "Updating Song migration"
~/.dotnet/tools/dotnet-ef database update --context SongContext dotnet dotnet-ef database update --context SongContext
@@ -0,0 +1,3 @@
drop database Icarus;
create database Icarus;
+137
View File
@@ -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