From 695916af4c629fdb5025e17a985543fe191efbab Mon Sep 17 00:00:00 2001 From: Sude Date: Tue, 9 Nov 2021 14:59:42 +0200 Subject: [PATCH] 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 --- include/config.h | 2 ++ include/downloader.h | 1 + include/website.h | 2 ++ main.cpp | 8 ++++++ src/downloader.cpp | 16 ++++++++++++ src/website.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 88 insertions(+), 1 deletion(-) diff --git a/include/config.h b/include/config.h index 78e6a43..3238b4b 100644 --- a/include/config.h +++ b/include/config.h @@ -36,6 +36,7 @@ struct DownloadConfig std::vector vPlatformPriority; std::vector vLanguagePriority; std::vector vGalaxyCDNPriority; + std::vector 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; diff --git a/include/downloader.h b/include/downloader.h index ed9240b..821f55f 100644 --- a/include/downloader.h +++ b/include/downloader.h @@ -94,6 +94,7 @@ class Downloader int init(); int login(); int listGames(); + int listTags(); void checkNotifications(); void clearUpdateNotifications(); void repair(); diff --git a/include/website.h b/include/website.h index cb0959b..a1c6f17 100644 --- a/include/website.h +++ b/include/website.h @@ -24,12 +24,14 @@ class Website std::vector getGames(); std::vector getWishlistItems(); bool IsLoggedIn(); + std::map getTags(); virtual ~Website(); protected: private: CURL* curlhandle; bool IsloggedInSimple(); bool IsLoggedInComplex(const std::string& email); + std::map getTagsFromJson(const Json::Value& json); int retries; }; diff --git a/main.cpp b/main.cpp index f1391f5..7793011 100644 --- a/main.cpp +++ b/main.cpp @@ -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 vFileIdStrings; std::vector unrecognized_options_cfg; @@ -215,6 +216,8 @@ int main(int argc, char *argv[]) #ifdef USE_QT_GUI_LOGIN ("enable-login-gui", bpo::value(&Globals::globalConfig.bEnableLoginGUI)->zero_tokens()->default_value(false), "Enable login GUI when encountering reCAPTCHA on login form") #endif + ("list-tags", bpo::value(&Globals::globalConfig.bListTags)->zero_tokens()->default_value(false), "List tags") + ("tag", bpo::value(&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) diff --git a/src/downloader.cpp b/src/downloader.cpp index 959ecaf..336ca8c 100644 --- a/src/downloader.cpp +++ b/src/downloader.cpp @@ -686,6 +686,22 @@ int Downloader::listGames() return 0; } +int Downloader::listTags() +{ + std::map 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()) diff --git a/src/website.cpp b/src/website.cpp index 1b887e0..08349b3 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -92,10 +92,21 @@ std::vector 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 Website::getWishlistItems() return wishlistItems; } + +std::map 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 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 Website::getTagsFromJson(const Json::Value& json) +{ + std::map tags; + + if (!json.empty()) + { + for (auto node : json) + { + tags[node["id"].asString()] = node["name"].asString(); + } + } + + return tags; +}