Made progress

This commit is contained in:
kdeng00
2021-12-31 19:09:31 -05:00
parent 9930aab985
commit 14d3c9acc6
10 changed files with 296 additions and 59 deletions
+17 -3
View File
@@ -1,6 +1,7 @@
#ifndef ACTIONMANAGER_H_ #ifndef ACTIONMANAGER_H_
#define ACTIONMANAGER_H_ #define ACTIONMANAGER_H_
#include<algorithm>
#include<string> #include<string>
#include<string_view> #include<string_view>
#include<array> #include<array>
@@ -18,11 +19,24 @@ namespace Managers
Models::IcarusAction retrieveIcarusAction() const; Models::IcarusAction retrieveIcarusAction() const;
private: private:
constexpr std::array<const char*, 12> supportedFlags() noexcept; constexpr std::array<const char*, 15> supportedFlags() noexcept
{
constexpr std::array<const char*, 15> allFlags{"-u", "-p", "-t", "-h", "-s",
"-sd", "-sr", "-d", "-D", "-b", "-rt", "-nc",
"-m", "-ca", "-smca"};
return allFlags;
}
constexpr std::array<const char*, 4> supportedActions() noexcept; constexpr std::array<const char*, 4> supportedActions() noexcept;
bool isNumber(const std::string_view) noexcept; bool isNumber(const std::string_view val) noexcept
{
return !val.empty() && std::find_if(val.begin(),
val.end(), [](char c)
{
return !std::isdigit(c);
}) == val.end();
}
void initialize(); void initialize();
void validateFlags(); void validateFlags();
+52 -2
View File
@@ -2,11 +2,14 @@
#define COMMITMANAGER_H_ #define COMMITMANAGER_H_
#include<map> #include<map>
#include<iostream>
#include<string> #include<string>
#include<string_view>
#include"Models/API.h" #include"Models/API.h"
#include"Models/Token.h"
#include"Models/IcarusAction.h" #include"Models/IcarusAction.h"
#include"Models/Song.h"
#include"Models/Token.h"
namespace Managers namespace Managers
{ {
@@ -22,6 +25,24 @@ namespace Managers
songs songs
}; };
// Used for parsing songs from the metadata file
class Album
{
public:
Album() = default;
void printInfo();
std::string album;
std::string albumArtist;
std::string genre;
int year;
int trackCount;
int discCount;
std::vector<Models::Song> songs;
};
private: private:
enum class ActionValues; enum class ActionValues;
@@ -33,15 +54,44 @@ namespace Managers
void downloadSong(); void downloadSong();
void retrieveObjects(); void retrieveObjects();
void uploadSong(); void uploadSong();
// Uploads a single song. The song is constructed from a metadata file that contains
// information about the album the song is from. Also, the cover art of the song must
// be present.
//
// Expects
// * Song - mp3 file path
// * Metadata - Source file containing metadata of the song
// * Cover art - path to image cover art
void uploadSingleSong();
// Checks for the no confirm flag. Used when uploading songs from a directory
bool checkForNoConfirm()
{
for (const auto &arg: this->icaAction.flags)
{
if (arg.flag.compare("-nc") == 0)
{
return true;
}
}
return false;
}
Album retrieveMetadata(const std::string_view path);
std::string retrieveFileContent(const std::string_view path);
enum class ActionValues enum class ActionValues
{ {
deleteAct, deleteAct,
downloadAct, downloadAct,
retrieveAct, retrieveAct,
uploadAct uploadAct,
UPLOAD_SONG_WITH_METADATA // Uploads the song with metadata, including cover art
}; };
Models::IcarusAction icaAction; Models::IcarusAction icaAction;
}; };
} }
+2 -1
View File
@@ -5,8 +5,9 @@
namespace Models namespace Models
{ {
struct Flags class Flags
{ {
public:
std::string flag; std::string flag;
std::string value; std::string value;
}; };
+34 -1
View File
@@ -2,14 +2,47 @@
#define ICARUSACTION_H_ #define ICARUSACTION_H_
#include<string> #include<string>
#include<algorithm>
#include<string_view>
#include<vector> #include<vector>
#include<iostream>
#include"Flags.h" #include"Flags.h"
namespace Models namespace Models
{ {
struct IcarusAction class IcarusAction
{ {
public:
std::string retrieveFlagValue(const std::string_view flag)
{
std::string value;
const auto fg = std::find_if(flags.begin(), flags.end(), [&](Flags f)
{
return f.flag.compare(flag) == 0 ? true : false;
});
if (fg != flags.end())
{
value.assign(fg->value);
}
return value;
}
void print_action_and_flags() noexcept
{
std::cout<<"Action: "<<this->action<<"\n";
std::cout<<"Flag count: "<<this->flags.size()<<"\n";
for (const auto &flag : this->flags)
{
std::cout<<"flag "<<flag.flag<<" value "<<flag.value<<"\n";
}
std::cout<<"\n";
}
std::string action; std::string action;
std::vector<Flags> flags; std::vector<Flags> flags;
}; };
+20 -1
View File
@@ -2,12 +2,22 @@
#define SONG_H_ #define SONG_H_
#include<string> #include<string>
#include<iostream>
namespace Models namespace Models
{ {
struct Song class Song
{ {
public:
Song() = default;
void printInfo()
{
std::cout<<"Title: "<<this->title<<"\n";
std::cout<<"\n";
}
int id; int id;
std::string title; std::string title;
std::string artist; std::string artist;
@@ -16,9 +26,18 @@ namespace Models
int year; int year;
int duration; int duration;
int track; int track;
int disc;
std::string data; std::string data;
std::string songPath; std::string songPath;
}; };
class CoverArt
{
public:
int id;
std::string title;
std::string path;
};
} }
#endif #endif
+9 -5
View File
@@ -7,6 +7,7 @@
#include<nlohmann/json.hpp> #include<nlohmann/json.hpp>
#include"Managers/CommitManager.h"
#include"Managers/FileManager.h" #include"Managers/FileManager.h"
#include"Models/API.h" #include"Models/API.h"
#include"Models/Song.h" #include"Models/Song.h"
@@ -21,16 +22,19 @@ namespace Syncers
class Upload class Upload
{ {
public: public:
Upload(); Upload(Models::API api, Models::Token token) : m_token(token), api(api)
Upload(Models::API); {
this->api.endpoint = "song/data";
}
Models::Song uploadSong(const Models::Token&, Models::Song&); Models::Song uploadSong(Models::Song&);
void uploadSongsFromDirectory(const Models::Token&, void uploadSongsFromDirectory(const std::string&, const bool, bool);
const std::string&, const bool, bool); void uploadSongWithMetadata(Managers::CommitManager::Album&, Models::Song&, Models::CoverArt&);
private: private:
Managers::FileManager fMgr; Managers::FileManager fMgr;
Models::API api; Models::API api;
Models::Song song; Models::Song song;
Models::Token m_token;
std::vector<Models::Song> retrieveAllSongsFromDirectory(const std::string&, std::vector<Models::Song> retrieveAllSongsFromDirectory(const std::string&,
bool); bool);
+2
View File
@@ -62,6 +62,8 @@ int main(int argc, char** argv)
ActionManager actMgr(argv, argc); ActionManager actMgr(argv, argc);
auto chosenAction = actMgr.retrieveIcarusAction(); auto chosenAction = actMgr.retrieveIcarusAction();
chosenAction.print_action_and_flags();
CommitManager commitMgr(chosenAction); CommitManager commitMgr(chosenAction);
commitMgr.commitAction(); commitMgr.commitAction();
+7 -23
View File
@@ -36,23 +36,6 @@ namespace Managers
} }
constexpr std::array<const char*, 12> ActionManager::supportedFlags() noexcept
{
constexpr std::array<const char*, 12> allFlags{"-u", "-p", "-t", "-h", "-s",
"-sd", "-sr", "-d", "-D", "-b", "-rt", "-nc"};
return allFlags;
}
bool ActionManager::isNumber(string_view val) noexcept
{
return !val.empty() && std::find_if(val.begin(),
val.end(), [](char c)
{
return !std::isdigit(c);
}) == val.end();
}
void ActionManager::initialize() void ActionManager::initialize()
{ {
@@ -62,13 +45,14 @@ namespace Managers
transform(action.begin(), action.end(), transform(action.begin(), action.end(),
action.begin(), ::tolower); action.begin(), ::tolower);
} }
void ActionManager::validateFlags() void ActionManager::validateFlags()
{ {
cout<<"Validating flags"<<endl; cout<<"Validating flags\n";
auto flagVals = parsedFlags(); const auto flagVals = parsedFlags();
Flags flg{}; Flags flg;
auto allSupportedFlags = supportedFlags(); auto allSupportedFlags = supportedFlags();
@@ -83,7 +67,7 @@ namespace Managers
if (flag.size() > 3 || isNumber(flag)) if (flag.size() > 3 || isNumber(flag))
{ {
flg.value = flag; flg.value = flag;
//cout<<"flag value "<<flg.value<<endl;
flags.push_back(flg); flags.push_back(flg);
flg = Flags{}; flg = Flags{};
continue; continue;
@@ -95,7 +79,6 @@ namespace Managers
return !flag.compare(val); return !flag.compare(val);
})) }))
{ {
//cout<<"flag "<<flag<<endl;
flg.flag = flag; flg.flag = flag;
} }
else else
@@ -108,7 +91,8 @@ namespace Managers
vector<string> ActionManager::parsedFlags() vector<string> ActionManager::parsedFlags()
{ {
auto parsed = vector<string>(); vector<string> parsed;
parsed.reserve(paramCount);
for (auto i = 2; i < paramCount; ++i) for (auto i = 2; i < paramCount; ++i)
{ {
+144 -10
View File
@@ -1,6 +1,11 @@
#include"Managers/CommitManager.h" #include"Managers/CommitManager.h"
#include<iostream> #include<iostream>
#include<fstream>
#include<sstream>
#include<filesystem>
#include"nlohmann/json.hpp"
#include"Models/API.h" #include"Models/API.h"
#include"Models/Song.h" #include"Models/Song.h"
@@ -31,6 +36,8 @@ using Syncers::Download;
using Syncers::RetrieveRecords; using Syncers::RetrieveRecords;
using Syncers::Upload; using Syncers::Upload;
namespace filesystem = std::filesystem;
namespace Managers namespace Managers
{ {
#pragma #pragma
@@ -44,6 +51,7 @@ namespace Managers
{ {
auto action = icaAction.action; auto action = icaAction.action;
cout<<"Commiting "<<action<<" action"<<endl; cout<<"Commiting "<<action<<" action"<<endl;
switch (mapActions()[action]) switch (mapActions()[action])
{ {
case ActionValues::deleteAct: case ActionValues::deleteAct:
@@ -58,6 +66,9 @@ namespace Managers
case ActionValues::uploadAct: case ActionValues::uploadAct:
uploadSong(); uploadSong();
break; break;
case ActionValues::UPLOAD_SONG_WITH_METADATA:
uploadSingleSong();
break;
default: default:
break; break;
} }
@@ -73,7 +84,8 @@ namespace Managers
{"delete", ActionValues::deleteAct}, {"delete", ActionValues::deleteAct},
{"download", ActionValues::downloadAct}, {"download", ActionValues::downloadAct},
{"retrieve", ActionValues::retrieveAct}, {"retrieve", ActionValues::retrieveAct},
{"upload", ActionValues::uploadAct} {"upload", ActionValues::uploadAct},
{"upload-meta", ActionValues::UPLOAD_SONG_WITH_METADATA}
}; };
return actions; return actions;
@@ -82,7 +94,7 @@ namespace Managers
Token CommitManager::parseToken(API api) Token CommitManager::parseToken(API api)
{ {
cout<<"fetching token"<<endl; cout<<"fetching token\n";
UserManager usrMgr{icaAction}; UserManager usrMgr{icaAction};
auto user = usrMgr.retrieveUser(); auto user = usrMgr.retrieveUser();
@@ -178,7 +190,7 @@ namespace Managers
{ {
auto uploadSingleSong = true; auto uploadSingleSong = true;
auto recursiveDirectory = false; auto recursiveDirectory = false;
auto noConfirm = false; const auto noConfirm = checkForNoConfirm();
string songDirectory; string songDirectory;
APIParser apiPrs{icaAction}; APIParser apiPrs{icaAction};
auto api = apiPrs.retrieveAPI(); auto api = apiPrs.retrieveAPI();
@@ -206,24 +218,146 @@ namespace Managers
songDirectory = value; songDirectory = value;
uploadSingleSong = false; uploadSingleSong = false;
recursiveDirectory = true; recursiveDirectory = true;
}
else if (flag.compare("-nc") == 0)
{
noConfirm = true;
} }
} }
Upload upld{api}; Upload upld{api, token};
if (uploadSingleSong) if (uploadSingleSong)
{ {
cout<<"Uploading song..."<<endl; cout<<"Uploading song..."<<endl;
upld.uploadSong(token, song); upld.uploadSong(song);
} }
else else
{ {
cout<<"Uploading songs from " << songDirectory << endl; cout<<"Uploading songs from " << songDirectory << endl;
upld.uploadSongsFromDirectory(token, songDirectory, noConfirm, recursiveDirectory); upld.uploadSongsFromDirectory(songDirectory, noConfirm, recursiveDirectory);
} }
} }
// TODO: Change the name
void CommitManager::uploadSingleSong()
{
cout<<"Uploading single song with metadata\n\n";
APIParser apiPrs{icaAction};
auto api = apiPrs.retrieveAPI();
const auto token = parseToken(api);
// Either the set of "-s", "-m", "-ca" flags or "-smca" must exist with values
// in order to be valid but not both
const auto songPath = this->icaAction.retrieveFlagValue("-s");
const auto metadataPath = this->icaAction.retrieveFlagValue("-m");
const auto coverPath = this->icaAction.retrieveFlagValue("-ca");
const auto singleTarget = !songPath.empty() && !metadataPath.empty() &&
!coverPath.empty() ? true : false;
const auto uni = this->icaAction.retrieveFlagValue("-smca");
const auto multiTarget = !uni.empty() ? true : false;
if (singleTarget && multiTarget)
{
cout<<"Cannot upload from source and directory\n";
return;
}
cout<<"song path: "<<songPath<<"\n";
cout<<"Metadata path: "<<metadataPath<<"\n";
cout<<"Cover Art path: "<<coverPath<<"\n";
auto album = retrieveMetadata(metadataPath);
album.printInfo();
for (auto sng : album.songs)
{
// sng.printInfo();
}
auto disc = 0;
auto track = 1;
auto sng = std::find_if(album.songs.begin(), album.songs.end(), [&](Song s)
{
return s.track == track && s.disc == disc;
});
if (sng == album.songs.end())
{
cout<<"Not found\n";
}
auto song = *sng;
song.songPath = songPath;
Models::CoverArt cover;
cover.title = song.title;
cover.path = coverPath;
Upload up(api, token);
up.uploadSongWithMetadata(album, song, cover);
}
#pragma region private
CommitManager::Album CommitManager::retrieveMetadata(const std::string_view path)
{
CommitManager::Album album;
const auto fileContent = retrieveFileContent(path);
cout<<"Parsing...\n";
auto serialized = nlohmann::json::parse(fileContent);
cout<<"Parsed\n";
album.album = serialized["album"].get<std::string>();
album.albumArtist = serialized["album_artist"].get<std::string>();
album.genre = serialized["genre"].get<std::string>();
album.year = serialized["year"].get<int>();
album.trackCount = serialized["track_count"].get<int>();
album.discCount = serialized["disc_count"].get<int>();
album.songs.reserve(album.trackCount);
for (auto &j : serialized["tracks"])
{
Song song;
song.title = j["title"].get<std::string>();
song.track = j["track"].get<int>();
song.disc = j["disc"].get<int>();
song.artist = j["artist"].get<std::string>();
song.album = album.album;
song.year = album.year;
song.genre = album.genre;
album.songs.push_back(song);
}
return album;
}
string CommitManager::retrieveFileContent(const std::string_view path)
{
string path_str(path);
string value;
std::stringstream buffer;
std::fstream file(path_str, std::ios::in);
buffer<<file.rdbuf();
file.close();
value.assign(buffer.str());
return value;
}
#pragma endregion
void CommitManager::Album::printInfo()
{
std::cout<<"Album: "<<this->album<<"\n";
std::cout<<"Album Artist: "<<this->albumArtist<<"\n";
std::cout<<"Genre: "<<this->genre<<"\n";
std::cout<<"Year: "<<this->year<<"\n";
std::cout<<"Track count: "<<this->trackCount<<"\n";
std::cout<<"Disc count: "<<this->discCount<<"\n";
std::cout<<"\n";
}
#pragma Functions #pragma Functions
} }
+9 -13
View File
@@ -24,22 +24,15 @@ using namespace cpr;
namespace Syncers namespace Syncers
{ {
Upload::Upload() { } Song Upload::uploadSong(Song& song)
Upload::Upload(API api) : api(api)
{
this->api.endpoint = "song/data";
}
Song Upload::uploadSong(const Models::Token& token, Song& song)
{ {
try try
{ {
auto url = retrieveUrl(); auto url = retrieveUrl();
cout<<"url "<<url<<endl; cout<<"url "<<url<<endl;
string auth{token.tokenType}; string auth{this->m_token.tokenType};
auth.append(" " + token.accessToken); auth.append(" " + this->m_token.accessToken);
auto r = cpr::Post(cpr::Url{url}, auto r = cpr::Post(cpr::Url{url},
cpr::Multipart{{"key", "small value"}, cpr::Multipart{{"key", "small value"},
{"file", cpr::File{song.songPath}}}, {"file", cpr::File{song.songPath}}},
@@ -70,8 +63,7 @@ namespace Syncers
return song; return song;
} }
void Upload::uploadSongsFromDirectory(const Models::Token& token, void Upload::uploadSongsFromDirectory(const std::string& directory,
const std::string& directory,
const bool noConfirm, bool recursive = false) const bool noConfirm, bool recursive = false)
{ {
try try
@@ -106,7 +98,7 @@ namespace Syncers
cout << "uploading songs\n"; cout << "uploading songs\n";
for (auto& song: songs) for (auto& song: songs)
{ {
song = uploadSong(token, song); song = uploadSong(song);
} }
} }
catch (exception& e) catch (exception& e)
@@ -116,6 +108,10 @@ namespace Syncers
} }
void Upload::uploadSongWithMetadata(Managers::CommitManager::Album &album, Models::Song& song, Models::CoverArt &cover)
{
// TODO: Implement
}
std::vector<Song> Upload::retrieveAllSongsFromDirectory(const std::string& directory, std::vector<Song> Upload::retrieveAllSongsFromDirectory(const std::string& directory,
bool recursive) bool recursive)
{ {