mirror of
https://github.com/Sude-/lgogdownloader.git
synced 2024-11-20 03:39:17 +01:00
Galaxy: Add support for downloading dependencies
Adds support for downloading dependencies for a game Added --galaxy-no-dependencies option to disable downloading dependencies during --galaxy-install
This commit is contained in:
parent
cae5f80698
commit
35b178e674
@ -51,6 +51,7 @@ struct DownloadConfig
|
||||
|
||||
bool bIgnoreDLCCount;
|
||||
bool bDuplicateHandler;
|
||||
bool bGalaxyDependencies;
|
||||
};
|
||||
|
||||
struct gameSpecificConfig
|
||||
|
@ -37,6 +37,7 @@ struct galaxyDepotItem
|
||||
uintmax_t totalSizeUncompressed;
|
||||
std::string md5;
|
||||
std::string product_id;
|
||||
bool isDependency = false;
|
||||
};
|
||||
|
||||
class galaxyAPI
|
||||
@ -50,15 +51,18 @@ class galaxyAPI
|
||||
Json::Value getProductBuilds(const std::string& product_id, const std::string& platform = "windows", const std::string& generation = "2");
|
||||
Json::Value getManifestV1(const std::string& product_id, const std::string& build_id, const std::string& manifest_id = "repository", const std::string& platform = "windows");
|
||||
Json::Value getManifestV1(const std::string& manifest_url);
|
||||
Json::Value getManifestV2(std::string manifest_hash);
|
||||
Json::Value getManifestV2(std::string manifest_hash, const bool& is_dependency = false);
|
||||
Json::Value getSecureLink(const std::string& product_id, const std::string& path);
|
||||
Json::Value getDependencyLink(const std::string& path);
|
||||
std::string getResponse(const std::string& url, const bool& zlib_decompress = false);
|
||||
Json::Value getResponseJson(const std::string& url, const bool& zlib_decompress = false);
|
||||
std::string hashToGalaxyPath(const std::string& hash);
|
||||
std::vector<galaxyDepotItem> getDepotItemsVector(const std::string& hash);
|
||||
std::vector<galaxyDepotItem> getDepotItemsVector(const std::string& hash, const bool& is_dependency = false);
|
||||
Json::Value getProductInfo(const std::string& product_id);
|
||||
gameDetails productInfoJsonToGameDetails(const Json::Value& json, const DownloadConfig& dlConf);
|
||||
Json::Value getUserData();
|
||||
Json::Value getDependenciesJson();
|
||||
std::vector<galaxyDepotItem> getFilteredDepotItemsVectorFromJson(const Json::Value& depot_json, const std::string& galaxy_language, const std::string& galaxy_arch, const bool& is_dependency = false);
|
||||
protected:
|
||||
private:
|
||||
CurlConfig curlConf;
|
||||
|
3
main.cpp
3
main.cpp
@ -144,6 +144,7 @@ int main(int argc, char *argv[])
|
||||
bool bNoSubDirectories = false;
|
||||
bool bNoPlatformDetection = false;
|
||||
bool bLogin = false;
|
||||
bool bNoGalaxyDependencies = false;
|
||||
std::string sInstallerPlatform;
|
||||
std::string sInstallerLanguage;
|
||||
std::string sIncludeOptions;
|
||||
@ -237,6 +238,7 @@ int main(int argc, char *argv[])
|
||||
("galaxy-platform", bpo::value<std::string>(&sGalaxyPlatform)->default_value("w"), galaxy_platform_text.c_str())
|
||||
("galaxy-language", bpo::value<std::string>(&sGalaxyLanguage)->default_value("en"), galaxy_language_text.c_str())
|
||||
("galaxy-arch", bpo::value<std::string>(&sGalaxyArch)->default_value("x64"), galaxy_arch_text.c_str())
|
||||
("galaxy-no-dependencies", bpo::value<bool>(&bNoGalaxyDependencies)->zero_tokens()->default_value(false), "Don't download dependencies during --galaxy-install")
|
||||
;
|
||||
|
||||
options_cli_all.add(options_cli_no_cfg).add(options_cli_cfg).add(options_cli_experimental);
|
||||
@ -436,6 +438,7 @@ int main(int argc, char *argv[])
|
||||
Globals::globalConfig.dlConf.bRemoteXML = !bNoRemoteXML;
|
||||
Globals::globalConfig.dirConf.bSubDirectories = !bNoSubDirectories;
|
||||
Globals::globalConfig.bPlatformDetection = !bNoPlatformDetection;
|
||||
Globals::globalConfig.dlConf.bGalaxyDependencies = !bNoGalaxyDependencies;
|
||||
|
||||
for (auto i = unrecognized_options_cli.begin(); i != unrecognized_options_cli.end(); ++i)
|
||||
if (i->compare(0, GlobalConstants::PROTOCOL_PREFIX.length(), GlobalConstants::PROTOCOL_PREFIX) == 0)
|
||||
|
@ -3323,48 +3323,49 @@ void Downloader::galaxyInstallGame(const std::string& product_id, int build_inde
|
||||
std::vector<galaxyDepotItem> items;
|
||||
for (unsigned int i = 0; i < json["depots"].size(); ++i)
|
||||
{
|
||||
bool bSelectedLanguage = false;
|
||||
bool bSelectedArch = false;
|
||||
boost::regex language_re("^(" + sLanguageRegex + ")$", boost::regex::perl | boost::regex::icase);
|
||||
boost::match_results<std::string::const_iterator> what;
|
||||
for (unsigned int j = 0; j < json["depots"][i]["languages"].size(); ++j)
|
||||
{
|
||||
std::string language = json["depots"][i]["languages"][j].asString();
|
||||
if (language == "*" || boost::regex_search(language, what, language_re))
|
||||
bSelectedLanguage = true;
|
||||
}
|
||||
std::vector<galaxyDepotItem> vec = gogGalaxy->getFilteredDepotItemsVectorFromJson(json["depots"][i], sLanguageRegex, sGalaxyArch);
|
||||
|
||||
if (json["depots"][i].isMember("osBitness"))
|
||||
if (!vec.empty())
|
||||
items.insert(std::end(items), std::begin(vec), std::end(vec));
|
||||
}
|
||||
|
||||
// Add dependency ids to vector
|
||||
std::vector<std::string> dependencies;
|
||||
if (json.isMember("dependencies") && Globals::globalConfig.dlConf.bGalaxyDependencies)
|
||||
{
|
||||
for (unsigned int i = 0; i < json["dependencies"].size(); ++i)
|
||||
{
|
||||
for (unsigned int j = 0; j < json["depots"][i]["osBitness"].size(); ++j)
|
||||
dependencies.push_back(json["dependencies"][i].asString());
|
||||
}
|
||||
}
|
||||
|
||||
// Add dependencies to items vector
|
||||
if (!dependencies.empty())
|
||||
{
|
||||
Json::Value dependenciesJson = gogGalaxy->getDependenciesJson();
|
||||
if (!dependenciesJson.empty() && dependenciesJson.isMember("depots"))
|
||||
{
|
||||
for (unsigned int i = 0; i < dependenciesJson["depots"].size(); ++i)
|
||||
{
|
||||
std::string osBitness = json["depots"][i]["osBitness"][j].asString();
|
||||
if (osBitness == "*" || osBitness == sGalaxyArch)
|
||||
bSelectedArch = true;
|
||||
std::string dependencyId = dependenciesJson["depots"][i]["dependencyId"].asString();
|
||||
if (std::any_of(dependencies.begin(), dependencies.end(), [dependencyId](std::string dependency){return dependency == dependencyId;}))
|
||||
{
|
||||
std::vector<galaxyDepotItem> vec = gogGalaxy->getFilteredDepotItemsVectorFromJson(dependenciesJson["depots"][i], sLanguageRegex, sGalaxyArch, true);
|
||||
|
||||
if (!vec.empty())
|
||||
items.insert(std::end(items), std::begin(vec), std::end(vec));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
// Set product id for items
|
||||
for (auto it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
if (it->product_id.empty())
|
||||
{
|
||||
// No osBitness found, assume that we want to download this depot
|
||||
bSelectedArch = true;
|
||||
it->product_id = product_id;
|
||||
}
|
||||
|
||||
if (!bSelectedLanguage || !bSelectedArch)
|
||||
continue;
|
||||
|
||||
std::string depotHash = json["depots"][i]["manifest"].asString();
|
||||
std::string depot_product_id = json["depots"][i]["productId"].asString();
|
||||
|
||||
if (depot_product_id.empty())
|
||||
depot_product_id = product_id;
|
||||
|
||||
std::vector<galaxyDepotItem> vec = gogGalaxy->getDepotItemsVector(depotHash);
|
||||
|
||||
// Set product id for items
|
||||
for (auto it = vec.begin(); it != vec.end(); ++it)
|
||||
it->product_id = depot_product_id;
|
||||
|
||||
items.insert(std::end(items), std::begin(vec), std::end(vec));
|
||||
}
|
||||
|
||||
uintmax_t totalSize = 0;
|
||||
@ -3626,7 +3627,11 @@ void Downloader::processGalaxyDownloadQueue(const std::string& install_path, Con
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value json = galaxy->getSecureLink(item.product_id, galaxy->hashToGalaxyPath(item.chunks[j].md5_compressed));
|
||||
Json::Value json;
|
||||
if (item.isDependency)
|
||||
json = galaxy->getDependencyLink(galaxy->hashToGalaxyPath(item.chunks[j].md5_compressed));
|
||||
else
|
||||
json = galaxy->getSecureLink(item.product_id, galaxy->hashToGalaxyPath(item.chunks[j].md5_compressed));
|
||||
|
||||
// Prefer edgecast urls
|
||||
bool bPreferEdgecast = true;
|
||||
|
@ -176,12 +176,16 @@ Json::Value galaxyAPI::getManifestV1(const std::string& manifest_url)
|
||||
return this->getResponseJson(manifest_url);
|
||||
}
|
||||
|
||||
Json::Value galaxyAPI::getManifestV2(std::string manifest_hash)
|
||||
Json::Value galaxyAPI::getManifestV2(std::string manifest_hash, const bool& is_dependency)
|
||||
{
|
||||
if (!manifest_hash.empty() && manifest_hash.find("/") == std::string::npos)
|
||||
manifest_hash = this->hashToGalaxyPath(manifest_hash);
|
||||
|
||||
std::string url = "https://cdn.gog.com/content-system/v2/meta/" + manifest_hash;
|
||||
std::string url;
|
||||
if (is_dependency)
|
||||
url = "https://cdn.gog.com/content-system/v2/dependencies/meta/" + manifest_hash;
|
||||
else
|
||||
url = "https://cdn.gog.com/content-system/v2/meta/" + manifest_hash;
|
||||
|
||||
return this->getResponseJson(url, true);
|
||||
}
|
||||
@ -193,6 +197,14 @@ Json::Value galaxyAPI::getSecureLink(const std::string& product_id, const std::s
|
||||
return this->getResponseJson(url);
|
||||
}
|
||||
|
||||
Json::Value galaxyAPI::getDependencyLink(const std::string& path)
|
||||
{
|
||||
std::string url = "https://content-system.gog.com/open_link?generation=2&_version=2&path=/dependencies/store/" + path;
|
||||
|
||||
return this->getResponseJson(url);
|
||||
}
|
||||
|
||||
|
||||
std::string galaxyAPI::hashToGalaxyPath(const std::string& hash)
|
||||
{
|
||||
std::string galaxy_path = hash;
|
||||
@ -202,9 +214,9 @@ std::string galaxyAPI::hashToGalaxyPath(const std::string& hash)
|
||||
return galaxy_path;
|
||||
}
|
||||
|
||||
std::vector<galaxyDepotItem> galaxyAPI::getDepotItemsVector(const std::string& hash)
|
||||
std::vector<galaxyDepotItem> galaxyAPI::getDepotItemsVector(const std::string& hash, const bool& is_dependency)
|
||||
{
|
||||
Json::Value json = this->getManifestV2(hash);
|
||||
Json::Value json = this->getManifestV2(hash, is_dependency);
|
||||
|
||||
std::vector<galaxyDepotItem> items;
|
||||
|
||||
@ -216,6 +228,7 @@ std::vector<galaxyDepotItem> galaxyAPI::getDepotItemsVector(const std::string& h
|
||||
item.totalSizeCompressed = 0;
|
||||
item.totalSizeUncompressed = 0;
|
||||
item.path = json["depot"]["items"][i]["path"].asString();
|
||||
item.isDependency = is_dependency;
|
||||
|
||||
while (Util::replaceString(item.path, "\\", "/"));
|
||||
for (unsigned int j = 0; j < json["depot"]["items"][i]["chunks"].size(); ++j)
|
||||
@ -443,3 +456,71 @@ Json::Value galaxyAPI::getUserData()
|
||||
|
||||
return this->getResponseJson(url);
|
||||
}
|
||||
|
||||
Json::Value galaxyAPI::getDependenciesJson()
|
||||
{
|
||||
std::string url = "https://content-system.gog.com/dependencies/repository?generation=2";
|
||||
Json::Value dependencies;
|
||||
Json::Value repository = this->getResponseJson(url);
|
||||
|
||||
if (!repository.empty())
|
||||
{
|
||||
if (repository.isMember("repository_manifest"))
|
||||
{
|
||||
std::string manifest_url = repository["repository_manifest"].asString();
|
||||
dependencies = this->getResponseJson(manifest_url, true);
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
std::vector<galaxyDepotItem> galaxyAPI::getFilteredDepotItemsVectorFromJson(const Json::Value& depot_json, const std::string& galaxy_language, const std::string& galaxy_arch, const bool& is_dependency)
|
||||
{
|
||||
std::vector<galaxyDepotItem> items;
|
||||
|
||||
bool bSelectedLanguage = false;
|
||||
bool bSelectedArch = false;
|
||||
boost::regex language_re("^(" + galaxy_language + ")$", boost::regex::perl | boost::regex::icase);
|
||||
boost::match_results<std::string::const_iterator> what;
|
||||
for (unsigned int j = 0; j < depot_json["languages"].size(); ++j)
|
||||
{
|
||||
std::string language = depot_json["languages"][j].asString();
|
||||
if (language == "*" || boost::regex_search(language, what, language_re))
|
||||
bSelectedLanguage = true;
|
||||
}
|
||||
|
||||
if (depot_json.isMember("osBitness"))
|
||||
{
|
||||
for (unsigned int j = 0; j < depot_json["osBitness"].size(); ++j)
|
||||
{
|
||||
std::string osBitness = depot_json["osBitness"][j].asString();
|
||||
if (osBitness == "*" || osBitness == galaxy_arch)
|
||||
bSelectedArch = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No osBitness found, assume that we want this depot
|
||||
bSelectedArch = true;
|
||||
}
|
||||
|
||||
if (bSelectedLanguage && bSelectedArch)
|
||||
{
|
||||
std::string depotHash = depot_json["manifest"].asString();
|
||||
std::string depot_product_id = depot_json["productId"].asString();
|
||||
|
||||
items = this->getDepotItemsVector(depotHash, is_dependency);
|
||||
|
||||
// Set product id for items
|
||||
for (auto it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
if (!depot_product_id.empty())
|
||||
{
|
||||
it->product_id = depot_product_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user