diff --git a/include/controller/SongController.hpp b/include/controller/SongController.hpp index 3a315cc..fad2a5c 100644 --- a/include/controller/SongController.hpp +++ b/include/controller/SongController.hpp @@ -43,7 +43,7 @@ namespace controller { // endpoint for uploading a song ENDPOINT("POST", "/api/v1/song/data", songUpload, - AUTHORIZATION(std::shared_ptr, authObject), + //AUTHORIZATION(std::shared_ptr, authObject), REQUEST(std::shared_ptr, request)) { auto authHeader = request->getHeader("Authorization"); OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); diff --git a/include/manager/DirectoryManager.h b/include/manager/DirectoryManager.h index f421f46..4fb4cdf 100644 --- a/include/manager/DirectoryManager.h +++ b/include/manager/DirectoryManager.h @@ -3,6 +3,7 @@ #include #include +#include #include @@ -12,7 +13,9 @@ namespace manager { class DirectoryManager { public: - static std::string createDirectoryProcess(model::Song, const std::string&); + DirectoryManager() = default; + + static std::string createDirectoryProcess(const model::Song&, const std::string&); static std::string createDirectoryProcess(const model::Song&, const model::BinaryPath&, type::PathType); static std::string configPath(std::string_view); @@ -29,6 +32,10 @@ namespace manager { void deleteCoverArtFile(const std::string&, const std::string&); private: + std::filesystem::path relativeDiscSongPathFilesystem(const std::filesystem::path&, + const model::Song&); + std::string relativeDiscSongPath(const std::filesystem::path&, const model::Song&); + void deleteSong(const model::Song); }; } diff --git a/include/type/SongFilter.h b/include/type/SongFilter.h index 5508c58..418b645 100644 --- a/include/type/SongFilter.h +++ b/include/type/SongFilter.h @@ -10,7 +10,9 @@ namespace type { albumArtist, genre, year, - titleAndArtist + titleAndArtist, + titleAlbArtistAlbum, + titleAlbArtistAlbumTrack }; } diff --git a/src/database/SongRepository.cpp b/src/database/SongRepository.cpp index 743579c..67a8545 100644 --- a/src/database/SongRepository.cpp +++ b/src/database/SongRepository.cpp @@ -41,6 +41,12 @@ namespace database { case type::SongFilter::titleAndArtist: valueFilterCount = 2; break; + case type::SongFilter::titleAlbArtistAlbum: + valueFilterCount = 3; + break; + case type::SongFilter::titleAlbArtistAlbumTrack: + valueFilterCount = 4; + break; default: break; } @@ -53,6 +59,8 @@ namespace database { auto titleLength = song.title.size(); auto artistLength = song.artist.size(); + auto albumArtistLength = song.albumArtist.size(); + auto albumLength = song.album.size(); switch (filter) { case type::SongFilter::id: qry << "sng.SongId = ?"; @@ -86,6 +94,47 @@ namespace database { std::cout << "title: " << song.title.c_str() << " artist: " << song.artist.c_str() << "\n"; break; + case type::SongFilter::titleAlbArtistAlbum: + qry << "sng.Title = ? AND sng.Album = ? AND alb.Artist = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.album.c_str(); + params[1].length = &albumLength; + params[1].is_null = 0; + + params[2].buffer_type = MYSQL_TYPE_STRING; + params[2].buffer = (char*)song.albumArtist.c_str(); + params[2].length = &albumArtistLength; + params[2].is_null = 0; + break; + case type::SongFilter::titleAlbArtistAlbumTrack: + qry << "sng.Title = ? AND sng.Album = ? AND alb.Artist = ? AND sng.Track = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.album.c_str(); + params[1].length = &titleLength; + params[1].is_null = 0; + + params[2].buffer_type = MYSQL_TYPE_STRING; + params[2].buffer = (char*)song.albumArtist.c_str(); + params[2].length = &titleLength; + params[2].is_null = 0; + + params[3].buffer_type = MYSQL_TYPE_LONG; + params[3].buffer = (char*)&song.track; + params[3].length = 0; + params[3].is_null = 0;; + break; default: break; } @@ -103,7 +152,6 @@ namespace database { mysql_stmt_close(stmt); mysql_close(conn); - std::cout << "done\n"; return retrievedSong; } @@ -119,6 +167,12 @@ namespace database { case type::SongFilter::titleAndArtist: valueFilterCount = 2; break; + case type::SongFilter::titleAlbArtistAlbum: + valueFilterCount = 3; + break; + case type::SongFilter::titleAlbArtistAlbumTrack: + valueFilterCount = 4; + break; default: break; } @@ -127,13 +181,16 @@ namespace database { MYSQL_BIND params[valueFilterCount]; memset(params, 0, sizeof(params)); - qry << "SELECT * FROM Song WHERE "; + qry << "SELECT sng.* FROM Song sng "; + qry << "LEFT JOIN Album alb ON sng.AlbumId = alb.AlbumId WHERE "; auto titleLength = song.title.size(); auto artistLength = song.artist.size(); + auto albumArtistLength = song.albumArtist.size(); + auto albumLength = song.album.size(); switch (filter) { case type::SongFilter::id: - qry << "SongId = ?"; + qry << "sng.SongId = ?"; params[0].buffer_type = MYSQL_TYPE_LONG; params[0].buffer = (char*)&song.id; @@ -141,7 +198,7 @@ namespace database { params[0].is_null = 0; break; case type::SongFilter::title: - qry << "Title = ?"; + qry << "sng.Title = ?"; params[0].buffer_type = MYSQL_TYPE_STRING; params[0].buffer = (char*)song.title.c_str(); @@ -149,7 +206,7 @@ namespace database { params[0].is_null = 0; break; case type::SongFilter::titleAndArtist: - qry << "Title = ? AND Artist = ?"; + qry << "sng.Title = ? AND sng.Artist = ?"; params[0].buffer_type = MYSQL_TYPE_STRING; params[0].buffer = (char*)song.title.c_str(); @@ -161,6 +218,47 @@ namespace database { params[1].length = &artistLength; params[1].is_null = 0; break; + case type::SongFilter::titleAlbArtistAlbum: + qry << "sng.Title = ? AND sng.Album = ? AND alb.Artist = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.album.c_str(); + params[1].length = &albumLength; + params[1].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.albumArtist.c_str(); + params[1].length = &albumArtistLength; + params[1].is_null = 0; + break; + case type::SongFilter::titleAlbArtistAlbumTrack: + qry << "sng.Title = ? AND sng.Album = ? AND alb.Artist = ? AND sng.Track = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.album.c_str(); + params[1].length = &titleLength; + params[1].is_null = 0; + + params[2].buffer_type = MYSQL_TYPE_STRING; + params[2].buffer = (char*)song.albumArtist.c_str(); + params[2].length = &titleLength; + params[2].is_null = 0; + + params[3].buffer_type = MYSQL_TYPE_LONG; + params[3].buffer = (char*)&song.track; + params[3].length = 0; + params[3].is_null = 0;; + break; default: break; } @@ -179,7 +277,6 @@ namespace database { mysql_stmt_close(stmt); mysql_close(conn); - std::cout << "done\n"; return (rowCount > 0) ? true : false; } diff --git a/src/manager/DirectoryManager.cpp b/src/manager/DirectoryManager.cpp index f34282b..0672c2d 100644 --- a/src/manager/DirectoryManager.cpp +++ b/src/manager/DirectoryManager.cpp @@ -8,7 +8,7 @@ namespace fs = std::filesystem; namespace manager { - std::string DirectoryManager::createDirectoryProcess(model::Song song, + std::string DirectoryManager::createDirectoryProcess(const model::Song& song, const std::string& rootPath) { auto currPath = fs::path(rootPath); @@ -27,7 +27,7 @@ namespace manager { fs::create_directory(artPath); } - auto albPath = fs::path(artPath.string() + "/" + song.album); + auto albPath = fs::path(artPath.string() + "/" + song.albumArtist); if (fs::exists(albPath)) { std::cout << "album path exists\n"; } else { @@ -35,7 +35,16 @@ namespace manager { fs::create_directory(albPath); } - return albPath.string() + "/"; + auto discPath = DirectoryManager().relativeDiscSongPathFilesystem(albPath, song); + + if (fs::exists(discPath)) { + std::cout << "disc path exists\n"; + } else { + std::cout << "creating disc path\n"; + fs::create_directory(discPath); + } + + return discPath.string() + "/"; } std::string DirectoryManager::createDirectoryProcess(const model::Song& song, @@ -67,7 +76,15 @@ namespace manager { fs::create_directory(albPath); } - return albPath.string() + "/"; + auto discPath = DirectoryManager().relativeDiscSongPathFilesystem(albPath, song); + if (fs::exists(discPath)) { + std::cout << "disc path exists\n"; + } else { + std::cout << "creating disc path\n"; + fs::create_directory(discPath); + } + + return discPath.string() + "/"; } std::string DirectoryManager::configPath(std::string_view path) { @@ -136,6 +153,15 @@ namespace manager { std::cout << "checking for empty directories to delete\n"; const std::string art(rootPath + std::string("/") + song.albumArtist); const std::string alb(art + "/" + song.album); + const std::string disc(alb + "/" + std::to_string(song.disc) + "/"); + + auto discPath = fs::path(disc); + + if (fs::exists(discPath)) { + std::cout << "disc directory does not exist\n"; + } else if (fs::is_empty(discPath)) { + fs::remove(discPath); + } auto albPath = fs::path(alb); @@ -168,6 +194,39 @@ namespace manager { } } + + fs::path DirectoryManager::relativeDiscSongPathFilesystem(const fs::path& albPath, + const model::Song& song) { + std::string albPathStr(albPath.string() + "/disc"); + if (song.disc >= 10) { + albPathStr.append(std::to_string(song.disc)); + } else { + albPathStr.append("0"); + albPathStr.append(std::to_string(song.disc)); + } + + albPathStr.append("/"); + auto relPath = fs::path(albPathStr.c_str()); + + return relPath; + } + + + std::string DirectoryManager::relativeDiscSongPath(const fs::path& albPath, + const model::Song& song) { + std::string albPathStr(albPath.string() + "/disc"); + if (song.disc >= 10) { + albPathStr.append(std::to_string(song.disc)); + } else { + albPathStr.append("0"); + albPathStr.append(std::to_string(song.disc)); + } + + albPathStr.append("/"); + return albPathStr; + } + + void DirectoryManager::deleteSong(const model::Song song) { std::cout << "deleting song\n"; auto songPath = fs::path(song.songPath); diff --git a/src/manager/SongManager.cpp b/src/manager/SongManager.cpp index cd37aab..d504cd6 100644 --- a/src/manager/SongManager.cpp +++ b/src/manager/SongManager.cpp @@ -33,7 +33,7 @@ namespace manager { song.data = std::move(data); database::SongRepository songRepo(m_bConf); - if (songRepo.doesSongExist(song, type::SongFilter::titleAndArtist)) { + if (songRepo.doesSongExist(song, type::SongFilter::titleAlbArtistAlbum)) { std::cout << "\ntitle: " << song.title << "\nartist: " << song.artist << "\n"; std::cout << "does not exist\n"; return std::make_pair(false, type::SongUpload::AlreadyExist); @@ -44,7 +44,7 @@ namespace manager { printSong(song); songRepo.saveRecord(song); - song = songRepo.retrieveRecord(song, type::SongFilter::titleAndArtist); + song = songRepo.retrieveRecord(song, type::SongFilter::titleAlbArtistAlbum); return std::make_pair(true, type::SongUpload::Successful); } @@ -293,8 +293,8 @@ namespace manager { fs::remove(songPath); } std::cout << "copying song to the appropriate directory\n"; - std::cout << song.songPath << std::endl; - std::cout << songPath << std::endl; + std::cout << song.songPath << "\n"; + std::cout << songPath << "\n"; fs::copy(song.songPath, songPath); fs::remove(song.songPath); song.songPath = std::move(songPath); diff --git a/src/utility/MetadataRetriever.cpp b/src/utility/MetadataRetriever.cpp index 132eb07..139d04b 100644 --- a/src/utility/MetadataRetriever.cpp +++ b/src/utility/MetadataRetriever.cpp @@ -84,7 +84,7 @@ namespace utility { tag->addFrame(pic); sngF.save(); - std::cout << "applied stock cover art" << std::endl; + std::cout << "applied stock cover art\n"; } else { auto frame = dynamic_cast( frameList.front()); diff --git a/src/utility/PasswordEncryption.cpp b/src/utility/PasswordEncryption.cpp index 742ec8d..6b5b73f 100644 --- a/src/utility/PasswordEncryption.cpp +++ b/src/utility/PasswordEncryption.cpp @@ -13,16 +13,16 @@ namespace utility { std::unique_ptr salt(new char[BCRYPT_HASHSIZE]); std::unique_ptr hash(new char[BCRYPT_HASHSIZE]); - std::cout << "generating salt" << std::endl; + std::cout << "generating salt\n"; bcrypt_gensalt(saltSize(), salt.get()); - std::cout << "hashing password" << std::endl; + std::cout << "hashing password\n"; bcrypt_hashpw(user.password.c_str(), salt.get(), hash.get()); passSec.salt = salt.get(); passSec.hashPassword = hash.get(); - std::cout << "hash: " << passSec.hashPassword << std::endl; - std::cout << "salt: " << passSec.salt << std::endl; + std::cout << "hash: " << passSec.hashPassword << "\n"; + std::cout << "salt: " << passSec.salt << "\n"; return passSec; }