mirror of
https://github.com/Sude-/lgogdownloader.git
synced 2024-11-20 03:39:17 +01:00
This commit is contained in:
commit
b90b7288d4
738
src/api.cpp
738
src/api.cpp
@ -83,47 +83,40 @@ int API::getAPIConfig()
|
||||
std::string url = "https://api.gog.com/downloader2/status/stable/"; // Stable API
|
||||
//std::string url = "https://api.gog.com/downloader2/status/beta/"; // Beta API
|
||||
//std::string url = "https://api.gog.com/downloader2/status/e77989ed21758e78331b20e477fc5582/"; // Development API? Not sure because the downloader version number it reports is lower than beta.
|
||||
int res = 0;
|
||||
|
||||
std::string json = this->getResponse(url);
|
||||
|
||||
if (!json.empty())
|
||||
{
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(json, root))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getAPIConfig)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
this->config.oauth_authorize_temp_token = root["config"]["oauth_authorize_temp_token"].asString() + "/";
|
||||
this->config.oauth_get_temp_token = root["config"]["oauth_get_temp_token"].asString() + "/";
|
||||
this->config.oauth_get_token = root["config"]["oauth_get_token"].asString() + "/";
|
||||
this->config.get_user_games = root["config"]["get_user_games"].asString() + "/";
|
||||
this->config.get_user_details = root["config"]["get_user_details"].asString() + "/";
|
||||
this->config.get_installer_link = root["config"]["get_installer_link"].asString() + "/";
|
||||
this->config.get_game_details = root["config"]["get_game_details"].asString() + "/";
|
||||
this->config.get_extra_link = root["config"]["get_extra_link"].asString() + "/";
|
||||
this->config.set_app_status = root["config"]["set_app_status"].asString() + "/";
|
||||
res = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getAPIConfig)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(jsonparser->getFormattedErrorMessages());
|
||||
res = 0;
|
||||
}
|
||||
delete jsonparser;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (json.empty()) {
|
||||
this->setError("Found nothing in " + url);
|
||||
res = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
Json::Value root;
|
||||
std::istringstream json_stream(json);
|
||||
|
||||
try {
|
||||
json_stream >> root;
|
||||
} catch (const Json::Exception& exc) {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getAPIConfig)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(exc.what());
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getAPIConfig)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
this->config.oauth_authorize_temp_token = root["config"]["oauth_authorize_temp_token"].asString() + "/";
|
||||
this->config.oauth_get_temp_token = root["config"]["oauth_get_temp_token"].asString() + "/";
|
||||
this->config.oauth_get_token = root["config"]["oauth_get_token"].asString() + "/";
|
||||
this->config.get_user_games = root["config"]["get_user_games"].asString() + "/";
|
||||
this->config.get_user_details = root["config"]["get_user_details"].asString() + "/";
|
||||
this->config.get_installer_link = root["config"]["get_installer_link"].asString() + "/";
|
||||
this->config.get_game_details = root["config"]["get_game_details"].asString() + "/";
|
||||
this->config.get_extra_link = root["config"]["get_extra_link"].asString() + "/";
|
||||
this->config.set_app_status = root["config"]["set_app_status"].asString() + "/";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int API::login(const std::string& email, const std::string& password)
|
||||
@ -191,48 +184,41 @@ int API::login(const std::string& email, const std::string& password)
|
||||
|
||||
int API::getUserDetails()
|
||||
{
|
||||
int res = 0;
|
||||
std::string url;
|
||||
|
||||
url = this->config.get_user_details;
|
||||
std::string json = this->getResponseOAuth(url);
|
||||
|
||||
if (!json.empty())
|
||||
{
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(json, root))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getUserDetails)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
this->user.id = std::stoull(root["user"]["id"].asString());
|
||||
this->user.username = root["user"]["xywka"].asString();
|
||||
this->user.email = root["user"]["email"].asString();
|
||||
this->user.avatar_big = root["user"]["avatar"]["big"].asString();
|
||||
this->user.avatar_small = root["user"]["avatar"]["small"].asString();
|
||||
this->user.notifications_forum = root["user"]["notifications"]["forum"].isInt() ? root["user"]["notifications"]["forum"].asInt() : std::stoi(root["user"]["notifications"]["forum"].asString());
|
||||
this->user.notifications_games = root["user"]["notifications"]["games"].isInt() ? root["user"]["notifications"]["games"].asInt() : std::stoi(root["user"]["notifications"]["games"].asString());
|
||||
this->user.notifications_messages = root["user"]["notifications"]["messages"].isInt() ? root["user"]["notifications"]["messages"].asInt() : std::stoi(root["user"]["notifications"]["messages"].asString());
|
||||
res = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getUserDetails)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(jsonparser->getFormattedErrorMessages());
|
||||
res = 0;
|
||||
}
|
||||
delete jsonparser;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (json.empty()) {
|
||||
this->setError("Found nothing in " + url);
|
||||
res = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
Json::Value root;
|
||||
std::istringstream json_stream(json);
|
||||
|
||||
try {
|
||||
json_stream >> root;
|
||||
} catch (const Json::Exception& exc) {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getUserDetails)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(exc.what());
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getUserDetails)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
this->user.id = std::stoull(root["user"]["id"].asString());
|
||||
this->user.username = root["user"]["xywka"].asString();
|
||||
this->user.email = root["user"]["email"].asString();
|
||||
this->user.avatar_big = root["user"]["avatar"]["big"].asString();
|
||||
this->user.avatar_small = root["user"]["avatar"]["small"].asString();
|
||||
this->user.notifications_forum = root["user"]["notifications"]["forum"].isInt() ? root["user"]["notifications"]["forum"].asInt() : std::stoi(root["user"]["notifications"]["forum"].asString());
|
||||
this->user.notifications_games = root["user"]["notifications"]["games"].isInt() ? root["user"]["notifications"]["games"].asInt() : std::stoi(root["user"]["notifications"]["games"].asString());
|
||||
this->user.notifications_messages = root["user"]["notifications"]["messages"].isInt() ? root["user"]["notifications"]["messages"].asInt() : std::stoi(root["user"]["notifications"]["messages"].asString());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -311,267 +297,265 @@ gameDetails API::getGameDetails(const std::string& game_name, const unsigned int
|
||||
url = this->config.get_game_details + game_name + "/" + "installer_win_en"; // can't get game details without file id, any file id seems to return all details which is good for us
|
||||
std::string json = this->getResponseOAuth(url);
|
||||
|
||||
if (!json.empty())
|
||||
{
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(json, root))
|
||||
if (json.empty()) {
|
||||
this->setError("Found nothing in " + url);
|
||||
return game;
|
||||
}
|
||||
|
||||
Json::Value root;
|
||||
std::istringstream json_stream(json);
|
||||
|
||||
try {
|
||||
json_stream >> root;
|
||||
} catch (Json::Exception exc) {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getGameDetails)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(exc.what());
|
||||
return game;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getGameDetails)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
game.gamename = game_name;
|
||||
game.title = root["game"]["title"].asString();
|
||||
game.icon = root["game"]["icon"].asString();
|
||||
std::vector<std::string> membernames = root["game"].getMemberNames();
|
||||
|
||||
// Installer details
|
||||
// Create a list of installers from JSON
|
||||
std::vector<gameFileInfo> installers;
|
||||
for (unsigned int i = 0; i < GlobalConstants::PLATFORMS.size(); ++i)
|
||||
{ // Check against the specified platforms
|
||||
if (platform & GlobalConstants::PLATFORMS[i].id)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getGameDetails)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
game.gamename = game_name;
|
||||
game.title = root["game"]["title"].asString();
|
||||
game.icon = root["game"]["icon"].asString();
|
||||
std::vector<std::string> membernames = root["game"].getMemberNames();
|
||||
|
||||
// Installer details
|
||||
// Create a list of installers from JSON
|
||||
std::vector<gameFileInfo> installers;
|
||||
for (unsigned int i = 0; i < GlobalConstants::PLATFORMS.size(); ++i)
|
||||
{ // Check against the specified platforms
|
||||
if (platform & GlobalConstants::PLATFORMS[i].id)
|
||||
{
|
||||
std::string installer = "installer_" + GlobalConstants::PLATFORMS[i].code + "_";
|
||||
for (unsigned int j = 0; j < GlobalConstants::LANGUAGES.size(); ++j)
|
||||
{ // Check against the specified languages
|
||||
if (lang & GlobalConstants::LANGUAGES[j].id)
|
||||
{ // Make sure that the installer exists in the JSON
|
||||
if (root["game"].isMember(installer+GlobalConstants::LANGUAGES[j].code))
|
||||
{
|
||||
gameFileInfo installerInfo;
|
||||
installerInfo.jsonNode = root["game"][installer+GlobalConstants::LANGUAGES[j].code];
|
||||
installerInfo.platform = GlobalConstants::PLATFORMS[i].id;
|
||||
installerInfo.language = GlobalConstants::LANGUAGES[j].id;
|
||||
installers.push_back(installerInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( unsigned int i = 0; i < installers.size(); ++i )
|
||||
{
|
||||
for ( unsigned int index = 0; index < installers[i].jsonNode.size(); ++index )
|
||||
{
|
||||
Json::Value installer = installers[i].jsonNode[index];
|
||||
unsigned int language = installers[i].language;
|
||||
std::string path = installer["link"].asString();
|
||||
path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL);
|
||||
|
||||
// Check for duplicate installers in different languages and add languageId of duplicate installer to the original installer
|
||||
// https://secure.gog.com/forum/general/introducing_the_beta_release_of_the_new_gogcom_downloader/post1483
|
||||
if (useDuplicateHandler)
|
||||
{
|
||||
bool bDuplicate = false;
|
||||
for (unsigned int j = 0; j < game.installers.size(); ++j)
|
||||
{
|
||||
if (game.installers[j].path == path)
|
||||
{
|
||||
game.installers[j].language |= language; // Add language code to installer
|
||||
bDuplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bDuplicate)
|
||||
continue;
|
||||
}
|
||||
|
||||
gameFile gf;
|
||||
gf.type = GFTYPE_INSTALLER;
|
||||
gf.gamename = game.gamename;
|
||||
gf.updated = installer["notificated"].isInt() ? installer["notificated"].asInt() : std::stoi(installer["notificated"].asString());
|
||||
gf.id = installer["id"].isInt() ? std::to_string(installer["id"].asInt()) : installer["id"].asString();
|
||||
gf.name = installer["name"].asString();
|
||||
gf.path = path;
|
||||
gf.size = installer["size"].asString();
|
||||
gf.language = language;
|
||||
gf.platform = installers[i].platform;
|
||||
gf.silent = installer["silent"].isInt() ? installer["silent"].asInt() : std::stoi(installer["silent"].asString());
|
||||
|
||||
game.installers.push_back(gf);
|
||||
}
|
||||
}
|
||||
|
||||
// Extra details
|
||||
const Json::Value extras = root["game"]["extras"];
|
||||
for ( unsigned int index = 0; index < extras.size(); ++index )
|
||||
{
|
||||
Json::Value extra = extras[index];
|
||||
|
||||
gameFile gf;
|
||||
gf.type = GFTYPE_EXTRA;
|
||||
gf.gamename = game.gamename;
|
||||
gf.updated = false; // extras don't have "updated" flag
|
||||
gf.id = extra["id"].isInt() ? std::to_string(extra["id"].asInt()) : extra["id"].asString();
|
||||
gf.name = extra["name"].asString();
|
||||
gf.path = extra["link"].asString();
|
||||
gf.path = (std::string)curl_easy_unescape(curlhandle, gf.path.c_str(), gf.path.size(), NULL);
|
||||
gf.size = extra["size_mb"].asString();
|
||||
|
||||
game.extras.push_back(gf);
|
||||
}
|
||||
|
||||
// Patch details
|
||||
for (unsigned int i = 0; i < GlobalConstants::LANGUAGES.size(); ++i)
|
||||
std::string installer = "installer_" + GlobalConstants::PLATFORMS[i].code + "_";
|
||||
for (unsigned int j = 0; j < GlobalConstants::LANGUAGES.size(); ++j)
|
||||
{ // Check against the specified languages
|
||||
if (lang & GlobalConstants::LANGUAGES[i].id)
|
||||
{
|
||||
// Try to find a patch
|
||||
_regex_namespace_::regex re(GlobalConstants::LANGUAGES[i].code + "\\d+patch\\d+", _regex_namespace_::regex_constants::icase); // regex for patch node names
|
||||
std::vector<gameFileInfo> patches;
|
||||
for (unsigned int j = 0; j < membernames.size(); ++j)
|
||||
if (lang & GlobalConstants::LANGUAGES[j].id)
|
||||
{ // Make sure that the installer exists in the JSON
|
||||
if (root["game"].isMember(installer+GlobalConstants::LANGUAGES[j].code))
|
||||
{
|
||||
if (_regex_namespace_::regex_match(membernames[j], re))
|
||||
{ // Regex matches, we have a patch node
|
||||
gameFileInfo patchInfo;
|
||||
patchInfo.jsonNode = root["game"][membernames[j]];
|
||||
patchInfo.language = GlobalConstants::LANGUAGES[i].id;
|
||||
if (patchInfo.jsonNode["link"].asString().find("/mac/") != std::string::npos)
|
||||
patchInfo.platform = GlobalConstants::PLATFORM_MAC;
|
||||
else if (patchInfo.jsonNode["link"].asString().find("/linux/") != std::string::npos)
|
||||
patchInfo.platform = GlobalConstants::PLATFORM_LINUX;
|
||||
else
|
||||
patchInfo.platform = GlobalConstants::PLATFORM_WINDOWS;
|
||||
|
||||
if (platform & patchInfo.platform)
|
||||
patches.push_back(patchInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (!patches.empty()) // found at least one patch
|
||||
{
|
||||
for (unsigned int j = 0; j < patches.size(); ++j)
|
||||
{
|
||||
Json::Value patchnode = patches[j].jsonNode;
|
||||
if (patchnode.isArray()) // Patch has multiple files
|
||||
{
|
||||
for ( unsigned int index = 0; index < patchnode.size(); ++index )
|
||||
{
|
||||
Json::Value patch = patchnode[index];
|
||||
std::string path = patch["link"].asString();
|
||||
path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL);
|
||||
|
||||
// Check for duplicate patches in different languages and add languageId of duplicate patch to the original patch
|
||||
if (useDuplicateHandler)
|
||||
{
|
||||
bool bDuplicate = false;
|
||||
for (unsigned int j = 0; j < game.patches.size(); ++j)
|
||||
{
|
||||
if (game.patches[j].path == path)
|
||||
{
|
||||
game.patches[j].language |= GlobalConstants::LANGUAGES[i].id; // Add language code to patch
|
||||
bDuplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bDuplicate)
|
||||
continue;
|
||||
}
|
||||
|
||||
gameFile gf;
|
||||
gf.type = GFTYPE_PATCH;
|
||||
gf.gamename = game.gamename;
|
||||
gf.updated = patch["notificated"].isInt() ? patch["notificated"].asInt() : std::stoi(patch["notificated"].asString());
|
||||
gf.id = patch["id"].isInt() ? std::to_string(patch["id"].asInt()) : patch["id"].asString();
|
||||
gf.name = patch["name"].asString();
|
||||
gf.path = path;
|
||||
gf.size = patch["size"].asString();
|
||||
gf.language = GlobalConstants::LANGUAGES[i].id;
|
||||
gf.platform = patches[j].platform;
|
||||
|
||||
game.patches.push_back(gf);
|
||||
}
|
||||
}
|
||||
else // Patch is a single file
|
||||
{
|
||||
std::string path = patchnode["link"].asString();
|
||||
path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL);
|
||||
|
||||
// Check for duplicate patches in different languages and add languageId of duplicate patch to the original patch
|
||||
if (useDuplicateHandler)
|
||||
{
|
||||
bool bDuplicate = false;
|
||||
for (unsigned int k = 0; k < game.patches.size(); ++k)
|
||||
{
|
||||
if (game.patches[k].path == path)
|
||||
{
|
||||
game.patches[k].language |= GlobalConstants::LANGUAGES[i].id; // Add language code to patch
|
||||
bDuplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bDuplicate)
|
||||
continue;
|
||||
}
|
||||
|
||||
gameFile gf;
|
||||
gf.type = GFTYPE_PATCH;
|
||||
gf.gamename = game.gamename;
|
||||
gf.updated = patchnode["notificated"].isInt() ? patchnode["notificated"].asInt() : std::stoi(patchnode["notificated"].asString());
|
||||
gf.id = patchnode["id"].isInt() ? std::to_string(patchnode["id"].asInt()) : patchnode["id"].asString();
|
||||
gf.name = patchnode["name"].asString();
|
||||
gf.path = path;
|
||||
gf.size = patchnode["size"].asString();
|
||||
gf.language = GlobalConstants::LANGUAGES[i].id;
|
||||
gf.platform = patches[j].platform;
|
||||
|
||||
game.patches.push_back(gf);
|
||||
}
|
||||
}
|
||||
gameFileInfo installerInfo;
|
||||
installerInfo.jsonNode = root["game"][installer+GlobalConstants::LANGUAGES[j].code];
|
||||
installerInfo.platform = GlobalConstants::PLATFORMS[i].id;
|
||||
installerInfo.language = GlobalConstants::LANGUAGES[j].id;
|
||||
installers.push_back(installerInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Language pack details
|
||||
for (unsigned int i = 0; i < GlobalConstants::LANGUAGES.size(); ++i)
|
||||
{ // Check against the specified languages
|
||||
if (lang & GlobalConstants::LANGUAGES[i].id)
|
||||
for ( unsigned int i = 0; i < installers.size(); ++i )
|
||||
{
|
||||
for ( unsigned int index = 0; index < installers[i].jsonNode.size(); ++index )
|
||||
{
|
||||
Json::Value installer = installers[i].jsonNode[index];
|
||||
unsigned int language = installers[i].language;
|
||||
std::string path = installer["link"].asString();
|
||||
path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL);
|
||||
|
||||
// Check for duplicate installers in different languages and add languageId of duplicate installer to the original installer
|
||||
// https://secure.gog.com/forum/general/introducing_the_beta_release_of_the_new_gogcom_downloader/post1483
|
||||
if (useDuplicateHandler)
|
||||
{
|
||||
bool bDuplicate = false;
|
||||
for (unsigned int j = 0; j < game.installers.size(); ++j)
|
||||
{
|
||||
// Try to find a language pack
|
||||
_regex_namespace_::regex re(GlobalConstants::LANGUAGES[i].code + "\\d+langpack\\d+", _regex_namespace_::regex_constants::icase); // regex for language pack node names
|
||||
std::vector<std::string> langpacknames;
|
||||
for (unsigned int j = 0; j < membernames.size(); ++j)
|
||||
if (game.installers[j].path == path)
|
||||
{
|
||||
if (_regex_namespace_::regex_match(membernames[j], re))
|
||||
langpacknames.push_back(membernames[j]);
|
||||
game.installers[j].language |= language; // Add language code to installer
|
||||
bDuplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bDuplicate)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!langpacknames.empty()) // found at least one language pack
|
||||
gameFile gf;
|
||||
gf.type = GFTYPE_INSTALLER;
|
||||
gf.gamename = game.gamename;
|
||||
gf.updated = installer["notificated"].isInt() ? installer["notificated"].asInt() : std::stoi(installer["notificated"].asString());
|
||||
gf.id = installer["id"].isInt() ? std::to_string(installer["id"].asInt()) : installer["id"].asString();
|
||||
gf.name = installer["name"].asString();
|
||||
gf.path = path;
|
||||
gf.size = installer["size"].asString();
|
||||
gf.language = language;
|
||||
gf.platform = installers[i].platform;
|
||||
gf.silent = installer["silent"].isInt() ? installer["silent"].asInt() : std::stoi(installer["silent"].asString());
|
||||
|
||||
game.installers.push_back(gf);
|
||||
}
|
||||
}
|
||||
|
||||
// Extra details
|
||||
const Json::Value extras = root["game"]["extras"];
|
||||
for ( unsigned int index = 0; index < extras.size(); ++index )
|
||||
{
|
||||
Json::Value extra = extras[index];
|
||||
|
||||
gameFile gf;
|
||||
gf.type = GFTYPE_EXTRA;
|
||||
gf.gamename = game.gamename;
|
||||
gf.updated = false; // extras don't have "updated" flag
|
||||
gf.id = extra["id"].isInt() ? std::to_string(extra["id"].asInt()) : extra["id"].asString();
|
||||
gf.name = extra["name"].asString();
|
||||
gf.path = extra["link"].asString();
|
||||
gf.path = (std::string)curl_easy_unescape(curlhandle, gf.path.c_str(), gf.path.size(), NULL);
|
||||
gf.size = extra["size_mb"].asString();
|
||||
|
||||
game.extras.push_back(gf);
|
||||
}
|
||||
|
||||
// Patch details
|
||||
for (unsigned int i = 0; i < GlobalConstants::LANGUAGES.size(); ++i)
|
||||
{ // Check against the specified languages
|
||||
if (lang & GlobalConstants::LANGUAGES[i].id)
|
||||
{
|
||||
// Try to find a patch
|
||||
_regex_namespace_::regex re(GlobalConstants::LANGUAGES[i].code + "\\d+patch\\d+", _regex_namespace_::regex_constants::icase); // regex for patch node names
|
||||
std::vector<gameFileInfo> patches;
|
||||
for (unsigned int j = 0; j < membernames.size(); ++j)
|
||||
{
|
||||
if (_regex_namespace_::regex_match(membernames[j], re))
|
||||
{ // Regex matches, we have a patch node
|
||||
gameFileInfo patchInfo;
|
||||
patchInfo.jsonNode = root["game"][membernames[j]];
|
||||
patchInfo.language = GlobalConstants::LANGUAGES[i].id;
|
||||
if (patchInfo.jsonNode["link"].asString().find("/mac/") != std::string::npos)
|
||||
patchInfo.platform = GlobalConstants::PLATFORM_MAC;
|
||||
else if (patchInfo.jsonNode["link"].asString().find("/linux/") != std::string::npos)
|
||||
patchInfo.platform = GlobalConstants::PLATFORM_LINUX;
|
||||
else
|
||||
patchInfo.platform = GlobalConstants::PLATFORM_WINDOWS;
|
||||
|
||||
if (platform & patchInfo.platform)
|
||||
patches.push_back(patchInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (!patches.empty()) // found at least one patch
|
||||
{
|
||||
for (unsigned int j = 0; j < patches.size(); ++j)
|
||||
{
|
||||
Json::Value patchnode = patches[j].jsonNode;
|
||||
if (patchnode.isArray()) // Patch has multiple files
|
||||
{
|
||||
for (unsigned int j = 0; j < langpacknames.size(); ++j)
|
||||
for ( unsigned int index = 0; index < patchnode.size(); ++index )
|
||||
{
|
||||
Json::Value langpack = root["game"][langpacknames[j]];
|
||||
Json::Value patch = patchnode[index];
|
||||
std::string path = patch["link"].asString();
|
||||
path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL);
|
||||
|
||||
// Check for duplicate patches in different languages and add languageId of duplicate patch to the original patch
|
||||
if (useDuplicateHandler)
|
||||
{
|
||||
bool bDuplicate = false;
|
||||
for (unsigned int j = 0; j < game.patches.size(); ++j)
|
||||
{
|
||||
if (game.patches[j].path == path)
|
||||
{
|
||||
game.patches[j].language |= GlobalConstants::LANGUAGES[i].id; // Add language code to patch
|
||||
bDuplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bDuplicate)
|
||||
continue;
|
||||
}
|
||||
|
||||
gameFile gf;
|
||||
gf.type = GFTYPE_LANGPACK;
|
||||
gf.type = GFTYPE_PATCH;
|
||||
gf.gamename = game.gamename;
|
||||
gf.updated = false; // language packs don't have "updated" flag
|
||||
gf.id = langpack["id"].isInt() ? std::to_string(langpack["id"].asInt()) : langpack["id"].asString();
|
||||
gf.name = langpack["name"].asString();
|
||||
gf.path = langpack["link"].asString();
|
||||
gf.path = (std::string)curl_easy_unescape(curlhandle, gf.path.c_str(), gf.path.size(), NULL);
|
||||
gf.size = langpack["size"].asString();
|
||||
gf.updated = patch["notificated"].isInt() ? patch["notificated"].asInt() : std::stoi(patch["notificated"].asString());
|
||||
gf.id = patch["id"].isInt() ? std::to_string(patch["id"].asInt()) : patch["id"].asString();
|
||||
gf.name = patch["name"].asString();
|
||||
gf.path = path;
|
||||
gf.size = patch["size"].asString();
|
||||
gf.language = GlobalConstants::LANGUAGES[i].id;
|
||||
gf.platform = patches[j].platform;
|
||||
|
||||
game.languagepacks.push_back(gf);
|
||||
game.patches.push_back(gf);
|
||||
}
|
||||
}
|
||||
else // Patch is a single file
|
||||
{
|
||||
std::string path = patchnode["link"].asString();
|
||||
path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL);
|
||||
|
||||
// Check for duplicate patches in different languages and add languageId of duplicate patch to the original patch
|
||||
if (useDuplicateHandler)
|
||||
{
|
||||
bool bDuplicate = false;
|
||||
for (unsigned int k = 0; k < game.patches.size(); ++k)
|
||||
{
|
||||
if (game.patches[k].path == path)
|
||||
{
|
||||
game.patches[k].language |= GlobalConstants::LANGUAGES[i].id; // Add language code to patch
|
||||
bDuplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bDuplicate)
|
||||
continue;
|
||||
}
|
||||
|
||||
gameFile gf;
|
||||
gf.type = GFTYPE_PATCH;
|
||||
gf.gamename = game.gamename;
|
||||
gf.updated = patchnode["notificated"].isInt() ? patchnode["notificated"].asInt() : std::stoi(patchnode["notificated"].asString());
|
||||
gf.id = patchnode["id"].isInt() ? std::to_string(patchnode["id"].asInt()) : patchnode["id"].asString();
|
||||
gf.name = patchnode["name"].asString();
|
||||
gf.path = path;
|
||||
gf.size = patchnode["size"].asString();
|
||||
gf.language = GlobalConstants::LANGUAGES[i].id;
|
||||
gf.platform = patches[j].platform;
|
||||
|
||||
game.patches.push_back(gf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getGameDetails)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(jsonparser->getFormattedErrorMessages());
|
||||
}
|
||||
delete jsonparser;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setError("Found nothing in " + url);
|
||||
|
||||
// Language pack details
|
||||
for (unsigned int i = 0; i < GlobalConstants::LANGUAGES.size(); ++i)
|
||||
{ // Check against the specified languages
|
||||
if (lang & GlobalConstants::LANGUAGES[i].id)
|
||||
{
|
||||
// Try to find a language pack
|
||||
_regex_namespace_::regex re(GlobalConstants::LANGUAGES[i].code + "\\d+langpack\\d+", _regex_namespace_::regex_constants::icase); // regex for language pack node names
|
||||
std::vector<std::string> langpacknames;
|
||||
for (unsigned int j = 0; j < membernames.size(); ++j)
|
||||
{
|
||||
if (_regex_namespace_::regex_match(membernames[j], re))
|
||||
langpacknames.push_back(membernames[j]);
|
||||
}
|
||||
|
||||
if (!langpacknames.empty()) // found at least one language pack
|
||||
{
|
||||
for (unsigned int j = 0; j < langpacknames.size(); ++j)
|
||||
{
|
||||
Json::Value langpack = root["game"][langpacknames[j]];
|
||||
|
||||
gameFile gf;
|
||||
gf.type = GFTYPE_LANGPACK;
|
||||
gf.gamename = game.gamename;
|
||||
gf.updated = false; // language packs don't have "updated" flag
|
||||
gf.id = langpack["id"].isInt() ? std::to_string(langpack["id"].asInt()) : langpack["id"].asString();
|
||||
gf.name = langpack["name"].asString();
|
||||
gf.path = langpack["link"].asString();
|
||||
gf.path = (std::string)curl_easy_unescape(curlhandle, gf.path.c_str(), gf.path.size(), NULL);
|
||||
gf.size = langpack["size"].asString();
|
||||
gf.language = GlobalConstants::LANGUAGES[i].id;
|
||||
|
||||
game.languagepacks.push_back(gf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return game;
|
||||
@ -584,33 +568,31 @@ std::string API::getInstallerLink(const std::string& game_name, const std::strin
|
||||
url = this->config.get_installer_link + game_name + "/" + id + "/";
|
||||
std::string json = this->getResponseOAuth(url);
|
||||
|
||||
if (!json.empty())
|
||||
{
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(json, root))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getInstallerLink)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString());
|
||||
if (available)
|
||||
link = root["file"]["link"].asString();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getInstallerLink)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(jsonparser->getFormattedErrorMessages());
|
||||
}
|
||||
delete jsonparser;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (json.empty()) {
|
||||
this->setError("Found nothing in " + url);
|
||||
return link;
|
||||
}
|
||||
|
||||
Json::Value root;
|
||||
std::istringstream json_stream(json);
|
||||
|
||||
try {
|
||||
json_stream >> root;
|
||||
} catch (const Json::Exception& exc) {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getInstallerLink)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(exc.what());
|
||||
return link;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getInstallerLink)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString());
|
||||
if (available)
|
||||
link = root["file"]["link"].asString();
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
@ -620,33 +602,31 @@ std::string API::getExtraLink(const std::string& game_name, const std::string& i
|
||||
url = this->config.get_extra_link + game_name + "/" + id + "/";
|
||||
std::string json = this->getResponseOAuth(url);
|
||||
|
||||
if (!json.empty())
|
||||
{
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(json, root))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getExtraLink)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString());
|
||||
if (available)
|
||||
link = root["file"]["link"].asString();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getExtraLink)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(jsonparser->getFormattedErrorMessages());
|
||||
}
|
||||
delete jsonparser;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (json.empty()) {
|
||||
this->setError("Found nothing in " + url);
|
||||
return link;
|
||||
}
|
||||
|
||||
Json::Value root;
|
||||
std::istringstream json_stream(json);
|
||||
|
||||
try {
|
||||
json_stream >> root;
|
||||
} catch (const Json::Exception& exc) {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getExtraLink)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(exc.what());
|
||||
return link;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getExtraLink)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString());
|
||||
if (available)
|
||||
link = root["file"]["link"].asString();
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
@ -666,34 +646,30 @@ std::string API::getXML(const std::string& game_name, const std::string& id)
|
||||
url = this->config.get_installer_link + game_name + "/" + id + "/crc/";
|
||||
std::string json = this->getResponseOAuth(url);
|
||||
|
||||
if (!json.empty())
|
||||
{
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(json, root))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getXML)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString());
|
||||
if (available)
|
||||
{
|
||||
url = root["file"]["link"].asString();
|
||||
XML = this->getResponse(url);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getXML)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(jsonparser->getFormattedErrorMessages());
|
||||
}
|
||||
delete jsonparser;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (json.empty()) {
|
||||
this->setError("Found nothing in " + url);
|
||||
return XML;
|
||||
}
|
||||
|
||||
try {
|
||||
std::istringstream iss(json);
|
||||
Json::Value root;
|
||||
iss >> root;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getXML)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString());
|
||||
if (available)
|
||||
{
|
||||
url = root["file"]["link"].asString();
|
||||
XML = this->getResponse(url);
|
||||
}
|
||||
} catch (const Json::Exception& exc) {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getXML)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
this->setError(exc.what());
|
||||
}
|
||||
|
||||
return XML;
|
||||
|
@ -121,9 +121,8 @@ Downloader::Downloader()
|
||||
{
|
||||
std::ifstream ifs(Globals::galaxyConf.getFilepath(), std::ifstream::binary);
|
||||
Json::Value json;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(ifs, json))
|
||||
{
|
||||
try {
|
||||
ifs >> json;
|
||||
if (!json.isMember("expires_at"))
|
||||
{
|
||||
std::time_t last_modified = boost::filesystem::last_write_time(Globals::galaxyConf.getFilepath());
|
||||
@ -132,13 +131,10 @@ Downloader::Downloader()
|
||||
}
|
||||
|
||||
Globals::galaxyConf.setJSON(json);
|
||||
}
|
||||
else
|
||||
{
|
||||
} catch (const Json::Exception& exc) {
|
||||
std::cerr << "Failed to parse " << Globals::galaxyConf.getFilepath() << std::endl;
|
||||
std::cerr << jsonparser->getFormattedErrorMessages() << std::endl;
|
||||
}
|
||||
delete jsonparser;
|
||||
std::cerr << exc.what() << std::endl;
|
||||
}
|
||||
|
||||
if (ifs)
|
||||
ifs.close();
|
||||
@ -739,8 +735,6 @@ void Downloader::repair()
|
||||
if (this->games.empty())
|
||||
this->getGameDetails();
|
||||
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
|
||||
// Create a vector containing all game files
|
||||
std::vector<gameFile> vGameFiles;
|
||||
for (unsigned int i = 0; i < games.size(); ++i)
|
||||
@ -793,8 +787,14 @@ void Downloader::repair()
|
||||
std::cerr << "Found nothing in " << vGameFiles[i].galaxy_downlink_json_url << ", skipping file" << std::endl;
|
||||
continue;
|
||||
}
|
||||
jsonparser->parse(response, downlinkJson);
|
||||
|
||||
try {
|
||||
std::istringstream iss(response);
|
||||
iss >> downlinkJson;
|
||||
} catch (const Json::Exception& exc) {
|
||||
std::cerr << "Could not parse JSON response, skipping file" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!downlinkJson.isMember("downlink"))
|
||||
{
|
||||
std::cerr << "Invalid JSON response, skipping file" << std::endl;
|
||||
@ -827,8 +827,6 @@ void Downloader::repair()
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
delete jsonparser;
|
||||
}
|
||||
|
||||
void Downloader::download()
|
||||
@ -2237,53 +2235,40 @@ int Downloader::loadGameDetailsCache()
|
||||
|
||||
std::ifstream json(cachepath, std::ifstream::binary);
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(json, root))
|
||||
{
|
||||
if (root.isMember("date"))
|
||||
{
|
||||
cachedate = bptime::from_iso_string(root["date"].asString());
|
||||
if ((now - cachedate) > bptime::minutes(Globals::globalConfig.iCacheValid))
|
||||
{
|
||||
// cache is too old
|
||||
delete jsonparser;
|
||||
json.close();
|
||||
return res = 3;
|
||||
}
|
||||
}
|
||||
|
||||
int iCacheVersion = 0;
|
||||
if (root.isMember("gamedetails-cache-version"))
|
||||
iCacheVersion = root["gamedetails-cache-version"].asInt();
|
||||
|
||||
if (iCacheVersion != GlobalConstants::GAMEDETAILS_CACHE_VERSION)
|
||||
{
|
||||
res = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (root.isMember("games"))
|
||||
{
|
||||
this->games = getGameDetailsFromJsonNode(root["games"]);
|
||||
res = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res = 2;
|
||||
try {
|
||||
json >> root;
|
||||
} catch (const Json::Exception& exc) {
|
||||
std::cout << "Failed to parse cache" << std::endl;
|
||||
std::cout << jsonparser->getFormattedErrorMessages() << std::endl;
|
||||
std::cout << exc.what() << std::endl;
|
||||
return 2;
|
||||
}
|
||||
delete jsonparser;
|
||||
if (json)
|
||||
json.close();
|
||||
|
||||
return res;
|
||||
if (root.isMember("date"))
|
||||
{
|
||||
cachedate = bptime::from_iso_string(root["date"].asString());
|
||||
if ((now - cachedate) > bptime::minutes(Globals::globalConfig.iCacheValid))
|
||||
{
|
||||
// cache is too old
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
int iCacheVersion = 0;
|
||||
if (root.isMember("gamedetails-cache-version"))
|
||||
iCacheVersion = root["gamedetails-cache-version"].asInt();
|
||||
|
||||
if (iCacheVersion != GlobalConstants::GAMEDETAILS_CACHE_VERSION)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (root.isMember("games"))
|
||||
{
|
||||
this->games = getGameDetailsFromJsonNode(root["games"]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
/* Save game details to cache file
|
||||
returns 0 if successful
|
||||
@ -2318,8 +2303,7 @@ int Downloader::saveGameDetailsCache()
|
||||
}
|
||||
else
|
||||
{
|
||||
Json::StyledStreamWriter jsonwriter;
|
||||
jsonwriter.write(ofs, json);
|
||||
ofs << json << std::endl;
|
||||
ofs.close();
|
||||
}
|
||||
return res;
|
||||
@ -2638,8 +2622,6 @@ void Downloader::processDownloadQueue(Config conf, const unsigned int& tid)
|
||||
}
|
||||
}
|
||||
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
|
||||
CURL* dlhandle = curl_easy_init();
|
||||
curl_easy_setopt(dlhandle, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(dlhandle, CURLOPT_USERAGENT, conf.curlConf.sUserAgent.c_str());
|
||||
@ -2736,7 +2718,6 @@ void Downloader::processDownloadQueue(Config conf, const unsigned int& tid)
|
||||
{
|
||||
msgQueue.push(Message("Galaxy API failed to refresh login", MSGTYPE_ERROR, msg_prefix));
|
||||
vDownloadInfo[tid].setStatus(DLSTATUS_FINISHED);
|
||||
delete jsonparser;
|
||||
delete galaxy;
|
||||
return;
|
||||
}
|
||||
@ -2751,7 +2732,14 @@ void Downloader::processDownloadQueue(Config conf, const unsigned int& tid)
|
||||
msgQueue.push(Message("Found nothing in " + gf.galaxy_downlink_json_url + ", skipping file", MSGTYPE_WARNING, msg_prefix));
|
||||
continue;
|
||||
}
|
||||
jsonparser->parse(response, downlinkJson);
|
||||
|
||||
try {
|
||||
std::istringstream iss(response);
|
||||
iss >> downlinkJson;
|
||||
} catch (const Json::Exception& exc) {
|
||||
msgQueue.push(Message("Could not parse JSON response, skipping file", MSGTYPE_WARNING, msg_prefix));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!downlinkJson.isMember("downlink"))
|
||||
{
|
||||
@ -2962,7 +2950,6 @@ void Downloader::processDownloadQueue(Config conf, const unsigned int& tid)
|
||||
}
|
||||
|
||||
curl_easy_cleanup(dlhandle);
|
||||
delete jsonparser;
|
||||
delete galaxy;
|
||||
|
||||
vDownloadInfo[tid].setStatus(DLSTATUS_FINISHED);
|
||||
@ -3316,8 +3303,7 @@ void Downloader::saveGalaxyJSON()
|
||||
}
|
||||
else
|
||||
{
|
||||
Json::StyledStreamWriter jsonwriter;
|
||||
jsonwriter.write(ofs, Globals::galaxyConf.getJSON());
|
||||
ofs << Globals::galaxyConf.getJSON() << std::endl;
|
||||
ofs.close();
|
||||
}
|
||||
if (!Globals::globalConfig.bRespectUmask)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <boost/iostreams/copy.hpp>
|
||||
#include <boost/iostreams/filter/zlib.hpp>
|
||||
#include <boost/iostreams/device/back_inserter.hpp>
|
||||
#include <sstream>
|
||||
|
||||
GalaxyConfig Globals::galaxyConf;
|
||||
|
||||
@ -78,19 +79,19 @@ bool galaxyAPI::refreshLogin()
|
||||
+ "&refresh_token=" + Globals::galaxyConf.getRefreshToken();
|
||||
|
||||
std::string json = this->getResponse(refresh_url);
|
||||
if (!json.empty())
|
||||
{
|
||||
Json::Value token_json;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(json, token_json))
|
||||
{
|
||||
Globals::galaxyConf.setJSON(token_json);
|
||||
res = true;
|
||||
}
|
||||
delete jsonparser;
|
||||
if (json.empty())
|
||||
return false;
|
||||
|
||||
Json::Value token_json;
|
||||
std::istringstream json_stream(json);
|
||||
try {
|
||||
json_stream >> token_json;
|
||||
Globals::galaxyConf.setJSON(token_json);
|
||||
} catch (const Json::Exception& exc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool galaxyAPI::isTokenExpired()
|
||||
@ -145,59 +146,47 @@ std::string galaxyAPI::getResponse(const std::string& url, const bool& zlib_deco
|
||||
|
||||
Json::Value galaxyAPI::getProductBuilds(const std::string& product_id, const std::string& platform, const std::string& generation)
|
||||
{
|
||||
std::string url = "https://content-system.gog.com/products/" + product_id + "/os/" + platform + "/builds?generation=" + generation;
|
||||
std::istringstream response(this->getResponse(url));
|
||||
Json::Value json;
|
||||
|
||||
std::string url = "https://content-system.gog.com/products/" + product_id + "/os/" + platform + "/builds?generation=" + generation;
|
||||
std::string response = this->getResponse(url);
|
||||
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
jsonparser->parse(response, json);
|
||||
delete jsonparser;
|
||||
response >> json;
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
Json::Value galaxyAPI::getManifestV1(const std::string& product_id, const std::string& build_id, const std::string& manifest_id, const std::string& platform)
|
||||
{
|
||||
std::string url = "https://cdn.gog.com/content-system/v1/manifests/" + product_id + "/" + platform + "/" + build_id + "/" + manifest_id + ".json";
|
||||
std::istringstream response(this->getResponse(url));
|
||||
Json::Value json;
|
||||
|
||||
std::string url = "https://cdn.gog.com/content-system/v1/manifests/" + product_id + "/" + platform + "/" + build_id + "/" + manifest_id + ".json";
|
||||
std::string response = this->getResponse(url);
|
||||
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
jsonparser->parse(response, json);
|
||||
delete jsonparser;
|
||||
response >> json;
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
Json::Value galaxyAPI::getManifestV2(std::string manifest_hash)
|
||||
{
|
||||
Json::Value json;
|
||||
|
||||
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 response = this->getResponse(url, true);
|
||||
std::istringstream response(this->getResponse(url, true));
|
||||
Json::Value json;
|
||||
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
jsonparser->parse(response, json);
|
||||
delete jsonparser;
|
||||
response >> json;
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
Json::Value galaxyAPI::getSecureLink(const std::string& product_id, const std::string& path)
|
||||
{
|
||||
std::string url = "https://content-system.gog.com/products/" + product_id + "/secure_link?generation=2&path=" + path + "&_version=2";
|
||||
std::istringstream response(this->getResponse(url));
|
||||
Json::Value json;
|
||||
|
||||
std::string url = "https://content-system.gog.com/products/" + product_id + "/secure_link?generation=2&path=" + path + "&_version=2";
|
||||
std::string response = this->getResponse(url);
|
||||
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
jsonparser->parse(response, json);
|
||||
delete jsonparser;
|
||||
response >>json;
|
||||
|
||||
return json;
|
||||
}
|
||||
@ -257,14 +246,11 @@ std::vector<galaxyDepotItem> galaxyAPI::getDepotItemsVector(const std::string& h
|
||||
|
||||
Json::Value galaxyAPI::getProductInfo(const std::string& product_id)
|
||||
{
|
||||
std::string url = "https://api.gog.com/products/" + product_id + "?expand=downloads,expanded_dlcs,description,screenshots,videos,related_products,changelog&locale=en-US";
|
||||
std::istringstream response(this->getResponse(url));
|
||||
Json::Value json;
|
||||
|
||||
std::string url = "https://api.gog.com/products/" + product_id + "?expand=downloads,expanded_dlcs,description,screenshots,videos,related_products,changelog&locale=en-US";
|
||||
std::string response = this->getResponse(url);
|
||||
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
jsonparser->parse(response, json);
|
||||
delete jsonparser;
|
||||
response >> json;
|
||||
|
||||
return json;
|
||||
}
|
||||
@ -384,9 +370,10 @@ std::vector<gameFile> galaxyAPI::fileJsonNodeToGameFileVector(const std::string&
|
||||
continue;
|
||||
|
||||
Json::Value downlinkJson;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
jsonparser->parse(downlinkResponse, downlinkJson);
|
||||
delete jsonparser;
|
||||
Json::CharReaderBuilder builder;
|
||||
std::istringstream downlink_stream(downlinkResponse);
|
||||
JSONCPP_STRING errs;
|
||||
Json::parseFromStream(builder, downlink_stream, &downlinkJson, &errs);
|
||||
|
||||
std::string downlink_url = downlinkJson["downlink"].asString();
|
||||
std::string downlink_url_unescaped = (std::string)curl_easy_unescape(curlhandle, downlink_url.c_str(), downlink_url.size(), NULL);
|
||||
|
155
src/util.cpp
155
src/util.cpp
@ -235,89 +235,84 @@ int Util::getGameSpecificConfig(std::string gamename, gameSpecificConfig* conf,
|
||||
|
||||
std::ifstream json(filepath, std::ifstream::binary);
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(json, root))
|
||||
{
|
||||
if (root.isMember("language"))
|
||||
{
|
||||
if (root["language"].isInt())
|
||||
conf->dlConf.iInstallerLanguage = root["language"].asUInt();
|
||||
else
|
||||
{
|
||||
Util::parseOptionString(root["language"].asString(), conf->dlConf.vLanguagePriority, conf->dlConf.iInstallerLanguage, GlobalConstants::LANGUAGES);
|
||||
}
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("platform"))
|
||||
{
|
||||
if (root["platform"].isInt())
|
||||
conf->dlConf.iInstallerPlatform = root["platform"].asUInt();
|
||||
else
|
||||
{
|
||||
Util::parseOptionString(root["platform"].asString(), conf->dlConf.vPlatformPriority, conf->dlConf.iInstallerPlatform, GlobalConstants::PLATFORMS);
|
||||
}
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("dlc"))
|
||||
{
|
||||
conf->dlConf.bDLC = root["dlc"].asBool();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("ignore-dlc-count"))
|
||||
{
|
||||
conf->dlConf.bIgnoreDLCCount = root["ignore-dlc-count"].asBool();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdirectories"))
|
||||
{
|
||||
conf->dirConf.bSubDirectories = root["subdirectories"].asBool();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("directory"))
|
||||
{
|
||||
conf->dirConf.sDirectory = root["directory"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-game"))
|
||||
{
|
||||
conf->dirConf.sGameSubdir = root["subdir-game"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-installers"))
|
||||
{
|
||||
conf->dirConf.sInstallersSubdir = root["subdir-installers"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-extras"))
|
||||
{
|
||||
conf->dirConf.sExtrasSubdir = root["subdir-extras"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-patches"))
|
||||
{
|
||||
conf->dirConf.sPatchesSubdir = root["subdir-patches"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-language-packs"))
|
||||
{
|
||||
conf->dirConf.sLanguagePackSubdir = root["subdir-language-packs"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-dlc"))
|
||||
{
|
||||
conf->dirConf.sDLCSubdir = root["subdir-dlc"].asString();
|
||||
res++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try {
|
||||
json >> root;
|
||||
} catch (const Json::Exception& exc) {
|
||||
std::cerr << "Failed to parse game specific config " << filepath << std::endl;
|
||||
std::cerr << jsonparser->getFormattedErrorMessages() << std::endl;
|
||||
std::cerr << exc.what() << std::endl;
|
||||
return res;
|
||||
}
|
||||
delete jsonparser;
|
||||
if (json)
|
||||
json.close();
|
||||
|
||||
if (root.isMember("language"))
|
||||
{
|
||||
if (root["language"].isInt())
|
||||
conf->dlConf.iInstallerLanguage = root["language"].asUInt();
|
||||
else
|
||||
{
|
||||
Util::parseOptionString(root["language"].asString(), conf->dlConf.vLanguagePriority, conf->dlConf.iInstallerLanguage, GlobalConstants::LANGUAGES);
|
||||
}
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("platform"))
|
||||
{
|
||||
if (root["platform"].isInt())
|
||||
conf->dlConf.iInstallerPlatform = root["platform"].asUInt();
|
||||
else
|
||||
{
|
||||
Util::parseOptionString(root["platform"].asString(), conf->dlConf.vPlatformPriority, conf->dlConf.iInstallerPlatform, GlobalConstants::PLATFORMS);
|
||||
}
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("dlc"))
|
||||
{
|
||||
conf->dlConf.bDLC = root["dlc"].asBool();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("ignore-dlc-count"))
|
||||
{
|
||||
conf->dlConf.bIgnoreDLCCount = root["ignore-dlc-count"].asBool();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdirectories"))
|
||||
{
|
||||
conf->dirConf.bSubDirectories = root["subdirectories"].asBool();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("directory"))
|
||||
{
|
||||
conf->dirConf.sDirectory = root["directory"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-game"))
|
||||
{
|
||||
conf->dirConf.sGameSubdir = root["subdir-game"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-installers"))
|
||||
{
|
||||
conf->dirConf.sInstallersSubdir = root["subdir-installers"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-extras"))
|
||||
{
|
||||
conf->dirConf.sExtrasSubdir = root["subdir-extras"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-patches"))
|
||||
{
|
||||
conf->dirConf.sPatchesSubdir = root["subdir-patches"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-language-packs"))
|
||||
{
|
||||
conf->dirConf.sLanguagePackSubdir = root["subdir-language-packs"].asString();
|
||||
res++;
|
||||
}
|
||||
if (root.isMember("subdir-dlc"))
|
||||
{
|
||||
conf->dirConf.sDLCSubdir = root["subdir-dlc"].asString();
|
||||
res++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -99,20 +99,20 @@ Json::Value Website::getGameDetailsJSON(const std::string& gameid)
|
||||
|
||||
// Parse JSON
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (!jsonparser->parse(json, root))
|
||||
{
|
||||
std::istringstream json_stream(json);
|
||||
|
||||
try {
|
||||
json_stream >> root;
|
||||
} catch(const Json::Exception& exc) {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (Website::getGameDetailsJSON)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
std::cout << jsonparser->getFormattedErrorMessages();
|
||||
delete jsonparser;
|
||||
std::cout << exc.what();
|
||||
exit(1);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (Website::getGameDetailsJSON)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
delete jsonparser;
|
||||
|
||||
return root;
|
||||
}
|
||||
@ -122,22 +122,22 @@ std::vector<gameItem> Website::getGames()
|
||||
{
|
||||
std::vector<gameItem> games;
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
int i = 1;
|
||||
bool bAllPagesParsed = false;
|
||||
|
||||
do
|
||||
{
|
||||
std::string response = this->getResponse("https://www.gog.com/account/getFilteredProducts?hasHiddenProducts=false&hiddenFlag=0&isUpdated=0&mediaType=1&sortBy=title&system=&page=" + std::to_string(i));
|
||||
std::istringstream json_stream(response);
|
||||
|
||||
// Parse JSON
|
||||
if (!jsonparser->parse(response, root))
|
||||
{
|
||||
try {
|
||||
// Parse JSON
|
||||
json_stream >> root;
|
||||
} catch (const Json::Exception& exc) {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (Website::getGames)" << std::endl << response << std::endl;
|
||||
#endif
|
||||
std::cout << jsonparser->getFormattedErrorMessages();
|
||||
delete jsonparser;
|
||||
std::cout << exc.what();
|
||||
if (!response.empty())
|
||||
{
|
||||
if(response[0] != '{')
|
||||
@ -269,8 +269,6 @@ std::vector<gameItem> Website::getGames()
|
||||
} while (!bAllPagesParsed);
|
||||
std::cerr << std::endl;
|
||||
|
||||
delete jsonparser;
|
||||
|
||||
return games;
|
||||
}
|
||||
|
||||
@ -278,20 +276,21 @@ std::vector<gameItem> Website::getGames()
|
||||
std::vector<gameItem> Website::getFreeGames()
|
||||
{
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
std::vector<gameItem> games;
|
||||
std::string json = this->getResponse("https://www.gog.com/games/ajax/filtered?mediaType=game&page=1&price=free&sort=title");
|
||||
std::istringstream json_stream(json);
|
||||
|
||||
// Parse JSON
|
||||
if (!jsonparser->parse(json, root))
|
||||
{
|
||||
try {
|
||||
// Parse JSON
|
||||
json_stream >> root;
|
||||
} catch (const Json::Exception& exc) {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (Website::getFreeGames)" << std::endl << json << std::endl;
|
||||
#endif
|
||||
std::cout << jsonparser->getFormattedErrorMessages();
|
||||
delete jsonparser;
|
||||
std::cout << exc.what();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (Website::getFreeGames)" << std::endl << root << std::endl;
|
||||
#endif
|
||||
@ -304,7 +303,6 @@ std::vector<gameItem> Website::getFreeGames()
|
||||
game.id = products[i]["id"].isInt() ? std::to_string(products[i]["id"].asInt()) : products[i]["id"].asString();
|
||||
games.push_back(game);
|
||||
}
|
||||
delete jsonparser;
|
||||
|
||||
return games;
|
||||
}
|
||||
@ -506,18 +504,16 @@ int Website::Login(const std::string& email, const std::string& password)
|
||||
if (!json.empty())
|
||||
{
|
||||
Json::Value token_json;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
if (jsonparser->parse(json, token_json))
|
||||
{
|
||||
std::istringstream json_stream(json);
|
||||
try {
|
||||
json_stream >> token_json;
|
||||
|
||||
Globals::galaxyConf.setJSON(token_json);
|
||||
res = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
} catch (const Json::Exception& exc) {
|
||||
std::cerr << "Failed to parse json" << std::endl << json << std::endl;
|
||||
std::cerr << jsonparser->getFormattedErrorMessages() << std::endl;
|
||||
std::cerr << exc.what() << std::endl;
|
||||
}
|
||||
delete jsonparser;
|
||||
}
|
||||
}
|
||||
|
||||
@ -608,23 +604,24 @@ bool Website::IsloggedInSimple()
|
||||
std::vector<wishlistItem> Website::getWishlistItems()
|
||||
{
|
||||
Json::Value root;
|
||||
Json::Reader *jsonparser = new Json::Reader;
|
||||
Json::CharReaderBuilder builder;
|
||||
int i = 1;
|
||||
bool bAllPagesParsed = false;
|
||||
std::vector<wishlistItem> wishlistItems;
|
||||
|
||||
do
|
||||
{
|
||||
std::string response = this->getResponse("https://www.gog.com/account/wishlist/search?hasHiddenProducts=false&hiddenFlag=0&isUpdated=0&mediaType=0&sortBy=title&system=&page=" + std::to_string(i));
|
||||
std::string response(this->getResponse("https://www.gog.com/account/wishlist/search?hasHiddenProducts=false&hiddenFlag=0&isUpdated=0&mediaType=0&sortBy=title&system=&page=" + std::to_string(i)));
|
||||
std::istringstream response_stream(response);
|
||||
|
||||
// Parse JSON
|
||||
if (!jsonparser->parse(response, root))
|
||||
{
|
||||
try {
|
||||
// Parse JSON
|
||||
response_stream >> root;
|
||||
} catch(const Json::Exception exc) {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (Website::getWishlistItems)" << std::endl << response << std::endl;
|
||||
#endif
|
||||
std::cout << jsonparser->getFormattedErrorMessages();
|
||||
delete jsonparser;
|
||||
std::cout << exc.what();
|
||||
exit(1);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
@ -712,7 +709,5 @@ std::vector<wishlistItem> Website::getWishlistItems()
|
||||
i++;
|
||||
} while (!bAllPagesParsed);
|
||||
|
||||
delete jsonparser;
|
||||
|
||||
return wishlistItems;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user