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:
@@ -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;
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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&);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user