Compare commits
5 Commits
673e8b779f
...
262f8b5d71
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
262f8b5d71 | ||
|
|
4f844868cd | ||
|
|
82cc90c713 | ||
|
|
588925cee8 | ||
|
|
74598813de |
16
README
16
README
@ -26,14 +26,16 @@ metaflac
|
||||
--preserve-modtime
|
||||
--no-utf8-convert
|
||||
|
||||
// First Step - Remove
|
||||
--remove --block-type=PICTURE
|
||||
// First Step - Remove Tags
|
||||
--remove-tag=TITLE
|
||||
--remove-tag=ARTIST
|
||||
--remove-tag=ALBUM
|
||||
--remove-tag=TRACKNUMBER
|
||||
|
||||
// Second Step - Add
|
||||
// Second Step - Remove Pictures
|
||||
--remove --block-type=PICTURE
|
||||
|
||||
// Third Step - Add
|
||||
--import-picture-from=3|image/jpeg|||"/path/to/cover"
|
||||
"--set-tag=TITLE=..."
|
||||
"--set-tag=ARTIST=..."
|
||||
@ -42,3 +44,11 @@ metaflac
|
||||
--dont-use-padding
|
||||
|
||||
file.flac
|
||||
|
||||
--- imagemagick ---
|
||||
https://imagemagick.org/script/download.php
|
||||
For Image Resizing
|
||||
magick
|
||||
Cover
|
||||
-resize 750x750
|
||||
Cover_small.jpg
|
||||
|
||||
10
example_download2.json
Normal file
10
example_download2.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"comment": "This file will attempt to download MCS1091, MCS1195, MCS1425, MCS1426",
|
||||
"releases":
|
||||
[
|
||||
"MCS1091",
|
||||
"MCS1195",
|
||||
"MCS1425",
|
||||
"MCS1426"
|
||||
]
|
||||
}
|
||||
366
main.cpp
366
main.cpp
@ -26,6 +26,8 @@ constexpr bool IS_FLAC = false;
|
||||
constexpr bool IS_JPG = true;
|
||||
constexpr bool IS_PNG = false;
|
||||
constexpr uint32_t COVER_SIZE = 750;
|
||||
constexpr const char ID3EDIT_INVOKE[] = "id3edit";
|
||||
constexpr const char MAGICK_INVOKE[] = "magick";
|
||||
|
||||
#ifdef _WIN32
|
||||
constexpr const char FOLDER_DELIM = '\\';
|
||||
@ -63,7 +65,7 @@ void usage(const string& name)
|
||||
cout << " -1 <catalog release id>" << endl;
|
||||
cout << " Single release" << endl;
|
||||
cout << " -j <json file>" << endl;
|
||||
cout << " JSON file denoting release range" << endl;
|
||||
cout << " JSON file denoting release range or releases array" << endl;
|
||||
cout << " path - root path to download to" << endl;
|
||||
cout << " Default: ." << endl;
|
||||
}
|
||||
@ -170,15 +172,16 @@ pair<string, string> get_artist_title(const json& obj)
|
||||
pair<string, string> artist_feat;
|
||||
string str;
|
||||
string feat;
|
||||
string version;
|
||||
bool contains;
|
||||
int pos;
|
||||
|
||||
artist_feat = get_artist_feat(obj["Release"]["ArtistsTitle"]);
|
||||
artist_feat = get_artist_feat(obj["ArtistsTitle"]);
|
||||
result.first = artist_feat.first;
|
||||
|
||||
contains = false;
|
||||
|
||||
str = obj["Release"]["Title"];
|
||||
str = obj["Title"];
|
||||
if (!artist_feat.second.empty())
|
||||
{
|
||||
str += " (";
|
||||
@ -187,19 +190,12 @@ pair<string, string> get_artist_title(const json& obj)
|
||||
contains = true;
|
||||
}
|
||||
|
||||
if (!(obj["Release"]["Version"].empty()))
|
||||
// Empty does not work on json string
|
||||
version = obj["Version"];
|
||||
if (!version.empty())
|
||||
{
|
||||
if (contains)
|
||||
{
|
||||
str += " [";
|
||||
}
|
||||
else
|
||||
{
|
||||
str += " (";
|
||||
}
|
||||
|
||||
str += obj["Release"]["Version"];
|
||||
|
||||
str += contains ? " [" : " (";
|
||||
str += version;
|
||||
str += contains ? ']' : ')';
|
||||
}
|
||||
|
||||
@ -305,14 +301,18 @@ string num_to_str(int num, int precision)
|
||||
return result;
|
||||
}
|
||||
|
||||
string get_release_dir_name(const string& main_path, int release_num,
|
||||
const string& artist, const string& title, int precision)
|
||||
string get_release_dir_name(const string& main_path, const string& release_prefix,
|
||||
int release_num, const string& release_suffix, const string& artist,
|
||||
const string& title, int precision)
|
||||
{
|
||||
string path;
|
||||
|
||||
path = main_path;
|
||||
path += FOLDER_DELIM;
|
||||
path += release_prefix;
|
||||
path += FOLDER_DELIM;
|
||||
path += num_to_str(release_num, precision);
|
||||
path += release_suffix;
|
||||
path += " - ";
|
||||
|
||||
if ((artist != "Monstercat") && (artist != "Various Artists"))
|
||||
@ -349,13 +349,20 @@ string get_track_filename(int track_num, const string& artist,
|
||||
return filename;
|
||||
}
|
||||
|
||||
bool should_resize_JPG(ifstream& file)
|
||||
bool should_resize_JPG(const string& path)
|
||||
{
|
||||
// Do a resize by default
|
||||
bool result = true;
|
||||
ifstream file;
|
||||
string filename;
|
||||
int marker = 0;
|
||||
int symbol;
|
||||
|
||||
filename = path;
|
||||
filename += FOLDER_DELIM;
|
||||
filename += "Cover";
|
||||
file.open(filename);
|
||||
|
||||
// Check Header 1
|
||||
symbol = file.get();
|
||||
if (symbol != 0xFF)
|
||||
@ -476,17 +483,21 @@ bool should_resize_JPG(ifstream& file)
|
||||
}
|
||||
}
|
||||
|
||||
bool should_resize_PNG(ifstream& file)
|
||||
bool should_resize_PNG(const string& path)
|
||||
{
|
||||
ifstream file;
|
||||
string filename;
|
||||
uint8_t buf[4];
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
filename = path;
|
||||
filename += FOLDER_DELIM;
|
||||
filename += "Cover";
|
||||
file.open(filename);
|
||||
|
||||
// Seek
|
||||
file.read(reinterpret_cast<char*>(&buf), 4);
|
||||
file.read(reinterpret_cast<char*>(&buf), 4);
|
||||
file.read(reinterpret_cast<char*>(&buf), 4);
|
||||
file.read(reinterpret_cast<char*>(&buf), 4);
|
||||
file.seekg(16);
|
||||
|
||||
// Read width
|
||||
width = 0;
|
||||
@ -506,6 +517,8 @@ bool should_resize_PNG(ifstream& file)
|
||||
height += buf[i];
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
if ((width > COVER_SIZE) || (height > COVER_SIZE))
|
||||
{
|
||||
return true;
|
||||
@ -543,6 +556,45 @@ bool get_cover_type(const string& path)
|
||||
throw invalid_argument(filename);
|
||||
}
|
||||
|
||||
bool resize_cover(const string& path, bool is_jpg)
|
||||
{
|
||||
string cmd;
|
||||
bool should_resize;
|
||||
|
||||
// Should we actually resize
|
||||
if (is_jpg == IS_JPG)
|
||||
{
|
||||
should_resize = should_resize_JPG(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
should_resize = should_resize_PNG(path);
|
||||
}
|
||||
|
||||
cmd = MAGICK_INVOKE;
|
||||
cmd += " \"";
|
||||
cmd += path;
|
||||
cmd += FOLDER_DELIM;
|
||||
cmd += "Cover";
|
||||
cmd += "\" ";
|
||||
|
||||
if (should_resize)
|
||||
{
|
||||
cmd += "-resize ";
|
||||
cmd += to_string(COVER_SIZE);
|
||||
cmd += "x";
|
||||
cmd += to_string(COVER_SIZE);
|
||||
cmd += " ";
|
||||
}
|
||||
|
||||
cmd += "\"";
|
||||
cmd += path;
|
||||
cmd += FOLDER_DELIM;
|
||||
cmd += "Cover_small.jpg\"";
|
||||
|
||||
return system_command(cmd);
|
||||
}
|
||||
|
||||
bool rename_cover(const string& path, bool is_jpg)
|
||||
{
|
||||
string filename;
|
||||
@ -578,7 +630,8 @@ bool tag_MP3(const string& path, const string& filename, bool is_single_dir,
|
||||
{
|
||||
string cmd;
|
||||
|
||||
cmd = "id3edit --set-name \"";
|
||||
cmd = ID3EDIT_INVOKE;
|
||||
cmd += " --set-name \"";
|
||||
cmd += title;
|
||||
cmd += "\" --set-album \"";
|
||||
cmd += album;
|
||||
@ -610,9 +663,8 @@ bool tag_FLAC(const string& path, const string& filename, bool is_single_dir,
|
||||
string cmd;
|
||||
bool ok;
|
||||
|
||||
// First command - remove metadata
|
||||
// First command - remove tags
|
||||
cmd = "metaflac --preserve-modtime --no-utf8-convert ";
|
||||
cmd += "--remove --block-type=PICTURE ";
|
||||
cmd += "--remove-tag=TITLE ";
|
||||
cmd += "--remove-tag=ARTIST ";
|
||||
cmd += "--remove-tag=ALBUM ";
|
||||
@ -633,7 +685,26 @@ bool tag_FLAC(const string& path, const string& filename, bool is_single_dir,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Second command - set metadata
|
||||
// Second command - remove pictures
|
||||
cmd = "metaflac --preserve-modtime --no-utf8-convert ";
|
||||
cmd += "--remove --block-type=PICTURE \"";
|
||||
cmd += path;
|
||||
cmd += FOLDER_DELIM;
|
||||
if (!is_single_dir)
|
||||
{
|
||||
cmd += "FLAC";
|
||||
cmd += FOLDER_DELIM;
|
||||
}
|
||||
cmd += filename;
|
||||
cmd += ".flac\"";
|
||||
|
||||
ok = system_command(cmd);
|
||||
if (!ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Third command - set metadata
|
||||
cmd = "metaflac --preserve-modtime --no-utf8-convert --dont-use-padding ";
|
||||
cmd += "\"--import-picture-from=3|image/jpeg|||";
|
||||
cmd += path;
|
||||
@ -660,6 +731,20 @@ bool tag_FLAC(const string& path, const string& filename, bool is_single_dir,
|
||||
return system_command(cmd);
|
||||
}
|
||||
|
||||
void save_release_date(const string& path, const string& date)
|
||||
{
|
||||
ofstream file;
|
||||
string filepath;
|
||||
|
||||
filepath = path;
|
||||
filepath += FOLDER_DELIM;
|
||||
filepath += "Date.txt";
|
||||
|
||||
file.open(filepath);
|
||||
file << date << endl;
|
||||
file.close();
|
||||
}
|
||||
|
||||
bool full_donwload(const string& path, const string& release_prefix,
|
||||
int release_num, const string& release_suffix)
|
||||
{
|
||||
@ -676,7 +761,7 @@ bool full_donwload(const string& path, const string& release_prefix,
|
||||
|
||||
catalog_release_str = release_prefix;
|
||||
catalog_release_str += num_to_str(release_num, 3);
|
||||
catalog_release_str == release_suffix;
|
||||
catalog_release_str += release_suffix;
|
||||
|
||||
release_precision = 3;
|
||||
if (release_prefix == "MCS")
|
||||
@ -695,8 +780,8 @@ bool full_donwload(const string& path, const string& release_prefix,
|
||||
info = parse_json_file(RELEASE_JSON);
|
||||
|
||||
release_artist_title = get_artist_title(info["Release"]);
|
||||
release_dir = get_release_dir_name(path, release_num,
|
||||
release_artist_title.first, release_artist_title.second,
|
||||
release_dir = get_release_dir_name(path, release_prefix, release_num,
|
||||
release_suffix, release_artist_title.first, release_artist_title.second,
|
||||
release_precision);
|
||||
|
||||
// Make Release Folder
|
||||
@ -706,6 +791,9 @@ bool full_donwload(const string& path, const string& release_prefix,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save Release Date
|
||||
save_release_date(release_dir, info["Release"]["ReleaseDate"]);
|
||||
|
||||
is_single_dir = (info["Tracks"].size() == 1);
|
||||
|
||||
// Make MP3 & FLAC Folders (If more than 1 Track)
|
||||
@ -735,7 +823,7 @@ bool full_donwload(const string& path, const string& release_prefix,
|
||||
}
|
||||
|
||||
// Download Cover
|
||||
ok = download_cover(info["Release"]["Id"], release_dir);
|
||||
ok = download_cover(catalog_release_str, release_dir);
|
||||
if (!ok)
|
||||
{
|
||||
return false;
|
||||
@ -751,7 +839,12 @@ bool full_donwload(const string& path, const string& release_prefix,
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Make 750x750 Cover JPEG Image
|
||||
// Make 750x750 Cover JPEG Image
|
||||
ok = resize_cover(release_dir, cover_is_jpg);
|
||||
if (!ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rename Cover Image (Proper Extension)
|
||||
ok = rename_cover(release_dir, cover_is_jpg);
|
||||
@ -802,8 +895,215 @@ bool full_donwload(const string& path, const string& release_prefix,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool break_down_release_str(const string& release, string& prefix, int& num, string& suffix)
|
||||
{
|
||||
int pos;
|
||||
int pos2;
|
||||
string digits = "0123456789";
|
||||
|
||||
prefix = "";
|
||||
num = 0;
|
||||
suffix = "";
|
||||
|
||||
pos = release.find_first_of(digits);
|
||||
if (string::npos == pos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
prefix = release.substr(0, pos);
|
||||
pos2 = release.find_first_not_of(digits, pos);
|
||||
if (string::npos == pos2)
|
||||
{
|
||||
try
|
||||
{
|
||||
num = stod(release.substr(pos));
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
num = stod(release.substr(pos, pos2 - pos));
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
suffix = release.substr(pos2);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// TODO: Implement
|
||||
vector<string> args(&argv[1], &argv[argc]);
|
||||
|
||||
pair<bool, string> single_release = {false, ""};
|
||||
pair<bool, string> json_option = {false, ""};
|
||||
string path = ".";
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
cout << "Too few arguments" << endl;
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Ugly getopt
|
||||
for (int i = 0; i < args.size(); ++i)
|
||||
{
|
||||
if ((args[i] == "-1") && (i + 1 < args.size()))
|
||||
{
|
||||
single_release.first = true;
|
||||
single_release.second = args[i + 1];
|
||||
args.erase(args.begin() + i);
|
||||
args.erase(args.begin() + i);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((args[i] == "-j") && (i + 1 < args.size()))
|
||||
{
|
||||
json_option.first = true;
|
||||
json_option.second = args[i + 1];
|
||||
args.erase(args.begin() + i);
|
||||
args.erase(args.begin() + i);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Both selected
|
||||
if (single_release.first && json_option.first)
|
||||
{
|
||||
cout << "Both single release and json file are selected." << endl;
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// None selected
|
||||
if (!single_release.first && !json_option.first)
|
||||
{
|
||||
cout << "Neither single release nor json file are selected." << endl;
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Add path from arguments
|
||||
if (!args.empty())
|
||||
{
|
||||
path = args[0];
|
||||
}
|
||||
|
||||
// Remove trailing slash
|
||||
if (path[path.size() - 1] == FOLDER_DELIM)
|
||||
{
|
||||
path.erase(path.size() - 1);
|
||||
}
|
||||
|
||||
#if 1
|
||||
// BEGIN TEST PRINTS
|
||||
if (single_release.first)
|
||||
{
|
||||
cout << "SINGLE: " << single_release.second << endl;
|
||||
}
|
||||
if (json_option.first)
|
||||
{
|
||||
cout << "JSON: " << json_option.second << endl;
|
||||
}
|
||||
cout << "PATH: " << path << endl;
|
||||
// END TEST PRINTS
|
||||
#endif
|
||||
|
||||
vector<string> releases;
|
||||
vector<string>::iterator it;
|
||||
|
||||
// Add single release
|
||||
if (single_release.first)
|
||||
{
|
||||
releases.push_back(single_release.second);
|
||||
}
|
||||
|
||||
// Parse JSON
|
||||
if (json_option.first)
|
||||
{
|
||||
json j = parse_json_file(json_option.second);
|
||||
|
||||
if (j.contains("releases") && j["releases"].is_array())
|
||||
{
|
||||
for (int i = 0; i < j["releases"].size(); ++i)
|
||||
{
|
||||
releases.push_back(j["releases"][i]);
|
||||
}
|
||||
}
|
||||
else if (j.contains("prefix") &&
|
||||
j.contains("start") && j["start"].is_number_integer() &&
|
||||
j.contains("end") && j["end"].is_number_integer())
|
||||
{
|
||||
string tmp;
|
||||
for (int i = j["start"]; i <= j["end"]; ++i)
|
||||
{
|
||||
// Add release
|
||||
tmp = j["prefix"];
|
||||
tmp += num_to_str(i, 3);
|
||||
releases.push_back(tmp);
|
||||
|
||||
// Add release with suffix
|
||||
if (j.contains("suffix_try") && !j["suffix_try"].empty())
|
||||
{
|
||||
tmp += j["suffix_try"];
|
||||
releases.push_back(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "JSON not recognized" << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
string release_prefix;
|
||||
int release_num;
|
||||
string release_suffix;
|
||||
bool ok;
|
||||
|
||||
|
||||
ok = login();
|
||||
if (!ok)
|
||||
{
|
||||
cout << "Failed to login" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Break down release string
|
||||
for (it = releases.begin(); it != releases.end(); ++it)
|
||||
{
|
||||
ok = break_down_release_str(*it, release_prefix, release_num, release_suffix);
|
||||
if (!ok)
|
||||
{
|
||||
cout << "Failed to break down - " << *it << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
ok = full_donwload(path, release_prefix, release_num, release_suffix);
|
||||
if (!ok)
|
||||
{
|
||||
cout << "Could not download - " << *it << endl;
|
||||
}
|
||||
}
|
||||
|
||||
ok = logout();
|
||||
if (!ok)
|
||||
{
|
||||
cout << "Failed to logout" << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user