3 Commits

Author SHA1 Message Date
kdeng00 7177b01a98 added flag to prevent the user from being prompted when uploading songs from a directory 2019-11-12 22:07:44 -05:00
kdeng00 996b84c25c Prompt user when uploading songs from a directory 2019-11-11 22:54:53 -05:00
Kun Deng 9d8122df5c Update README.md 2019-10-26 10:22:12 -04:00
9 changed files with 150 additions and 57 deletions
+25 -11
View File
@@ -1,6 +1,17 @@
# IcarusDownloadManager # IcarusDownloadManager
IcarusDownloadManager is a Linux UI software client application that has the feature of uploading and downloading songs from the [Icarus](https://github.com/amazing-username/Icarus) Music Server. IcarusDownloadManager is a Linux CLI software client application that has the feature of uploading and downloading songs from the [Icarus](https://github.com/amazing-username/Icarus) Music Server.
## Built With
* C++
* CMake
* GCC
* [Hunter](https://github.com/ruslo/hunter)
* libCurl
* [json](https://github.com/nlohmann/json)
* [cpr](http://whoshuu.github.io/cpr/)
### Getting Started ### Getting Started
@@ -16,18 +27,20 @@ cmake --build _builds --config Debug
make make
``` ```
The program has been built and can be executed by the binary file *icd* The program has been built and can be executed by the binary file *icd*. For information on how to use icd, merely execute the program without any command line arguments.
### Downloading Song
``icd download -u spacecadet -p stellar40 -h https://icarus.com -b 15``
## Built With ### Uploading Song
``icd upload -u spacecadet -p stellar40 -h https://icarus.com -s /path/of/song.mp3``
### Retrieving Song in json
``icd retrieve -u spacecadet -p stellar40 -h https://icarus.com -rt songs``
### Deleting Song
``icd delete -u spacecadet -p stellar40 -h https://icarus.com -D 15``
* C++
* CMake
* GCC
* [Hunter](https://github.com/ruslo/hunter)
* libCurl
* [json](https://github.com/nlohmann/json)
* [cpr](http://whoshuu.github.io/cpr/)
## Contributing ## Contributing
@@ -35,7 +48,8 @@ Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on the code of conduc
## Versioning ## Versioning
[v0.1.0](https://github.com/amazing-username/IcarusDownloadManager/releases/tag/0.1.0) [v0.1.1](https://github.com/kdeng00/IcarusDownloadManager/releases/tag/v0.1.1)
[v0.1.0](https://github.com/kdeng00/IcarusDownloadManager/releases/tag/0.1.0)
## Authors ## Authors
+9 -10
View File
@@ -2,6 +2,7 @@
#define ACTIONMANAGER_H_ #define ACTIONMANAGER_H_
#include<string> #include<string>
#include<string_view>
#include<array> #include<array>
#include<vector> #include<vector>
@@ -17,25 +18,23 @@ namespace Managers
Models::IcarusAction retrieveIcarusAction() const; Models::IcarusAction retrieveIcarusAction() const;
private: private:
bool isNumber(std::string); constexpr std::array<const char*, 12> supportedFlags() noexcept;
constexpr std::array<const char*, 4> supportedActions() noexcept;
bool isNumber(const std::string_view) noexcept;
void initialize(); void initialize();
void validateFlags(); void validateFlags();
std::vector<std::string> parsedFlags(); std::vector<std::string> parsedFlags();
void printAction(); void printAction() noexcept;
void printFlags(); void printFlags() noexcept;
std::string action; std::string action;
std::array<std::string, 4> supportedActions{
"download", "upload", "retrieve", "delete"
};
std::array<std::string, 11> supportedFlags{
"-u", "-p", "-t", "-h", "-s", "-sd",
"-sr", "-d", "-D", "-b", "-rt"
};
std::vector<Models::Flags> flags; std::vector<Models::Flags> flags;
char **params; char **params;
int paramCount; int paramCount;
}; };
+6 -8
View File
@@ -17,12 +17,16 @@ namespace Managers
void commitAction(); void commitAction();
enum RetrieveTypes enum class RetrieveTypes
{ {
songs songs
}; };
private: private:
enum class ActionValues;
std::map<std::string, ActionValues> mapActions() noexcept;
Models::Token parseToken(Models::API); Models::Token parseToken(Models::API);
void deleteSong(); void deleteSong();
@@ -30,7 +34,7 @@ namespace Managers
void retrieveObjects(); void retrieveObjects();
void uploadSong(); void uploadSong();
enum ActionValues enum class ActionValues
{ {
deleteAct, deleteAct,
downloadAct, downloadAct,
@@ -38,12 +42,6 @@ namespace Managers
uploadAct uploadAct
}; };
std::map<std::string, ActionValues> mapActions{
{"delete", deleteAct}, {"download", downloadAct},
{"retrieve", retrieveAct},
{"upload", uploadAct}
};
Models::IcarusAction icaAction; Models::IcarusAction icaAction;
}; };
} }
+7
View File
@@ -14,6 +14,13 @@ namespace Syncers
const int OK = 200; const int OK = 200;
const int UNAUTHORIZED = 401; const int UNAUTHORIZED = 401;
const int NOTFOUND = 404; const int NOTFOUND = 404;
enum class Result
{
OK = 200,
UNAUTHORIZED = 401,
NOTFOUND = 404
};
}; };
} }
+3 -2
View File
@@ -25,7 +25,8 @@ namespace Syncers
Upload(Models::API); Upload(Models::API);
Models::Song uploadSong(const Models::Token&, Models::Song&); Models::Song uploadSong(const Models::Token&, Models::Song&);
void uploadSongsFromDirectory(const Models::Token&, const std::string&, bool); void uploadSongsFromDirectory(const Models::Token&,
const std::string&, const bool, bool);
private: private:
Managers::FileManager fMgr; Managers::FileManager fMgr;
Models::API api; Models::API api;
@@ -40,7 +41,7 @@ namespace Syncers
void printSongDetails(); void printSongDetails();
void printSongDetails(std::vector<Models::Song>&); void printSongDetails(std::vector<Models::Song>&);
void printJsonData(nlohmann::json); void printJsonData(const nlohmann::json&);
}; };
} }
+5 -4
View File
@@ -31,7 +31,8 @@ void printHelp()
cout<<"Required for upload\n"; cout<<"Required for upload\n";
cout<<"-s path of song\n"; cout<<"-s path of song\n";
cout<<"-sd directory where to search for songs to upload (Optional)\n"; cout<<"-sd directory where to search for songs to upload (Optional)\n";
cout<<"-sr directory where to recursively search for songs to upload (Optional)\n\n"; cout<<"-sr directory where to recursively search for songs to upload (Optional)\n";
cout<<"-nc will not prompt the user when uploading from a directory\n\n";
cout<<"Required for download\n"; cout<<"Required for download\n";
cout<<"-b song id\n"; cout<<"-b song id\n";
@@ -50,13 +51,13 @@ int main(int argc, char** argv)
if (argc < 2) if (argc < 2)
{ {
printHelp(); printHelp();
return 1; return -1;
} }
ActionManager actMgr{argv, argc}; ActionManager actMgr(argv, argc);
auto chosenAction = actMgr.retrieveIcarusAction(); auto chosenAction = actMgr.retrieveIcarusAction();
CommitManager commitMgr{chosenAction}; CommitManager commitMgr(chosenAction);
commitMgr.commitAction(); commitMgr.commitAction();
return 0; return 0;
+30 -10
View File
@@ -8,6 +8,7 @@
using std::cout; using std::cout;
using std::endl; using std::endl;
using std::string; using std::string;
using std::string_view;
using std::vector; using std::vector;
using Models::Flags; using Models::Flags;
@@ -27,14 +28,24 @@ namespace Managers
#pragma #pragma
IcarusAction ActionManager::retrieveIcarusAction() const IcarusAction ActionManager::retrieveIcarusAction() const
{ {
auto icarusAction = IcarusAction{}; IcarusAction icarusAction;
icarusAction.flags = flags; icarusAction.flags = flags;
icarusAction.action = action; icarusAction.action = action;
return icarusAction; return icarusAction;
} }
bool ActionManager::isNumber(string val)
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(), return !val.empty() && std::find_if(val.begin(),
val.end(), [](char c) val.end(), [](char c)
@@ -59,8 +70,16 @@ namespace Managers
Flags flg{}; Flags flg{};
auto allSupportedFlags = supportedFlags();
for (auto flag : flagVals) for (auto flag : flagVals)
{ {
if (flag.compare("-nc") == 0)
{
flg.flag = flag;
flags.push_back(flg);
continue;
}
if (flag.size() > 3 || isNumber(flag)) if (flag.size() > 3 || isNumber(flag))
{ {
flg.value = flag; flg.value = flag;
@@ -70,10 +89,10 @@ namespace Managers
continue; continue;
} }
if (std::any_of(supportedFlags.begin(), supportedFlags.end(), if (std::any_of(allSupportedFlags.begin(), allSupportedFlags.end(),
[&](string& val) [&](const char *val)
{ {
return !val.compare(flag); return !flag.compare(val);
})) }))
{ {
//cout<<"flag "<<flag<<endl; //cout<<"flag "<<flag<<endl;
@@ -81,7 +100,7 @@ namespace Managers
} }
else else
{ {
cout<<"Action is not valid"<<endl; cout<<"Flag is not valid"<<endl;
exit(1); exit(1);
} }
} }
@@ -89,18 +108,19 @@ namespace Managers
vector<string> ActionManager::parsedFlags() vector<string> ActionManager::parsedFlags()
{ {
auto parsed = vector<string>{}; auto parsed = vector<string>();
for (auto i = 2; i < paramCount; ++i) for (auto i = 2; i < paramCount; ++i)
{ {
parsed.push_back(std::move(*(params + i))); const std::string flag(std::move(*(params + i)));
parsed.push_back(std::move(flag));
} }
return parsed; return parsed;
} }
#pragma #pragma
void ActionManager::printAction() void ActionManager::printAction() noexcept
{ {
if (action.empty()) if (action.empty())
{ {
@@ -111,7 +131,7 @@ namespace Managers
cout<<"Action is "<<action<<endl; cout<<"Action is "<<action<<endl;
} }
} }
void ActionManager::printFlags() void ActionManager::printFlags() noexcept
{ {
cout<<"\nPrinting flags..."<<endl; cout<<"\nPrinting flags..."<<endl;
for (auto flag: flags) for (auto flag: flags)
+33 -9
View File
@@ -36,7 +36,7 @@ namespace Managers
#pragma #pragma
CommitManager::CommitManager(IcarusAction& icaAct) : icaAction(std::move(icaAct)) CommitManager::CommitManager(IcarusAction& icaAct) : icaAction(std::move(icaAct))
{ } { }
#pragma Constructors; #pragma Constructors
#pragma #pragma
@@ -44,23 +44,42 @@ 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 deleteAct: case ActionValues::deleteAct:
deleteSong(); deleteSong();
break; break;
case downloadAct: case ActionValues::downloadAct:
downloadSong(); downloadSong();
break; break;
case retrieveAct: case ActionValues::retrieveAct:
retrieveObjects(); retrieveObjects();
break; break;
case uploadAct: case ActionValues::uploadAct:
uploadSong(); uploadSong();
break; break;
default:
break;
} }
} }
enum class ActionValues;
std::map<std::string, CommitManager::ActionValues>
CommitManager::mapActions() noexcept
{
const std::map<std::string, ActionValues> actions{
{"delete", ActionValues::deleteAct},
{"download", ActionValues::downloadAct},
{"retrieve", ActionValues::retrieveAct},
{"upload", ActionValues::uploadAct}
};
return actions;
}
Token CommitManager::parseToken(API api) Token CommitManager::parseToken(API api)
{ {
cout<<"fetching token"<<endl; cout<<"fetching token"<<endl;
@@ -157,8 +176,9 @@ namespace Managers
} }
void CommitManager::uploadSong() void CommitManager::uploadSong()
{ {
bool uploadSingleSong = true; auto uploadSingleSong = true;
bool recursiveDirectory = false; auto recursiveDirectory = false;
auto noConfirm = false;
string songDirectory; string songDirectory;
APIParser apiPrs{icaAction}; APIParser apiPrs{icaAction};
auto api = apiPrs.retrieveAPI(); auto api = apiPrs.retrieveAPI();
@@ -186,6 +206,10 @@ namespace Managers
songDirectory = value; songDirectory = value;
uploadSingleSong = false; uploadSingleSong = false;
recursiveDirectory = true; recursiveDirectory = true;
}
else if (flag.compare("-nc") == 0)
{
noConfirm = true;
} }
} }
@@ -198,7 +222,7 @@ namespace Managers
else else
{ {
cout<<"Uploading songs from " << songDirectory << endl; cout<<"Uploading songs from " << songDirectory << endl;
upld.uploadSongsFromDirectory(token, songDirectory, recursiveDirectory); upld.uploadSongsFromDirectory(token, songDirectory, noConfirm, recursiveDirectory);
} }
} }
#pragma Functions #pragma Functions
+32 -3
View File
@@ -8,6 +8,7 @@
#include"Syncers/Upload.h" #include"Syncers/Upload.h"
using std::cout; using std::cout;
using std::cin;
using std::endl; using std::endl;
using std::exception; using std::exception;
using std::string; using std::string;
@@ -46,6 +47,7 @@ namespace Syncers
); );
cout << "status code: " << r.status_code<< std::endl; cout << "status code: " << r.status_code<< std::endl;
cout << r.text << endl;
auto result = nlohmann::json::parse(r.text); auto result = nlohmann::json::parse(r.text);
cout<<"Finished"<<endl; cout<<"Finished"<<endl;
song.id = result["id"].get<int>(); song.id = result["id"].get<int>();
@@ -59,7 +61,7 @@ namespace Syncers
return song; return song;
} }
catch (exception e) catch (exception& e)
{ {
auto msg = e.what(); auto msg = e.what();
cout<<msg<<endl; cout<<msg<<endl;
@@ -70,11 +72,38 @@ namespace Syncers
void Upload::uploadSongsFromDirectory(const Models::Token& token, void Upload::uploadSongsFromDirectory(const Models::Token& token,
const std::string& directory, const std::string& directory,
bool recursive = false) const bool noConfirm, bool recursive = false)
{ {
try try
{ {
auto songs = retrieveAllSongsFromDirectory(directory, recursive); auto songs = retrieveAllSongsFromDirectory(directory, recursive);
auto confirmUpload = true;
while (!noConfirm)
{
auto answer = 'a';
cout << "are you sure you want to upload " << songs.size() << " songs? [y/n]";
cin >> answer;
if (answer == 'y' || answer == 'Y')
{
confirmUpload = true;
break;
}
else if (answer == 'n' || answer == 'N')
{
confirmUpload = false;
break;
}
}
if (!confirmUpload)
{
cout << "exiting...\n";
std::exit(-1);
}
cout << "uploading songs\n";
for (auto& song: songs) for (auto& song: songs)
{ {
song = uploadSong(token, song); song = uploadSong(token, song);
@@ -168,7 +197,7 @@ namespace Syncers
cout<<"Path: "<<song.songPath<<endl; cout<<"Path: "<<song.songPath<<endl;
} }
} }
void Upload::printJsonData(json obj) void Upload::printJsonData(const json& obj)
{ {
cout<<endl<<endl<<"JSon data: "<<endl; cout<<endl<<endl<<"JSon data: "<<endl;
cout<<"id: "<<obj["id"]<<endl; cout<<"id: "<<obj["id"]<<endl;