Add support for tags

Adds basic support for filtering games using tags that the user can set on account page
Add option --list-tags to list all the tags user has assigned
Add option --tag to filter games using the tags
This commit is contained in:
Sude 2021-11-09 14:59:42 +02:00
parent 3251e9c42d
commit 695916af4c
6 changed files with 88 additions and 1 deletions

View File

@ -36,6 +36,7 @@ struct DownloadConfig
std::vector<unsigned int> vPlatformPriority;
std::vector<unsigned int> vLanguagePriority;
std::vector<unsigned int> vGalaxyCDNPriority;
std::vector<std::string> vTags;
unsigned int iInclude;
unsigned int iGalaxyPlatform;
unsigned int iGalaxyLanguage;
@ -229,6 +230,7 @@ class Config
#ifdef USE_QT_GUI_LOGIN
bool bEnableLoginGUI;
#endif
bool bListTags;
// Cache
bool bUseCache;

View File

@ -94,6 +94,7 @@ class Downloader
int init();
int login();
int listGames();
int listTags();
void checkNotifications();
void clearUpdateNotifications();
void repair();

View File

@ -24,12 +24,14 @@ class Website
std::vector<gameItem> getGames();
std::vector<wishlistItem> getWishlistItems();
bool IsLoggedIn();
std::map<std::string, std::string> getTags();
virtual ~Website();
protected:
private:
CURL* curlhandle;
bool IsloggedInSimple();
bool IsLoggedInComplex(const std::string& email);
std::map<std::string, std::string> getTagsFromJson(const Json::Value& json);
int retries;
};

View File

@ -151,6 +151,7 @@ int main(int argc, char *argv[])
std::string galaxy_product_id_install;
std::string galaxy_product_id_show_builds;
std::string tags;
std::vector<std::string> vFileIdStrings;
std::vector<std::string> unrecognized_options_cfg;
@ -215,6 +216,8 @@ int main(int argc, char *argv[])
#ifdef USE_QT_GUI_LOGIN
("enable-login-gui", bpo::value<bool>(&Globals::globalConfig.bEnableLoginGUI)->zero_tokens()->default_value(false), "Enable login GUI when encountering reCAPTCHA on login form")
#endif
("list-tags", bpo::value<bool>(&Globals::globalConfig.bListTags)->zero_tokens()->default_value(false), "List tags")
("tag", bpo::value<std::string>(&tags)->default_value(""), "Filter using tags. Separate with \",\" to use multiple values")
;
// Commandline options (config file)
options_cli_cfg.add_options()
@ -491,6 +494,9 @@ int main(int argc, char *argv[])
vFileIdStrings = Util::tokenize(Globals::globalConfig.sFileIdString, ",");
}
if (!tags.empty())
Globals::globalConfig.dlConf.vTags = Util::tokenize(tags, ",");
if (!Globals::globalConfig.sOutputFilename.empty() && vFileIdStrings.size() > 1)
{
std::cerr << "Cannot specify an output file name when downloading multiple files." << std::endl;
@ -754,6 +760,8 @@ int main(int argc, char *argv[])
downloader.download();
else if (Globals::globalConfig.bListDetails || Globals::globalConfig.bList) // Detailed list of games/extras
res = downloader.listGames();
else if (Globals::globalConfig.bListTags) // List tags
res = downloader.listTags();
else if (!Globals::globalConfig.sOrphanRegex.empty()) // Check for orphaned files if regex for orphans is set
downloader.checkOrphans();
else if (Globals::globalConfig.bCheckStatus)

View File

@ -686,6 +686,22 @@ int Downloader::listGames()
return 0;
}
int Downloader::listTags()
{
std::map<std::string, std::string> tags;
tags = gogWebsite->getTags();
if (!tags.empty())
{
for (auto tag : tags)
{
std::cout << tag.first << " = " << tag.second << std::endl;
}
}
return 0;
}
void Downloader::repair()
{
if (this->games.empty())

View File

@ -92,10 +92,21 @@ std::vector<gameItem> Website::getGames()
bool bAllPagesParsed = false;
int iUpdated = Globals::globalConfig.bUpdated ? 1 : 0;
int iHidden = 0;
std::string tags;
for (auto tag : Globals::globalConfig.dlConf.vTags)
{
if (tags.empty())
tags = tag;
else
tags += "," + tag;
}
do
{
std::string response = this->getResponse("https://www.gog.com/account/getFilteredProducts?hiddenFlag=" + std::to_string(iHidden) + "&isUpdated=" + std::to_string(iUpdated) + "&mediaType=1&sortBy=title&system=&page=" + std::to_string(i));
std::string url = "https://www.gog.com/account/getFilteredProducts?hiddenFlag=" + std::to_string(iHidden) + "&isUpdated=" + std::to_string(iUpdated) + "&mediaType=1&sortBy=title&system=&page=" + std::to_string(i);
if (!tags.empty())
url += "&tags=" + tags;
std::string response = this->getResponse(url);
std::istringstream json_stream(response);
try {
@ -680,3 +691,50 @@ std::vector<wishlistItem> Website::getWishlistItems()
return wishlistItems;
}
std::map<std::string, std::string> Website::getTags()
{
std::string url = "https://www.gog.com/account/getFilteredProducts?mediaType=1&sortBy=title&system=&page=1";
std::string response = this->getResponse(url);
std::istringstream json_stream(response);
Json::Value json;
std::map<std::string, std::string> tags;
try
{
// Parse JSON
json_stream >> json;
}
catch (const Json::Exception& exc)
{
std::cout << exc.what();
if (!response.empty())
{
if(response[0] != '{')
{
// Response was not JSON. Assume that cookies have expired.
std::cerr << "Response was not JSON. Cookies have most likely expired. Try --login first." << std::endl;
}
}
exit(1);
}
tags = this->getTagsFromJson(json["tags"]);
return tags;
}
std::map<std::string, std::string> Website::getTagsFromJson(const Json::Value& json)
{
std::map<std::string, std::string> tags;
if (!json.empty())
{
for (auto node : json)
{
tags[node["id"].asString()] = node["name"].asString();
}
}
return tags;
}