Added feature to upload all songs from a directory (optional recursive). Need to document the use of it as well as how to even use this CLI

This commit is contained in:
kdeng00
2019-10-23 20:48:42 -04:00
parent 27aecc7a0d
commit 81892cc52e
11 changed files with 162 additions and 29 deletions
+3 -3
View File
@@ -31,9 +31,9 @@ namespace Managers
std::array<std::string, 4> supportedActions{ std::array<std::string, 4> supportedActions{
"download", "upload", "retrieve", "delete" "download", "upload", "retrieve", "delete"
}; };
std::array<std::string, 9> supportedFlags{ std::array<std::string, 11> supportedFlags{
"-u", "-p", "-t", "-h", "-s", "-u", "-p", "-t", "-h", "-s", "-sd",
"-d", "-D", "-b", "-rt" "-sr", "-d", "-D", "-b", "-rt"
}; };
std::vector<Models::Flags> flags; std::vector<Models::Flags> flags;
char **params; char **params;
+1 -2
View File
@@ -38,8 +38,7 @@ namespace Managers
uploadAct uploadAct
}; };
std::map<std::string, ActionValues> mapActions = std::map<std::string, ActionValues> mapActions{
std::map<std::string, ActionValues>{
{"delete", deleteAct}, {"download", downloadAct}, {"delete", deleteAct}, {"download", downloadAct},
{"retrieve", retrieveAct}, {"retrieve", retrieveAct},
{"upload", uploadAct} {"upload", uploadAct}
+2 -2
View File
@@ -10,8 +10,8 @@ namespace Managers
class TokenManager class TokenManager
{ {
public: public:
TokenManager(const Models::User); TokenManager(const Models::User&);
TokenManager(const Models::User, Models::API); TokenManager(const Models::User&, Models::API&);
Models::Token requestToken(); Models::Token requestToken();
private: private:
+2 -1
View File
@@ -15,7 +15,8 @@ namespace Models
std::string genre; std::string genre;
int year; int year;
int duration; int duration;
std::string data; int track;
std::string data;
std::string songPath; std::string songPath;
}; };
} }
+1 -1
View File
@@ -24,7 +24,7 @@ namespace Syncers
std::string retrieveUrl(Models::Song); std::string retrieveUrl(Models::Song);
std::string downloadFilePath; std::string downloadFilePath;
void saveSong(Models::Song*); void saveSong(Models::Song&);
}; };
} }
+12 -1
View File
@@ -1,7 +1,9 @@
#ifndef UPLOAD_H_ #ifndef UPLOAD_H_
#define UPLOAD_H_ #define UPLOAD_H_
#include<filesystem>
#include<string> #include<string>
#include<vector>
#include<nlohmann/json.hpp> #include<nlohmann/json.hpp>
@@ -11,6 +13,8 @@
#include"Models/Token.h" #include"Models/Token.h"
#include"Models/UploadForm.h" #include"Models/UploadForm.h"
namespace fs = std::filesystem;
namespace Syncers namespace Syncers
{ {
@@ -20,15 +24,22 @@ namespace Syncers
Upload(); Upload();
Upload(Models::API); Upload(Models::API);
void uploadSong(const Models::Token, Models::Song); Models::Song uploadSong(const Models::Token&, Models::Song&);
void uploadSongsFromDirectory(const Models::Token&, const std::string&, bool);
private: private:
Managers::FileManager fMgr; Managers::FileManager fMgr;
Models::API api; Models::API api;
Models::Song song; Models::Song song;
std::vector<Models::Song> retrieveAllSongsFromDirectory(const std::string&,
bool);
std::string retrieveUrl(); std::string retrieveUrl();
Models::Song retrieveSongPath(fs::directory_entry&);
void printSongDetails(); void printSongDetails();
void printSongDetails(std::vector<Models::Song>&);
void printJsonData(nlohmann::json); void printJsonData(nlohmann::json);
}; };
} }
+1 -1
View File
@@ -71,7 +71,7 @@ namespace Managers
} }
if (std::any_of(supportedFlags.begin(), supportedFlags.end(), if (std::any_of(supportedFlags.begin(), supportedFlags.end(),
[&](string val) [&](string& val)
{ {
return !val.compare(flag); return !val.compare(flag);
})) }))
+26 -4
View File
@@ -157,14 +157,17 @@ namespace Managers
} }
void CommitManager::uploadSong() void CommitManager::uploadSong()
{ {
bool uploadSingleSong = true;
bool recursiveDirectory = false;
string songDirectory;
APIParser apiPrs{icaAction}; APIParser apiPrs{icaAction};
auto api = apiPrs.retrieveAPI(); auto api = apiPrs.retrieveAPI();
auto token = parseToken(api); auto token = parseToken(api);
Song song{}; Song song;
for (auto arg : icaAction.flags) for (auto& arg : icaAction.flags)
{ {
auto flag = arg.flag; auto flag = arg.flag;
auto value = arg.value; auto value = arg.value;
@@ -173,11 +176,30 @@ namespace Managers
{ {
song.songPath.assign(arg.value); song.songPath.assign(arg.value);
} }
else if (flag.compare("-sd") == 0)
{
songDirectory = value;
uploadSingleSong = false;
}
else if (flag.compare("-sr") == 0)
{
songDirectory = value;
uploadSingleSong = false;
recursiveDirectory = true;
}
} }
Upload upld{api}; Upload upld{api};
cout<<"Uploading song..."<<endl; if (uploadSingleSong)
upld.uploadSong(token, song); {
cout<<"Uploading song..."<<endl;
upld.uploadSong(token, song);
}
else
{
cout<<"Uploading songs from " << songDirectory << endl;
upld.uploadSongsFromDirectory(token, songDirectory, recursiveDirectory);
}
} }
#pragma Functions #pragma Functions
} }
+2 -2
View File
@@ -18,11 +18,11 @@ using Models::User;
namespace Managers namespace Managers
{ {
#pragma #pragma
TokenManager::TokenManager(const User user) TokenManager::TokenManager(const User& user)
{ {
this->user = user; this->user = user;
} }
TokenManager::TokenManager(const User user, API api) TokenManager::TokenManager(const User& user, API& api)
{ {
this->user = user; this->user = user;
this->api = api; this->api = api;
+12 -8
View File
@@ -42,15 +42,19 @@ namespace Syncers
cout<<"song path "<<song.songPath<<endl; cout<<"song path "<<song.songPath<<endl;
string auth{token.tokenType}; string auth{token.tokenType};
auth.append(" " + token.accessToken); auth.append(" " + token.accessToken);
/**
auto r = cpr::Get(cpr::Url(url), auto r = cpr::Get(cpr::Url(url),
cpr::Header{{"authorization", auth}}); cpr::Header{{"authorization", auth}});
*/
auto r = cpr::Get(cpr::Url(url),
cpr::Header{{"Content-type", "audio/mpeg"}});
int statusCode = r.status_code; int statusCode = r.status_code;
if (statusCode == OK) if (statusCode == OK) {
{
song.data = r.text; song.data = r.text;
saveSong(&song); saveSong(song);
} }
@@ -74,14 +78,14 @@ namespace Syncers
return url; return url;
} }
void Download::saveSong(Song *song) void Download::saveSong(Song& song)
{ {
cout<<"\nSaving song to: "<<song->songPath<<endl; cout<<"\nSaving song to: "<<song.songPath<<endl;
int bufferLength = song->data.length(); int bufferLength = song.data.length();
const char *data = song->data.c_str(); const char *data = song.data.c_str();
cout<<"buff length "<<bufferLength<<endl; cout<<"buff length "<<bufferLength<<endl;
ofstream saveSong{song->songPath, std::ios::binary}; ofstream saveSong{song.songPath, std::ios::binary};
saveSong.write(data, bufferLength); saveSong.write(data, bufferLength);
saveSong.close(); saveSong.close();
} }
+100 -4
View File
@@ -1,6 +1,6 @@
#include<iostream> #include<iostream>
#include<filesystem>
#include<exception> #include<exception>
#include<string>
#include<cpr/cpr.h> #include<cpr/cpr.h>
#include<nlohmann/json.hpp> #include<nlohmann/json.hpp>
@@ -30,7 +30,7 @@ namespace Syncers
} }
void Upload::uploadSong(const Models::Token token, Song song) Song Upload::uploadSong(const Models::Token& token, Song& song)
{ {
try try
{ {
@@ -45,16 +45,77 @@ namespace Syncers
cpr::Header{{"authorization", auth}} cpr::Header{{"authorization", auth}}
); );
cout << r.status_code<< std::endl; cout << "status code: " << r.status_code<< std::endl;
auto result = nlohmann::json::parse(r.text);
cout<<"Finished"<<endl;
song.id = result["id"].get<int>();
song.title = result["title"].get<std::string>();
song.artist = result["artist"].get<std::string>();
song.album = result["album"].get<std::string>();
song.genre = result["genre"].get<std::string>();
song.year = result["year"].get<int>();
song.duration = result["duration"].get<int>();
song.track = result["track"].get<int>();
return song;
} }
catch (exception e) catch (exception e)
{ {
auto msg = e.what(); auto msg = e.what();
cout<<msg<<endl; cout<<msg<<endl;
} }
cout<<"Finished"<<endl;
return song;
} }
void Upload::uploadSongsFromDirectory(const Models::Token& token,
const std::string& directory,
bool recursive = false)
{
try
{
auto songs = retrieveAllSongsFromDirectory(directory, recursive);
for (auto& song: songs)
{
song = uploadSong(token, song);
}
printSongDetails(songs);
}
catch (exception& e)
{
cout<<e.what()<<endl;
}
}
std::vector<Song> Upload::retrieveAllSongsFromDirectory(const std::string& directory,
bool recursive)
{
std::vector<Song> allSongs;
if (recursive)
{
for (auto p: fs::recursive_directory_iterator(directory))
{
auto song = retrieveSongPath(p);
if (!song.songPath.empty())
allSongs.push_back(song);
}
}
else
{
for (auto p: fs::directory_iterator(directory))
{
auto song = retrieveSongPath(p);
if (!song.songPath.empty())
allSongs.push_back(song);
}
}
return allSongs;
}
string Upload::retrieveUrl() string Upload::retrieveUrl()
{ {
const string url{api.url + "api/" + api.version + "/" + const string url{api.url + "api/" + api.version + "/" +
@@ -62,6 +123,26 @@ namespace Syncers
return url; return url;
} }
Song Upload::retrieveSongPath(fs::directory_entry& dirEntry)
{
constexpr auto mp3Ext = ".mp3";
Song song;
if (fs::is_regular_file(dirEntry.path()))
{
const auto ext = dirEntry.path().extension().string();
if (ext.compare(mp3Ext) == 0)
{
cout << "found mp3 file" << endl;
song.songPath = dirEntry.path().string();
}
}
return song;
}
#pragma #pragma
void Upload::printSongDetails() void Upload::printSongDetails()
{ {
@@ -74,6 +155,21 @@ namespace Syncers
cout<<"Year: "<<song.year<<endl; cout<<"Year: "<<song.year<<endl;
cout<<"Duration: "<<song.duration<<endl; cout<<"Duration: "<<song.duration<<endl;
} }
void Upload::printSongDetails(std::vector<Song>& songs)
{
for (auto& song: songs)
{
cout<<"Song details: "<<endl;
cout<<"Id: "<<song.id<<endl;
cout<<"Title: "<<song.title<<endl;
cout<<"Artist: "<<song.artist<<endl;
cout<<"Album: "<<song.album<<endl;
cout<<"Genre: "<<song.genre<<endl;
cout<<"Year: "<<song.year<<endl;
cout<<"Duration: "<<song.duration<<endl;
cout<<"Path: "<<song.songPath<<endl;
}
}
void Upload::printJsonData(json obj) void Upload::printJsonData(json obj)
{ {
cout<<endl<<endl<<"JSon data: "<<endl; cout<<endl<<endl<<"JSon data: "<<endl;