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_
#define ACTIONMANAGER_H_
#include<algorithm>
#include<string>
#include<string_view>
#include<array>
@@ -18,11 +19,24 @@ namespace Managers
Models::IcarusAction retrieveIcarusAction() const;
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;
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 validateFlags();
+52 -2
View File
@@ -2,11 +2,14 @@
#define COMMITMANAGER_H_
#include<map>
#include<iostream>
#include<string>
#include<string_view>
#include"Models/API.h"
#include"Models/Token.h"
#include"Models/IcarusAction.h"
#include"Models/Song.h"
#include"Models/Token.h"
namespace Managers
{
@@ -22,6 +25,24 @@ namespace Managers
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:
enum class ActionValues;
@@ -33,15 +54,44 @@ namespace Managers
void downloadSong();
void retrieveObjects();
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
{
deleteAct,
downloadAct,
retrieveAct,
uploadAct
uploadAct,
UPLOAD_SONG_WITH_METADATA // Uploads the song with metadata, including cover art
};
Models::IcarusAction icaAction;
};
}
+2 -1
View File
@@ -5,8 +5,9 @@
namespace Models
{
struct Flags
class Flags
{
public:
std::string flag;
std::string value;
};
+34 -1
View File
@@ -2,14 +2,47 @@
#define ICARUSACTION_H_
#include<string>
#include<algorithm>
#include<string_view>
#include<vector>
#include<iostream>
#include"Flags.h"
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::vector<Flags> flags;
};
+20 -1
View File
@@ -2,12 +2,22 @@
#define SONG_H_
#include<string>
#include<iostream>
namespace Models
{
struct Song
class Song
{
public:
Song() = default;
void printInfo()
{
std::cout<<"Title: "<<this->title<<"\n";
std::cout<<"\n";
}
int id;
std::string title;
std::string artist;
@@ -16,9 +26,18 @@ namespace Models
int year;
int duration;
int track;
int disc;
std::string data;
std::string songPath;
};
class CoverArt
{
public:
int id;
std::string title;
std::string path;
};
}
#endif
+9 -5
View File
@@ -7,6 +7,7 @@
#include<nlohmann/json.hpp>
#include"Managers/CommitManager.h"
#include"Managers/FileManager.h"
#include"Models/API.h"
#include"Models/Song.h"
@@ -21,16 +22,19 @@ namespace Syncers
class Upload
{
public:
Upload();
Upload(Models::API);
Upload(Models::API api, Models::Token token) : m_token(token), api(api)
{
this->api.endpoint = "song/data";
}
Models::Song uploadSong(const Models::Token&, Models::Song&);
void uploadSongsFromDirectory(const Models::Token&,
const std::string&, const bool, bool);
Models::Song uploadSong(Models::Song&);
void uploadSongsFromDirectory(const std::string&, const bool, bool);
void uploadSongWithMetadata(Managers::CommitManager::Album&, Models::Song&, Models::CoverArt&);
private:
Managers::FileManager fMgr;
Models::API api;
Models::Song song;
Models::Token m_token;
std::vector<Models::Song> retrieveAllSongsFromDirectory(const std::string&,
bool);
+2
View File
@@ -62,6 +62,8 @@ int main(int argc, char** argv)
ActionManager actMgr(argv, argc);
auto chosenAction = actMgr.retrieveIcarusAction();
chosenAction.print_action_and_flags();
CommitManager commitMgr(chosenAction);
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()
{
@@ -62,13 +45,14 @@ namespace Managers
transform(action.begin(), action.end(),
action.begin(), ::tolower);
}
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();
@@ -83,7 +67,7 @@ namespace Managers
if (flag.size() > 3 || isNumber(flag))
{
flg.value = flag;
//cout<<"flag value "<<flg.value<<endl;
flags.push_back(flg);
flg = Flags{};
continue;
@@ -95,7 +79,6 @@ namespace Managers
return !flag.compare(val);
}))
{
//cout<<"flag "<<flag<<endl;
flg.flag = flag;
}
else
@@ -108,7 +91,8 @@ namespace Managers
vector<string> ActionManager::parsedFlags()
{
auto parsed = vector<string>();
vector<string> parsed;
parsed.reserve(paramCount);
for (auto i = 2; i < paramCount; ++i)
{
+144 -10
View File
@@ -1,6 +1,11 @@
#include"Managers/CommitManager.h"
#include<iostream>
#include<fstream>
#include<sstream>
#include<filesystem>
#include"nlohmann/json.hpp"
#include"Models/API.h"
#include"Models/Song.h"
@@ -31,6 +36,8 @@ using Syncers::Download;
using Syncers::RetrieveRecords;
using Syncers::Upload;
namespace filesystem = std::filesystem;
namespace Managers
{
#pragma
@@ -44,6 +51,7 @@ namespace Managers
{
auto action = icaAction.action;
cout<<"Commiting "<<action<<" action"<<endl;
switch (mapActions()[action])
{
case ActionValues::deleteAct:
@@ -58,6 +66,9 @@ namespace Managers
case ActionValues::uploadAct:
uploadSong();
break;
case ActionValues::UPLOAD_SONG_WITH_METADATA:
uploadSingleSong();
break;
default:
break;
}
@@ -73,7 +84,8 @@ namespace Managers
{"delete", ActionValues::deleteAct},
{"download", ActionValues::downloadAct},
{"retrieve", ActionValues::retrieveAct},
{"upload", ActionValues::uploadAct}
{"upload", ActionValues::uploadAct},
{"upload-meta", ActionValues::UPLOAD_SONG_WITH_METADATA}
};
return actions;
@@ -82,7 +94,7 @@ namespace Managers
Token CommitManager::parseToken(API api)
{
cout<<"fetching token"<<endl;
cout<<"fetching token\n";
UserManager usrMgr{icaAction};
auto user = usrMgr.retrieveUser();
@@ -178,7 +190,7 @@ namespace Managers
{
auto uploadSingleSong = true;
auto recursiveDirectory = false;
auto noConfirm = false;
const auto noConfirm = checkForNoConfirm();
string songDirectory;
APIParser apiPrs{icaAction};
auto api = apiPrs.retrieveAPI();
@@ -206,24 +218,146 @@ namespace Managers
songDirectory = value;
uploadSingleSong = false;
recursiveDirectory = true;
}
else if (flag.compare("-nc") == 0)
{
noConfirm = true;
}
}
Upload upld{api};
Upload upld{api, token};
if (uploadSingleSong)
{
cout<<"Uploading song..."<<endl;
upld.uploadSong(token, song);
upld.uploadSong(song);
}
else
{
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
}
+9 -13
View File
@@ -24,22 +24,15 @@ using namespace cpr;
namespace Syncers
{
Upload::Upload() { }
Upload::Upload(API api) : api(api)
{
this->api.endpoint = "song/data";
}
Song Upload::uploadSong(const Models::Token& token, Song& song)
Song Upload::uploadSong(Song& song)
{
try
{
auto url = retrieveUrl();
cout<<"url "<<url<<endl;
string auth{token.tokenType};
auth.append(" " + token.accessToken);
string auth{this->m_token.tokenType};
auth.append(" " + this->m_token.accessToken);
auto r = cpr::Post(cpr::Url{url},
cpr::Multipart{{"key", "small value"},
{"file", cpr::File{song.songPath}}},
@@ -70,8 +63,7 @@ namespace Syncers
return song;
}
void Upload::uploadSongsFromDirectory(const Models::Token& token,
const std::string& directory,
void Upload::uploadSongsFromDirectory(const std::string& directory,
const bool noConfirm, bool recursive = false)
{
try
@@ -106,7 +98,7 @@ namespace Syncers
cout << "uploading songs\n";
for (auto& song: songs)
{
song = uploadSong(token, song);
song = uploadSong(song);
}
}
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,
bool recursive)
{