Got functionality working
This commit is contained in:
@@ -35,10 +35,14 @@ cmake --build . -j
|
|||||||
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.
|
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
|
### Downloading Song
|
||||||
``icd download -u spacecadet -p stellar40 -h https://icarus.com -b 15``
|
``BASH
|
||||||
|
icd download -u spacecadet -p stellar40 -h https://icarus.com -b 15
|
||||||
|
```
|
||||||
|
|
||||||
### Uploading Song
|
### Uploading Song
|
||||||
``icd upload -u spacecadet -p stellar40 -h https://icarus.com -s /path/of/song.mp3``
|
```BASH
|
||||||
|
icd upload -u spacecadet -p stellar40 -h https://icarus.com -s /path/of/song.mp3
|
||||||
|
```
|
||||||
|
|
||||||
### Uploading Song with metadata
|
### Uploading Song with metadata
|
||||||
|
|
||||||
@@ -54,10 +58,14 @@ icd upload-meta -u spacecadet -p stellar40 -h https://icarus.com -smca /path/whe
|
|||||||
|
|
||||||
|
|
||||||
### Retrieving Song in json
|
### Retrieving Song in json
|
||||||
``icd retrieve -u spacecadet -p stellar40 -h https://icarus.com -rt songs``
|
```Bash
|
||||||
|
icd retrieve -u spacecadet -p stellar40 -h https://icarus.com -rt songs
|
||||||
|
```
|
||||||
|
|
||||||
### Deleting Song
|
### Deleting Song
|
||||||
``icd delete -u spacecadet -p stellar40 -h https://icarus.com -D 15``
|
```BASH
|
||||||
|
icd delete -u spacecadet -p stellar40 -h https://icarus.com -D 15
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include"Models/IcarusAction.h"
|
#include"Models/IcarusAction.h"
|
||||||
#include"Models/Song.h"
|
#include"Models/Song.h"
|
||||||
#include"Models/Token.h"
|
#include"Models/Token.h"
|
||||||
|
#include"Utilities/Checks.h"
|
||||||
|
|
||||||
namespace Managers
|
namespace Managers
|
||||||
{
|
{
|
||||||
@@ -63,15 +64,116 @@ namespace Managers
|
|||||||
// * TrackID - track number to chose from when retrieving metadata. "1" and "1:1" are similar
|
// * TrackID - track number to chose from when retrieving metadata. "1" and "1:1" are similar
|
||||||
// * Metadata - Source file containing metadata of the song
|
// * Metadata - Source file containing metadata of the song
|
||||||
// * Cover art - path to image cover art
|
// * Cover art - path to image cover art
|
||||||
// TODO: Change the name
|
|
||||||
void uploadSongWithMetadata();
|
void uploadSongWithMetadata();
|
||||||
|
|
||||||
// Expects the song path, trackID, metadata file path, and cover path
|
// Expects the song path, trackID, metadata file path, and cover path
|
||||||
void singTargetUpload(const std::string &songPath, const std::string &trackID,
|
void singTargetUpload(const std::string &songPath, const std::string &trackID,
|
||||||
const std::string &metaPath, const std::string &coverPath);
|
const std::string &metaPath, const std::string &coverPath);
|
||||||
// Expects the source directory that contains songs, a metadata file, and cover image
|
// Expects the source directory that contains songs, a metadata file, and cover image
|
||||||
|
// Disc and Track is retrieved from the filename if the filename conforms to a standard.
|
||||||
|
// If not, then the disc and track will default to 1
|
||||||
|
//
|
||||||
|
// Standards
|
||||||
|
// * track01.mp3 - Disc 1, Track 1
|
||||||
|
// * track05d02.mp3 - Disc 2, Track 5
|
||||||
void multiTargetUpload(const std::string &sourcePath);
|
void multiTargetUpload(const std::string &sourcePath);
|
||||||
|
|
||||||
|
// Standards
|
||||||
|
// * track01.mp3 - Disc 1, Track 1
|
||||||
|
// * track05d02.mp3 - Disc 2, Track 5
|
||||||
|
template<typename Song, typename Str>
|
||||||
|
void initializeDiscAndTrack(Song &song)
|
||||||
|
{
|
||||||
|
auto disc = 1;
|
||||||
|
auto track = 1;
|
||||||
|
// If 1 go with first standard, if 2 go with the second, if 0 then will default to 1 for disc and track
|
||||||
|
auto mode = 0;
|
||||||
|
const Str &songPath = song.songPath;
|
||||||
|
|
||||||
|
auto trd = song.songPath.find("trackd");
|
||||||
|
auto tr = song.songPath.find("track");
|
||||||
|
|
||||||
|
if (tr != Str::npos)
|
||||||
|
{
|
||||||
|
mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trd != Str::npos)
|
||||||
|
{
|
||||||
|
mode = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dl = [](char c, char t){ return c == t; };
|
||||||
|
auto d = Utilities::Checks::itemIterInContainer<char, Str>(songPath, 'd', dl);
|
||||||
|
auto k = Utilities::Checks::itemIterInContainer<char, Str>(songPath, 'k', dl);
|
||||||
|
auto dot = Utilities::Checks::itemIterInContainer<char, Str>(songPath, '.', dl);
|
||||||
|
|
||||||
|
switch(mode)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
if (k != songPath.end() && dot != songPath.end())
|
||||||
|
{
|
||||||
|
auto tStr = std::string(++k, dot);
|
||||||
|
std::cout << "TStr: " << tStr<<"\n";
|
||||||
|
|
||||||
|
if (Utilities::Checks::isNumber(tStr))
|
||||||
|
{
|
||||||
|
track = std::atoi(tStr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
if (k != songPath.end() && dot != songPath.end() && d != songPath.end())
|
||||||
|
{
|
||||||
|
auto tStr = std::string(++k, d);
|
||||||
|
auto dStr = std::string(++d, dot);
|
||||||
|
std::cout<<"DStr: "<<dStr<<" TStr: " << tStr<<"\n";
|
||||||
|
|
||||||
|
if (Utilities::Checks::isNumber(tStr))
|
||||||
|
{
|
||||||
|
track = std::atoi(tStr.c_str());
|
||||||
|
}
|
||||||
|
else if (Utilities::Checks::isNumber(dStr))
|
||||||
|
{
|
||||||
|
disc = std::atoi(dStr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
song.disc = disc;
|
||||||
|
song.track = track;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Song, typename Str>
|
||||||
|
void parseDiscAndTrack(Song &song, const Str &trackID)
|
||||||
|
{
|
||||||
|
auto sep = [](char c, char t) { return c == t; };
|
||||||
|
auto separator = Utilities::Checks::itemIterInContainer<char, Str>(trackID, ':', sep);
|
||||||
|
|
||||||
|
if (separator != trackID.end())
|
||||||
|
{
|
||||||
|
auto dStr = Str(trackID.begin(), separator);
|
||||||
|
auto tStr = Str(++separator, trackID.end());
|
||||||
|
|
||||||
|
song.disc = std::atoi(dStr.c_str());
|
||||||
|
song.track = std::atoi(tStr.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto isNumber = Utilities::Checks::isNumber(trackID);
|
||||||
|
if (isNumber)
|
||||||
|
{
|
||||||
|
song.track = std::atoi(trackID.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Checks for the no confirm flag. Used when uploading songs from a directory
|
// Checks for the no confirm flag. Used when uploading songs from a directory
|
||||||
bool checkForNoConfirm()
|
bool checkForNoConfirm()
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ namespace Models
|
|||||||
std::cout<<"\n";
|
std::cout<<"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Incomplete implementation
|
|
||||||
std::string toMetadataJson();
|
std::string toMetadataJson();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Utilities
|
|||||||
public:
|
public:
|
||||||
Checks() = delete;
|
Checks() = delete;
|
||||||
|
|
||||||
static bool isNumber(const std::string &val)
|
static auto isNumber(const std::string &val)
|
||||||
{
|
{
|
||||||
return !val.empty() && std::find_if(val.begin(),
|
return !val.empty() && std::find_if(val.begin(),
|
||||||
val.end(), [](char c)
|
val.end(), [](char c)
|
||||||
@@ -20,6 +20,44 @@ namespace Utilities
|
|||||||
return !std::isdigit(c);
|
return !std::isdigit(c);
|
||||||
}) == val.end();
|
}) == val.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: Not implemented
|
||||||
|
template<typename Item, typename Container, typename Func>
|
||||||
|
static auto itemInContainer(const Container container, const Item item, Func func)
|
||||||
|
{
|
||||||
|
auto result = false;
|
||||||
|
auto i = std::find_if(container.begin(), container.end(), [&](Item i)
|
||||||
|
{
|
||||||
|
return func(item, i);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (i != container.end())
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Item, typename Container, typename Func>
|
||||||
|
static auto itemIterInContainer(const Container &container, const Item &item, Func func)
|
||||||
|
{
|
||||||
|
auto result = false;
|
||||||
|
// std::cout<<container<<"\n";
|
||||||
|
auto ii = std::find_if(container.begin(), container.end(), [&](Item i)
|
||||||
|
{
|
||||||
|
// std::cout<<"iter "<<i<<" target "<<item<<"\n";
|
||||||
|
return func(i, item);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ii == container.end())
|
||||||
|
{
|
||||||
|
// std::cout<<item<<" not found in container\n";
|
||||||
|
ii = container.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ii;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include"Syncers/Download.h"
|
#include"Syncers/Download.h"
|
||||||
#include"Syncers/RetrieveRecords.h"
|
#include"Syncers/RetrieveRecords.h"
|
||||||
#include"Syncers/Upload.h"
|
#include"Syncers/Upload.h"
|
||||||
#include"Utilities/Checks.h"
|
|
||||||
|
|
||||||
#include"Managers/TokenManager.h"
|
#include"Managers/TokenManager.h"
|
||||||
#include"Managers/UserManager.h"
|
#include"Managers/UserManager.h"
|
||||||
@@ -282,50 +281,25 @@ namespace Managers
|
|||||||
|
|
||||||
auto album = retrieveMetadata(metaPath);
|
auto album = retrieveMetadata(metaPath);
|
||||||
album.printInfo();
|
album.printInfo();
|
||||||
for (auto sng : album.songs)
|
|
||||||
{
|
|
||||||
// sng.printInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto disc = 1;
|
Song song;
|
||||||
auto track = 1;
|
song.track = 1;
|
||||||
|
song.disc = 1;
|
||||||
|
|
||||||
auto separator = std::find_if(trackID.begin(), trackID.end(), [&](char c)
|
cout<<"TrackID: "<<trackID<<"\n";
|
||||||
{
|
|
||||||
return c == ':';
|
|
||||||
});
|
|
||||||
|
|
||||||
if (separator != trackID.end())
|
parseDiscAndTrack<Song, std::string>(song, trackID);
|
||||||
{
|
|
||||||
cout<<"Found colon\n";
|
|
||||||
auto dStr = string(trackID.begin(), separator);
|
|
||||||
auto tStr = string(++separator, trackID.end());
|
|
||||||
|
|
||||||
cout<<"disc "<<dStr<<" track "<<tStr<<"\n";
|
auto c = [](const Song &songA, const Song &songB) { return songA.track == songB.track && songA.disc == songB.disc; };
|
||||||
disc = std::atoi(dStr.c_str());
|
auto sng = Utilities::Checks::itemIterInContainer<Song, std::vector<Song>>(album.songs, song, c);
|
||||||
track = std::atoi(tStr.c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto isNumber = Utilities::Checks::isNumber(trackID);
|
|
||||||
if (isNumber)
|
|
||||||
{
|
|
||||||
track = std::atoi(trackID.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
if (sng == album.songs.end())
|
||||||
{
|
{
|
||||||
cout<<"Not found with disc "<<disc<<" track "<<track<<"\n";
|
cout<<"Not found with disc "<<song.disc<<" track "<<song.track<<"\n";
|
||||||
std::exit(-1);
|
std::exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto song = *sng;
|
song = *sng;
|
||||||
song.songPath = songPath;
|
song.songPath = songPath;
|
||||||
|
|
||||||
Models::CoverArt cover;
|
Models::CoverArt cover;
|
||||||
@@ -341,6 +315,53 @@ namespace Managers
|
|||||||
APIParser apiPrs(icaAction);
|
APIParser apiPrs(icaAction);
|
||||||
auto api = apiPrs.retrieveAPI();
|
auto api = apiPrs.retrieveAPI();
|
||||||
const auto token = parseToken(api);
|
const auto token = parseToken(api);
|
||||||
|
|
||||||
|
if (!fs::is_directory(sourcePath))
|
||||||
|
{
|
||||||
|
cout<<sourcePath<<" is not a directory\n";
|
||||||
|
std::exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Song> songs;
|
||||||
|
Models::CoverArt cover;
|
||||||
|
string metadataPath;
|
||||||
|
|
||||||
|
for (auto &p: fs::directory_iterator(sourcePath))
|
||||||
|
{
|
||||||
|
const auto &pp = p.path();
|
||||||
|
const auto stem = pp.stem();
|
||||||
|
const auto file = pp.filename();
|
||||||
|
const auto extension = pp.extension();
|
||||||
|
|
||||||
|
cout<<"Stem "<<stem<<" Extension "<<extension<<"\n";
|
||||||
|
|
||||||
|
if (extension.compare(".mp3") == 0)
|
||||||
|
{
|
||||||
|
Song song;
|
||||||
|
song.songPath = pp.string();
|
||||||
|
|
||||||
|
initializeDiscAndTrack<Song, std::string>(song);
|
||||||
|
|
||||||
|
songs.emplace_back(std::move(song));
|
||||||
|
}
|
||||||
|
else if (extension.compare(".jpg") == 0 || extension.compare(".png") == 0)
|
||||||
|
{
|
||||||
|
cover.path.assign(pp.string());
|
||||||
|
}
|
||||||
|
else if (extension.compare(".json") == 0)
|
||||||
|
{
|
||||||
|
metadataPath.assign(pp.string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto album = retrieveMetadata(metadataPath);
|
||||||
|
|
||||||
|
Upload up(api, token);
|
||||||
|
|
||||||
|
for (auto &song : songs)
|
||||||
|
{
|
||||||
|
up.uploadSongWithMetadata(album, song, cover);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma region private
|
#pragma region private
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ namespace Models
|
|||||||
{
|
{
|
||||||
nlohmann::json s;
|
nlohmann::json s;
|
||||||
s["title"] = this->title;
|
s["title"] = this->title;
|
||||||
|
s["artist"] = this->artist;
|
||||||
|
s["album"] = this->album;
|
||||||
|
s["genre"] = this->genre;
|
||||||
|
s["year"] = this->year;
|
||||||
|
s["track"] = this->track;
|
||||||
|
s["disc"] = this->disc;
|
||||||
|
|
||||||
return s.dump();
|
return s.dump();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,9 +43,6 @@ namespace Parsers
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: For now I will hard code
|
|
||||||
// the api version since I am only
|
|
||||||
// on version 1
|
|
||||||
api.version = "v1";
|
api.version = "v1";
|
||||||
}
|
}
|
||||||
#pragma functions
|
#pragma functions
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ namespace Syncers
|
|||||||
|
|
||||||
void Upload::uploadSongWithMetadata(Managers::CommitManager::Album &album, Models::Song& song, Models::CoverArt &cover)
|
void Upload::uploadSongWithMetadata(Managers::CommitManager::Album &album, Models::Song& song, Models::CoverArt &cover)
|
||||||
{
|
{
|
||||||
this->api.endpoint.append("/upload/with/data");
|
this->api.endpoint.assign("song/data/upload/with/data");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -133,8 +133,9 @@ namespace Syncers
|
|||||||
|
|
||||||
const auto meta = s.dump();
|
const auto meta = s.dump();
|
||||||
|
|
||||||
// cout<<"\n\nMeta:\n"<<meta<<"\n";
|
cout<<"\n\nMeta:\n"<<meta<<"\n";
|
||||||
|
|
||||||
|
/**
|
||||||
auto multipart = cpr::Multipart{{"cover", cpr::File{cover.path}},
|
auto multipart = cpr::Multipart{{"cover", cpr::File{cover.path}},
|
||||||
{"metadata", meta},
|
{"metadata", meta},
|
||||||
{"file", cpr::File{song.songPath}}};
|
{"file", cpr::File{song.songPath}}};
|
||||||
@@ -145,6 +146,7 @@ namespace Syncers
|
|||||||
|
|
||||||
cout << "status code: " << r.status_code<< std::endl;
|
cout << "status code: " << r.status_code<< std::endl;
|
||||||
cout << r.text << endl;
|
cout << r.text << endl;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
catch (exception &e)
|
catch (exception &e)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user