mirror of
https://github.com/Sude-/lgogdownloader.git
synced 2024-11-20 11:49:17 +01:00
Merge branch 'cloud-save' of https://github.com/loki-47-6F-64/lgogdownloader
This commit is contained in:
commit
6ae6ab2469
@ -19,6 +19,7 @@ struct DirectoryConfig
|
|||||||
{
|
{
|
||||||
bool bSubDirectories;
|
bool bSubDirectories;
|
||||||
std::string sDirectory;
|
std::string sDirectory;
|
||||||
|
std::string sWinePrefix;
|
||||||
std::string sGameSubdir;
|
std::string sGameSubdir;
|
||||||
std::string sInstallersSubdir;
|
std::string sInstallersSubdir;
|
||||||
std::string sExtrasSubdir;
|
std::string sExtrasSubdir;
|
||||||
@ -102,6 +103,16 @@ class GalaxyConfig
|
|||||||
return this->token_json;
|
return this->token_json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string getUserId() {
|
||||||
|
std::unique_lock<std::mutex> lock(m);
|
||||||
|
|
||||||
|
if(this->token_json.isMember("user_id")) {
|
||||||
|
return this->token_json["user_id"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void setJSON(Json::Value json)
|
void setJSON(Json::Value json)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m);
|
std::unique_lock<std::mutex> lock(m);
|
||||||
@ -131,16 +142,34 @@ class GalaxyConfig
|
|||||||
return this->filepath;
|
return this->filepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resetClient() {
|
||||||
|
std::lock_guard<std::mutex> lock(m);
|
||||||
|
if(token_json.isMember("client_id")) {
|
||||||
|
token_json["client_id"] = default_client_id;
|
||||||
|
}
|
||||||
|
if(token_json.isMember("client_secret")) {
|
||||||
|
token_json["client_secret"] = default_client_secret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string getClientId()
|
std::string getClientId()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m);
|
std::lock_guard<std::mutex> lock(m);
|
||||||
return this->client_id;
|
if(token_json.isMember("client_id")) {
|
||||||
|
return token_json["client_id"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_client_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getClientSecret()
|
std::string getClientSecret()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m);
|
std::lock_guard<std::mutex> lock(m);
|
||||||
return this->client_secret;
|
if(token_json.isMember("client_secret")) {
|
||||||
|
return token_json["client_secret"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_client_secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getRedirectUri()
|
std::string getRedirectUri()
|
||||||
@ -154,8 +183,6 @@ class GalaxyConfig
|
|||||||
GalaxyConfig(const GalaxyConfig& other)
|
GalaxyConfig(const GalaxyConfig& other)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(other.m);
|
std::lock_guard<std::mutex> guard(other.m);
|
||||||
client_id = other.client_id;
|
|
||||||
client_secret = other.client_secret;
|
|
||||||
redirect_uri = other.redirect_uri;
|
redirect_uri = other.redirect_uri;
|
||||||
filepath = other.filepath;
|
filepath = other.filepath;
|
||||||
token_json = other.token_json;
|
token_json = other.token_json;
|
||||||
@ -169,8 +196,6 @@ class GalaxyConfig
|
|||||||
std::unique_lock<std::mutex> lock1(m, std::defer_lock);
|
std::unique_lock<std::mutex> lock1(m, std::defer_lock);
|
||||||
std::unique_lock<std::mutex> lock2(other.m, std::defer_lock);
|
std::unique_lock<std::mutex> lock2(other.m, std::defer_lock);
|
||||||
std::lock(lock1, lock2);
|
std::lock(lock1, lock2);
|
||||||
client_id = other.client_id;
|
|
||||||
client_secret = other.client_secret;
|
|
||||||
redirect_uri = other.redirect_uri;
|
redirect_uri = other.redirect_uri;
|
||||||
filepath = other.filepath;
|
filepath = other.filepath;
|
||||||
token_json = other.token_json;
|
token_json = other.token_json;
|
||||||
@ -178,8 +203,9 @@ class GalaxyConfig
|
|||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
std::string client_id = "46899977096215655";
|
const std::string default_client_id = "46899977096215655";
|
||||||
std::string client_secret = "9d85c43b1482497dbbce61f6e4aa173a433796eeae2ca8c5f6129f2dc4de46d9";
|
const std::string default_client_secret = "9d85c43b1482497dbbce61f6e4aa173a433796eeae2ca8c5f6129f2dc4de46d9";
|
||||||
|
|
||||||
std::string redirect_uri = "https://embed.gog.com/on_login_success?origin=client";
|
std::string redirect_uri = "https://embed.gog.com/on_login_success?origin=client";
|
||||||
std::string filepath;
|
std::string filepath;
|
||||||
Json::Value token_json;
|
Json::Value token_json;
|
||||||
@ -281,6 +307,12 @@ class Config
|
|||||||
Blacklist blacklist;
|
Blacklist blacklist;
|
||||||
Blacklist ignorelist;
|
Blacklist ignorelist;
|
||||||
Blacklist gamehasdlc;
|
Blacklist gamehasdlc;
|
||||||
|
|
||||||
|
// Cloud save options
|
||||||
|
std::vector<std::string> cloudWhiteList;
|
||||||
|
std::vector<std::string> cloudBlackList;
|
||||||
|
bool bCloudForce;
|
||||||
|
|
||||||
std::string sGameHasDLCList;
|
std::string sGameHasDLCList;
|
||||||
|
|
||||||
// Integers
|
// Integers
|
||||||
|
@ -32,9 +32,11 @@
|
|||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <functional>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
class cloudSaveFile;
|
||||||
class Timer
|
class Timer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -99,6 +101,14 @@ class Downloader
|
|||||||
void clearUpdateNotifications();
|
void clearUpdateNotifications();
|
||||||
void repair();
|
void repair();
|
||||||
void download();
|
void download();
|
||||||
|
|
||||||
|
void downloadCloudSaves(const std::string& product_id, int build_index = -1);
|
||||||
|
void downloadCloudSavesById(const std::string& product_id, int build_index = -1);
|
||||||
|
void uploadCloudSaves(const std::string& product_id, int build_index = -1);
|
||||||
|
void uploadCloudSavesById(const std::string& product_id, int build_index = -1);
|
||||||
|
void deleteCloudSaves(const std::string& product_id, int build_index = -1);
|
||||||
|
void deleteCloudSavesById(const std::string& product_id, int build_index = -1);
|
||||||
|
|
||||||
void checkOrphans();
|
void checkOrphans();
|
||||||
void checkStatus();
|
void checkStatus();
|
||||||
void updateCache();
|
void updateCache();
|
||||||
@ -113,9 +123,16 @@ class Downloader
|
|||||||
void galaxyInstallGame(const std::string& product_id, int build_index = -1, const unsigned int& iGalaxyArch = GlobalConstants::ARCH_X64);
|
void galaxyInstallGame(const std::string& product_id, int build_index = -1, const unsigned int& iGalaxyArch = GlobalConstants::ARCH_X64);
|
||||||
void galaxyInstallGameById(const std::string& product_id, int build_index = -1, const unsigned int& iGalaxyArch = GlobalConstants::ARCH_X64);
|
void galaxyInstallGameById(const std::string& product_id, int build_index = -1, const unsigned int& iGalaxyArch = GlobalConstants::ARCH_X64);
|
||||||
void galaxyShowBuilds(const std::string& product_id, int build_index = -1);
|
void galaxyShowBuilds(const std::string& product_id, int build_index = -1);
|
||||||
|
void galaxyShowCloudSaves(const std::string& product_id, int build_index = -1);
|
||||||
|
void galaxyShowLocalCloudSaves(const std::string& product_id, int build_index = -1);
|
||||||
|
void galaxyShowLocalCloudSavesById(const std::string& product_id, int build_index = -1);
|
||||||
void galaxyShowBuildsById(const std::string& product_id, int build_index = -1);
|
void galaxyShowBuildsById(const std::string& product_id, int build_index = -1);
|
||||||
|
void galaxyShowCloudSavesById(const std::string& product_id, int build_index = -1);
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
|
std::map<std::string, std::string> cloudSaveLocations(const std::string& product_id, int build_index);
|
||||||
|
int cloudSaveListByIdForEach(const std::string& product_id, int build_index, const std::function<void(cloudSaveFile &)> &f);
|
||||||
|
|
||||||
CURLcode downloadFile(const std::string& url, const std::string& filepath, const std::string& xml_data = std::string(), const std::string& gamename = std::string());
|
CURLcode downloadFile(const std::string& url, const std::string& filepath, const std::string& xml_data = std::string(), const std::string& gamename = std::string());
|
||||||
int repairFile(const std::string& url, const std::string& filepath, const std::string& xml_data = std::string(), const std::string& gamename = std::string());
|
int repairFile(const std::string& url, const std::string& filepath, const std::string& xml_data = std::string(), const std::string& gamename = std::string());
|
||||||
int getGameDetails();
|
int getGameDetails();
|
||||||
@ -133,6 +150,8 @@ class Downloader
|
|||||||
static std::string getChangelogFromJSON(const Json::Value& json);
|
static std::string getChangelogFromJSON(const Json::Value& json);
|
||||||
void saveChangelog(const std::string& changelog, const std::string& filepath);
|
void saveChangelog(const std::string& changelog, const std::string& filepath);
|
||||||
static void processDownloadQueue(Config conf, const unsigned int& tid);
|
static void processDownloadQueue(Config conf, const unsigned int& tid);
|
||||||
|
static void processCloudSaveDownloadQueue(Config conf, const unsigned int& tid);
|
||||||
|
static void processCloudSaveUploadQueue(Config conf, const unsigned int& tid);
|
||||||
static int progressCallbackForThread(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
|
static int progressCallbackForThread(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
|
||||||
template <typename T> void printProgress(const ThreadSafeQueue<T>& download_queue);
|
template <typename T> void printProgress(const ThreadSafeQueue<T>& download_queue);
|
||||||
static void getGameDetailsThread(Config config, const unsigned int& tid);
|
static void getGameDetailsThread(Config config, const unsigned int& tid);
|
||||||
|
@ -46,16 +46,20 @@ class galaxyAPI
|
|||||||
galaxyAPI(CurlConfig& conf);
|
galaxyAPI(CurlConfig& conf);
|
||||||
virtual ~galaxyAPI();
|
virtual ~galaxyAPI();
|
||||||
int init();
|
int init();
|
||||||
|
|
||||||
bool isTokenExpired();
|
bool isTokenExpired();
|
||||||
bool refreshLogin();
|
bool refreshLogin();
|
||||||
|
bool refreshLogin(const std::string &clientId, const std::string &clientSecret, const std::string &refreshToken, bool newSession);
|
||||||
|
|
||||||
Json::Value getProductBuilds(const std::string& product_id, const std::string& platform = "windows", const std::string& generation = "2");
|
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& 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 getManifestV1(const std::string& manifest_url);
|
||||||
Json::Value getManifestV2(std::string manifest_hash, const bool& is_dependency = false);
|
Json::Value getManifestV2(std::string manifest_hash, const bool& is_dependency = false);
|
||||||
|
Json::Value getCloudPathAsJson(const std::string &clientId);
|
||||||
Json::Value getSecureLink(const std::string& product_id, const std::string& path);
|
Json::Value getSecureLink(const std::string& product_id, const std::string& path);
|
||||||
Json::Value getDependencyLink(const std::string& path);
|
Json::Value getDependencyLink(const std::string& path);
|
||||||
std::string getResponse(const std::string& url);
|
std::string getResponse(const std::string& url, const char *encoding = nullptr);
|
||||||
Json::Value getResponseJson(const std::string& url);
|
Json::Value getResponseJson(const std::string& url, const char *encoding = nullptr);
|
||||||
std::string hashToGalaxyPath(const std::string& hash);
|
std::string hashToGalaxyPath(const std::string& hash);
|
||||||
std::vector<galaxyDepotItem> getDepotItemsVector(const std::string& hash, const bool& is_dependency = false);
|
std::vector<galaxyDepotItem> getDepotItemsVector(const std::string& hash, const bool& is_dependency = false);
|
||||||
Json::Value getProductInfo(const std::string& product_id);
|
Json::Value getProductInfo(const std::string& product_id);
|
||||||
|
@ -66,6 +66,7 @@ namespace Util
|
|||||||
int createXML(std::string filepath, uintmax_t chunk_size, std::string xml_dir = std::string());
|
int createXML(std::string filepath, uintmax_t chunk_size, std::string xml_dir = std::string());
|
||||||
int getGameSpecificConfig(std::string gamename, gameSpecificConfig* conf, std::string directory = std::string());
|
int getGameSpecificConfig(std::string gamename, gameSpecificConfig* conf, std::string directory = std::string());
|
||||||
int replaceString(std::string& str, const std::string& to_replace, const std::string& replace_with);
|
int replaceString(std::string& str, const std::string& to_replace, const std::string& replace_with);
|
||||||
|
int replaceAllString(std::string& str, const std::string& to_replace, const std::string& replace_with);
|
||||||
void filepathReplaceReservedStrings(std::string& str, const std::string& gamename, const unsigned int& platformId = 0, const std::string& dlcname = "");
|
void filepathReplaceReservedStrings(std::string& str, const std::string& gamename, const unsigned int& platformId = 0, const std::string& dlcname = "");
|
||||||
void setFilePermissions(const boost::filesystem::path& path, const boost::filesystem::perms& permissions);
|
void setFilePermissions(const boost::filesystem::path& path, const boost::filesystem::perms& permissions);
|
||||||
int getTerminalWidth();
|
int getTerminalWidth();
|
||||||
@ -90,6 +91,7 @@ namespace Util
|
|||||||
CURLcode CurlHandleGetResponse(CURL* curlhandle, std::string& response, int max_retries = -1);
|
CURLcode CurlHandleGetResponse(CURL* curlhandle, std::string& response, int max_retries = -1);
|
||||||
curl_off_t CurlWriteMemoryCallback(char *ptr, curl_off_t size, curl_off_t nmemb, void *userp);
|
curl_off_t CurlWriteMemoryCallback(char *ptr, curl_off_t size, curl_off_t nmemb, void *userp);
|
||||||
curl_off_t CurlWriteChunkMemoryCallback(void *contents, curl_off_t size, curl_off_t nmemb, void *userp);
|
curl_off_t CurlWriteChunkMemoryCallback(void *contents, curl_off_t size, curl_off_t nmemb, void *userp);
|
||||||
|
curl_off_t CurlReadChunkMemoryCallback(void *contents, curl_off_t size, curl_off_t nmemb, ChunkMemoryStruct *userp);
|
||||||
|
|
||||||
template<typename ... Args> std::string formattedString(const std::string& format, Args ... args)
|
template<typename ... Args> std::string formattedString(const std::string& format, Args ... args)
|
||||||
{
|
{
|
||||||
|
91
main.cpp
91
main.cpp
@ -24,6 +24,18 @@ template<typename T> void set_vm_value(std::map<std::string, bpo::variable_value
|
|||||||
vm[option].value() = boost::any(value);
|
vm[option].value() = boost::any(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ensure_trailing_slash(std::string &path, const char *default_ = nullptr) {
|
||||||
|
if (!path.empty())
|
||||||
|
{
|
||||||
|
if (path.at(path.length()-1)!='/')
|
||||||
|
path += "/";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path = default_; // Directory wasn't specified, use current directory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
@ -151,6 +163,11 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
std::string galaxy_product_id_install;
|
std::string galaxy_product_id_install;
|
||||||
std::string galaxy_product_id_show_builds;
|
std::string galaxy_product_id_show_builds;
|
||||||
|
std::string galaxy_product_id_show_cloud_paths;
|
||||||
|
std::string galaxy_product_id_show_local_cloud_paths;
|
||||||
|
std::string galaxy_product_cloud_saves;
|
||||||
|
std::string galaxy_product_cloud_saves_delete;
|
||||||
|
std::string galaxy_upload_product_cloud_saves;
|
||||||
std::string tags;
|
std::string tags;
|
||||||
|
|
||||||
std::vector<std::string> vFileIdStrings;
|
std::vector<std::string> vFileIdStrings;
|
||||||
@ -213,6 +230,11 @@ int main(int argc, char *argv[])
|
|||||||
("cacert", bpo::value<std::string>(&Globals::globalConfig.curlConf.sCACertPath)->default_value(""), "Path to CA certificate bundle in PEM format")
|
("cacert", bpo::value<std::string>(&Globals::globalConfig.curlConf.sCACertPath)->default_value(""), "Path to CA certificate bundle in PEM format")
|
||||||
("respect-umask", bpo::value<bool>(&Globals::globalConfig.bRespectUmask)->zero_tokens()->default_value(false), "Do not adjust permissions of sensitive files")
|
("respect-umask", bpo::value<bool>(&Globals::globalConfig.bRespectUmask)->zero_tokens()->default_value(false), "Do not adjust permissions of sensitive files")
|
||||||
("user-agent", bpo::value<std::string>(&Globals::globalConfig.curlConf.sUserAgent)->default_value(DEFAULT_USER_AGENT), "Set user agent")
|
("user-agent", bpo::value<std::string>(&Globals::globalConfig.curlConf.sUserAgent)->default_value(DEFAULT_USER_AGENT), "Set user agent")
|
||||||
|
|
||||||
|
("wine-prefix", bpo::value<std::string>(&Globals::globalConfig.dirConf.sWinePrefix)->default_value("."), "Set wineprefix directory")
|
||||||
|
("cloud-whitelist", bpo::value<std::vector<std::string>>(&Globals::globalConfig.cloudWhiteList)->multitoken(), "Include this list of cloud saves, by default all cloud saves are included\n Example: --cloud-whitelist saves/AutoSave-0 saves/AutoSave-1/screenshot.png")
|
||||||
|
("cloud-blacklist", bpo::value<std::vector<std::string>>(&Globals::globalConfig.cloudBlackList)->multitoken(), "Exclude this list of cloud saves\n Example: --cloud-blacklist saves/AutoSave-0 saves/AutoSave-1/screenshot.png")
|
||||||
|
("cloud-force", bpo::value<bool>(&Globals::globalConfig.bCloudForce)->zero_tokens()->default_value(false), "Download or Upload cloud saves even if they're up-to-date\nDelete remote cloud saves even if no saves are whitelisted")
|
||||||
#ifdef USE_QT_GUI_LOGIN
|
#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")
|
("enable-login-gui", bpo::value<bool>(&Globals::globalConfig.bEnableLoginGUI)->zero_tokens()->default_value(false), "Enable login GUI when encountering reCAPTCHA on login form")
|
||||||
#endif
|
#endif
|
||||||
@ -271,6 +293,11 @@ int main(int argc, char *argv[])
|
|||||||
options_cli_experimental.add_options()
|
options_cli_experimental.add_options()
|
||||||
("galaxy-install", bpo::value<std::string>(&galaxy_product_id_install)->default_value(""), "Install game using product id [product_id/build_index] or gamename regex [gamename/build_id]\nBuild index is used to select a build and defaults to 0 if not specified.\n\nExample: 12345/2 selects build 2 for product 12345")
|
("galaxy-install", bpo::value<std::string>(&galaxy_product_id_install)->default_value(""), "Install game using product id [product_id/build_index] or gamename regex [gamename/build_id]\nBuild index is used to select a build and defaults to 0 if not specified.\n\nExample: 12345/2 selects build 2 for product 12345")
|
||||||
("galaxy-show-builds", bpo::value<std::string>(&galaxy_product_id_show_builds)->default_value(""), "Show game builds using product id [product_id/build_index] or gamename regex [gamename/build_id]\nBuild index is used to select a build and defaults to 0 if not specified.\n\nExample: 12345/2 selects build 2 for product 12345")
|
("galaxy-show-builds", bpo::value<std::string>(&galaxy_product_id_show_builds)->default_value(""), "Show game builds using product id [product_id/build_index] or gamename regex [gamename/build_id]\nBuild index is used to select a build and defaults to 0 if not specified.\n\nExample: 12345/2 selects build 2 for product 12345")
|
||||||
|
("galaxy-download-cloud-saves", bpo::value<std::string>(&galaxy_product_cloud_saves)->default_value(""), "Download cloud saves using product-id [product_id/build_index] or gamename regex [gamename/build_id]\nBuild index is used to select a build and defaults to 0 if not specified.\n\nExample: 12345/2 selects build 2 for product 12345")
|
||||||
|
("galaxy-upload-cloud-saves", bpo::value<std::string>(&galaxy_upload_product_cloud_saves)->default_value(""), "Upload cloud saves using product-id [product_id/build_index] or gamename regex [gamename/build_id]\nBuild index is used to select a build and defaults to 0 if not specified.\n\nExample: 12345/2 selects build 2 for product 12345")
|
||||||
|
("galaxy-show-cloud-saves", bpo::value<std::string>(&galaxy_product_id_show_cloud_paths)->default_value(""), "Show game cloud-saves using product id [product_id/build_index] or gamename regex [gamename/build_id]\nBuild index is used to select a build and defaults to 0 if not specified.\n\nExample: 12345/2 selects build 2 for product 12345")
|
||||||
|
("galaxy-show-local-cloud-saves", bpo::value<std::string>(&galaxy_product_id_show_local_cloud_paths)->default_value(""), "Show local cloud-saves using product id [product_id/build_index] or gamename regex [gamename/build_id]\nBuild index is used to select a build and defaults to 0 if not specified.\n\nExample: 12345/2 selects build 2 for product 12345")
|
||||||
|
("galaxy-delete-cloud-saves", bpo::value<std::string>(&galaxy_product_cloud_saves_delete)->default_value(""), "Delete cloud-saves using product id [product_id/build_index] or gamename regex [gamename/build_id]\nBuild index is used to select a build and defaults to 0 if not specified.\n\nExample: 12345/2 selects build 2 for product 12345")
|
||||||
("galaxy-platform", bpo::value<std::string>(&sGalaxyPlatform)->default_value("w"), galaxy_platform_text.c_str())
|
("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-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-arch", bpo::value<std::string>(&sGalaxyArch)->default_value("x64"), galaxy_arch_text.c_str())
|
||||||
@ -578,15 +605,8 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that directory has trailing slash
|
// Make sure that directory has trailing slash
|
||||||
if (!Globals::globalConfig.dirConf.sDirectory.empty())
|
ensure_trailing_slash(Globals::globalConfig.dirConf.sDirectory, "./");
|
||||||
{
|
ensure_trailing_slash(Globals::globalConfig.dirConf.sWinePrefix, "./");
|
||||||
if (Globals::globalConfig.dirConf.sDirectory.at(Globals::globalConfig.dirConf.sDirectory.length()-1)!='/')
|
|
||||||
Globals::globalConfig.dirConf.sDirectory += "/";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Globals::globalConfig.dirConf.sDirectory = "./"; // Directory wasn't specified, use current directory
|
|
||||||
}
|
|
||||||
|
|
||||||
// CA certificate bundle
|
// CA certificate bundle
|
||||||
if (Globals::globalConfig.curlConf.sCACertPath.empty())
|
if (Globals::globalConfig.curlConf.sCACertPath.empty())
|
||||||
@ -777,6 +797,39 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
downloader.galaxyShowBuilds(product_id, build_index);
|
downloader.galaxyShowBuilds(product_id, build_index);
|
||||||
}
|
}
|
||||||
|
else if (!galaxy_product_id_show_cloud_paths.empty())
|
||||||
|
{
|
||||||
|
int build_index = -1;
|
||||||
|
std::vector<std::string> tokens = Util::tokenize(galaxy_product_id_show_cloud_paths, "/");
|
||||||
|
std::string product_id = tokens[0];
|
||||||
|
if (tokens.size() == 2)
|
||||||
|
{
|
||||||
|
build_index = std::stoi(tokens[1]);
|
||||||
|
}
|
||||||
|
downloader.galaxyShowCloudSaves(product_id, build_index);
|
||||||
|
}
|
||||||
|
else if (!galaxy_product_id_show_local_cloud_paths.empty())
|
||||||
|
{
|
||||||
|
int build_index = -1;
|
||||||
|
std::vector<std::string> tokens = Util::tokenize(galaxy_product_id_show_local_cloud_paths, "/");
|
||||||
|
std::string product_id = tokens[0];
|
||||||
|
if (tokens.size() == 2)
|
||||||
|
{
|
||||||
|
build_index = std::stoi(tokens[1]);
|
||||||
|
}
|
||||||
|
downloader.galaxyShowLocalCloudSaves(product_id, build_index);
|
||||||
|
}
|
||||||
|
else if (!galaxy_product_cloud_saves_delete.empty())
|
||||||
|
{
|
||||||
|
int build_index = -1;
|
||||||
|
std::vector<std::string> tokens = Util::tokenize(galaxy_product_cloud_saves_delete, "/");
|
||||||
|
std::string product_id = tokens[0];
|
||||||
|
if (tokens.size() == 2)
|
||||||
|
{
|
||||||
|
build_index = std::stoi(tokens[1]);
|
||||||
|
}
|
||||||
|
downloader.deleteCloudSaves(product_id, build_index);
|
||||||
|
}
|
||||||
else if (!galaxy_product_id_install.empty())
|
else if (!galaxy_product_id_install.empty())
|
||||||
{
|
{
|
||||||
int build_index = -1;
|
int build_index = -1;
|
||||||
@ -788,6 +841,26 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
downloader.galaxyInstallGame(product_id, build_index, Globals::globalConfig.dlConf.iGalaxyArch);
|
downloader.galaxyInstallGame(product_id, build_index, Globals::globalConfig.dlConf.iGalaxyArch);
|
||||||
}
|
}
|
||||||
|
else if (!galaxy_product_cloud_saves.empty()) {
|
||||||
|
int build_index = -1;
|
||||||
|
std::vector<std::string> tokens = Util::tokenize(galaxy_product_cloud_saves, "/");
|
||||||
|
std::string product_id = tokens[0];
|
||||||
|
if (tokens.size() == 2)
|
||||||
|
{
|
||||||
|
build_index = std::stoi(tokens[1]);
|
||||||
|
}
|
||||||
|
downloader.downloadCloudSaves(product_id, build_index);
|
||||||
|
}
|
||||||
|
else if (!galaxy_upload_product_cloud_saves.empty()) {
|
||||||
|
int build_index = -1;
|
||||||
|
std::vector<std::string> tokens = Util::tokenize(galaxy_upload_product_cloud_saves, "/");
|
||||||
|
std::string product_id = tokens[0];
|
||||||
|
if (tokens.size() == 2)
|
||||||
|
{
|
||||||
|
build_index = std::stoi(tokens[1]);
|
||||||
|
}
|
||||||
|
downloader.uploadCloudSaves(product_id, build_index);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!Globals::globalConfig.bLogin)
|
if (!Globals::globalConfig.bLogin)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -53,23 +53,33 @@ int galaxyAPI::init()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool galaxyAPI::refreshLogin()
|
bool galaxyAPI::refreshLogin(const std::string &clientId, const std::string &clientSecret, const std::string &refreshToken, bool newSession)
|
||||||
{
|
{
|
||||||
std::string refresh_url = "https://auth.gog.com/token?client_id=" + Globals::galaxyConf.getClientId()
|
std::string refresh_url = "https://auth.gog.com/token?client_id=" + clientId
|
||||||
+ "&client_secret=" + Globals::galaxyConf.getClientSecret()
|
+ "&client_secret=" + clientSecret
|
||||||
+ "&grant_type=refresh_token"
|
+ "&grant_type=refresh_token"
|
||||||
+ "&refresh_token=" + Globals::galaxyConf.getRefreshToken();
|
+ "&refresh_token=" + refreshToken
|
||||||
|
+ (newSession ? "" : "&without_new_session=1");
|
||||||
|
|
||||||
|
// std::cout << refresh_url << std::endl;
|
||||||
Json::Value token_json = this->getResponseJson(refresh_url);
|
Json::Value token_json = this->getResponseJson(refresh_url);
|
||||||
|
|
||||||
if (token_json.empty())
|
if (token_json.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
token_json["client_id"] = clientId;
|
||||||
|
token_json["client_secret"] = clientSecret;
|
||||||
|
|
||||||
Globals::galaxyConf.setJSON(token_json);
|
Globals::galaxyConf.setJSON(token_json);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool galaxyAPI::refreshLogin()
|
||||||
|
{
|
||||||
|
return refreshLogin(Globals::galaxyConf.getClientId(), Globals::galaxyConf.getClientSecret(), Globals::galaxyConf.getRefreshToken(), true);
|
||||||
|
}
|
||||||
|
|
||||||
bool galaxyAPI::isTokenExpired()
|
bool galaxyAPI::isTokenExpired()
|
||||||
{
|
{
|
||||||
bool res = false;
|
bool res = false;
|
||||||
@ -80,7 +90,7 @@ bool galaxyAPI::isTokenExpired()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string galaxyAPI::getResponse(const std::string& url)
|
std::string galaxyAPI::getResponse(const std::string& url, const char *encoding)
|
||||||
{
|
{
|
||||||
struct curl_slist *header = NULL;
|
struct curl_slist *header = NULL;
|
||||||
|
|
||||||
@ -92,13 +102,26 @@ std::string galaxyAPI::getResponse(const std::string& url)
|
|||||||
std::string bearer = "Authorization: Bearer " + access_token;
|
std::string bearer = "Authorization: Bearer " + access_token;
|
||||||
header = curl_slist_append(header, bearer.c_str());
|
header = curl_slist_append(header, bearer.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(encoding) {
|
||||||
|
auto accept = "Accept: " + std::string(encoding);
|
||||||
|
header = curl_slist_append(header, accept.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_HTTPHEADER, header);
|
curl_easy_setopt(curlhandle, CURLOPT_HTTPHEADER, header);
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_URL, url.c_str());
|
curl_easy_setopt(curlhandle, CURLOPT_URL, url.c_str());
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_ACCEPT_ENCODING, "");
|
curl_easy_setopt(curlhandle, CURLOPT_ACCEPT_ENCODING, "");
|
||||||
|
|
||||||
int max_retries = std::min(3, Globals::globalConfig.iRetries);
|
int max_retries = std::min(3, Globals::globalConfig.iRetries);
|
||||||
std::string response;
|
std::string response;
|
||||||
Util::CurlHandleGetResponse(curlhandle, response, max_retries);
|
auto res = Util::CurlHandleGetResponse(curlhandle, response, max_retries);
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
long int response_code = 0;
|
||||||
|
curl_easy_getinfo(curlhandle, CURLINFO_RESPONSE_CODE, &response_code);
|
||||||
|
|
||||||
|
std::cout << "Response code for " << url << " is [" << response_code << ']' << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_ACCEPT_ENCODING, NULL);
|
curl_easy_setopt(curlhandle, CURLOPT_ACCEPT_ENCODING, NULL);
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_HTTPHEADER, NULL);
|
curl_easy_setopt(curlhandle, CURLOPT_HTTPHEADER, NULL);
|
||||||
@ -107,9 +130,9 @@ std::string galaxyAPI::getResponse(const std::string& url)
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value galaxyAPI::getResponseJson(const std::string& url)
|
Json::Value galaxyAPI::getResponseJson(const std::string& url, const char *encoding)
|
||||||
{
|
{
|
||||||
std::istringstream response(this->getResponse(url));
|
std::istringstream response(this->getResponse(url, encoding));
|
||||||
Json::Value json;
|
Json::Value json;
|
||||||
|
|
||||||
if (!response.str().empty())
|
if (!response.str().empty())
|
||||||
@ -149,8 +172,13 @@ Json::Value galaxyAPI::getResponseJson(const std::string& url)
|
|||||||
catch(const Json::Exception& exc)
|
catch(const Json::Exception& exc)
|
||||||
{
|
{
|
||||||
// Failed to parse json
|
// Failed to parse json
|
||||||
|
|
||||||
|
std::cout << "Failed to parse json: " << exc.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
std::cout << "Failed to parse json: " << exc.what();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +218,12 @@ Json::Value galaxyAPI::getManifestV2(std::string manifest_hash, const bool& is_d
|
|||||||
return this->getResponseJson(url);
|
return this->getResponseJson(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json::Value galaxyAPI::getCloudPathAsJson(const std::string &clientId) {
|
||||||
|
std::string url = "https://remote-config.gog.com/components/galaxy_client/clients/" + clientId + "?component_version=2.0.51";
|
||||||
|
|
||||||
|
return this->getResponseJson(url);
|
||||||
|
}
|
||||||
|
|
||||||
Json::Value galaxyAPI::getSecureLink(const std::string& product_id, const std::string& path)
|
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::string url = "https://content-system.gog.com/products/" + product_id + "/secure_link?generation=2&path=" + path + "&_version=2";
|
||||||
|
34
src/util.cpp
34
src/util.cpp
@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/algorithm/string/case_conv.hpp>
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
|
#include <boost/iostreams/filter/gzip.hpp>
|
||||||
|
#include <boost/iostreams/filtering_streambuf.hpp>
|
||||||
|
#include <boost/iostreams/copy.hpp>
|
||||||
#include <tinyxml2.h>
|
#include <tinyxml2.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -391,6 +394,22 @@ int Util::replaceString(std::string& str, const std::string& to_replace, const s
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Util::replaceAllString(std::string& str, const std::string& to_replace, const std::string& replace_with) {
|
||||||
|
size_t pos = str.find(to_replace);
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
str.replace(str.begin()+pos, str.begin()+pos+to_replace.length(), replace_with);
|
||||||
|
|
||||||
|
pos = str.find(to_replace, pos + to_replace.length());
|
||||||
|
} while(pos != std::string::npos);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void Util::filepathReplaceReservedStrings(std::string& str, const std::string& gamename, const unsigned int& platformId, const std::string& dlcname)
|
void Util::filepathReplaceReservedStrings(std::string& str, const std::string& gamename, const unsigned int& platformId, const std::string& dlcname)
|
||||||
{
|
{
|
||||||
std::string platform;
|
std::string platform;
|
||||||
@ -749,7 +768,6 @@ void Util::CurlHandleSetDefaultOptions(CURL* curlhandle, const CurlConfig& conf)
|
|||||||
curl_easy_setopt(curlhandle, CURLOPT_USERAGENT, conf.sUserAgent.c_str());
|
curl_easy_setopt(curlhandle, CURLOPT_USERAGENT, conf.sUserAgent.c_str());
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_FOLLOWLOCATION, 1);
|
curl_easy_setopt(curlhandle, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1);
|
curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1);
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_FAILONERROR, true);
|
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_NOSIGNAL, 1);
|
curl_easy_setopt(curlhandle, CURLOPT_NOSIGNAL, 1);
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, conf.iTimeout);
|
curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, conf.iTimeout);
|
||||||
curl_easy_setopt(curlhandle, CURLOPT_FAILONERROR, true);
|
curl_easy_setopt(curlhandle, CURLOPT_FAILONERROR, true);
|
||||||
@ -823,8 +841,9 @@ CURLcode Util::CurlHandleGetResponse(CURL* curlhandle, std::string& response, in
|
|||||||
// Retry on CURLE_HTTP_RETURNED_ERROR if response code is not "404 Not Found"
|
// Retry on CURLE_HTTP_RETURNED_ERROR if response code is not "404 Not Found"
|
||||||
case CURLE_HTTP_RETURNED_ERROR:
|
case CURLE_HTTP_RETURNED_ERROR:
|
||||||
curl_easy_getinfo(curlhandle, CURLINFO_RESPONSE_CODE, &response_code);
|
curl_easy_getinfo(curlhandle, CURLINFO_RESPONSE_CODE, &response_code);
|
||||||
if (response_code == 404)
|
if (response_code == 404 || response_code == 403) {
|
||||||
bShouldRetry = false;
|
bShouldRetry = false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
bShouldRetry = true;
|
bShouldRetry = true;
|
||||||
break;
|
break;
|
||||||
@ -865,3 +884,14 @@ curl_off_t Util::CurlWriteChunkMemoryCallback(void *contents, curl_off_t size, c
|
|||||||
|
|
||||||
return realsize;
|
return realsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curl_off_t Util::CurlReadChunkMemoryCallback(void *contents, curl_off_t size, curl_off_t nmemb, ChunkMemoryStruct *mem) {
|
||||||
|
curl_off_t realsize = std::min(size * nmemb, mem->size);
|
||||||
|
|
||||||
|
std::copy(mem->memory, mem->memory + realsize, (char*)contents);
|
||||||
|
|
||||||
|
mem->size -= realsize;
|
||||||
|
mem->memory += realsize;
|
||||||
|
|
||||||
|
return realsize;
|
||||||
|
}
|
||||||
|
@ -264,6 +264,9 @@ std::vector<gameItem> Website::getGames()
|
|||||||
// Login to GOG website
|
// Login to GOG website
|
||||||
int Website::Login(const std::string& email, const std::string& password)
|
int Website::Login(const std::string& email, const std::string& password)
|
||||||
{
|
{
|
||||||
|
// Reset client id and client secret to ensure we can log-in
|
||||||
|
Globals::galaxyConf.resetClient();
|
||||||
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
std::string postdata;
|
std::string postdata;
|
||||||
std::ostringstream memory;
|
std::ostringstream memory;
|
||||||
|
Loading…
Reference in New Issue
Block a user