Made progress
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
|
||||
namespace Models
|
||||
{
|
||||
struct Flags
|
||||
class Flags
|
||||
{
|
||||
public:
|
||||
std::string flag;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user