Merge pull request #60 from kdeng00/experiment
Switching to C++
This commit was merged in pull request #60.
This commit is contained in:
+16
-1
@@ -1,3 +1,18 @@
|
||||
[submodule "Libs/cpr"]
|
||||
path = Libs/cpr
|
||||
path = 3rdparty/cpr
|
||||
url = https://github.com/whoshuu/cpr.git
|
||||
[submodule "3rdparty/taglib"]
|
||||
path = 3rdparty/taglib
|
||||
url = https://github.com/taglib/taglib
|
||||
[submodule "3rdparty/oatpp"]
|
||||
path = 3rdparty/oatpp
|
||||
url = https://github.com/oatpp/oatpp
|
||||
[submodule "build/3rdparty/jwt-cpp"]
|
||||
path = build/3rdparty/jwt-cpp
|
||||
url = https://github.com/Thalhammer/jwt-cpp
|
||||
[submodule "3rdparty/jwt-cpp"]
|
||||
path = 3rdparty/jwt-cpp
|
||||
url = https://github.com/Thalhammer/jwt-cpp
|
||||
[submodule "3rdparty/ormpp"]
|
||||
path = 3rdparty/ormpp
|
||||
url = https://github.com/qicosmos/ormpp
|
||||
|
||||
Vendored
+1
Submodule 3rdparty/jwt-cpp added at 27f32983fb
+1
Submodule 3rdparty/oatpp added at 215642129d
+1
Submodule 3rdparty/taglib added at 79bc9ccf8e
@@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
using Icarus.Authorization;
|
||||
|
||||
namespace Icarus.Authorization.Handlers
|
||||
{
|
||||
public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
|
||||
{
|
||||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement)
|
||||
{
|
||||
if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var scopes = context.User.FindFirst(c =>
|
||||
c.Type == "scope" && c.Issuer == requirement.Issuer).Value.Split(' ');
|
||||
|
||||
if (scopes.Any(s => s == requirement.Scope))
|
||||
{
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Icarus.Authorization
|
||||
{
|
||||
public class HasScopeRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public string Issuer { get; }
|
||||
public string Scope { get; }
|
||||
|
||||
|
||||
public HasScopeRequirement(string scope, string issuer)
|
||||
{
|
||||
Scope = scope ?? throw new ArgumentNullException(nameof(scope));
|
||||
Issuer = issuer ?? throw new ArgumentNullException(nameof(issuer));
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(icarus)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set(SOURCES
|
||||
src/database/albumRepository.cpp
|
||||
src/database/artistRepository.cpp
|
||||
src/database/base_repository.cpp
|
||||
src/database/coverArtRepository.cpp
|
||||
src/database/genreRepository.cpp
|
||||
src/database/songRepository.cpp
|
||||
src/database/yearRepository.cpp
|
||||
src/main.cpp
|
||||
src/managers/albumManager.cpp
|
||||
src/managers/artistManager.cpp
|
||||
src/managers/coverArtManager.cpp
|
||||
src/managers/directory_manager.cpp
|
||||
src/managers/genreManager.cpp
|
||||
src/managers/song_manager.cpp
|
||||
src/managers/token_manager.cpp
|
||||
src/managers/yearManager.cpp
|
||||
src/utilities/imageFile.cpp
|
||||
src/utilities/metadata_retriever.cpp
|
||||
)
|
||||
set(HEADERS
|
||||
include/component/appComponent.hpp
|
||||
include/controller/loginController.hpp
|
||||
include/controller/songController.hpp
|
||||
include/database/albumRepository.h
|
||||
include/database/artistRepository.h
|
||||
include/database/base_repository.h
|
||||
include/database/coverArtRepository.h
|
||||
include/database/genreRepository.h
|
||||
include/database/songRepository.h
|
||||
include/database/yearRepository.h
|
||||
include/dto/loginResultDto.hpp
|
||||
include/dto/songDto.hpp
|
||||
include/managers/albumManager.h
|
||||
include/managers/artistManager.h
|
||||
include/managers/coverArtManager.h
|
||||
include/managers/directory_manager.h
|
||||
include/managers/genreManager.h
|
||||
include/managers/song_manager.h
|
||||
include/managers/token_manager.h
|
||||
include/managers/yearManager.h
|
||||
include/models/models.h
|
||||
include/utilities/imageFile.h
|
||||
include/utilities/metadata_retriever.h
|
||||
include/types/albumFilter.h
|
||||
include/types/artistFilter.h
|
||||
include/types/coverFilter.h
|
||||
include/types/genreFilter.h
|
||||
include/types/scopes.h
|
||||
include/types/songFilter.h
|
||||
include/types/yearFilter.h
|
||||
)
|
||||
|
||||
set (TAGLIB
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/taglib/3rdparty
|
||||
)
|
||||
|
||||
set(TAGLIB_HEADERS
|
||||
"${CMAKE_SOURCE_DIR}/build/3rdparty/taglib"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/ape"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/asf"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/dsdiff"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/dsf"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/flac"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/it"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mod"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mp4"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mpc"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mpeg"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mpeg/id3v2"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mpeg/id3v2/frames"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/ogg"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/riff"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/s3m"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/toolkit"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/trueaudio"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/wavpack"
|
||||
"${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/xm"
|
||||
)
|
||||
|
||||
set(JWT_CPP_INCLUDE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/jwt-cpp/include
|
||||
)
|
||||
|
||||
set (ORM_DIR
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/ormpp
|
||||
)
|
||||
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup()
|
||||
|
||||
include_directories(include ${CPR_INCLUDE_DIRS} ${TAGLIB} ${TAGLIB_HEADERS})
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/cpr)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/taglib)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/oatpp)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/appsettings.json ${CMAKE_BINARY_DIR}/bin/appsettings.json COPYONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/authcredentials.json ${CMAKE_BINARY_DIR}/bin/authcredentials.json COPYONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/database.json ${CMAKE_BINARY_DIR}/bin/database.json COPYONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/paths.json ${CMAKE_BINARY_DIR}/bin/paths.json COPYONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Images/Stock/CoverArt.png ${CMAKE_BINARY_DIR}/bin/CoverArt.png COPYONLY)
|
||||
|
||||
add_executable(icarus ${SOURCES} ${HEADERS})
|
||||
target_include_directories(icarus PUBLIC ${JWT_CPP_INCLUDE})
|
||||
target_link_libraries(icarus "-lstdc++fs" tag oatpp mysqlclient ${CONAN_LIBS} ${CPR_LIBRARIES})
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Icarus.Constants
|
||||
{
|
||||
public class DirectoryPaths
|
||||
{
|
||||
public static string CoverArtPath =>
|
||||
Directory.GetCurrentDirectory() + "/Images/Stock/CoverArt.png";
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
|
||||
using NLog;
|
||||
|
||||
namespace Icarus.Controllers.Managers
|
||||
{
|
||||
public class BaseManager
|
||||
{
|
||||
#region Fields
|
||||
protected static Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using Icarus.Constants;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Models;
|
||||
using Icarus.Types;
|
||||
|
||||
namespace Icarus.Controllers.Managers
|
||||
{
|
||||
public class CoverArtManager : BaseManager
|
||||
{
|
||||
#region Fields
|
||||
private string _rootCoverArtPath;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public CoverArtManager(string rootPath)
|
||||
{
|
||||
_rootCoverArtPath = rootPath;
|
||||
Initialize();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public void SaveCoverArtToDatabase(ref Song song, ref CoverArt coverArt,
|
||||
CoverArtRepository coverArtRepository)
|
||||
{
|
||||
_logger.Info("Saving cover art record to the database");
|
||||
coverArtRepository.SaveCoverArt(coverArt);
|
||||
|
||||
coverArt = coverArtRepository.GetCoverArt(CoverArtField.SongTitle,
|
||||
coverArt);
|
||||
|
||||
song.CoverArtId = coverArt.CoverArtId;
|
||||
_logger.Info("Cover art Process saving complete");
|
||||
}
|
||||
public void DeleteCoverArtFromDatabase(CoverArt coverArt,
|
||||
CoverArtRepository coverArtRepository)
|
||||
{
|
||||
_logger.Info("Attempting to delete cover art from the database");
|
||||
coverArtRepository.DeleteCoverArt(coverArt);
|
||||
}
|
||||
public void DeleteCoverArt(CoverArt coverArt)
|
||||
{
|
||||
var stockCoverArtPath = _rootCoverArtPath + "CoverArtPath.png";
|
||||
DirectoryManager.delete_cover_art(coverArt.ImagePath, stockCoverArtPath);
|
||||
}
|
||||
|
||||
public CoverArt SaveCoverArt(Song song)
|
||||
{
|
||||
var sng = SongManager.ConvertSongToSng(song);
|
||||
|
||||
var cov = ConvertCoverArtToCovArt(new CoverArt
|
||||
{
|
||||
SongTitle = song.Title,
|
||||
ImagePath = _rootCoverArtPath
|
||||
});
|
||||
|
||||
MetadataRetriever.update_cover_art(ref cov,
|
||||
ref sng, _rootCoverArtPath);
|
||||
|
||||
return ConvertCovArtToCoverArt(cov);
|
||||
}
|
||||
|
||||
public static CovArt ConvertCoverArtToCovArt(CoverArt cover)
|
||||
{
|
||||
return new CovArt
|
||||
{
|
||||
SongTitle = cover.SongTitle,
|
||||
ImagePath = cover.ImagePath
|
||||
};
|
||||
}
|
||||
public static CoverArt ConvertCovArtToCoverArt(CovArt cov)
|
||||
{
|
||||
return new CoverArt
|
||||
{
|
||||
SongTitle = cov.SongTitle,
|
||||
ImagePath = cov.ImagePath
|
||||
};
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
var stockCover = _rootCoverArtPath + "CoverArt.png";
|
||||
DirectoryManager.copy_stock_cover_art(stockCover,
|
||||
DirectoryPaths.CoverArtPath);
|
||||
}
|
||||
#region Testing
|
||||
private void PrintCoverArtDetails(CoverArt cover)
|
||||
{
|
||||
Console.WriteLine("\nCover art");
|
||||
Console.WriteLine($"Song Title: {cover.SongTitle}");
|
||||
Console.WriteLine($"ImagePath: {cover.ImagePath}\n");
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Types;
|
||||
|
||||
namespace Icarus.Controllers.Managers
|
||||
{
|
||||
public class DirectoryManager : BaseManager
|
||||
{
|
||||
#region Methods
|
||||
#region C++ libs
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern void create_directory(Sng song, string root_path, StringBuilder created_dir);
|
||||
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern void copy_stock_cover_art(string target_path, string source_path);
|
||||
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern void copy_song(string target_path, string source_path);
|
||||
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern void delete_cover_art(string cover_art_path, string stock_path);
|
||||
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern void delete_empty_directories(Sng song, string root_path);
|
||||
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern void delete_from_filesystem(Sng song);
|
||||
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern void delete_song_empty_directories(Sng song, string root_path);
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,753 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Contexts;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controllers.Managers
|
||||
{
|
||||
public class SongManager : BaseManager
|
||||
{
|
||||
#region Fields
|
||||
private Song _song;
|
||||
private IConfiguration _config;
|
||||
private string _tempDirectoryRoot;
|
||||
private string _archiveDirectoryRoot;
|
||||
private string _compressedSongFilename;
|
||||
private string _message;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
public Song SongDetails
|
||||
{
|
||||
get => _song;
|
||||
set => _song = value;
|
||||
}
|
||||
|
||||
public string ArchiveDirectoryRoot
|
||||
{
|
||||
get => _archiveDirectoryRoot;
|
||||
set => _archiveDirectoryRoot = value;
|
||||
}
|
||||
public string CompressedSongFilename
|
||||
{
|
||||
get => _compressedSongFilename;
|
||||
set => _compressedSongFilename = value;
|
||||
}
|
||||
public string Message
|
||||
{
|
||||
get => _message;
|
||||
set => _message = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public SongManager()
|
||||
{
|
||||
}
|
||||
public SongManager(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
public SongManager(IConfiguration config, string tempDirectoryRoot)
|
||||
{
|
||||
_config = config;
|
||||
_tempDirectoryRoot = tempDirectoryRoot;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public SongResult UpdateSong(Song song, SongRepository songStore, AlbumRepository albumStore,
|
||||
ArtistRepository artistStore, GenreRepository genreStore, YearRepository yearStore)
|
||||
{
|
||||
var result = new SongResult();
|
||||
|
||||
try
|
||||
{
|
||||
var oldSongRecord = songStore.GetSong(song);
|
||||
song.SongPath = oldSongRecord.SongPath;
|
||||
var oldSng = ConvertSongToSng(oldSongRecord);
|
||||
var updatedSng = ConvertSongToSng(song);
|
||||
|
||||
MetadataRetriever.update_metadata(ref updatedSng, ref oldSng);
|
||||
|
||||
var updatedSong = ConvertSngToSong(updatedSng);
|
||||
|
||||
var updatedAlbum = UpdateAlbumInDatabase(oldSongRecord, updatedSong, albumStore);
|
||||
oldSongRecord.AlbumId = updatedAlbum.AlbumId;
|
||||
|
||||
var updatedArtist = UpdateArtistInDatabase(oldSongRecord, updatedSong, artistStore);
|
||||
oldSongRecord.ArtistId = updatedArtist.ArtistId;
|
||||
|
||||
var updatedGenre = UpdateGenreInDatabase(oldSongRecord, updatedSong, genreStore);
|
||||
oldSongRecord.GenreId = updatedGenre.GenreId;
|
||||
|
||||
var updatedYear = UpdateYearInDatabase(oldSongRecord, updatedSong, yearStore);
|
||||
oldSongRecord.YearId = updatedYear.YearId;
|
||||
|
||||
UpdateSongInDatabase(ref oldSongRecord, ref updatedSong, songStore, ref result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
|
||||
result.Message = $"An error occurred: {msg}";
|
||||
result.SongTitle = song.Title;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public void DeleteSong(Song song, SongRepository songStore,
|
||||
AlbumRepository albumStore, ArtistRepository artistStore,
|
||||
GenreRepository genreStore, YearRepository yearStore,
|
||||
CoverArtRepository coverStore)
|
||||
{
|
||||
try
|
||||
{
|
||||
DirectoryManager.delete_song_empty_directories(
|
||||
ConvertSongToSng(song),
|
||||
_config.GetValue<string>("RootMusicPath"));
|
||||
_logger.Info("Song deleted from the filesystem");
|
||||
|
||||
var coverMgr = new CoverArtManager(_config.GetValue<string>(
|
||||
"CoverArtPath"));
|
||||
var coverArt = coverStore.GetCoverArt(song);
|
||||
coverMgr.DeleteCoverArt(coverArt);
|
||||
|
||||
coverMgr.DeleteCoverArtFromDatabase(coverArt, coverStore);
|
||||
DeleteSongFromDatabase(song, songStore, albumStore, artistStore,
|
||||
genreStore, yearStore);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveSongToFileSystem(IFormFile songFile, SongRepository songStore,
|
||||
AlbumRepository albumStore, ArtistRepository artistStore,
|
||||
GenreRepository genreStore, YearRepository yearStore,
|
||||
CoverArtRepository coverArtStore)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Starting the process of saving the song to the filesystem");
|
||||
|
||||
var song = await SaveSongTemp(songFile,
|
||||
Path.Combine(_tempDirectoryRoot, songFile.FileName));
|
||||
|
||||
var rootPath = _config.GetValue<string>("RootMusicPath");
|
||||
var strCount = rootPath.Length + song.Artist.Length +
|
||||
song.AlbumTitle.Length + 2;
|
||||
|
||||
var filePathSB = new StringBuilder(strCount);
|
||||
|
||||
DirectoryManager.create_directory(ConvertSongToSng(song),
|
||||
rootPath, filePathSB);
|
||||
|
||||
var tmpSongPath = song.SongPath;
|
||||
|
||||
song.SongPath = filePathSB.ToString().Substring(0, strCount);
|
||||
|
||||
if (!songFile.FileName.EndsWith(".mp3"))
|
||||
song.SongPath += $"{songFile.FileName}.mp3";
|
||||
else
|
||||
song.SongPath += $"{songFile.FileName}";
|
||||
|
||||
_logger.Info($"Absolute song path: {song.SongPath}");
|
||||
|
||||
DirectoryManager.copy_song(song.SongPath, tmpSongPath);
|
||||
|
||||
var coverMgr = new CoverArtManager(_config.GetValue<string>("CoverArtPath"));
|
||||
var coverArt = coverMgr.SaveCoverArt(song);
|
||||
|
||||
coverMgr.SaveCoverArtToDatabase(ref song, ref coverArt,
|
||||
coverArtStore);
|
||||
SaveSongToDatabase(song, songStore, albumStore, artistStore, genreStore,
|
||||
yearStore);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SongData> RetrieveSong(Song songMetaData)
|
||||
{
|
||||
SongData song = new SongData();
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Fetching song from filesystem");
|
||||
song = await RetrieveSongFromFileSystem(songMetaData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred: {exMsg}");
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
public static Sng ConvertSongToSng(Song song)
|
||||
{
|
||||
return new Sng
|
||||
{
|
||||
Id = (song.Id == 0) ? 0 : song.Id,
|
||||
Title = (string.IsNullOrEmpty(song.Title)) ? string.Empty :
|
||||
song.Title,
|
||||
Artist = (string.IsNullOrEmpty(song.Artist)) ? string.Empty :
|
||||
song.Artist,
|
||||
Album = (string.IsNullOrEmpty(song.AlbumTitle)) ? string.Empty :
|
||||
song.AlbumTitle,
|
||||
Genre = (string.IsNullOrEmpty(song.Genre)) ? string.Empty :
|
||||
song.Genre,
|
||||
Year = (song.Year == null) ? 0 : song.Year.Value,
|
||||
Duration = song.Duration,
|
||||
SongPath = song.SongPath
|
||||
};
|
||||
}
|
||||
public static Song ConvertSngToSong(Sng song)
|
||||
{
|
||||
return new Song
|
||||
{
|
||||
Id = song.Id,
|
||||
Title = song.Title,
|
||||
Artist = song.Artist,
|
||||
AlbumTitle = song.Album,
|
||||
Genre = song.Genre,
|
||||
Year = (song.Year == 0) ? 0 : song.Year,
|
||||
Duration = song.Duration,
|
||||
SongPath = song.SongPath
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private async Task<SongData> RetrieveSongFromFileSystem(Song details)
|
||||
{
|
||||
return new SongData
|
||||
{
|
||||
Data = await System.IO.File.ReadAllBytesAsync(details.SongPath)
|
||||
};
|
||||
}
|
||||
private async Task<Song> SaveSongTemp(IFormFile songFile, string filePath)
|
||||
{
|
||||
using (var filestream = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
_logger.Info("Saving song to temporary directory");
|
||||
await songFile.CopyToAsync(filestream);
|
||||
}
|
||||
|
||||
var sng = new Sng();
|
||||
MetadataRetriever.retrieve_metadata(ref sng, filePath);
|
||||
var song = ConvertSngToSong(sng);
|
||||
|
||||
_logger.Info("Assigning song filename");
|
||||
song.Filename = songFile.FileName;
|
||||
song.SongPath = filePath;
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
private bool SongRecordChanged(Song currentSong, Song songUpdates)
|
||||
{
|
||||
var currentTitle = currentSong.Title;
|
||||
var currentArtist = currentSong.Artist;
|
||||
var currentAlbum = currentSong.AlbumTitle;
|
||||
var currentGenre = currentSong.Genre;
|
||||
var currentYear = currentSong.Year;
|
||||
|
||||
if (!currentTitle.Equals(songUpdates.Title) || !currentArtist.Equals(songUpdates.Artist) ||
|
||||
!currentAlbum.Equals(songUpdates.AlbumTitle) ||
|
||||
!currentGenre.Equals(songUpdates.Genre) || currentYear != songUpdates.Year)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SaveSongToDatabase(Song song, SongRepository songStore, AlbumRepository albumStore,
|
||||
ArtistRepository artistStore, GenreRepository genreStore, YearRepository yearStore)
|
||||
{
|
||||
_logger.Info("Starting process to save the song to the database");
|
||||
|
||||
SaveAlbumToDatabase(ref song, albumStore);
|
||||
SaveArtistToDatabase(ref song, artistStore);
|
||||
SaveGenreToDatabase(ref song, genreStore);
|
||||
SaveYearToDatabase(ref song, yearStore);
|
||||
|
||||
var info = "Saving Song to DB";
|
||||
Console.WriteLine(info);
|
||||
_logger.Info(info);
|
||||
|
||||
songStore.SaveSong(song);
|
||||
}
|
||||
private void SaveAlbumToDatabase(ref Song song, AlbumRepository albumStore)
|
||||
{
|
||||
_logger.Info("Starting process to save the album record of the song to the database");
|
||||
|
||||
var album = new Album()
|
||||
{
|
||||
Title = song.AlbumTitle,
|
||||
AlbumArtist = song.Artist
|
||||
};
|
||||
|
||||
if (!albumStore.DoesAlbumExist(song))
|
||||
{
|
||||
album.SongCount = 1;
|
||||
albumStore.SaveAlbum(album);
|
||||
album = albumStore.GetAlbum(song);
|
||||
}
|
||||
else
|
||||
{
|
||||
var albumRetrieved = albumStore.GetAlbum(song);
|
||||
album.AlbumId = albumRetrieved.AlbumId;
|
||||
album.SongCount = albumRetrieved.SongCount + 1;
|
||||
|
||||
albumStore.UpdateAlbum(album);
|
||||
}
|
||||
|
||||
song.AlbumId = album.AlbumId;
|
||||
}
|
||||
private void SaveArtistToDatabase(ref Song song, ArtistRepository artistStore)
|
||||
{
|
||||
_logger.Info("Starting process to save the artist record of the song to the database");
|
||||
|
||||
var artist = new Artist
|
||||
{
|
||||
Name = song.Artist,
|
||||
SongCount = 1
|
||||
};
|
||||
|
||||
if (!artistStore.DoesArtistExist(song))
|
||||
{
|
||||
artist.SongCount = 1;
|
||||
artistStore.SaveArtist(artist);
|
||||
artist = artistStore.GetArtist(song);
|
||||
}
|
||||
else
|
||||
{
|
||||
var artistRetrieved = artistStore.GetArtist(song);
|
||||
artist.ArtistId = artistRetrieved.ArtistId;
|
||||
artist.SongCount = artistRetrieved.SongCount + 1;
|
||||
|
||||
artistStore.UpdateArtist(artist);
|
||||
}
|
||||
|
||||
song.ArtistId = artist.ArtistId;
|
||||
}
|
||||
private void SaveGenreToDatabase(ref Song song, GenreRepository genreStore)
|
||||
{
|
||||
_logger.Info("Starting process to save the genre record of the song to the database");
|
||||
|
||||
var genre = new Genre
|
||||
{
|
||||
GenreName = song.Genre,
|
||||
SongCount = 1
|
||||
};
|
||||
|
||||
if (!genreStore.DoesGenreExist(song))
|
||||
{
|
||||
genreStore.SaveGenre(genre);
|
||||
genre = genreStore.GetGenre(song);
|
||||
}
|
||||
else
|
||||
{
|
||||
var genreRetrieved = genreStore.GetGenre(song);
|
||||
genre.GenreId = genreRetrieved.GenreId;
|
||||
genre.SongCount = genreRetrieved.SongCount + 1;
|
||||
|
||||
genreStore.UpdateGenre(genre);
|
||||
}
|
||||
|
||||
song.GenreId = genre.GenreId;
|
||||
}
|
||||
private void SaveYearToDatabase(ref Song song, YearRepository yearStore)
|
||||
{
|
||||
_logger.Info("Starting process to save the year record of the song to the database");
|
||||
|
||||
var year = new Year
|
||||
{
|
||||
YearValue = song.Year.Value,
|
||||
SongCount = 1
|
||||
};
|
||||
|
||||
if (!yearStore.DoesYearExist(song))
|
||||
{
|
||||
yearStore.SaveYear(year);
|
||||
year = yearStore.GetSongYear(song);
|
||||
}
|
||||
else
|
||||
{
|
||||
var yearRetrieved = yearStore.GetSongYear(song);
|
||||
year.YearId = yearRetrieved.YearId;
|
||||
year.SongCount = yearRetrieved.SongCount + 1;
|
||||
|
||||
yearStore.UpdateYear(year);
|
||||
}
|
||||
|
||||
song.YearId = year.YearId;
|
||||
}
|
||||
|
||||
public Song SongCopy(Song song)
|
||||
{
|
||||
var updatedSongRecord = new Song
|
||||
{
|
||||
Id = song.Id,
|
||||
Title = song.Title,
|
||||
Artist = song.Artist,
|
||||
AlbumTitle = song.AlbumTitle,
|
||||
Genre = song.Genre,
|
||||
Year = song.Year,
|
||||
Duration = song.Duration,
|
||||
Filename = song.Filename,
|
||||
SongPath = song.SongPath,
|
||||
ArtistId = song.ArtistId,
|
||||
AlbumId = song.AlbumId,
|
||||
GenreId = song.GenreId,
|
||||
YearId = song.YearId
|
||||
};
|
||||
|
||||
return updatedSongRecord;
|
||||
}
|
||||
|
||||
private Album UpdateAlbumInDatabase(Song oldSongRecord, Song newSongRecord, AlbumRepository albumStore)
|
||||
{
|
||||
var albumRecord = albumStore.GetAlbum(oldSongRecord, true);
|
||||
var oldAlbumTitle = oldSongRecord.AlbumTitle;
|
||||
var oldAlbumArtist = oldSongRecord.Artist;
|
||||
var newAlbumTitle = newSongRecord.AlbumTitle;
|
||||
var newAlbumArtist = newSongRecord.Artist;
|
||||
|
||||
var info = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(newAlbumArtist))
|
||||
newAlbumArtist = oldAlbumArtist;
|
||||
if (string.IsNullOrEmpty(newAlbumTitle))
|
||||
newAlbumTitle = oldAlbumTitle;
|
||||
|
||||
if ((string.IsNullOrEmpty(newAlbumTitle) && string.IsNullOrEmpty(newAlbumArtist) ||
|
||||
oldAlbumTitle.Equals(newAlbumTitle) && oldAlbumArtist.Equals(newAlbumArtist)))
|
||||
{
|
||||
_logger.Info("No change to the song's album");
|
||||
return albumRecord;
|
||||
}
|
||||
|
||||
info = "Change to the song's album";
|
||||
_logger.Info(info);
|
||||
|
||||
if (!albumStore.DoesAlbumExist(newSongRecord))
|
||||
{
|
||||
_logger.Info("Creating new album record");
|
||||
|
||||
albumStore.SaveAlbum(new Album
|
||||
{
|
||||
Title = newAlbumTitle,
|
||||
AlbumArtist = newAlbumArtist
|
||||
});
|
||||
|
||||
newSongRecord.AlbumTitle = newAlbumTitle;
|
||||
|
||||
return albumStore.GetAlbum(newSongRecord, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info("Updating existing album record");
|
||||
|
||||
var existingAlbumRecord = albumStore.GetAlbum(newSongRecord);
|
||||
existingAlbumRecord.AlbumArtist = newAlbumArtist;
|
||||
|
||||
albumStore.UpdateAlbum(existingAlbumRecord);
|
||||
|
||||
return existingAlbumRecord;
|
||||
}
|
||||
}
|
||||
private Artist UpdateArtistInDatabase(Song oldSongRecord, Song newSongRecord, ArtistRepository artistStore)
|
||||
{
|
||||
var oldArtistRecord = artistStore.GetArtist(oldSongRecord, true);
|
||||
var oldArtistName = oldArtistRecord.Name;
|
||||
var newArtistName = newSongRecord.Artist;
|
||||
|
||||
if (string.IsNullOrEmpty(newArtistName) || oldArtistName.Equals(newArtistName))
|
||||
{
|
||||
_logger.Info("No change to the song's Artist");
|
||||
return oldArtistRecord;
|
||||
}
|
||||
|
||||
_logger.Info("Change to the song's record found");
|
||||
|
||||
if (oldArtistRecord.SongCount <= 1)
|
||||
{
|
||||
_logger.Info("Deleting artist record that no longer has any songs");
|
||||
|
||||
artistStore.DeleteArtist(oldArtistRecord);
|
||||
}
|
||||
|
||||
if (!artistStore.DoesArtistExist(newSongRecord))
|
||||
{
|
||||
_logger.Info("Creating new artist record");
|
||||
|
||||
var newArtistRecord = new Artist
|
||||
{
|
||||
Name = newArtistName
|
||||
};
|
||||
|
||||
artistStore.SaveArtist(newArtistRecord);
|
||||
|
||||
return artistStore.GetArtist(newSongRecord, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info("Updating existing artist record");
|
||||
|
||||
var existingArtistRecord = artistStore.GetArtist(newSongRecord);
|
||||
|
||||
artistStore.UpdateArtist(existingArtistRecord);
|
||||
|
||||
return existingArtistRecord;
|
||||
}
|
||||
}
|
||||
private Genre UpdateGenreInDatabase(Song oldSongRecord, Song newSongRecord, GenreRepository genreStore)
|
||||
{
|
||||
var oldGenreRecord = genreStore.GetGenre(oldSongRecord, true);
|
||||
var oldGenreName = oldGenreRecord.GenreName;
|
||||
var newGenreName = newSongRecord.Genre;
|
||||
|
||||
if (string.IsNullOrEmpty(newGenreName) || oldGenreName.Equals(newGenreName))
|
||||
{
|
||||
_logger.Info("No change to the song's Genre");
|
||||
return oldGenreRecord;
|
||||
}
|
||||
|
||||
_logger.Info("Change to the song's genre found");
|
||||
|
||||
if (oldGenreRecord.SongCount <= 1)
|
||||
{
|
||||
_logger.Info("Deleting genre record");
|
||||
|
||||
genreStore.DeleteGenre(oldGenreRecord);
|
||||
}
|
||||
|
||||
if (!genreStore.DoesGenreExist(newSongRecord))
|
||||
{
|
||||
_logger.Info("Creating new genre record");
|
||||
|
||||
var newGenreRecord = new Genre
|
||||
{
|
||||
GenreName = newGenreName
|
||||
};
|
||||
|
||||
genreStore.SaveGenre(newGenreRecord);
|
||||
|
||||
return genreStore.GetGenre(newSongRecord, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info("Updating existing genre record");
|
||||
|
||||
var existingGenreRecord = genreStore.GetGenre(newSongRecord);
|
||||
|
||||
genreStore.UpdateGenre(existingGenreRecord);
|
||||
return genreStore.GetGenre(existingGenreRecord);
|
||||
}
|
||||
}
|
||||
private Year UpdateYearInDatabase(Song oldSongRecord, Song newSongRecord, YearRepository yearStore)
|
||||
{
|
||||
var oldYearRecord = yearStore.GetSongYear(oldSongRecord, true);
|
||||
var oldYearValue = oldYearRecord.YearValue;
|
||||
var newYearValue = newSongRecord.Year;
|
||||
|
||||
if (oldYearValue == newYearValue || newYearValue == 0 || newYearValue == null)
|
||||
{
|
||||
_logger.Info("No change to the song's Year");
|
||||
return oldYearRecord;
|
||||
}
|
||||
|
||||
_logger.Info("Change to the song's year found");
|
||||
|
||||
if (oldYearRecord.SongCount <= 1)
|
||||
{
|
||||
_logger.Info("Deleting year record");
|
||||
|
||||
yearStore.DeleteYear(oldYearRecord);
|
||||
}
|
||||
|
||||
if(!yearStore.DoesYearExist(newSongRecord))
|
||||
{
|
||||
_logger.Info("Creating new year record");
|
||||
|
||||
var newYearRecord = new Year
|
||||
{
|
||||
YearValue = newYearValue.Value
|
||||
};
|
||||
|
||||
yearStore.SaveYear(newYearRecord);
|
||||
|
||||
return yearStore.GetSongYear(newSongRecord, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info("Updating existing year record");
|
||||
|
||||
var existingYearRecord = yearStore.GetSongYear(newSongRecord);
|
||||
|
||||
yearStore.UpdateYear(existingYearRecord);
|
||||
|
||||
return existingYearRecord;
|
||||
}
|
||||
}
|
||||
private void UpdateSongInDatabase(ref Song oldSongRecord, ref Song newSongRecord, SongRepository songStore,
|
||||
ref SongResult result)
|
||||
{
|
||||
var updatedSongRecord = SongCopy(oldSongRecord);
|
||||
var artistOrAlbumChanged = false;
|
||||
|
||||
if (!SongRecordChanged(oldSongRecord, newSongRecord))
|
||||
{
|
||||
_logger.Info("No change to the song record");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.Info("Changes to song record found");
|
||||
|
||||
if (!string.IsNullOrEmpty(newSongRecord.Title))
|
||||
updatedSongRecord.Title = newSongRecord.Title;
|
||||
if (!string.IsNullOrEmpty(newSongRecord.AlbumTitle))
|
||||
{
|
||||
updatedSongRecord.AlbumTitle = newSongRecord.AlbumTitle;
|
||||
artistOrAlbumChanged = true;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(newSongRecord.Artist))
|
||||
{
|
||||
updatedSongRecord.Artist = newSongRecord.Artist;
|
||||
artistOrAlbumChanged = true;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(newSongRecord.Genre))
|
||||
{
|
||||
updatedSongRecord.Genre = newSongRecord.Genre;
|
||||
}
|
||||
if (newSongRecord.Year > 0)
|
||||
updatedSongRecord.Year = newSongRecord.Year;
|
||||
else
|
||||
updatedSongRecord.Year = oldSongRecord.Year;
|
||||
|
||||
_logger.Info("Applied changes to song record");
|
||||
|
||||
if (artistOrAlbumChanged)
|
||||
{
|
||||
_logger.Info("Change to song's album or artist");
|
||||
|
||||
var rootPath = _config.GetValue<string>("RootMusicPath");
|
||||
var strCount = rootPath.Length + updatedSongRecord.Artist.Length +
|
||||
updatedSongRecord.AlbumTitle.Length + 2;
|
||||
var updatedPath = new StringBuilder(strCount);
|
||||
|
||||
DirectoryManager.create_directory(ConvertSongToSng(updatedSongRecord),
|
||||
rootPath, updatedPath);
|
||||
|
||||
var newSongPath = updatedPath.ToString().Substring(0, strCount) +
|
||||
updatedSongRecord.Filename;
|
||||
|
||||
DirectoryManager.copy_song(newSongPath, updatedSongRecord.SongPath);
|
||||
|
||||
updatedSongRecord.SongPath = newSongPath;
|
||||
}
|
||||
|
||||
_logger.Info("Saving song metadata to the database");
|
||||
|
||||
if (songStore.DoesSongExist(newSongRecord))
|
||||
songStore.UpdateSong(updatedSongRecord);
|
||||
else
|
||||
songStore.SaveSong(updatedSongRecord);
|
||||
|
||||
newSongRecord = updatedSongRecord;
|
||||
|
||||
result.Message = "Successfully updated song";
|
||||
result.SongTitle = updatedSongRecord.Title;
|
||||
}
|
||||
|
||||
private void DeleteSongFromDatabase(Song song, SongRepository songStore, AlbumRepository albumStore,
|
||||
ArtistRepository artistStore, GenreRepository genreStore, YearRepository yearStore)
|
||||
{
|
||||
_logger.Info("Starting process to delete records related to the song from the database");
|
||||
|
||||
DeleteAlbumFromDatabase(song, albumStore);
|
||||
DeleteArtistFromDatabase(song, artistStore);
|
||||
DeleteGenreFromDatabase(song, genreStore);
|
||||
DeleteYearFromDatabase(song, yearStore);
|
||||
|
||||
songStore.DeleteSong(song);
|
||||
}
|
||||
private void DeleteAlbumFromDatabase(Song song, AlbumRepository albumStore)
|
||||
{
|
||||
if (!albumStore.DoesAlbumExist(song))
|
||||
{
|
||||
_logger.Info("Cannot delete the album record because it does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
var album = albumStore.GetAlbum(song, true);
|
||||
|
||||
if (album.SongCount <= 1)
|
||||
albumStore.DeleteAlbum(album);
|
||||
}
|
||||
private void DeleteArtistFromDatabase(Song song, ArtistRepository artistStore)
|
||||
{
|
||||
if (!artistStore.DoesArtistExist(song))
|
||||
{
|
||||
_logger.Info("Cannot delete the artist record because it does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
var artist = artistStore.GetArtist(song, true);
|
||||
|
||||
if (artist.SongCount <= 1)
|
||||
artistStore.DeleteArtist(artist);
|
||||
}
|
||||
private void DeleteGenreFromDatabase(Song song, GenreRepository genreStore)
|
||||
{
|
||||
if (!genreStore.DoesGenreExist(song))
|
||||
{
|
||||
_logger.Info("Cannot delete the genre record because it does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
var genre = genreStore.GetGenre(song, true);
|
||||
|
||||
if (genre.SongCount <= 1)
|
||||
genreStore.DeleteGenre(genre);
|
||||
}
|
||||
private void DeleteYearFromDatabase(Song song, YearRepository yearStore)
|
||||
{
|
||||
if (!yearStore.DoesYearExist(song))
|
||||
{
|
||||
_logger.Info("Cannot delete the year record because it does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
var year = yearStore.GetSongYear(song, true);
|
||||
|
||||
if (year.SongCount <= 1)
|
||||
yearStore.DeleteYear(year);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
//using RestSharp;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Controllers.Managers
|
||||
{
|
||||
public class TokenManager : BaseManager
|
||||
{
|
||||
#region Fields
|
||||
private IConfiguration _config;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public TokenManager(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
#region c++ Libs
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern IntPtr retrieve_token(ref TokenReq req);
|
||||
#endregion
|
||||
|
||||
public static LoginResult ConvertLogResToLoginResult(ref LogRes res)
|
||||
{
|
||||
return new LoginResult
|
||||
{
|
||||
Token = res.Token,
|
||||
TokenType = res.TokenType,
|
||||
Expiration = res.Expiration,
|
||||
Message = res.Message
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NLog;
|
||||
//using TagLib;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Controllers.Managers;
|
||||
|
||||
namespace Icarus.Controllers.Utilities
|
||||
{
|
||||
public class MetadataRetriever
|
||||
{
|
||||
#region Fields
|
||||
private static NLog.Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
|
||||
private string _message;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
public string Message
|
||||
{
|
||||
get => _message;
|
||||
set => _message = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#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($"YearId: {song.YearId}");
|
||||
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}");
|
||||
}
|
||||
|
||||
#region C++ Libs
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern void retrieve_metadata(ref Sng sng,
|
||||
string file_path);
|
||||
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern void update_metadata(ref Sng sng_updated,
|
||||
ref Sng sng_old);
|
||||
|
||||
[DllImport("libicarus.so")]
|
||||
public static extern void update_cover_art(ref CovArt cov,
|
||||
ref Sng sng, string root_cover_path);
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using BCrypt.Net;
|
||||
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
||||
using NLog;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Controllers.Utilities
|
||||
{
|
||||
public class PasswordEncryption
|
||||
{
|
||||
#region Fields
|
||||
private static Logger _logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructor
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public bool VerifyPassword(User user, string password)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = BCrypt.Net.BCrypt.Verify(password, user.Password);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public string HashPassword(User user)
|
||||
{
|
||||
try
|
||||
{
|
||||
string hashedPassword = string.Empty;
|
||||
hashedPassword = BCrypt.Net.BCrypt.HashPassword(user.Password);
|
||||
|
||||
_logger.Info("Successfully hashed password");
|
||||
|
||||
return hashedPassword;
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
_logger.Error(exMsg, "An error occurred");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
string GenerateHash(string password, byte[] salt)
|
||||
{
|
||||
|
||||
string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
|
||||
password: password, salt: salt,
|
||||
prf: KeyDerivationPrf.HMACSHA1,
|
||||
iterationCount: 10000,
|
||||
numBytesRequested: 256/8));
|
||||
|
||||
return hashed;
|
||||
}
|
||||
|
||||
byte[] GenerateSalt()
|
||||
{
|
||||
byte[] salt = new byte[128/8];
|
||||
|
||||
using (var rng = RandomNumberGenerator.Create())
|
||||
rng.GetBytes(salt);
|
||||
|
||||
|
||||
return salt;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
using Ionic.Zip;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Controllers.Utilities
|
||||
{
|
||||
public class SongCompression
|
||||
{
|
||||
#region Fields
|
||||
string _compressedSongFilename;
|
||||
string _tempDirectory;
|
||||
byte[] _uncompressedSong;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Propterties
|
||||
public string CompressedSongFilename
|
||||
{
|
||||
get => _compressedSongFilename;
|
||||
set => _compressedSongFilename = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public SongCompression()
|
||||
{
|
||||
}
|
||||
public SongCompression(string tempDirectory)
|
||||
{
|
||||
_tempDirectory = tempDirectory;
|
||||
}
|
||||
public SongCompression(byte[] uncompressedSong)
|
||||
{
|
||||
_uncompressedSong = uncompressedSong;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public async Task<SongData> RetrieveCompressedSong(Song song)
|
||||
{
|
||||
SongData songData = new SongData();
|
||||
try
|
||||
{
|
||||
var archivePath = RetrieveCompressesSongPath(song);
|
||||
Console.WriteLine($"Compressed song saved to: {archivePath}");
|
||||
|
||||
songData.Data = await System.IO.File.ReadAllBytesAsync(archivePath);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error ocurred: \n{exMsg}");
|
||||
}
|
||||
|
||||
return songData;
|
||||
}
|
||||
|
||||
public string RetrieveCompressesSongPath(Song songDetails)
|
||||
{
|
||||
string tmpZipFilePath = _tempDirectory + songDetails.Filename;
|
||||
|
||||
try
|
||||
{
|
||||
using (ZipFile zip = new ZipFile())
|
||||
{
|
||||
zip.AddFile(songDetails.SongPath);
|
||||
zip.Save(tmpZipFilePath);
|
||||
}
|
||||
Console.WriteLine("Successfully compressed");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine("An error ocurred");
|
||||
Console.WriteLine(exMsg);
|
||||
}
|
||||
|
||||
if (songDetails.Filename.Contains(".mp3"))
|
||||
{
|
||||
_compressedSongFilename = StripMP3Extension(songDetails.Filename);
|
||||
}
|
||||
|
||||
return tmpZipFilePath;
|
||||
}
|
||||
|
||||
// Method not being used
|
||||
public byte[] CompressedSong(byte[] uncompressedSong)
|
||||
{
|
||||
byte[] compressedSong = null;
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Song has been successfully compressed");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine("An error ocurred:");
|
||||
Console.WriteLine(exMsg);
|
||||
}
|
||||
|
||||
return compressedSong;
|
||||
}
|
||||
|
||||
|
||||
string StripMP3Extension(string filename)
|
||||
{
|
||||
Console.WriteLine($"Before: {filename}");
|
||||
int filenameLength = filename.Length;
|
||||
Console.WriteLine($"Filename length {filenameLength}");
|
||||
var endIndex = filenameLength - 1;
|
||||
var startIndex = endIndex - 3;
|
||||
Console.WriteLine($"Starting index {startIndex} and ending index {endIndex}");
|
||||
var stripped = filename.Remove(startIndex, 4);
|
||||
stripped += ".zip";
|
||||
Console.WriteLine($"After {stripped}");
|
||||
|
||||
return stripped;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/album")]
|
||||
[ApiController]
|
||||
public class AlbumController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<AlbumController> _logger;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public AlbumController(ILogger<AlbumController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP Routes
|
||||
[HttpGet]
|
||||
[Authorize("read:albums")]
|
||||
public IActionResult Get()
|
||||
{
|
||||
List<Album> albums = new List<Album>();
|
||||
|
||||
AlbumRepository albumStoreContext = HttpContext.RequestServices
|
||||
.GetService(typeof(AlbumRepository)) as AlbumRepository;
|
||||
|
||||
albums = albumStoreContext.GetAlbums();
|
||||
|
||||
if (albums.Count > 0)
|
||||
return Ok(albums);
|
||||
else
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("read:albums")]
|
||||
public IActionResult Get(int id)
|
||||
{
|
||||
Album album = new Album
|
||||
{
|
||||
AlbumId = id
|
||||
};
|
||||
|
||||
AlbumRepository albumStoreContext = HttpContext.RequestServices
|
||||
.GetService(typeof(AlbumRepository)) as AlbumRepository;
|
||||
|
||||
if (albumStoreContext.DoesAlbumExist(album))
|
||||
{
|
||||
album = albumStoreContext.GetAlbum(album);
|
||||
|
||||
return Ok(album);
|
||||
}
|
||||
else
|
||||
return NotFound();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/artist")]
|
||||
[ApiController]
|
||||
public class ArtistController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<ArtistController> _logger;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public ArtistController(ILogger<ArtistController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP Routes
|
||||
[HttpGet]
|
||||
[Authorize("read:artists")]
|
||||
public IActionResult Get()
|
||||
{
|
||||
ArtistRepository artistStoreContext = HttpContext.RequestServices
|
||||
.GetService(typeof(ArtistRepository)) as ArtistRepository;
|
||||
|
||||
var artists = artistStoreContext.GetArtists();
|
||||
|
||||
if (artists.Count > 0)
|
||||
return Ok(artists);
|
||||
else
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("read:artists")]
|
||||
public IActionResult Get(int id)
|
||||
{
|
||||
Artist artist = new Artist
|
||||
{
|
||||
ArtistId = id
|
||||
};
|
||||
|
||||
ArtistRepository artistStoreContext = HttpContext.RequestServices
|
||||
.GetService(typeof(ArtistRepository)) as ArtistRepository;
|
||||
|
||||
if (artistStoreContext.DoesArtistExist(artist))
|
||||
{
|
||||
artist = artistStoreContext.GetArtist(artist);
|
||||
|
||||
return Ok(artist);
|
||||
}
|
||||
else
|
||||
return NotFound();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/coverart")]
|
||||
[ApiController]
|
||||
public class CoverArtController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<CoverArtController> _logger;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public CoverArtController(ILogger<CoverArtController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP Routes
|
||||
public IActionResult Get()
|
||||
{
|
||||
var coverArtRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService(
|
||||
typeof(CoverArtRepository)) as CoverArtRepository;
|
||||
|
||||
var coverArtRecords = coverArtRepository.GetCoverArtRecords();
|
||||
|
||||
if (coverArtRecords == null)
|
||||
{
|
||||
_logger.LogInformation("No cover art records");
|
||||
return NotFound();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Found cover art records");
|
||||
return Ok(coverArtRecords);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("download:cover_art")]
|
||||
public async Task<IActionResult> Get(int id)
|
||||
{
|
||||
var coverArt = new CoverArt { CoverArtId = id };
|
||||
|
||||
var coverArtRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService(
|
||||
typeof(CoverArtRepository)) as CoverArtRepository;
|
||||
|
||||
coverArt = coverArtRepository.GetCoverArt(coverArt);
|
||||
|
||||
if (coverArt != null)
|
||||
{
|
||||
_logger.LogInformation("Found cover art record");
|
||||
var coverArtBytes = await System.IO.File.ReadAllBytesAsync(
|
||||
coverArt.ImagePath);
|
||||
|
||||
return File(coverArtBytes, "application/x-msdownload",
|
||||
coverArt.SongTitle);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Cover art not found");
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/genre")]
|
||||
[ApiController]
|
||||
public class GenreController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<GenreController> _logger;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public GenreController(ILogger<GenreController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP Routes
|
||||
[HttpGet]
|
||||
[Authorize("read:genre")]
|
||||
public IActionResult Get()
|
||||
{
|
||||
var genres = new List<Genre>();
|
||||
|
||||
var genreStore = HttpContext.RequestServices
|
||||
.GetService(typeof(GenreRepository)) as GenreRepository;
|
||||
|
||||
genres = genreStore.GetGenres();
|
||||
|
||||
if (genres.Count > 0)
|
||||
return Ok(genres);
|
||||
else
|
||||
return NotFound(new List<Genre>());
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("read:genre")]
|
||||
public IActionResult Get(int id)
|
||||
{
|
||||
var genre = new Genre
|
||||
{
|
||||
GenreId = id
|
||||
};
|
||||
|
||||
var genreStore = HttpContext.RequestServices
|
||||
.GetService(typeof(GenreRepository)) as GenreRepository;
|
||||
|
||||
if (genreStore.DoesGenreExist(genre))
|
||||
{
|
||||
genre = genreStore.GetGenre(genre);
|
||||
|
||||
return Ok(genre);
|
||||
}
|
||||
else
|
||||
return NotFound(new Genre());
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/login")]
|
||||
[ApiController]
|
||||
public class LoginController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private IConfiguration _config;
|
||||
private ILogger<LoginController> _logger;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Contructors
|
||||
public LoginController(IConfiguration config, ILogger<LoginController> logger)
|
||||
{
|
||||
_config = config;
|
||||
_logger = logger;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP endpoints
|
||||
public IActionResult Post([FromBody] User user)
|
||||
{
|
||||
UserRepository context = HttpContext.RequestServices
|
||||
.GetService(typeof(UserRepository)) as UserRepository;
|
||||
|
||||
_logger.LogInformation("Starting process of validating credentials");
|
||||
|
||||
var loginRes = new LoginResult
|
||||
{
|
||||
Username = user.Username,
|
||||
Message = "Invalid credentials"
|
||||
};
|
||||
|
||||
if (context.DoesUserExist(user))
|
||||
{
|
||||
var password = user.Password;
|
||||
user = context.RetrieveUser(user);
|
||||
|
||||
var validatePass = new PasswordEncryption();
|
||||
var validated = validatePass.VerifyPassword(user, password);
|
||||
if (!validated)
|
||||
{
|
||||
_logger.LogInformation(loginRes.Message);
|
||||
|
||||
return Ok(loginRes);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Successfully validated user credentials");
|
||||
|
||||
var tok = new TokenReq
|
||||
{
|
||||
ClientId = _config["Auth0:ClientId"],
|
||||
ClientSecret = _config["Auth0:ClientSecret"],
|
||||
Audience = _config["Auth0:ApiIdentifier"],
|
||||
GrantType = "client_credentials",
|
||||
URI = $"https://{_config["Auth0:Domain"]}",
|
||||
Endpoint = "oauth/token"
|
||||
};
|
||||
|
||||
IntPtr logRes = TokenManager.retrieve_token(ref tok);
|
||||
var lr = (LogRes)Marshal.PtrToStructure(logRes, typeof(LogRes));
|
||||
loginRes = TokenManager.ConvertLogResToLoginResult(ref lr);
|
||||
loginRes.Username = user.Username;
|
||||
loginRes.UserId = user.Id;
|
||||
|
||||
return Ok(loginRes);
|
||||
}
|
||||
else
|
||||
return NotFound(loginRes);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/register")]
|
||||
[ApiController]
|
||||
public class RegisterController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private IConfiguration _config;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructor
|
||||
public RegisterController(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
#endregion
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Post([FromBody] User user)
|
||||
{
|
||||
PasswordEncryption pe = new PasswordEncryption();
|
||||
user.Password = pe.HashPassword(user);
|
||||
user.EmailVerified = false;
|
||||
|
||||
UserRepository context = HttpContext.RequestServices
|
||||
.GetService(typeof(UserRepository)) as UserRepository;
|
||||
|
||||
context.SaveUser(user);
|
||||
|
||||
var registerResult = new RegisterResult
|
||||
{
|
||||
Username = user.Username
|
||||
};
|
||||
|
||||
if (context.DoesUserExist(user))
|
||||
{
|
||||
registerResult.Message = "Successful registration";
|
||||
registerResult.SuccessfullyRegistered = true;
|
||||
|
||||
return Ok(registerResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
registerResult.Message = "Registration failed";
|
||||
registerResult.SuccessfullyRegistered = false;
|
||||
|
||||
return Ok(registerResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/song/compressed/data")]
|
||||
[ApiController]
|
||||
public class SongCompressedDataController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private IConfiguration _config;
|
||||
private string _songTempDir;
|
||||
private string _archiveDir;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructor
|
||||
public SongCompressedDataController(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
_songTempDir = _config.GetValue<string>("TemporaryMusicPath");
|
||||
_archiveDir = _config.GetValue<string>("ArchivePath");
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region API Routes
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("download:songs")]
|
||||
public async Task<IActionResult> Get(int id)
|
||||
{
|
||||
SongRepository context = HttpContext.RequestServices
|
||||
.GetService(typeof(SongRepository)) as SongRepository;
|
||||
|
||||
SongCompression cmp = new SongCompression(_archiveDir);
|
||||
|
||||
Console.WriteLine($"Archive directory root: {_archiveDir}");
|
||||
|
||||
Console.WriteLine("Starting process of retrieving comrpessed song");
|
||||
SongData song = await cmp.RetrieveCompressedSong(context.GetSong(id));
|
||||
|
||||
return File(song.Data, "application/x-msdownload", cmp.CompressedSongFilename);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/song")]
|
||||
[ApiController]
|
||||
public class SongController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<SongController> _logger;
|
||||
private IConfiguration _config;
|
||||
private SongManager _songMgr;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructor
|
||||
public SongController(IConfiguration config, ILogger<SongController> logger)
|
||||
{
|
||||
_config = config;
|
||||
_logger = logger;
|
||||
_songMgr = new SongManager(config);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
[HttpGet]
|
||||
[Authorize("read:song_details")]
|
||||
public IActionResult Get()
|
||||
{
|
||||
var songs = new List<Song>();
|
||||
Console.WriteLine("Attemtping to retrieve songs");
|
||||
_logger.LogInformation("Attempting to retrieve songs");
|
||||
|
||||
var context = HttpContext.RequestServices
|
||||
.GetService(typeof(SongRepository)) as SongRepository;
|
||||
|
||||
songs = context.GetAllSongs();
|
||||
|
||||
if (songs.Count > 0)
|
||||
return Ok(songs);
|
||||
else
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("read:song_details")]
|
||||
public IActionResult Get(int id)
|
||||
{
|
||||
var context = HttpContext.RequestServices
|
||||
.GetService(typeof(SongRepository)) as SongRepository;
|
||||
|
||||
var song = new Song { Id = id };
|
||||
song = context.GetSong(song);
|
||||
|
||||
if (song.Id != 0)
|
||||
return Ok(song);
|
||||
else
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[Authorize("update:songs")]
|
||||
[HttpPut("{id}")]
|
||||
public IActionResult Put(int id, [FromBody] Song song)
|
||||
{
|
||||
var context = HttpContext.RequestServices
|
||||
.GetService(typeof(SongRepository)) as SongRepository;
|
||||
|
||||
var artistStore = HttpContext.RequestServices
|
||||
.GetService(typeof(ArtistRepository)) as ArtistRepository;
|
||||
|
||||
var albumStore = HttpContext.RequestServices
|
||||
.GetService(typeof(AlbumRepository)) as AlbumRepository;
|
||||
|
||||
var genreStore = HttpContext.RequestServices
|
||||
.GetService(typeof(GenreRepository)) as GenreRepository;
|
||||
|
||||
var yearStore = HttpContext.RequestServices
|
||||
.GetService(typeof(YearRepository)) as YearRepository;
|
||||
|
||||
song.Id = id;
|
||||
Console.WriteLine("Retrieving filepath of song");
|
||||
_logger.LogInformation("Retrieving filepath of song");
|
||||
|
||||
if (!context.DoesSongExist(song))
|
||||
return NotFound(new SongResult
|
||||
{
|
||||
Message = "Song does not exist"
|
||||
});
|
||||
|
||||
var songRes = _songMgr.UpdateSong(song, context, albumStore, artistStore, genreStore,
|
||||
yearStore);
|
||||
|
||||
return Ok(songRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Contexts;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/song/data")]
|
||||
[ApiController]
|
||||
public class SongDataController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private SongRepository _songRepository;
|
||||
private AlbumRepository _albumRepository;
|
||||
private ArtistRepository _artistRepository;
|
||||
private GenreRepository _genreRepository;
|
||||
private YearRepository _yearRepository;
|
||||
private CoverArtRepository _coverArtRepository;
|
||||
private IConfiguration _config;
|
||||
private ILogger<SongDataController> _logger;
|
||||
private SongManager _songMgr;
|
||||
private string _songTempDir;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructor
|
||||
public SongDataController(IConfiguration config, ILogger<SongDataController> logger)
|
||||
{
|
||||
_config = config;
|
||||
_logger = logger;
|
||||
_songTempDir = _config.GetValue<string>("TemporaryMusicPath");
|
||||
_songMgr = new SongManager(config, _songTempDir);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
_songRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService
|
||||
(typeof(SongRepository)) as SongRepository;
|
||||
|
||||
_albumRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(AlbumRepository)) as AlbumRepository;
|
||||
|
||||
_artistRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(ArtistRepository)) as ArtistRepository;
|
||||
|
||||
_genreRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(GenreRepository)) as GenreRepository;
|
||||
|
||||
_yearRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(YearRepository)) as YearRepository;
|
||||
|
||||
_coverArtRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(CoverArtRepository)) as CoverArtRepository;
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Route("private-scoped")]
|
||||
[Authorize("download:songs")]
|
||||
public async Task<IActionResult> Get(int id)
|
||||
{
|
||||
Initialize();
|
||||
var songMetaData = _songRepository.GetSong(id);
|
||||
|
||||
SongData song = await _songMgr.RetrieveSong(songMetaData);
|
||||
|
||||
return File(song.Data, "application/x-msdownload", songMetaData.Filename);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize("upload:songs")]
|
||||
public async Task Post([FromForm(Name = "file")] List<IFormFile> songData)
|
||||
{
|
||||
try
|
||||
{
|
||||
Initialize();
|
||||
|
||||
Console.WriteLine("Uploading song...");
|
||||
_logger.LogInformation("Uploading song...");
|
||||
|
||||
Console.WriteLine($"Song Root Path {_songTempDir}");
|
||||
_logger.LogInformation($"Song root path {_songTempDir}");
|
||||
foreach (var sng in songData)
|
||||
if (sng.Length > 0) {
|
||||
Console.WriteLine($"Song filename {sng.FileName}");
|
||||
_logger.LogInformation($"Song filename {sng.FileName}");
|
||||
|
||||
await _songMgr.SaveSongToFileSystem(sng, _songRepository,
|
||||
_albumRepository, _artistRepository,
|
||||
_genreRepository, _yearRepository, _coverArtRepository);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.LogError(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize("delete:songs")]
|
||||
public IActionResult Delete(int id)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
var songMetaData = new Song{ Id = id };
|
||||
songMetaData = _songRepository.GetSong(songMetaData);
|
||||
|
||||
if (string.IsNullOrEmpty(songMetaData.Title))
|
||||
{
|
||||
_logger.LogInformation("Song does not exist");
|
||||
return NotFound("Song does not exist");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Starting process of deleting song from the filesystem and database");
|
||||
|
||||
_songMgr.DeleteSong(songMetaData, _songRepository,
|
||||
_albumRepository, _artistRepository,
|
||||
_genreRepository, _yearRepository,
|
||||
_coverArtRepository);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Web;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/song/stream")]
|
||||
[ApiController]
|
||||
public class SongStreamController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private ILogger<SongStreamController> _logger;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructor
|
||||
public SongStreamController(ILogger<SongStreamController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP endpoints
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("stream:songs")]
|
||||
public IActionResult Get(int id)
|
||||
{
|
||||
var songStore= HttpContext.RequestServices
|
||||
.GetService(typeof(SongRepository)) as SongRepository;
|
||||
|
||||
var song = songStore.GetSong(new Song { Id = id });
|
||||
|
||||
var stream = new FileStream(song.SongPath, FileMode.Open, FileAccess.Read);
|
||||
stream.Position = 0;
|
||||
var filename = $"{song.Title}.mp3";
|
||||
|
||||
_logger.LogInformation("Starting to stream song...>");
|
||||
Console.WriteLine("Starting to streamsong...");
|
||||
|
||||
return File(stream, "application/octet-stream", filename);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus.Controller.V1
|
||||
{
|
||||
[Route("api/v1/year")]
|
||||
[ApiController]
|
||||
public class YearController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<YearController> _logger;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public YearController(ILogger<YearController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP Routes
|
||||
[HttpGet]
|
||||
[Authorize("read:year")]
|
||||
public IActionResult Get()
|
||||
{
|
||||
var yearValues = new List<Year>();
|
||||
|
||||
var yearStore = HttpContext.RequestServices
|
||||
.GetService(typeof(YearRepository)) as YearRepository;
|
||||
|
||||
yearValues = yearStore.GetSongYears();
|
||||
|
||||
if (yearValues.Count > 0)
|
||||
return Ok(yearValues);
|
||||
else
|
||||
return NotFound(new List<Year>());
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("read:year")]
|
||||
public IActionResult Get(int id)
|
||||
{
|
||||
var year = new Year
|
||||
{
|
||||
YearId = id
|
||||
};
|
||||
|
||||
var yearStore = HttpContext.RequestServices
|
||||
.GetService(typeof(YearRepository)) as YearRepository;
|
||||
|
||||
if (yearStore.DoesYearExist(year))
|
||||
{
|
||||
year = yearStore.GetSongYear(year);
|
||||
|
||||
return Ok(year);
|
||||
}
|
||||
else
|
||||
return NotFound(new Year());
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Contexts
|
||||
{
|
||||
public class AlbumContext : DbContext
|
||||
{
|
||||
public DbSet<Album> Albums { get; set; }
|
||||
|
||||
public AlbumContext(DbContextOptions<AlbumContext> options) : base(options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Album>()
|
||||
.ToTable("Album");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Contexts
|
||||
{
|
||||
public class ArtistContext : DbContext
|
||||
{
|
||||
public DbSet<Artist> Artists { get; set; }
|
||||
|
||||
public ArtistContext(DbContextOptions<ArtistContext> options) : base (options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Artist>()
|
||||
.ToTable("Artist");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Contexts
|
||||
{
|
||||
public class CoverArtContext : DbContext
|
||||
{
|
||||
public DbSet<CoverArt> CoverArtImages { get; set; }
|
||||
|
||||
public CoverArtContext(DbContextOptions<CoverArtContext> options) : base(options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<CoverArt>()
|
||||
.ToTable("CoverArt");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Contexts
|
||||
{
|
||||
public class GenreContext : DbContext
|
||||
{
|
||||
public DbSet<Genre> Genres { get; set; }
|
||||
public GenreContext(DbContextOptions<GenreContext> options) : base(options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Genre>()
|
||||
.ToTable("Genre");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Contexts
|
||||
{
|
||||
public class SongContext : DbContext
|
||||
{
|
||||
public DbSet<Song> Songs { get; set; }
|
||||
|
||||
|
||||
public SongContext(DbContextOptions<SongContext> options) : base(options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Song>()
|
||||
.ToTable("Song");
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(s => s.Album)
|
||||
.WithMany(al => al.Songs)
|
||||
.HasForeignKey(s => s.AlbumId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(sa => sa.SongArtist)
|
||||
.WithMany(ar => ar.Songs)
|
||||
.HasForeignKey(s => s.ArtistId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(s => s.SongGenre)
|
||||
.WithMany(gnr => gnr.Songs)
|
||||
.HasForeignKey(s => s.GenreId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(s => s.SongYear)
|
||||
.WithMany(yr => yr.Songs)
|
||||
.HasForeignKey(s => s.YearId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(s => s.SongCoverArt)
|
||||
.WithMany(ca => ca.Songs)
|
||||
.HasForeignKey(s => s.CoverArtId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.Year)
|
||||
.IsRequired(false);
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.YearId)
|
||||
.IsRequired(false);
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.GenreId)
|
||||
.IsRequired(false);
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.ArtistId)
|
||||
.IsRequired(false);
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.AlbumId)
|
||||
.IsRequired(false);
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.CoverArtId)
|
||||
.IsRequired(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Contexts
|
||||
{
|
||||
public class UserContext : DbContext
|
||||
{
|
||||
public DbSet<User> Users { get; set; }
|
||||
|
||||
|
||||
public UserContext(DbContextOptions<UserContext> options) : base(options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<User>()
|
||||
.ToTable("User");
|
||||
modelBuilder.Entity<User>()
|
||||
.Property(u => u.LastLogin).IsRequired(false);
|
||||
modelBuilder.Entity<User>()
|
||||
.Property(u => u.DateCreated).HasDefaultValue(DateTime.Now);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Contexts
|
||||
{
|
||||
public class YearContext : DbContext
|
||||
{
|
||||
public DbSet<Year> YearValues { get; set; }
|
||||
|
||||
public YearContext(DbContextOptions<YearContext> options) : base(options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Year>()
|
||||
.ToTable("Year");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,386 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Repositories
|
||||
{
|
||||
public class AlbumRepository : BaseRepository
|
||||
{
|
||||
#region Fields
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public AlbumRepository(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public List<Album> GetAlbumWithoutCount()
|
||||
{
|
||||
var albums = new List<Album>();
|
||||
|
||||
if (AnyAlbums())
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT * FROM Album";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
albums = ParseData(reader);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return albums;
|
||||
}
|
||||
public List<Album> GetAlbums()
|
||||
{
|
||||
List<Album> albums = new List<Album>();
|
||||
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT alb.*,COUNT(*) AS SongCount FROM Album alb " +
|
||||
"LEFT JOIN Song sng ON alb.AlbumId=sng.AlbumId WHERE " +
|
||||
"alb.AlbumId=sng.AlbumId GROUP BY alb.AlbumId";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
albums = ParseData(reader);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return albums;
|
||||
}
|
||||
|
||||
public Album GetAlbum(Album album)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT alb.*, COUNT(*) AS SongCount FROM Album alb " +
|
||||
"LEFT JOIN Song sng ON alb.AlbumId=sng.AlbumId WHERE "+
|
||||
"alb.AlbumId=@AlbumId LIMIT 1";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@AlbumId", album.AlbumId);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
album = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return album;
|
||||
}
|
||||
public Album GetAlbum(Song song)
|
||||
{
|
||||
var album = new Album();
|
||||
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT alb.*, 0 AS SongCount FROM Album alb " +
|
||||
"WHERE alb.Title=@Title LIMIT 1";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
Console.WriteLine($"Album title {song.AlbumTitle}");
|
||||
cmd.Parameters.AddWithValue("@Title", song.AlbumTitle);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
album = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return album;
|
||||
}
|
||||
public Album GetAlbum(Song song, bool retrieveCount)
|
||||
{
|
||||
var album = new Album();
|
||||
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = string.Empty;
|
||||
if (retrieveCount)
|
||||
query = "SELECT alb.*, COUNT(*) AS SongCount FROM Album alb " +
|
||||
"LEFT JOIN Song sng ON alb.AlbumId=sng.AlbumId WHERE " +
|
||||
"alb.Title=@Title GROUP BY alb.AlbumId LIMIT 1";
|
||||
else
|
||||
query = "SELECT alb.*, 0 AS SongCount FROM Album alb WHERE " +
|
||||
"alb.Title=@Title LIMIT 1";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", song.AlbumTitle);
|
||||
Console.WriteLine($"repo alb {song.AlbumTitle}");
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
album = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return album;
|
||||
}
|
||||
|
||||
public bool DoesAlbumExist(Album album)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT alb.*, 0 AS SongCount FROM Album alb WHERE alb.AlbumId=@AlbumId";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@AlbumId", album.AlbumId);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
album = ParseSingleData(reader);
|
||||
|
||||
if (album.Title != null)
|
||||
{
|
||||
_logger.Info($"Album {album.Title} exists");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public bool DoesAlbumExist(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT alb.*, 0 AS SongCount FROM Album alb WHERE alb.Title=@Title";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", song.AlbumTitle);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
var album = ParseSingleData(reader);
|
||||
|
||||
if (!String.IsNullOrEmpty(album.Title))
|
||||
{
|
||||
_logger.Info($"Album {album.Title} exists");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SaveAlbum(Album album)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "INSERT INTO Album(Title, AlbumArtist)" +
|
||||
" VALUES (@Title, @AlbumArtist)";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", album.Title);
|
||||
cmd.Parameters.AddWithValue("@AlbumArtist", album.AlbumArtist);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void UpdateAlbum(Album album)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "UPDATE Album SET Title=@Title, AlbumArtist=" +
|
||||
"@AlbumArtist WHERE AlbumId=@AlbumId";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", album.Title);
|
||||
cmd.Parameters.AddWithValue("@AlbumArtist", album.AlbumArtist);
|
||||
cmd.Parameters.AddWithValue("@AlbumId", album.AlbumId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void DeleteAlbum(Album album)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "DELETE FROM Album WHERE AlbumId=@AlbumId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@AlbumId", album.AlbumId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Album> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
List<Album> albums = new List<Album>();
|
||||
_logger.Info("Retrieving album records");
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["AlbumId"]);
|
||||
var title = reader["Title"].ToString();
|
||||
var albumArtist = reader["AlbumArtist"].ToString();
|
||||
var songCount = Convert.ToInt32(reader["SongCount"]);
|
||||
albums.Add(new Album
|
||||
{
|
||||
AlbumId = id,
|
||||
Title = title,
|
||||
AlbumArtist = albumArtist,
|
||||
SongCount = songCount
|
||||
});
|
||||
}
|
||||
|
||||
_logger.Info("Album records retrieved");
|
||||
|
||||
return albums;
|
||||
}
|
||||
private Album ParseSingleData(MySqlDataReader reader)
|
||||
{
|
||||
Album album = new Album();
|
||||
_logger.Info("Retrieving single album record");
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["AlbumId"]);
|
||||
var title = reader["Title"].ToString();
|
||||
var albumArtist = reader["AlbumArtist"].ToString();
|
||||
var songCount = Convert.ToInt32(reader["SongCount"]);
|
||||
album = new Album
|
||||
{
|
||||
AlbumId = id,
|
||||
Title = title,
|
||||
AlbumArtist = albumArtist,
|
||||
SongCount = songCount
|
||||
};
|
||||
}
|
||||
_logger.Info("Single ablum retreived");
|
||||
|
||||
return album;
|
||||
}
|
||||
|
||||
private bool AnyAlbums()
|
||||
{
|
||||
var albums = new List<Album>();
|
||||
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT * FROM Album";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
albums = ParseData(reader);
|
||||
}
|
||||
|
||||
if (albums.Count > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,355 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MySql.Data.MySqlClient;
|
||||
//using NLog;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Repositories
|
||||
{
|
||||
public class ArtistRepository : BaseRepository
|
||||
{
|
||||
#region Fields
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public ArtistRepository(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public List<Artist> GetArtists()
|
||||
{
|
||||
List<Artist> artists = new List<Artist>();
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT art.*, COUNT(*) AS SongCount FROM Artist " +
|
||||
"art LEFT JOIN Song sng ON art.ArtistId=sng.ArtistId " +
|
||||
"GROUP BY art.ArtistId";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
artists = ParseData(reader);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return artists;
|
||||
}
|
||||
|
||||
public Artist GetArtist(Artist artist)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Retrieving artist record from the database");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT art.*, COUNT(*) AS SongCount FROM Artist " +
|
||||
"art LEFT JOIN Song sng ON art.ArtistId=sng.ArtistId " +
|
||||
"WHERE art.ArtistId=@ArtistId";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@ArtistId", artist.ArtistId);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
artist = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return artist;
|
||||
}
|
||||
public Artist GetArtist(Song song)
|
||||
{
|
||||
Artist artist = new Artist();
|
||||
try
|
||||
{
|
||||
_logger.Info("Retrieving artist record from the database");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT art.*, 0 AS SongCount FROM Artist " +
|
||||
"art WHERE art.Name=@Name";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Name", song.Artist);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
artist = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return artist;
|
||||
}
|
||||
public Artist GetArtist(Song song, bool retrieveCount)
|
||||
{
|
||||
var artist = new Artist();
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Info("Retrieving artist record from the database");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = string.Empty;
|
||||
|
||||
if (retrieveCount)
|
||||
query = "SELECT art.*, COUNT(*) AS SongCount FROM Artist " +
|
||||
"art LEFT JOIN Song sng ON art.ArtistId=sng.ArtistId " +
|
||||
"WHERE art.Name=@Name GROUP BY art.ArtistId LIMIT 1";
|
||||
else
|
||||
query = "SELECT art.*, 0 AS SongCount FROM Artist art " +
|
||||
"WHERE art.Name=@Name LIMIT 1";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Name", song.Artist);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
artist = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return artist;
|
||||
}
|
||||
|
||||
public bool DoesArtistExist(Artist artist)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Checking to see if Artist exists");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT art.*, 0 AS SongCount FROM Artist art WHERE art.ArtistId=@ArtistId";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@ArtistId", artist.ArtistId);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
artist = ParseSingleData(reader);
|
||||
|
||||
if (artist.Name != null)
|
||||
{
|
||||
_logger.Info($"Artist {artist.Name} exists");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
_logger.Info("Could not successfully retrieve Artist");
|
||||
|
||||
return false;
|
||||
}
|
||||
public bool DoesArtistExist(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Checking to see if Artist exists");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT art.*, 0 AS SongCount FROM Artist art WHERE art.Name=@Name";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Name", song.Artist);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
var artist = ParseSingleData(reader);
|
||||
|
||||
if (!String.IsNullOrEmpty(artist.Name))
|
||||
{
|
||||
_logger.Info($"Artist {artist.Name} exists");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
_logger.Info("Could not successfully retrieve Artist");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void SaveArtist(Artist artist)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Saving artist record");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "INSERT INTO Artist(Name) VALUES(@Name)";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Name", artist.Name);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Info("Artist record has successfully been saved");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void UpdateArtist(Artist artist)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Updating artist record");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "UPDATE Artist SET Name=@Name WHERE ArtistId=@ArtistId";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Name", artist.Name);
|
||||
cmd.Parameters.AddWithValue("@ArtistId", artist.ArtistId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Info("Artist record has successfully been saved");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void DeleteArtist(Artist artist)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Deleting artist record");
|
||||
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "DELETE FROM Artist WHERE ArtistId=@ArtistId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@ArtistId", artist.ArtistId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Artist> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
List<Artist> artists = new List<Artist>();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["ArtistId"]);
|
||||
var name = reader["Name"].ToString();
|
||||
var songCount = Convert.ToInt32(reader["SongCount"].ToString());
|
||||
artists.Add(new Artist
|
||||
{
|
||||
ArtistId = id,
|
||||
Name = name,
|
||||
SongCount = songCount
|
||||
});
|
||||
}
|
||||
|
||||
_logger.Info("Artist records retrieved");
|
||||
|
||||
return artists;
|
||||
}
|
||||
|
||||
private Artist ParseSingleData(MySqlDataReader reader)
|
||||
{
|
||||
Artist artist = new Artist();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["ArtistId"]);
|
||||
var name = reader["Name"].ToString();
|
||||
var songCount = Convert.ToInt32(reader["SongCount"].ToString());
|
||||
artist.ArtistId = id;
|
||||
artist.Name = name;
|
||||
artist.SongCount = songCount;
|
||||
}
|
||||
|
||||
_logger.Info("Single artist record retrieved");
|
||||
|
||||
return artist;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System;
|
||||
|
||||
using MySql.Data.MySqlClient;
|
||||
using NLog;
|
||||
|
||||
namespace Icarus.Database.Repositories
|
||||
{
|
||||
public class BaseRepository
|
||||
{
|
||||
#region Fields
|
||||
protected string _connectionString;
|
||||
protected static Logger _logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
protected MySqlConnection GetConnection()
|
||||
{
|
||||
return new MySqlConnection(_connectionString);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Types;
|
||||
|
||||
namespace Icarus.Database.Repositories
|
||||
{
|
||||
public class CoverArtRepository : BaseRepository
|
||||
{
|
||||
#region Constructors
|
||||
public CoverArtRepository(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public List<CoverArt> GetCoverArtRecords()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
_logger.Info("Querying cover art records");
|
||||
|
||||
var query = "SELECT cv.*, sng.Id AS SongId FROM CoverArt " +
|
||||
"cv LEFT JOIN Song sng ON cv.CoverArtId=sng.CoverArtId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
return ParseData(reader);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public CoverArt GetCoverArt(CoverArt cover)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
_logger.Info("Querying cover art record");
|
||||
|
||||
var query = "SELECT * FROM CoverArt WHERE " +
|
||||
"CoverArtId=@CoverArtId";
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters
|
||||
.AddWithValue("@CoverArtId", cover.CoverArtId);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
return ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public CoverArt GetCoverArt(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
_logger.Info("Querying cover art record");
|
||||
|
||||
var query = "SELECT cov.* FROM CoverArt cov LEFT JOIN " +
|
||||
"Song sng ON cov.CoverArtId=sng.CoverArtId WHERE " +
|
||||
"sng.Id=@SongId";
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@SongId", song.Id);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
return ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public CoverArt GetCoverArt(CoverArtField field, CoverArt cover)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
_logger.Info("Querying cover art record");
|
||||
|
||||
using (var cmd = new MySqlCommand(BuildQuery(field), conn))
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case CoverArtField.SongTitle:
|
||||
cmd.Parameters.AddWithValue("@SongTitle",
|
||||
cover.SongTitle);
|
||||
break;
|
||||
case CoverArtField.ImagePath:
|
||||
cmd.Parameters.AddWithValue("@ImagePath",
|
||||
cover.ImagePath);
|
||||
break;
|
||||
}
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
return ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool DoesCoverArtExist(CoverArt cover)
|
||||
{
|
||||
return GetCoverArt(cover) != null ? true : false;
|
||||
}
|
||||
public bool DoesCoverArtExist(Song song)
|
||||
{
|
||||
return GetCoverArt(song) != null ? true : false;
|
||||
}
|
||||
|
||||
public void SaveCoverArt(CoverArt coverArt)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
_logger.Info("Saving cover art record");
|
||||
|
||||
var query = "INSERT INTO CoverArt(SongTitle, ImagePath) " +
|
||||
"VALUES(@SongTitle, @ImagePath)";
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters
|
||||
.AddWithValue("@SongTitle", coverArt.SongTitle);
|
||||
cmd.Parameters
|
||||
.AddWithValue("@ImagePath", coverArt.ImagePath);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void DeleteCoverArt(CoverArt cover)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
_logger.Info("Deleting cover art record");
|
||||
|
||||
var query = "DELETE FROM CoverArt WHERE " +
|
||||
"CoverArtId=@CoverArtId";
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters
|
||||
.AddWithValue("@CoverArtId", cover.CoverArtId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
private List<CoverArt> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
if (reader.HasRows)
|
||||
{
|
||||
var coverArtList = new List<CoverArt>();
|
||||
_logger.Info("Parsing cover art records");
|
||||
while (reader.Read())
|
||||
coverArtList.Add(new CoverArt
|
||||
{
|
||||
CoverArtId = Convert.ToInt32(reader["CoverArtId"]),
|
||||
SongTitle = reader["SongTitle"].ToString(),
|
||||
ImagePath = reader["ImagePath"].ToString(),
|
||||
SongId = Convert.ToInt32(reader["SongId"].ToString())
|
||||
});
|
||||
|
||||
return coverArtList;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private CoverArt ParseSingleData(MySqlDataReader reader)
|
||||
{
|
||||
if (reader.HasRows)
|
||||
{
|
||||
_logger.Info("Parsing single cover art record");
|
||||
reader.Read();
|
||||
|
||||
return new CoverArt
|
||||
{
|
||||
CoverArtId = Convert.ToInt32(reader["CoverArtId"]),
|
||||
SongTitle = reader["SongTitle"].ToString(),
|
||||
ImagePath = reader["ImagePath"].ToString()
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string BuildQuery(CoverArtField field)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case CoverArtField.SongTitle:
|
||||
return "SELECT * FROM CoverArt WHERE SongTitle=@SongTitle";
|
||||
case CoverArtField.ImagePath:
|
||||
return "SELECT * FROM CoverArt WHERE ImagePath=" +
|
||||
"@ImagePath";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool? AnyCoverArt()
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
_logger.Info("Checking to see if there are any cover art " +
|
||||
"records");
|
||||
|
||||
var query = "SELECT * FROM CoverArt";
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
return reader.HasRows;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,447 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Repositories
|
||||
{
|
||||
public class GenreRepository : BaseRepository
|
||||
{
|
||||
#region Fields
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public GenreRepository(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public List<Genre> GetGenresWithoutCount()
|
||||
{
|
||||
_logger.Info("Retrieving all genre records without song counts");
|
||||
|
||||
var genres = new List<Genre>();
|
||||
|
||||
if (AnyGenre())
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT * FROM Genre";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
genres = ParseData(reader);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
return genres;
|
||||
}
|
||||
public List<Genre> GetGenres()
|
||||
{
|
||||
_logger.Info("Retrieving Genre records");
|
||||
|
||||
var genres = new List<Genre>();
|
||||
|
||||
if (AnyGenre())
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT gnr.*, COUNT(*) AS SongCount FROM Genre " +
|
||||
"gnr LEFT JOIN Song sng ON gnr.GenreId=sng.GenreId " +
|
||||
"GROUP BY gnr.GenreId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
genres = ParseData(reader);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
return genres;
|
||||
}
|
||||
|
||||
public Genre GetGenre(Genre genre)
|
||||
{
|
||||
_logger.Info("Retrieving Genre record");
|
||||
|
||||
if (DoesGenreExist(genre))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT gnr.*, COUNT(*) AS SongCount FROM Genre " +
|
||||
"gnr LEFT JOIN Song sng ON gnr.GenreId=sng.GenreId " +
|
||||
"WHERE gnr.GenreId=@GenreId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@GenreId", genre.GenreId);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
genre = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
return genre;
|
||||
}
|
||||
public Genre GetGenre(Song song)
|
||||
{
|
||||
_logger.Info("Retrieving Genre record");
|
||||
|
||||
var genre = new Genre();
|
||||
|
||||
if (DoesGenreExist(song))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT gnr.*, 0 AS SongCount FROM Genre " +
|
||||
"gnr WHERE gnr.GenreName=@GenreName";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@GenreName", song.Genre);
|
||||
_logger.Info($"Song genre:\n\n\n {song.Genre}");
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
genre = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
return genre;
|
||||
}
|
||||
public Genre GetGenre(Song song, bool retrieveCount)
|
||||
{
|
||||
_logger.Info("Retrieving Genre record");
|
||||
|
||||
var genre = new Genre();
|
||||
|
||||
if (DoesGenreExist(song))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = string.Empty;
|
||||
|
||||
if (retrieveCount)
|
||||
query = "SELECT gnr.*, COUNT(*) AS SongCount FROM Genre gnr " +
|
||||
"LEFT JOIN Song sng ON gnr.GenreId=sng.GenreId " +
|
||||
"WHERE gnr.GenreName=@GenreName GROUP BY gnr.GenreId " +
|
||||
"LIMIT 1";
|
||||
else
|
||||
query = "SELECT gnr.*, 0 AS SongCount FROM Genre gnr " +
|
||||
"WHERE gnr.GenreName=@GenreName LIMIT 1";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@GenreName", song.Genre);
|
||||
_logger.Info($"Song genre:\n\n\n {song.Genre}");
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
genre = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
return genre;
|
||||
}
|
||||
|
||||
public bool DoesGenreExist(Genre genre)
|
||||
{
|
||||
_logger.Info("Checking to see if Genre record exists");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT gnr.*, 0 AS SongCount FROM Genre gnr WHERE " +
|
||||
"gnr.GenreId=@GenreId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@GenreId", genre.GenreId);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
genre = ParseSingleData(reader);
|
||||
var genreName = genre.GenreName;
|
||||
|
||||
if (!string.IsNullOrEmpty(genreName))
|
||||
{
|
||||
_logger.Info("Genre exists");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
_logger.Info("Genre does not exist");
|
||||
|
||||
return false;
|
||||
}
|
||||
public bool DoesGenreExist(Song song)
|
||||
{
|
||||
_logger.Info("Checking to see if Genre record exists");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT gnr.*, 0 AS SongCount FROM Genre gnr WHERE " +
|
||||
"gnr.GenreName=@GenreName";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@GenreName", song.Genre);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
var genre = ParseSingleData(reader);
|
||||
var genreName = genre.GenreName;
|
||||
|
||||
if (!string.IsNullOrEmpty(genreName))
|
||||
{
|
||||
_logger.Info("Genre exists");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
_logger.Info("Genre does not exist");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SaveGenre(Genre genre)
|
||||
{
|
||||
_logger.Info("Saving Genre record");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "INSERT INTO Genre(GenreName) VALUES(@GenreName)";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@GenreName", genre.GenreName);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void UpdateGenre(Genre genre)
|
||||
{
|
||||
_logger.Info("Updating Genre record");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "UPDATE Genre SET GenreName=@GenreName " +
|
||||
"WHERE GenreId=@GenreId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@GenreName", genre.GenreName);
|
||||
cmd.Parameters.AddWithValue("@GenreId", genre.GenreId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void DeleteGenre(Genre genre)
|
||||
{
|
||||
_logger.Info("Deleting Genre record");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "DELETE FROM Genre WHERE GenreId=@GenreId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@GenreId", genre.GenreId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Genre> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
var genres = new List<Genre>();
|
||||
_logger.Info("Retrieving genre records");
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["GenreId"].ToString());
|
||||
var genreName = reader["GenreName"].ToString();
|
||||
var songCount = Convert.ToInt32(reader["SongCount"].ToString());
|
||||
|
||||
genres.Add(new Genre
|
||||
{
|
||||
GenreId = id,
|
||||
GenreName = genreName,
|
||||
SongCount = songCount
|
||||
});
|
||||
}
|
||||
|
||||
_logger.Info("Genre records retrieved");
|
||||
|
||||
return genres;
|
||||
}
|
||||
|
||||
private Genre ParseSingleData(MySqlDataReader reader)
|
||||
{
|
||||
var genre = new Genre();
|
||||
_logger.Info("Retrieving single genre record");
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["GenreId"].ToString());
|
||||
var genreName = reader["GenreName"].ToString();
|
||||
var songCount = Convert.ToInt32(reader["SongCount"].ToString());
|
||||
genre.GenreId = id;
|
||||
genre.GenreName = genreName;
|
||||
genre.SongCount = songCount;
|
||||
}
|
||||
|
||||
_logger.Info("Single genre record retrieved");
|
||||
|
||||
return genre;
|
||||
}
|
||||
|
||||
private bool AnyGenre()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT * FROM Genre";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
return reader.HasRows;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
_logger.Info("No genre records found");
|
||||
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,315 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Repositories
|
||||
{
|
||||
public class SongRepository : BaseRepository
|
||||
{
|
||||
#region Constructors
|
||||
public SongRepository(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public void SaveSong(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Saving song to the database");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
string query = "INSERT INTO Song(Title, AlbumTitle, Artist," +
|
||||
" Year, Genre, Duration, Filename, SongPath, AlbumId, " +
|
||||
"ArtistId, GenreId, YearId, CoverArtId) VALUES(@Title," +
|
||||
" @AlbumTitle, @Artist, @Year, @Genre, @Duration, " +
|
||||
"@Filename, @SongPath, @AlbumId, @ArtistId, @GenreId," +
|
||||
" @YearId, @CoverArtId)";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", song.Title);
|
||||
cmd.Parameters.AddWithValue("@AlbumTitle", song.AlbumTitle);
|
||||
cmd.Parameters.AddWithValue("@Artist", song.Artist);
|
||||
cmd.Parameters.AddWithValue("@Year", song.Year);
|
||||
cmd.Parameters.AddWithValue("@Genre", song.Genre);
|
||||
cmd.Parameters.AddWithValue("@Duration", song.Duration);
|
||||
cmd.Parameters.AddWithValue("@Filename", song.Filename);
|
||||
cmd.Parameters.AddWithValue("@SongPath", song.SongPath);
|
||||
cmd.Parameters.AddWithValue("@AlbumId", song.AlbumId);
|
||||
cmd.Parameters.AddWithValue("@ArtistId", song.ArtistId);
|
||||
cmd.Parameters.AddWithValue("@GenreId", song.GenreId);
|
||||
cmd.Parameters.AddWithValue("@YearId", song.YearId);
|
||||
cmd.Parameters.AddWithValue("@CoverArtId", song.CoverArtId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
_logger.Info("Successfully saved song to the database");
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred:\n{exMsg}");
|
||||
_logger.Error(exMsg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void UpdateSong(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
string query = "UPDATE Song SET Title=@Title, AlbumTitle=@AlbumTitle, " +
|
||||
"Artist=@Artist, Year=@Year, Genre=@Genre, Duration=@Duration, " +
|
||||
"Filename=@Filename, SongPath=@SongPath, AlbumId=@AlbumId, " +
|
||||
"ArtistId=@ArtistId, GenreId=@GenreId, YearId=@YearId WHERE Id=@Id";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", song.Title);
|
||||
cmd.Parameters.AddWithValue("@AlbumTitle", song.AlbumTitle);
|
||||
cmd.Parameters.AddWithValue("@Artist", song.Artist);
|
||||
cmd.Parameters.AddWithValue("@Year", song.Year);
|
||||
cmd.Parameters.AddWithValue("@Genre", song.Genre);
|
||||
cmd.Parameters.AddWithValue("@Duration", song.Duration);
|
||||
cmd.Parameters.AddWithValue("@Filename", song.Filename);
|
||||
cmd.Parameters.AddWithValue("@SongPath", song.SongPath);
|
||||
cmd.Parameters.AddWithValue("@Id", song.Id);
|
||||
cmd.Parameters.AddWithValue("@AlbumId", song.AlbumId);
|
||||
cmd.Parameters.AddWithValue("@ArtistId", song.ArtistId);
|
||||
cmd.Parameters.AddWithValue("@GenreId", song.GenreId);
|
||||
cmd.Parameters.AddWithValue("@YearId", song.YearId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
_logger.Info("Updated song");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
Console.WriteLine("An error occurred in SongRepository:");
|
||||
Console.WriteLine(msg);
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void DeleteSong(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Deleting song record");
|
||||
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "Delete FROM Song WHERE Id=@Id";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Id", song.Id);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void DeleteSong(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Deleting song record");
|
||||
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
string query = "DELETE FROM Song WHERE Id=@Id";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Id", id);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred:\n{exMsg}");
|
||||
_logger.Error(exMsg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
public List<Song> GetAllSongs()
|
||||
{
|
||||
var songs = new List<Song>();
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Info("Retrieving songs from the database");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT * FROM Song";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
songs = ParseData(reader);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error ocurred:\n{exMsg}");
|
||||
songs.Clear();
|
||||
_logger.Error(exMsg, "An error occurred");
|
||||
}
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
public Song GetSong(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Retrieving song from database");
|
||||
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT * FROM Song WHERE Id=@Id";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Id", song.Id);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
song = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
public Song GetSong(int id)
|
||||
{
|
||||
Song song = new Song();
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Info("Retrieving song from database");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT * FROM Song WHERE Id=@Id";
|
||||
|
||||
MySqlCommand cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@Id", id);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
song = ParseSingleData(reader);
|
||||
}
|
||||
_logger.Info("Song found");
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error ocurred: {exMsg}");
|
||||
_logger.Error(exMsg, "An error occurred");
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
public bool DoesSongExist(Song song)
|
||||
{
|
||||
_logger.Info("Checking to see if the song exists");
|
||||
var songInDatabase = GetSong(song);
|
||||
var title = songInDatabase.Title;
|
||||
|
||||
if (!string.IsNullOrEmpty(title))
|
||||
{
|
||||
_logger.Info("Song exists");
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.Info("Song does not exists");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<Song> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
|
||||
var songs = new List<Song>();
|
||||
while (reader.Read())
|
||||
{
|
||||
songs.Add(new Song
|
||||
{
|
||||
Id = Convert.ToInt32(reader["Id"]),
|
||||
Title = reader["Title"].ToString(),
|
||||
AlbumTitle = reader["AlbumTitle"].ToString(),
|
||||
Artist = reader["Artist"].ToString(),
|
||||
Year = Convert.ToInt32(reader["Year"]),
|
||||
Genre = reader["Genre"].ToString(),
|
||||
Duration = Convert.ToInt32(reader["Duration"]),
|
||||
Filename = reader["Filename"].ToString(),
|
||||
SongPath = reader["SongPath"].ToString(),
|
||||
AlbumId = Convert.ToInt32(reader["AlbumId"].ToString()),
|
||||
ArtistId = Convert.ToInt32(reader["ArtistId"].ToString()),
|
||||
GenreId = Convert.ToInt32(reader["GenreId"].ToString()),
|
||||
YearId = Convert.ToInt32(reader["YearId"].ToString()),
|
||||
CoverArtId = Convert.ToInt32(reader["CoverArtId"].ToString())
|
||||
});
|
||||
}
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
private Song ParseSingleData(MySqlDataReader reader)
|
||||
{
|
||||
var song = new Song();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
song.Id = Convert.ToInt32(reader["Id"]);
|
||||
song.Title = reader["Title"].ToString();
|
||||
song.AlbumTitle = reader["AlbumTitle"].ToString();
|
||||
song.Artist = reader["Artist"].ToString();
|
||||
song.Year = Convert.ToInt32(reader["Year"].ToString());
|
||||
song.Genre = reader["Genre"].ToString();
|
||||
song.Duration = Convert.ToInt32(reader["Duration"]);
|
||||
song.Filename = reader["Filename"].ToString();
|
||||
song.SongPath = reader["SongPath"].ToString();
|
||||
song.AlbumId = Convert.ToInt32(reader["AlbumId"].ToString());
|
||||
song.ArtistId = Convert.ToInt32(reader["ArtistId"].ToString());
|
||||
song.GenreId = Convert.ToInt32(reader["GenreId"].ToString());
|
||||
song.YearId = Convert.ToInt32(reader["YearId"].ToString());
|
||||
song.CoverArtId = Convert.ToInt32(reader["CoverArtId"].ToString());
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Repositories
|
||||
{
|
||||
public class UserRepository: BaseRepository
|
||||
{
|
||||
#region Fields
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructor
|
||||
public UserRepository(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public void SaveUser(User user)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Saving user");
|
||||
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
string query = "INSERT INTO User(Username, Password, Nickname, Email" +
|
||||
", PhoneNumber, Firstname, Lastname, EmailVerified) " +
|
||||
"VALUES(@Username, @Password, @Nickname, @Email, @PhoneNumber," +
|
||||
" @Firstname, @Lastname, @EmailVerified)";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Username", user.Username);
|
||||
cmd.Parameters.AddWithValue("@Password", user.Password);
|
||||
cmd.Parameters.AddWithValue("@Nickname", user.Nickname);
|
||||
cmd.Parameters.AddWithValue("@Email", user.Email);
|
||||
cmd.Parameters.AddWithValue("@PhoneNumber", user.PhoneNumber);
|
||||
cmd.Parameters.AddWithValue("@Firstname", user.Firstname);
|
||||
cmd.Parameters.AddWithValue("@Lastname", user.Lastname);
|
||||
cmd.Parameters.AddWithValue("@EmailVerified", user.EmailVerified);
|
||||
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Info("Successfully saved user");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred:\n{exMsg}");
|
||||
_logger.Error(exMsg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
public User RetrieveUser(User user)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Info("Retrieving user");
|
||||
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT * FROM User WHERE Username=@Username";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Username", user.Username);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
user = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Info("Successfully retrieved user");
|
||||
|
||||
return user;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred:\n{exMsg}");
|
||||
_logger.Error(exMsg, "An error occurred");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool DoesUserExist(User user)
|
||||
{
|
||||
var username = user.Username;
|
||||
try
|
||||
{
|
||||
_logger.Info($"Checking to see if {user.Username} exists");
|
||||
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT * FROM User WHERE Username=@Username";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Username", user.Username);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
user = ParseSingleData(reader, true);
|
||||
username = user.Username;
|
||||
|
||||
if (!string.IsNullOrEmpty(username))
|
||||
{
|
||||
_logger.Info($"The user {username} exists");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
_logger.Info($"The user {username} does not exists");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private User ParseSingleData(MySqlDataReader reader)
|
||||
{
|
||||
var user = new User();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["Id"].ToString());
|
||||
var username = reader["Username"].ToString();
|
||||
var password = reader["Password"].ToString();
|
||||
var nickname = reader["Nickname"].ToString();
|
||||
var email = reader["Email"].ToString();
|
||||
var phoneNumber = reader["PhoneNumber"].ToString();
|
||||
var emailVerified = reader["EmailVerified"].ToString() == "1";
|
||||
var firstname = reader["Firstname"].ToString();
|
||||
var lastname = reader["Lastname"].ToString();
|
||||
var rawLastLogin = reader["LastLogin"].ToString();
|
||||
|
||||
var parsedDateCreated = DateTime.Parse(reader["DateCreated"].ToString());
|
||||
|
||||
var dateCreated = DateTime.Parse(parsedDateCreated.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
|
||||
if (!string.IsNullOrEmpty(rawLastLogin))
|
||||
{
|
||||
var parsedLastLogin = DateTime.Parse(rawLastLogin);
|
||||
var lastLogin = DateTime.Parse(parsedLastLogin.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
user.LastLogin = lastLogin;
|
||||
}
|
||||
|
||||
user.Id = id;
|
||||
user.Username = username;
|
||||
user.Password = password;
|
||||
user.Nickname = nickname;
|
||||
user.Email = email;
|
||||
user.PhoneNumber = phoneNumber;
|
||||
user.EmailVerified = emailVerified;
|
||||
user.Firstname = firstname;
|
||||
user.Lastname = lastname;
|
||||
user.DateCreated = dateCreated;
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
private User ParseSingleData(MySqlDataReader reader, bool ignoreLastLogin)
|
||||
{
|
||||
var user = new User();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["Id"].ToString());
|
||||
var username = reader["Username"].ToString();
|
||||
var nickname = reader["Nickname"].ToString();
|
||||
var email = reader["Email"].ToString();
|
||||
var phoneNumber = reader["PhoneNumber"].ToString();
|
||||
var emailVerified = reader["EmailVerified"].ToString() == "1";
|
||||
var firstname = reader["Firstname"].ToString();
|
||||
var lastname = reader["Lastname"].ToString();
|
||||
|
||||
var parsedDateCreated = DateTime.Parse(reader["DateCreated"].ToString());
|
||||
|
||||
var dateCreated = DateTime.Parse(parsedDateCreated.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
|
||||
if (!ignoreLastLogin)
|
||||
{
|
||||
var parsedLastLogin = DateTime.Parse(reader["LastLogin"].ToString());
|
||||
var lastLogin = DateTime.Parse(parsedLastLogin.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
user.LastLogin = lastLogin;
|
||||
}
|
||||
|
||||
user.Id = id;
|
||||
user.Username = username;
|
||||
user.Nickname = nickname;
|
||||
user.Email = email;
|
||||
user.PhoneNumber = phoneNumber;
|
||||
user.EmailVerified = emailVerified;
|
||||
user.Firstname = firstname;
|
||||
user.Lastname = lastname;
|
||||
user.DateCreated = dateCreated;
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,367 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Repositories
|
||||
{
|
||||
public class YearRepository : BaseRepository
|
||||
{
|
||||
#region Fields
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public YearRepository(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public List<Year> GetSongYears()
|
||||
{
|
||||
_logger.Info("Retrieving Year records");
|
||||
|
||||
var yearValues = new List<Year>();
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT yr.*, COUNT(*) AS SongCount FROM Year " +
|
||||
"yr LEFT JOIN Song sng ON yr.YearId=sng.YearId " +
|
||||
"GROUP BY yr.YearId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
yearValues = ParseData(reader);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return yearValues;
|
||||
}
|
||||
|
||||
public Year GetSongYear(Year year)
|
||||
{
|
||||
_logger.Info("Retrieving Year record");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT yr.*, COUNT(*) AS SongCount FROM Year " +
|
||||
"yr LEFT JOIN Song sng ON yr.YearId=sng.YearId WHERE " +
|
||||
"YearId=@YearId GROUP BY yr.YearId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@YearId", year.YearId);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
year = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return year;
|
||||
}
|
||||
public Year GetSongYear(Song song)
|
||||
{
|
||||
var year = new Year();
|
||||
|
||||
_logger.Info("Retrieving Year record");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT yr.*, 0 AS SongCount FROM Year " +
|
||||
"yr WHERE yr.YearValue=@YearValue";
|
||||
|
||||
using(var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@YearValue", song.Year);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
year = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return year;
|
||||
}
|
||||
public Year GetSongYear(Song song, bool retrieveCount)
|
||||
{
|
||||
var year = new Year();
|
||||
|
||||
_logger.Info("Retrieving year record");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = string.Empty;
|
||||
|
||||
if (retrieveCount)
|
||||
query = "SELECT yr.*, COUNT(*) AS SongCount FROM Year yr " +
|
||||
"LEFT JOIN Song sng ON yr.YearValue=sng.Year WHERE " +
|
||||
"yr.YearValue=@YearValue GROUP BY yr.YearId LIMIT 1";
|
||||
else
|
||||
query = "SELECT yr.*, 0 AS SongCount FROM Year yr " +
|
||||
"WHERE yr.YearValue=@YearValue LIMIT 1";
|
||||
|
||||
using(var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@YearValue", song.Year);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
year = ParseSingleData(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return year;
|
||||
}
|
||||
|
||||
public bool DoesYearExist(Year year)
|
||||
{
|
||||
_logger.Info("Checking to see if Year record exists");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT yr.*, 0 AS SongCount FROM Year yr WHERE " +
|
||||
"yr.YearId=@YearId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@YearId", year.YearId);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
year = ParseSingleData(reader);
|
||||
|
||||
if (year.YearValue > 0)
|
||||
{
|
||||
_logger.Info("Year record exists");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
_logger.Info("Year record does not exist");
|
||||
|
||||
return false;
|
||||
}
|
||||
public bool DoesYearExist(Song song)
|
||||
{
|
||||
_logger.Info("Checking to see if Year record exists");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "SELECT yr.*, 0 AS SongCount FROM Year yr WHERE " +
|
||||
"yr.YearValue=@YearValue";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@YearValue", song.Year);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
var year = ParseSingleData(reader);
|
||||
|
||||
if (year.YearValue > 0)
|
||||
{
|
||||
_logger.Info("Year record exists");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
|
||||
_logger.Info("Year record does not exist");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SaveYear(Year year)
|
||||
{
|
||||
_logger.Info("Saving Year record");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "INSERT INTO Year(YearValue) VALUES(@YearValue)";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@YearValue", year.YearValue);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void UpdateYear(Year year)
|
||||
{
|
||||
_logger.Info("Deleting Year record");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "UPDATE Year SET YearValue=@YearValue WHERE YearId=@YearId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@YearId", year.YearId);
|
||||
cmd.Parameters.AddWithValue("@YearValue", year.YearValue);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void DeleteYear(Year year)
|
||||
{
|
||||
_logger.Info("Deleting Year record");
|
||||
|
||||
try
|
||||
{
|
||||
using (var conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
var query = "DELETE FROM Year WHERE YearId=@YearId";
|
||||
|
||||
using (var cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@YearId", year.YearId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Year> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
var yearValues = new List<Year>();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["YearId"].ToString());
|
||||
var year = Convert.ToInt32(reader["YearValue"].ToString());
|
||||
var songCount = Convert.ToInt32(reader["SongCount"].ToString());
|
||||
|
||||
yearValues.Add(new Year
|
||||
{
|
||||
YearId = id,
|
||||
YearValue = year,
|
||||
SongCount = songCount
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return yearValues;
|
||||
}
|
||||
|
||||
private Year ParseSingleData(MySqlDataReader reader)
|
||||
{
|
||||
var yearValue = new Year();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["YearId"].ToString());
|
||||
var year = Convert.ToInt32(reader["YearValue"].ToString());
|
||||
var songCount = Convert.ToInt32(reader["SongCount"].ToString());
|
||||
|
||||
yearValue.YearId = id;
|
||||
yearValue.YearValue = year;
|
||||
yearValue.SongCount = songCount;
|
||||
}
|
||||
|
||||
return yearValue;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="3.1.3" />
|
||||
<PackageReference Include="DotNetZip" Version="1.13.3" />
|
||||
<PackageReference Include="EntityFramework" Version="6.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.2.6">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="mysql.data" Version="8.0.15" />
|
||||
<PackageReference Include="MySql.Data.Entity" Version="7.0.7-m61" />
|
||||
<PackageReference Include="MySql.Data.EntityFrameworkCore" Version="8.0.15" />
|
||||
<PackageReference Include="MySql.Data.EntityFrameworkCore.Design" Version="8.0.15" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="4.8.1" />
|
||||
<!--<PackageReference Include="RestSharp" Version="106.6.9" /> -->
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.4.0" />
|
||||
<!--<PackageReference Include="taglib" Version="2.1.0" /> -->
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Update="nlog.config" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Content Include="Images/Stock/*.*" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ActiveDebugProfile>Icarus</ActiveDebugProfile>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26124.0
|
||||
MinimumVisualStudioVersion = 15.0.26124.0
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Icarus", "Icarus.csproj", "{3BEBAB33-17BF-4183-9664-3D537A684138}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3BEBAB33-17BF-4183-9664-3D537A684138}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,28 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(icarus)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set(SOURCES
|
||||
src/directory_manager.cpp
|
||||
src/imageFile.cpp
|
||||
src/metadata_retriever.cpp
|
||||
src/token_manager.cpp
|
||||
)
|
||||
set(HEADERS
|
||||
include/models.h
|
||||
include/directory_manager.h
|
||||
include/imageFile.h
|
||||
include/metadata_retriever.h
|
||||
)
|
||||
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup()
|
||||
|
||||
add_subdirectory(cpr)
|
||||
|
||||
add_library(icarus SHARED ${SOURCES} ${HEADERS})
|
||||
include_directories(${CPR_INCLUDE_DIRS} include)
|
||||
target_link_libraries(icarus "-lstdc++fs" tag ${CONAN_LIBS} ${CPR_LIBRARIES})
|
||||
@@ -1,14 +0,0 @@
|
||||
#include "models.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string create_directory_process(Song, const char*);
|
||||
std::string read_cover_art(const char*);
|
||||
|
||||
bool delete_song(Song*);
|
||||
|
||||
void copy_stock_to_root(const char*, const std::string);
|
||||
void copy_song_to_path(const char*, const char*);
|
||||
void delete_cover_art_file(const std::string);
|
||||
void delete_directories(Song, const char*);
|
||||
void delete_song(Song);
|
||||
@@ -1,38 +0,0 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <taglib/attachedpictureframe.h>
|
||||
#include <taglib/mpegfile.h>
|
||||
#include <taglib/tag.h>
|
||||
#include <taglib/tfile.h>
|
||||
#include <taglib/tfilestream.h>
|
||||
#include <taglib/fileref.h>
|
||||
#include <taglib/tbytevector.h>
|
||||
#include <taglib/tbytevectorstream.h>
|
||||
#include <taglib/tpropertymap.h>
|
||||
#include <taglib/id3v2tag.h>
|
||||
|
||||
class imageFile : public TagLib::File
|
||||
{
|
||||
public:
|
||||
imageFile(const char *file);
|
||||
/**
|
||||
imageFile(const char *file) : TagLib::File(file)
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
TagLib::ByteVector data();
|
||||
/**
|
||||
TagLib::ByteVector data()
|
||||
{
|
||||
return readBlock(length());
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
private:
|
||||
virtual TagLib::Tag *tag() const { return 0; }
|
||||
virtual TagLib::AudioProperties *audioProperties() const { return 0; }
|
||||
virtual bool save() { return false; }
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "models.h"
|
||||
@@ -1,43 +0,0 @@
|
||||
#ifndef MODELS_H_
|
||||
#define MODELS_H_
|
||||
|
||||
struct Song
|
||||
{
|
||||
int Id;
|
||||
char Title[1024];
|
||||
char Artist[1024];
|
||||
char Album[1024];
|
||||
char Genre[1024];
|
||||
int Year;
|
||||
int Duration;
|
||||
char SongPath[1024];
|
||||
};
|
||||
|
||||
struct Cover
|
||||
{
|
||||
int Id;
|
||||
char SongTitle[1024];
|
||||
char ImagePath[1024];
|
||||
};
|
||||
|
||||
struct LoginRes
|
||||
{
|
||||
int UserId;
|
||||
char Username[1024];
|
||||
char Token[1024];
|
||||
char TokenType[1024];
|
||||
char Message[1024];
|
||||
int Expiration;
|
||||
};
|
||||
|
||||
struct TokenReq
|
||||
{
|
||||
char ClientId[1024];
|
||||
char ClientSecret[1024];
|
||||
char Audience[1024];
|
||||
char GrantType[1024];
|
||||
char URI[1024];
|
||||
char Endpoint[1024];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,199 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "directory_manager.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::string create_directory_process(Song song, const char *root_path)
|
||||
{
|
||||
auto curr_path = fs::path(root_path);
|
||||
|
||||
if (fs::exists(curr_path)) {
|
||||
std::cout<<"path exists"<<std::endl;
|
||||
} else {
|
||||
std::cout<<"creating path"<<std::endl;
|
||||
fs::create_directory(curr_path);
|
||||
}
|
||||
|
||||
auto art_path = fs::path(curr_path.string() + song.Artist);
|
||||
if (fs::exists(art_path)) {
|
||||
std::cout<<"artist path exists"<<std::endl;
|
||||
} else {
|
||||
std::cout<<"creating artist path"<<std::endl;
|
||||
fs::create_directory(art_path);
|
||||
}
|
||||
|
||||
auto alb_path = fs::path(art_path.string() + "/" + song.Album);
|
||||
if (fs::exists(alb_path)) {
|
||||
std::cout<<"album path exists"<<std::endl;
|
||||
} else {
|
||||
std::cout<<"creating album path"<<std::endl;
|
||||
fs::create_directory(alb_path);
|
||||
}
|
||||
|
||||
return alb_path.string() + "/";
|
||||
}
|
||||
std::string read_cover_art(const char *source)
|
||||
{
|
||||
auto source_path = fs::path(source);
|
||||
|
||||
std::fstream cov(source, std::ios::in | std::ios::binary);
|
||||
|
||||
cov.seekg(0);
|
||||
|
||||
std::stringstream buf;
|
||||
std::copy(std::istreambuf_iterator<char>(cov),
|
||||
std::istreambuf_iterator<char>(),
|
||||
std::ostreambuf_iterator<char>(buf));
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
bool delete_song(Song *song)
|
||||
{
|
||||
return fs::remove(song->SongPath);
|
||||
}
|
||||
|
||||
void copy_stock_to_root(const char *target, const std::string buff)
|
||||
{
|
||||
std::cout<<"starting process"<<std::endl;
|
||||
auto target_path = fs::path(target);
|
||||
if (fs::exists(target_path)) {
|
||||
std::cout<<target_path.string()<<" exists"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout<<target_path.string()<<" does not exist, copying over"<<std::endl;
|
||||
std::fstream cov(target, std::ios::out | std::ios::binary);
|
||||
cov.write(buff.c_str(), buff.size());
|
||||
cov.close();
|
||||
|
||||
std::cout<<"copy finished"<<std::endl;
|
||||
}
|
||||
void copy_song_to_path(const char *target, const char *source)
|
||||
{
|
||||
std::cout<<"starting process to copy song"<<std::endl;
|
||||
auto target_path = fs::path(target);
|
||||
auto src_path = fs::path(source);
|
||||
|
||||
std::cout<<"copting over to "<<target_path.string()<<std::endl;
|
||||
fs::copy(src_path, target_path);
|
||||
|
||||
fs::remove(source);
|
||||
std::cout<<"copy finished"<<std::endl;
|
||||
}
|
||||
void delete_cover_art_file(const std::string cov_path)
|
||||
{
|
||||
auto cov = fs::path(cov_path);
|
||||
fs::remove(cov);
|
||||
}
|
||||
void delete_directories(Song song, const char *root_path)
|
||||
{
|
||||
std::cout<<"checking to for empty directories to delete"<<std::endl;
|
||||
const std::string art{root_path + std::string{"/"} + song.Artist};
|
||||
const std::string alb{art + "/" + song.Album};
|
||||
|
||||
auto alb_path = fs::path(alb);
|
||||
|
||||
if (!fs::exists(alb_path)) {
|
||||
std::cout<<"directory does not exists"<<std::endl;
|
||||
} else if (fs::is_empty(alb_path)) {
|
||||
fs::remove(alb_path);
|
||||
}
|
||||
|
||||
auto art_path = fs::path(art);
|
||||
|
||||
if (!fs::exists(art_path)) {
|
||||
std::cout<<"directory does not exists"<<std::endl;
|
||||
return;
|
||||
} else if (fs::is_empty(art_path)) {
|
||||
fs::remove(art_path);
|
||||
}
|
||||
|
||||
std::cout<<"deleted empty directory or directories"<<std::endl;
|
||||
}
|
||||
void delete_song(Song song)
|
||||
{
|
||||
std::cout<<"deleting song"<<std::endl;
|
||||
auto song_path = fs::path(song.SongPath);
|
||||
|
||||
if (!fs::exists(song_path)) {
|
||||
std::cout<<"song does not exists"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
fs::remove(song_path);
|
||||
std::cout<<"deleted song"<<std::endl;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void create_directory(Song, const char*, char*);
|
||||
void copy_stock_cover_art(const char*, const char*);
|
||||
void copy_song(const char*, const char*);
|
||||
void delete_cover_art(const char*, const char*);
|
||||
void delete_empty_directories(Song, const char*);
|
||||
void delete_from_filesystem(Song);
|
||||
void delete_song_empty_directories(Song, const char*);
|
||||
void print_song_details(const Song);
|
||||
|
||||
void create_directory(Song song, const char *root_path, char *dir)
|
||||
{
|
||||
const auto tmp = create_directory_process(song, root_path);
|
||||
size_t tmp_sz = tmp.size();
|
||||
tmp.copy(dir, tmp_sz, 0);
|
||||
}
|
||||
void copy_stock_cover_art(const char *target, const char *source)
|
||||
{
|
||||
const auto buff = read_cover_art(source);
|
||||
copy_stock_to_root(target, buff);
|
||||
}
|
||||
void copy_song(const char *target, const char *source)
|
||||
{
|
||||
copy_song_to_path(target, source);
|
||||
}
|
||||
void delete_cover_art(const char *cover_path, const char *stock_path)
|
||||
{
|
||||
std::cout<<"starting process to delete cover art"<<std::endl;
|
||||
const auto cov_path = std::string{cover_path};
|
||||
const auto s_path = std::string{stock_path};
|
||||
if (cov_path.compare(s_path) != 0) {
|
||||
std::cout<<"cover art is not the stock path"<<std::endl;
|
||||
delete_cover_art_file(cov_path);
|
||||
} else {
|
||||
std::cout<<"cover art is the stock path and will not be deleted"<<std::endl;
|
||||
}
|
||||
}
|
||||
void delete_empty_directories(Song song, const char *root_path)
|
||||
{
|
||||
delete_directories(song, root_path);
|
||||
}
|
||||
void delete_from_filesystem(Song song)
|
||||
{
|
||||
if (delete_song(&song)) {
|
||||
std::cout<<"successfully deleted song from filesystem"<<std::endl;
|
||||
} else {
|
||||
std::cout<<"failed to deleted song from filesystem"<<std::endl;
|
||||
}
|
||||
}
|
||||
void delete_song_empty_directories(Song song, const char *root_path)
|
||||
{
|
||||
delete_song(song);
|
||||
delete_directories(song, root_path);
|
||||
}
|
||||
void print_song_details(const Song song)
|
||||
{
|
||||
std::cout<<"song details"<<std::endl;
|
||||
std::cout<<"title: "<<song.Title<<std::endl;
|
||||
std::cout<<"artist: "<<song.Artist<<std::endl;
|
||||
std::cout<<"album: "<<song.Album<<std::endl;
|
||||
std::cout<<"genre: "<<song.Genre<<std::endl;
|
||||
std::cout<<"year: "<<song.Year<<std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#include "imageFile.h"
|
||||
|
||||
imageFile::imageFile(const char *file) : TagLib::File(file)
|
||||
{
|
||||
}
|
||||
|
||||
TagLib::ByteVector imageFile::data()
|
||||
{
|
||||
return readBlock(length());
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
#include <taglib/attachedpictureframe.h>
|
||||
#include <taglib/fileref.h>
|
||||
#include <taglib/mpegfile.h>
|
||||
#include <taglib/tag.h>
|
||||
|
||||
#include "directory_manager.h"
|
||||
#include "metadata_retriever.h"
|
||||
#include "imageFile.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void retrieve_metadata(Song*, char*);
|
||||
void update_metadata(Song*, Song*);
|
||||
|
||||
void retrieve_metadata(Song *sng, char* song_path)
|
||||
{
|
||||
std::cout<<"extern C"<<std::endl;
|
||||
TagLib::FileRef file(song_path);
|
||||
|
||||
strcpy(sng->Title, file.tag()->title().toCString());
|
||||
strcpy(sng->Artist, file.tag()->artist().toCString());
|
||||
strcpy(sng->Album, file.tag()->album().toCString());
|
||||
strcpy(sng->Genre, file.tag()->genre().toCString());
|
||||
sng->Year = file.tag()->year();
|
||||
sng->Duration = file.audioProperties()->lengthInSeconds();
|
||||
strcpy(sng->SongPath, song_path);
|
||||
}
|
||||
void update_metadata(Song *sng_updated, Song *sng_old)
|
||||
{
|
||||
std::cout<<"updating metadata"<<std::endl;
|
||||
TagLib::FileRef file(sng_old->SongPath);
|
||||
|
||||
if (strlen(sng_updated->Title) > 0) {
|
||||
file.tag()->setTitle(sng_updated->Title);
|
||||
}
|
||||
if (strlen(sng_updated->Artist) > 0) {
|
||||
file.tag()->setArtist(sng_updated->Artist);
|
||||
}
|
||||
if (strlen(sng_updated->Album) > 0) {
|
||||
file.tag()->setAlbum(sng_updated->Album);
|
||||
}
|
||||
if (strlen(sng_updated->Genre) > 0) {
|
||||
file.tag()->setGenre(sng_updated->Genre);
|
||||
}
|
||||
if (sng_updated->Year > 0) {
|
||||
file.tag()->setYear(sng_updated->Year);
|
||||
}
|
||||
|
||||
file.save();
|
||||
}
|
||||
void update_cover_art(Cover *cov, Song *song, const char *root_path)
|
||||
{
|
||||
TagLib::MPEG::File sngF(song->SongPath);
|
||||
TagLib::ID3v2::Tag *tag = sngF.ID3v2Tag();
|
||||
auto frameList = tag->frameListMap()["APIC"];
|
||||
|
||||
if (frameList.isEmpty()) {
|
||||
std::string stock_path{root_path};
|
||||
stock_path.append("CoverArt.png");
|
||||
strcpy(cov->ImagePath, stock_path.c_str());
|
||||
|
||||
imageFile stock_img(stock_path.c_str());
|
||||
|
||||
TagLib::ID3v2::AttachedPictureFrame *pic =
|
||||
new TagLib::ID3v2::AttachedPictureFrame;
|
||||
pic->setPicture(stock_img.data());
|
||||
pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
|
||||
|
||||
tag->addFrame(pic);
|
||||
|
||||
sngF.save();
|
||||
std::cout<<"applied stock cover art"<<std::endl;
|
||||
} else {
|
||||
auto frame = dynamic_cast<TagLib::ID3v2::AttachedPictureFrame*>(
|
||||
frameList.front());
|
||||
auto img_path = create_directory_process(*song, root_path);
|
||||
img_path.append(song->Title);
|
||||
img_path.append(".png");
|
||||
strcpy(cov->ImagePath, img_path.c_str());
|
||||
std::cout<<cov->ImagePath<<std::endl;
|
||||
|
||||
std::fstream img_save(cov->ImagePath, std::ios::out |
|
||||
std::ios::binary);
|
||||
img_save.write(frame->picture().data(), frame->picture().size());
|
||||
img_save.close();
|
||||
std::cout<<"saved to "<<cov->ImagePath<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <cpr/cpr.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "models.h"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
|
||||
LoginRes* retrieve_token(TokenReq *tok)
|
||||
{
|
||||
LoginRes *res = new LoginRes;
|
||||
|
||||
nlohmann::json reqObj;
|
||||
reqObj["client_id"] = tok->ClientId;
|
||||
reqObj["client_secret"] = tok->ClientSecret;
|
||||
reqObj["audience"] = tok->Audience;
|
||||
reqObj["grant_type"] = tok->GrantType;
|
||||
|
||||
std::string uri{tok->URI};
|
||||
uri.append("/");
|
||||
uri.append(tok->Endpoint);
|
||||
|
||||
auto r = cpr::Post(cpr::Url{uri},
|
||||
cpr::Body{reqObj.dump()},
|
||||
cpr::Header{{"Content-Type", "application/json"}});
|
||||
|
||||
auto post_res = nlohmann::json::parse(r.text);
|
||||
strcpy(res->Token, post_res["access_token"].get<std::string>().c_str());
|
||||
strcpy(res->TokenType, post_res["token_type"].get<std::string>().c_str());
|
||||
res->Expiration = post_res["expires_in"].get<int>();
|
||||
strcpy(res->Message, "Success");
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class Album
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int AlbumId { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("album_artist")]
|
||||
public string AlbumArtist { get; set; }
|
||||
[JsonProperty("song_count")]
|
||||
[NotMapped]
|
||||
public int SongCount { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public List<Song> Songs { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class Artist
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int ArtistId { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("song_count")]
|
||||
[NotMapped]
|
||||
public int SongCount { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public List<Song> Songs { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class BaseResult
|
||||
{
|
||||
[JsonProperty("message")]
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class CoverArt
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int CoverArtId { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string SongTitle { get; set; }
|
||||
[JsonIgnore]
|
||||
public string ImagePath { get; set; }
|
||||
[NotMapped]
|
||||
[JsonProperty("song_id")]
|
||||
public int SongId { get; set; }
|
||||
[JsonIgnore]
|
||||
public List<Song> Songs { get; set; }
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public struct CovArt
|
||||
{
|
||||
public int CoverArtId;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string SongTitle;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string ImagePath;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class Genre
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int GenreId { get; set; }
|
||||
[JsonProperty("genre")]
|
||||
public string GenreName { get; set; }
|
||||
[JsonProperty("song_count")]
|
||||
[NotMapped]
|
||||
public int SongCount { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public List<Song> Songs { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class LoginResult : BaseResult
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int UserId { get; set; }
|
||||
[JsonProperty("username")]
|
||||
public string Username { get; set; }
|
||||
[JsonProperty("token")]
|
||||
public string Token { get; set; }
|
||||
[JsonProperty("token_type")]
|
||||
public string TokenType { get; set; }
|
||||
[JsonProperty("expiration")]
|
||||
public int Expiration { get; set; }
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi), Serializable]
|
||||
public struct LogRes
|
||||
{
|
||||
public int UserId;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string Username;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string Token;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string TokenType;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string Message;
|
||||
public int Expiration;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class RegisterResult : BaseResult
|
||||
{
|
||||
[JsonProperty("username")]
|
||||
public string Username { get; set; }
|
||||
[JsonProperty("successfully_registered")]
|
||||
public bool SuccessfullyRegistered { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class Song
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int Id { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("album")]
|
||||
public string AlbumTitle { get; set; }
|
||||
[JsonProperty("artist")]
|
||||
public string Artist { get; set; }
|
||||
[JsonProperty("year")]
|
||||
public int? Year { get; set; }
|
||||
[JsonProperty("genre")]
|
||||
public string Genre { get; set; }
|
||||
[JsonProperty("duration")]
|
||||
public int Duration { get; set; }
|
||||
[JsonProperty("filename")]
|
||||
public string Filename { get; set; }
|
||||
[JsonProperty("song_path")]
|
||||
public string SongPath { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Album Album { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? AlbumId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Artist SongArtist { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? ArtistId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Genre SongGenre { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? GenreId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Year SongYear { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? YearId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public CoverArt SongCoverArt { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? CoverArtId { get; set; }
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public struct Sng
|
||||
{
|
||||
public int Id;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string Title;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string Artist;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string Album;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string Genre;
|
||||
public int Year;
|
||||
public int Duration;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string SongPath;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class SongData
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
public int SongId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class SongResult
|
||||
{
|
||||
[JsonProperty("message")]
|
||||
public string Message { get; set; }
|
||||
[JsonProperty("song_title")]
|
||||
public string SongTitle { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct TokenReq
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string ClientId;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string ClientSecret;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string Audience;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string GrantType;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string URI;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
|
||||
public string Endpoint;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class User
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int Id { get; set; }
|
||||
[JsonProperty("username")]
|
||||
public string Username { get; set; }
|
||||
[JsonProperty("nickname")]
|
||||
public string Nickname { get; set; }
|
||||
[JsonProperty("password")]
|
||||
public string Password { get; set; }
|
||||
[JsonProperty("email")]
|
||||
public string Email { get; set; }
|
||||
[JsonProperty("phone_number")]
|
||||
public string PhoneNumber { get; set; }
|
||||
[JsonProperty("first_name")]
|
||||
public string Firstname { get; set; }
|
||||
[JsonProperty("last_name")]
|
||||
public string Lastname { get; set; }
|
||||
[JsonProperty("email_verified")]
|
||||
public bool EmailVerified { get; set; }
|
||||
[JsonProperty("date_created")]
|
||||
public DateTime DateCreated { get; set; }
|
||||
[JsonProperty("last_login")]
|
||||
public DateTime? LastLogin { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class Year
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int YearId { get; set; }
|
||||
[JsonProperty("year")]
|
||||
public int YearValue { get; set; }
|
||||
[JsonProperty("song_count")]
|
||||
[NotMapped]
|
||||
public int SongCount { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public List<Song> Songs { get; set; }
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NLog.Web;
|
||||
|
||||
namespace Icarus
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
|
||||
|
||||
try
|
||||
{
|
||||
logger.Debug("init main");
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "An error occurred");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
NLog.LogManager.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args).UseStartup<Startup>()
|
||||
.UseUrls("http://localhost:5002")
|
||||
.ConfigureLogging(logging =>
|
||||
{
|
||||
logging.ClearProviders();
|
||||
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
|
||||
})
|
||||
.UseNLog();
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:20781",
|
||||
"sslPort": 44394
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api/values",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"Icarus": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api/values",
|
||||
"applicationUrl": "http://localhost:5002",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
CREATE DATABASE Icarus;
|
||||
|
||||
USE Icarus;
|
||||
|
||||
CREATE TABLE CoverArt (
|
||||
CoverArtId INT NOT NULL AUTO_INCREMENT,
|
||||
SongTitle TEXT NOT NULL,
|
||||
ImagePath TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (CoverArtId)
|
||||
);
|
||||
|
||||
CREATE TABLE Album (
|
||||
AlbumId INT NOT NULL AUTO_INCREMENT,
|
||||
Title TEXT NOT NULL,
|
||||
Year INT NOT NULL,
|
||||
|
||||
PRIMARY KEY (AlbumId)
|
||||
);
|
||||
|
||||
CREATE TABLE Artist (
|
||||
ArtistId INT NOT NULL AUTO_INCREMENT,
|
||||
Artist TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (ArtistId)
|
||||
);
|
||||
|
||||
CREATE TABLE Genre (
|
||||
GenreId INT NOT NULL AUTO_INCREMENT,
|
||||
Category TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (GenreId)
|
||||
);
|
||||
|
||||
CREATE TABLE Year (
|
||||
YearId INT NOT NULL AUTO_INCREMENT,
|
||||
Year INT NOT NULL,
|
||||
|
||||
PRIMARY KEY (YearId)
|
||||
);
|
||||
|
||||
CREATE TABLE Song (
|
||||
SongId INT NOT NULL AUTO_INCREMENT,
|
||||
Title TEXT NOT NULL,
|
||||
Artist TEXT NOT NULL,
|
||||
Album TEXT NOT NULL,
|
||||
Genre TEXT NOT NULL,
|
||||
Year INT NOT NULL,
|
||||
Duration INT NOT NULL,
|
||||
Track INT NOT NULL,
|
||||
Disc INT NOT NULL,
|
||||
SongPath TEXT NOT NULL,
|
||||
CoverArtId INT NOT NULL,
|
||||
ArtistId INT NOT NULL,
|
||||
AlbumId INT NOT NULL,
|
||||
GenreId INT NOT NULL,
|
||||
YearId INT NOT NULL,
|
||||
|
||||
PRIMARY KEY (SongId),
|
||||
CONSTRAINT FK_CoverArtId FOREIGN KEY (CoverArtId) REFERENCES CoverArt (CoverArtId),
|
||||
CONSTRAINT FK_ArtistId FOREIGN KEY (ArtistId) REFERENCES Artist (ArtistId),
|
||||
CONSTRAINT FK_AlbumId FOREIGN KEY (AlbumId) REFERENCES Album (AlbumId),
|
||||
CONSTRAINT FK_GenreId FOREIGN KEY (GenreId) REFERENCES Genre (GenreId),
|
||||
CONSTRAINT FK_YearId FOREIGN KEY (YearId) REFERENCES Year (YearId)
|
||||
);
|
||||
|
||||
CREATE TABLE User (
|
||||
UserId INT NOT NULL AUTO_INCREMENT,
|
||||
Firstname TEXT NOT NULL,
|
||||
Lastname TEXT NOT NULL,
|
||||
Email TEXT NOT NULL,
|
||||
Phone TEXT NOT NULL,
|
||||
Username TEXT NOT NULL,
|
||||
Password TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (UserId)
|
||||
);
|
||||
-157
@@ -1,157 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
using NLog;
|
||||
using NLog.Web;
|
||||
using NLog.Web.AspNetCore;
|
||||
|
||||
using Icarus.Authorization;
|
||||
using Icarus.Authorization.Handlers;
|
||||
using Icarus.Database.Contexts;
|
||||
using Icarus.Database.Repositories;
|
||||
|
||||
namespace Icarus
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
|
||||
services.AddSingleton<IConfiguration>(Configuration);
|
||||
|
||||
string domain = $"https://{Configuration["Auth0:Domain"]}/";
|
||||
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
}).AddJwtBearer(options =>
|
||||
{
|
||||
options.Authority = domain;
|
||||
options.Audience = Configuration["Auth0:ApiIdentifier"];
|
||||
});
|
||||
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
options.AddPolicy("download:songs", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("download:songs", domain)));
|
||||
|
||||
options.AddPolicy("download:cover_art", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("download:cover_art", domain)));
|
||||
|
||||
options.AddPolicy("upload:songs", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("upload:songs", domain)));
|
||||
|
||||
options.AddPolicy("delete:songs", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("delete:songs", domain)));
|
||||
|
||||
options.AddPolicy("read:song_details", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("read:song_details", domain)));
|
||||
|
||||
options.AddPolicy("update:songs", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("update:songs", domain)));
|
||||
|
||||
options.AddPolicy("read:artists", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("read:artists", domain)));
|
||||
|
||||
options.AddPolicy("read:albums", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("read:albums", domain)));
|
||||
|
||||
options.AddPolicy("read:genre", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("read:genre", domain)));
|
||||
|
||||
options.AddPolicy("read:year", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("read:year", domain)));
|
||||
|
||||
options.AddPolicy("stream:songs", policy =>
|
||||
policy.Requirements
|
||||
.Add(new HasScopeRequirement("stream:songs", domain)));
|
||||
});
|
||||
|
||||
|
||||
services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();
|
||||
|
||||
var connString = Configuration.GetConnectionString("DefaultConnection");
|
||||
|
||||
services.Add(new ServiceDescriptor(typeof(SongRepository),
|
||||
new SongRepository(Configuration.GetConnectionString("DefaultConnection"))));
|
||||
|
||||
services.Add(new ServiceDescriptor(typeof(AlbumRepository),
|
||||
new AlbumRepository(Configuration.GetConnectionString("DefaultConnection"))));
|
||||
|
||||
services.Add(new ServiceDescriptor(typeof(ArtistRepository),
|
||||
new ArtistRepository(Configuration.GetConnectionString("DefaultConnection"))));
|
||||
|
||||
services.Add(new ServiceDescriptor(typeof(GenreRepository),
|
||||
new GenreRepository(Configuration.GetConnectionString("DefaultConnection"))));
|
||||
|
||||
services.Add(new ServiceDescriptor(typeof(YearRepository),
|
||||
new YearRepository(Configuration.GetConnectionString("DefaultConnection"))));
|
||||
|
||||
services.Add(new ServiceDescriptor(typeof(CoverArtRepository),
|
||||
new CoverArtRepository(Configuration.GetConnectionString("DefaultConnection"))));
|
||||
|
||||
services.Add(new ServiceDescriptor(typeof(UserRepository),
|
||||
new UserRepository(Configuration.GetConnectionString("DefaultConnection"))));
|
||||
|
||||
services.AddDbContext<SongContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<AlbumContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<ArtistContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<UserContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<GenreContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<YearContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<CoverArtContext>(options => options.UseMySQL(connString));
|
||||
}
|
||||
|
||||
// Called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
app.UseDeveloperExceptionPage();
|
||||
else
|
||||
// The default HSTS value is 30 days.
|
||||
// You may want to change this for production scenarios
|
||||
app.UseHsts();
|
||||
|
||||
app.UseAuthentication();
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseMvc();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Icarus.Types
|
||||
{
|
||||
public enum CoverArtField
|
||||
{
|
||||
SongTitle = 0,
|
||||
ImagePath
|
||||
};
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Icarus.Types
|
||||
{
|
||||
public enum DirectoryType
|
||||
{
|
||||
Music = 0,
|
||||
CoverArt
|
||||
};
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
},
|
||||
"Auth0": {
|
||||
"Domain": "[domain].auth0.com",
|
||||
"ApiIdentifier": "https://[identifier]/api",
|
||||
"ClientId": "",
|
||||
"ClientSecret": ""
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=;Database=;Uid=;Pwd=;"
|
||||
},
|
||||
"RootMusicPath": "/music/path/",
|
||||
"TemporaryMusicPath": "/music/temp/path/",
|
||||
"ArchivePath": "/archive/path/",
|
||||
"CoverArtPath": "/cover/art/path/"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "[domain].auth0.com",
|
||||
"api_identifier": "https://[identifier]/api",
|
||||
"client_id": "dfdfdfdf",
|
||||
"client_secret": "dfdfdfdf"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
{
|
||||
"server": "localhost",
|
||||
"database": "Icarus",
|
||||
"username": "icarus-admin",
|
||||
"password": "dreamofpeace"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef APPCOMPONENT_H_
|
||||
#define APPCOMPONENT_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "oatpp/core/macro/component.hpp"
|
||||
#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp"
|
||||
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
|
||||
#include "oatpp/web/server/HttpConnectionHandler.hpp"
|
||||
|
||||
namespace Component
|
||||
{
|
||||
|
||||
class appComponent
|
||||
{
|
||||
public:
|
||||
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, serverConnectionProvider)([] {
|
||||
return oatpp::network::server::SimpleTCPConnectionProvider::createShared(5002);
|
||||
}());
|
||||
|
||||
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, httpRouter)([] {
|
||||
return oatpp::web::server::HttpRouter::createShared();
|
||||
}());
|
||||
|
||||
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::server::ConnectionHandler>, serverConnectionHandler)([] {
|
||||
OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
|
||||
|
||||
return oatpp::web::server::HttpConnectionHandler::createShared(router);
|
||||
}());
|
||||
|
||||
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, apiObjectMapper)([] {
|
||||
return oatpp::parser::json::mapping::ObjectMapper::createShared();
|
||||
}());
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
#ifndef LOGINCONTROLLER_H_
|
||||
#define LOGINCONTROLLER_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
#include "oatpp/core/macro/component.hpp"
|
||||
#include "oatpp/web/server/api/ApiController.hpp"
|
||||
|
||||
#include "dto/loginResultDto.hpp"
|
||||
#include "managers/token_manager.h"
|
||||
|
||||
namespace Controller
|
||||
{
|
||||
class loginController : public oatpp::web::server::api::ApiController
|
||||
{
|
||||
public:
|
||||
loginController(std::string p, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper))
|
||||
: oatpp::web::server::api::ApiController(objectMapper), exe_path(p)
|
||||
{ }
|
||||
loginController(const Model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper))
|
||||
:oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf)
|
||||
{ }
|
||||
|
||||
|
||||
#include OATPP_CODEGEN_BEGIN(ApiController)
|
||||
|
||||
ENDPOINT("POST", "/api/v1/login", data, BODY_DTO(Dto::userDto::ObjectWrapper, usr)) {
|
||||
OATPP_LOGI("icarus", "logging in");
|
||||
|
||||
Manager::token_manager tok;
|
||||
auto token = tok.retrieve_token(m_bConf);
|
||||
|
||||
auto logRes = Dto::loginResultDto::createShared();
|
||||
logRes->id = 0; // TODO: change this later on to something meaningful
|
||||
logRes->username = usr->username->c_str();
|
||||
logRes->token = token.access_token.c_str();
|
||||
logRes->token_type = token.token_type.c_str();
|
||||
logRes->expiration = token.expiration;
|
||||
logRes->message = "Successful";
|
||||
|
||||
return createDtoResponse(Status::CODE_200, logRes);
|
||||
}
|
||||
|
||||
#include OATPP_CODEGEN_END(ApiController)
|
||||
private:
|
||||
std::string exe_path;
|
||||
Model::BinaryPath m_bConf;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
#ifndef SONGCONTROLLER_H_
|
||||
#define SONGCONTROLLER_H_
|
||||
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "oatpp/core/data/stream/ChunkedBuffer.hpp"
|
||||
#include "oatpp/core/data/stream/FileStream.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
#include "oatpp/core/macro/component.hpp"
|
||||
#include "oatpp/web/mime/multipart/InMemoryPartReader.hpp"
|
||||
#include "oatpp/web/mime/multipart/Reader.hpp"
|
||||
#include "oatpp/web/server/api/ApiController.hpp"
|
||||
|
||||
#include "database/songRepository.h"
|
||||
#include "dto/songDto.hpp"
|
||||
#include "managers/song_manager.h"
|
||||
#include "managers/token_manager.h"
|
||||
#include "models/models.h"
|
||||
#include "types/scopes.h"
|
||||
#include "types/songFilter.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Controller
|
||||
{
|
||||
class songController : public oatpp::web::server::api::ApiController
|
||||
{
|
||||
public:
|
||||
songController(std::string p, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper))
|
||||
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p)
|
||||
{ }
|
||||
|
||||
songController(const Model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper))
|
||||
: oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf)
|
||||
{ }
|
||||
|
||||
#include OATPP_CODEGEN_BEGIN(ApiController)
|
||||
|
||||
// endpoint for uploading a song
|
||||
ENDPOINT("POST", "/api/v1/song/data", songUpload,
|
||||
REQUEST(std::shared_ptr<IncomingRequest>, request))
|
||||
{
|
||||
auto authHeader = request->getHeader("Authorization");
|
||||
|
||||
OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope");
|
||||
|
||||
auto auth = authHeader->std_str();
|
||||
|
||||
Manager::token_manager tok;
|
||||
OATPP_ASSERT_HTTP(tok.is_token_valid(auth, Type::Scope::upload), Status::CODE_403, "Not allowed");
|
||||
|
||||
auto mp = std::make_shared<oatpp::web::mime::multipart::Multipart>(request->getHeaders());
|
||||
|
||||
oatpp::web::mime::multipart::Reader mp_reader(mp.get());
|
||||
|
||||
mp_reader.setPartReader("file", oatpp::web::mime::multipart::createInMemoryPartReader(m_dataSize));
|
||||
|
||||
request->transferBody(&mp_reader);
|
||||
|
||||
auto file = mp->getNamedPart("file");
|
||||
|
||||
OATPP_ASSERT_HTTP(file, Status::CODE_400, "file is null");
|
||||
|
||||
auto buff = std::unique_ptr<char>(new char[file->getKnownSize()]);
|
||||
auto buffSize = file->getInputStream()->read(buff.get(), file->getKnownSize());
|
||||
|
||||
std::vector<unsigned char> data(buff.get(), buff.get() + buffSize);
|
||||
|
||||
Model::Song sng;
|
||||
sng.data = std::move(data);
|
||||
|
||||
Manager::song_manager s_mgr(m_bConf);
|
||||
s_mgr.saveSong(sng);
|
||||
|
||||
return createResponse(Status::CODE_200, "OK");
|
||||
}
|
||||
|
||||
// endpoint for retrieving all song records in json format
|
||||
ENDPOINT("GET", "/api/v1/song", songRecords,
|
||||
REQUEST(std::shared_ptr<IncomingRequest>, request))
|
||||
{
|
||||
std::cout << "starting process of retrieving songs" << std::endl;
|
||||
Database::songRepository songRepo(m_bConf);
|
||||
auto songsDb = songRepo.retrieveRecords();
|
||||
auto songs = oatpp::data::mapping::type::List<Dto::songDto::ObjectWrapper>::createShared();
|
||||
|
||||
std::cout << "creating object to send" << std::endl;
|
||||
for (auto& songDb : songsDb) {
|
||||
auto song = Dto::songDto::createShared();
|
||||
song->id = songDb.id;
|
||||
song->title = songDb.title.c_str();
|
||||
song->artist = songDb.artist.c_str();
|
||||
song->album = songDb.album.c_str();
|
||||
song->genre = songDb.genre.c_str();
|
||||
song->year = songDb.year;
|
||||
song->duration = songDb.duration;
|
||||
song->track = songDb.track;
|
||||
song->disc = songDb.disc;
|
||||
|
||||
songs->pushBack(song);
|
||||
}
|
||||
|
||||
return createDtoResponse(Status::CODE_200, songs);
|
||||
}
|
||||
|
||||
// endpoint for retrieving song record by the song id in json format
|
||||
ENDPOINT("GET", "/api/v1/song/{id}", songRecord,
|
||||
PATH(Int32, id)) {
|
||||
|
||||
Database::songRepository songRepo(m_bConf);
|
||||
Model::Song songDb;
|
||||
songDb.id = id;
|
||||
|
||||
OATPP_ASSERT_HTTP(songRepo.doesSongExist(songDb, Type::songFilter::id) , Status::CODE_403, "song does not exist");
|
||||
|
||||
std::cout << "song exists" << std::endl;
|
||||
songDb = songRepo.retrieveRecord(songDb, Type::songFilter::id);
|
||||
|
||||
auto song = Dto::songDto::createShared();
|
||||
song->id = songDb.id;
|
||||
song->title = songDb.title.c_str();
|
||||
song->artist = songDb.artist.c_str();
|
||||
song->album = songDb.album.c_str();
|
||||
song->genre = songDb.genre.c_str();
|
||||
song->year = songDb.year;
|
||||
song->duration = songDb.duration;
|
||||
song->track = songDb.track;
|
||||
song->disc = songDb.disc;
|
||||
|
||||
return createDtoResponse(Status::CODE_200, song);
|
||||
}
|
||||
|
||||
ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong,
|
||||
PATH(Int32, id)) {
|
||||
|
||||
Database::songRepository songRepo(m_bConf);
|
||||
Model::Song songDb;
|
||||
songDb.id = id;
|
||||
songDb = songRepo.retrieveRecord(songDb, Type::songFilter::id);
|
||||
|
||||
std::ifstream fl(songDb.songPath.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
|
||||
fl.seekg(0);
|
||||
|
||||
std::stringstream buf;
|
||||
std::copy(std::istreambuf_iterator<char>(fl),
|
||||
std::istreambuf_iterator<char>(),
|
||||
std::ostreambuf_iterator<char>(buf));
|
||||
fl.close();
|
||||
|
||||
auto rawSong = std::make_shared<oatpp::String>(oatpp::String(buf.str().data(), (v_int32)buf.str().size(), true));
|
||||
|
||||
auto response = createResponse(Status::CODE_200, *rawSong);
|
||||
response->putHeader(Header::CONTENT_TYPE, "audio/mpeg");
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// TODO: create endpoint for updating songs
|
||||
|
||||
ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, PATH(Int32, id)) {
|
||||
|
||||
Model::Song song;
|
||||
song.id = id;
|
||||
|
||||
Manager::song_manager sngMgr(m_bConf);
|
||||
sngMgr.deleteSong(song);
|
||||
|
||||
return createResponse(Status::CODE_200, "OK");
|
||||
}
|
||||
|
||||
// TODO: create endpoint for streaming songs
|
||||
|
||||
#include OATPP_CODEGEN_END(ApiController)
|
||||
private:
|
||||
std::string m_exe_path;
|
||||
Model::BinaryPath m_bConf;
|
||||
const long m_dataSize = std::numeric_limits<long long int>::max();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef ALBUMREPOSITORY_H_
|
||||
#define ALBUMREPOSITORY_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "database/base_repository.h"
|
||||
#include "models/models.h"
|
||||
#include "types/albumFilter.h"
|
||||
|
||||
namespace Database
|
||||
{
|
||||
class albumRepository : public base_repository
|
||||
{
|
||||
public:
|
||||
albumRepository(const Model::BinaryPath&);
|
||||
|
||||
std::vector<Model::Album> retrieveRecords();
|
||||
|
||||
Model::Album retrieveRecord(Model::Album&, Type::albumFilter);
|
||||
|
||||
bool doesAlbumExists(const Model::Album&, Type::albumFilter);
|
||||
|
||||
void saveAlbum(const Model::Album&);
|
||||
private:
|
||||
std::vector<Model::Album> parseRecords(MYSQL_RES*);
|
||||
|
||||
// TODO: after parseRecord(MYSQL_STMT*) is implemented remove
|
||||
// parseRecord(MYSQL_RES*)
|
||||
Model::Album parseRecord(MYSQL_RES*);
|
||||
Model::Album parseRecord(MYSQL_STMT*);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef ARTISTREPOSITORY_H_
|
||||
#define ARTISTREPOSITORY_H_
|
||||
|
||||
#include "database/base_repository.h"
|
||||
#include "models/models.h"
|
||||
#include "types/artistFilter.h"
|
||||
|
||||
namespace Database
|
||||
{
|
||||
class artistRepository : public base_repository
|
||||
{
|
||||
public:
|
||||
artistRepository(const Model::BinaryPath&);
|
||||
|
||||
Model::Artist retrieveRecord(Model::Artist&, Type::artistFilter);
|
||||
|
||||
bool doesArtistExist(const Model::Artist&, Type::artistFilter);
|
||||
|
||||
void saveRecord(const Model::Artist&);
|
||||
private:
|
||||
// TODO: After parseRecord(MYSQL_STMT*) is implemented
|
||||
// remove parseRecord(MYSQL_RES*)
|
||||
Model::Artist parseRecord(MYSQL_RES*);
|
||||
Model::Artist parseRecord(MYSQL_STMT*);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef BASE_REPOSITORY_H_
|
||||
#define BASE_REPOSITORY_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
#include "models/models.h"
|
||||
|
||||
namespace Database
|
||||
{
|
||||
class base_repository
|
||||
{
|
||||
public:
|
||||
base_repository();
|
||||
base_repository(const std::string&);
|
||||
base_repository(const Model::BinaryPath&);
|
||||
protected:
|
||||
MYSQL* setup_mysql_connection();
|
||||
MYSQL* setup_mysql_connection(Model::database_connection);
|
||||
|
||||
MYSQL_RES* perform_mysql_query(MYSQL*, const std::string&);
|
||||
|
||||
Model::database_connection details;
|
||||
private:
|
||||
void intitalizeDetails();
|
||||
void initializeDetails(const Model::BinaryPath&);
|
||||
|
||||
std::string path;
|
||||
Model::BinaryPath m_binConf;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef COVERARTREPOSITORY_H_
|
||||
#define COVERARTREPOSITORY_H_
|
||||
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
#include "database/base_repository.h"
|
||||
#include "models/models.h"
|
||||
#include "types/coverFilter.h"
|
||||
|
||||
namespace Database
|
||||
{
|
||||
class coverArtRepository : public base_repository
|
||||
{
|
||||
public:
|
||||
coverArtRepository(const std::string&);
|
||||
coverArtRepository(const Model::BinaryPath&);
|
||||
|
||||
Model::Cover retrieveRecord(Model::Cover&, Type::coverFilter);
|
||||
|
||||
bool doesCoverArtExist(const Model::Cover&, Type::coverFilter);
|
||||
|
||||
void deleteRecord(const Model::Cover&);
|
||||
void saveRecord(const Model::Cover&);
|
||||
private:
|
||||
// TODO: After parseRecord(MYSQL_STMT*) is implemented
|
||||
// remove parseRecord(MYSQL_RES*)
|
||||
Model::Cover parseRecord(MYSQL_RES*);
|
||||
Model::Cover parseRecord(MYSQL_STMT*);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef GENREREPOSITORY_H_
|
||||
#define GENREREPOSITORY_H_
|
||||
|
||||
#include "database/base_repository.h"
|
||||
#include "models/models.h"
|
||||
#include "types/genreFilter.h"
|
||||
|
||||
namespace Database
|
||||
{
|
||||
class genreRepository : public base_repository
|
||||
{
|
||||
public:
|
||||
genreRepository(const Model::BinaryPath&);
|
||||
|
||||
Model::Genre retrieveRecord(Model::Genre&, Type::genreFilter);
|
||||
|
||||
bool doesGenreExist(const Model::Genre&, Type::genreFilter);
|
||||
|
||||
void saveRecord(const Model::Genre&);
|
||||
private:
|
||||
// TODO: After parseRecord(MYSQL_STMT*) is implemented
|
||||
// remove parseRecord(MYSQL_RES*)
|
||||
Model::Genre parseRecord(MYSQL_RES*);
|
||||
Model::Genre parseRecord(MYSQL_STMT*);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef SONGREPOSITORY_H_
|
||||
#define SONGREPOSITORY_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
#include "database/base_repository.h"
|
||||
#include "models/models.h"
|
||||
#include "types/songFilter.h"
|
||||
|
||||
namespace Database
|
||||
{
|
||||
class songRepository : public base_repository
|
||||
{
|
||||
public:
|
||||
songRepository(const std::string&);
|
||||
songRepository(const Model::BinaryPath&);
|
||||
|
||||
std::vector<Model::Song> retrieveRecords();
|
||||
|
||||
bool doesSongExist(const Model::Song&, Type::songFilter);
|
||||
|
||||
Model::Song retrieveRecord(Model::Song&, Type::songFilter);
|
||||
|
||||
void deleteRecord(const Model::Song&);
|
||||
void saveRecord(const Model::Song&);
|
||||
private:
|
||||
std::vector<Model::Song> parseRecords(MYSQL_RES*); // TODO: to be removed
|
||||
std::vector<Model::Song> parseRecords(MYSQL_STMT*);
|
||||
|
||||
Model::Song parseRecord(MYSQL_RES*); // TODO: to be removed
|
||||
Model::Song parseRecord(MYSQL_STMT*);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef YEARREPOSITORY_H_
|
||||
#define YEARREPOSITORY_H_
|
||||
|
||||
#include "database/base_repository.h"
|
||||
#include "models/models.h"
|
||||
#include "types/yearFilter.h"
|
||||
|
||||
namespace Database
|
||||
{
|
||||
class yearRepository : public base_repository
|
||||
{
|
||||
public:
|
||||
yearRepository(const Model::BinaryPath&);
|
||||
|
||||
Model::Year retrieveRecord(Model::Year&, Type::yearFilter);
|
||||
|
||||
bool doesYearExist(const Model::Year&, Type::yearFilter);
|
||||
|
||||
void saveRecord(const Model::Year&);
|
||||
private:
|
||||
// TODO: After parseRecord(MYSQL_STMT*) is implemented
|
||||
// remove parseRecord(MYSQL_RES*)
|
||||
Model::Year parseRecord(MYSQL_RES*);
|
||||
Model::Year parseRecord(MYSQL_STMT*);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef LOGINRESULTDTO_H_
|
||||
#define LOGINRESULTDTO_H_
|
||||
|
||||
#include "oatpp/core/data/mapping/type/Object.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
|
||||
namespace Dto
|
||||
{
|
||||
#include OATPP_CODEGEN_BEGIN(DTO)
|
||||
|
||||
class loginResultDto : public oatpp::data::mapping::type::Object
|
||||
{
|
||||
DTO_INIT(loginResultDto, Object)
|
||||
|
||||
DTO_FIELD(Int32, id);
|
||||
DTO_FIELD(String, username);
|
||||
DTO_FIELD(String, token);
|
||||
DTO_FIELD(String, token_type);
|
||||
DTO_FIELD(Int32, expiration);
|
||||
DTO_FIELD(String, message);
|
||||
};
|
||||
|
||||
class userDto : public oatpp::data::mapping::type::Object
|
||||
{
|
||||
DTO_INIT(userDto, Object)
|
||||
|
||||
DTO_FIELD(String, username);
|
||||
DTO_FIELD(String, password);
|
||||
};
|
||||
|
||||
#include OATPP_CODEGEN_END(DTO)
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef SONGDTO_H_
|
||||
#define SONGDTO_H_
|
||||
|
||||
#include "oatpp/core/data/mapping/type/Object.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
|
||||
namespace Dto
|
||||
{
|
||||
#include OATPP_CODEGEN_BEGIN(DTO)
|
||||
|
||||
class songDto : public oatpp::data::mapping::type::Object
|
||||
{
|
||||
DTO_INIT(songDto, Object)
|
||||
|
||||
DTO_FIELD(Int32, id);
|
||||
DTO_FIELD(String, title);
|
||||
DTO_FIELD(String, artist);
|
||||
DTO_FIELD(String, album);
|
||||
DTO_FIELD(String, genre);
|
||||
DTO_FIELD(Int32, track);
|
||||
DTO_FIELD(Int32, disc);
|
||||
DTO_FIELD(Int32, year);
|
||||
DTO_FIELD(Int32, duration);
|
||||
};
|
||||
|
||||
#include OATPP_CODEGEN_END(DTO)
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef ALBUMMANAGER_H_
|
||||
#define ALBUMMANAGER_H_
|
||||
|
||||
#include "models/models.h"
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
class albumManager
|
||||
{
|
||||
public:
|
||||
albumManager(const Model::BinaryPath&);
|
||||
|
||||
Model::Album retrieveAlbum(Model::Album&);
|
||||
Model::Album saveAlbum(const Model::Song&);
|
||||
|
||||
static void printAlbum(const Model::Album&);
|
||||
private:
|
||||
Model::BinaryPath m_bConf;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef ARTISTMANAGER_H_
|
||||
#define ARTISTMANAGER_H_
|
||||
|
||||
#include "models/models.h"
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
class artistManager
|
||||
{
|
||||
public:
|
||||
artistManager(const Model::BinaryPath&);
|
||||
|
||||
Model::Artist retrieveArtist(Model::Artist&);
|
||||
Model::Artist saveArtist(const Model::Song&);
|
||||
|
||||
static void printArtist(const Model::Artist&);
|
||||
private:
|
||||
Model::BinaryPath m_bConf;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef COVERARTMANAGER_H_
|
||||
#define COVERARTMANAGER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "models/models.h"
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
class coverArtManager
|
||||
{
|
||||
public:
|
||||
coverArtManager(const std::string&);
|
||||
coverArtManager(const Model::BinaryPath& bConf);
|
||||
|
||||
Model::Cover saveCover(const Model::Song&, std::string&, const std::string&);
|
||||
private:
|
||||
Model::BinaryPath m_bConf;
|
||||
std::string path;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef DIRECTORY_MANAGER_H_
|
||||
#define DIRECTORY_MANAGER_H_
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "models/models.h"
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
class directory_manager
|
||||
{
|
||||
public:
|
||||
static std::string create_directory_process(Model::Song, const std::string&);
|
||||
static std::string configPath(std::string_view);
|
||||
static std::string configPath(const Model::BinaryPath&);
|
||||
static std::string contentOfPath(const std::string&);
|
||||
|
||||
//static nlohmann::json credentialConfigContent(const std::string&);
|
||||
static nlohmann::json credentialConfigContent(const Model::BinaryPath&);
|
||||
//static nlohmann::json databaseConfigContent(const std::string&);
|
||||
static nlohmann::json databaseConfigContent(const Model::BinaryPath&);
|
||||
//static nlohmann::json pathConfigContent(const std::string&);
|
||||
static nlohmann::json pathConfigContent(const Model::BinaryPath&);
|
||||
|
||||
void delete_cover_art_file(const std::string&, const std::string&);
|
||||
static void delete_directories(Model::Song, const std::string&);
|
||||
|
||||
private:
|
||||
void delete_song(const Model::Song);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef GENREMANAGER_H_
|
||||
#define GENREMANAGER_H_
|
||||
|
||||
#include "models/models.h"
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
class genreManager
|
||||
{
|
||||
public:
|
||||
genreManager(const Model::BinaryPath&);
|
||||
|
||||
Model::Genre retrieveGenre(Model::Genre&);
|
||||
Model::Genre saveGenre(const Model::Song&);
|
||||
|
||||
static void printGenre(const Model::Genre&);
|
||||
private:
|
||||
Model::BinaryPath m_bConf;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef SONGMANAGER_H_
|
||||
#define SONGMANAGER_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "models/models.h"
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
class song_manager
|
||||
{
|
||||
public:
|
||||
song_manager(std::string&);
|
||||
song_manager(const Model::BinaryPath&);
|
||||
|
||||
void saveSong(Model::Song&);
|
||||
void deleteSong(Model::Song&);
|
||||
|
||||
static void printSong(const Model::Song&);
|
||||
private:
|
||||
void saveSongTemp(Model::Song&);
|
||||
void saveMisc(Model::Song&);
|
||||
|
||||
Model::BinaryPath m_bConf;
|
||||
std::string exe_path;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef TOKEN_MANAGER_H_
|
||||
#define TOKEN_MANAGER_H_
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <jwt-cpp/jwt.h>
|
||||
|
||||
#include "models/models.h"
|
||||
#include "types/scopes.h"
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
class token_manager
|
||||
{
|
||||
public:
|
||||
token_manager();
|
||||
|
||||
Model::loginResult retrieve_token();
|
||||
Model::loginResult retrieve_token(std::string_view);
|
||||
Model::loginResult retrieve_token(const Model::BinaryPath&);
|
||||
|
||||
bool is_token_valid(std::string&, Type::Scope);
|
||||
private:
|
||||
Model::auth_credentials parse_auth_credentials(std::string_view);
|
||||
Model::auth_credentials parse_auth_credentials(const Model::BinaryPath&);
|
||||
|
||||
std::vector<std::string> extract_scopes(const jwt::decoded_jwt&&);
|
||||
std::pair<bool, std::vector<std::string>> fetch_auth_header(const std::string&);
|
||||
|
||||
bool token_supports_scope(const std::vector<std::string>, const std::string&&);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef YEARMANAGER_H_
|
||||
#define YEARMANAGER_H_
|
||||
|
||||
#include "models/models.h"
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
class yearManager
|
||||
{
|
||||
public:
|
||||
yearManager(const Model::BinaryPath&);
|
||||
|
||||
Model::Year retrieveYear(Model::Year&);
|
||||
Model::Year saveYear(const Model::Song&);
|
||||
|
||||
static void printYear(const Model::Year&);
|
||||
private:
|
||||
Model::BinaryPath m_bConf;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifndef MODELS_H_
|
||||
#define MODELS_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Model
|
||||
{
|
||||
struct Song
|
||||
{
|
||||
int id;
|
||||
std::string title;
|
||||
std::string artist;
|
||||
std::string album;
|
||||
std::string genre;
|
||||
int year;
|
||||
int duration;
|
||||
int track;
|
||||
int disc;
|
||||
std::string songPath;
|
||||
std::vector<unsigned char> data;
|
||||
int coverArtId;
|
||||
int artistId;
|
||||
int albumId;
|
||||
int genreId;
|
||||
int yearId;
|
||||
};
|
||||
|
||||
struct Artist
|
||||
{
|
||||
int id;
|
||||
std::string artist;
|
||||
};
|
||||
|
||||
struct Album
|
||||
{
|
||||
int id;
|
||||
std::string title;
|
||||
int year;
|
||||
std::vector<Song> songs;
|
||||
};
|
||||
|
||||
struct Genre
|
||||
{
|
||||
int id;
|
||||
std::string category;
|
||||
|
||||
};
|
||||
|
||||
struct Year
|
||||
{
|
||||
int id;
|
||||
int year;
|
||||
};
|
||||
|
||||
struct Cover
|
||||
{
|
||||
int id;
|
||||
std::string songTitle;
|
||||
std::string imagePath;
|
||||
// Not being used but it should be
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
struct loginResult
|
||||
{
|
||||
int user_id;
|
||||
std::string username;
|
||||
std::string access_token;
|
||||
std::string token_type;
|
||||
std::string message;
|
||||
int expiration;
|
||||
};
|
||||
|
||||
struct auth_credentials
|
||||
{
|
||||
std::string domain;
|
||||
std::string api_identifier;
|
||||
std::string client_id;
|
||||
std::string client_secret;
|
||||
std::string uri;
|
||||
std::string endpoint;
|
||||
};
|
||||
|
||||
struct database_connection
|
||||
{
|
||||
std::string server;
|
||||
std::string username;
|
||||
std::string password;
|
||||
std::string database;
|
||||
};
|
||||
|
||||
struct BinaryPath
|
||||
{
|
||||
BinaryPath() = default;
|
||||
BinaryPath(const char *p) : path(std::move(p)) { }
|
||||
BinaryPath(std::string& p) : path(std::move(p)) { }
|
||||
BinaryPath(const std::string& p) : path(std::move(p)) { }
|
||||
std::string path;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user