mirror of
https://github.com/Sude-/lgogdownloader.git
synced 2024-11-20 11:49:17 +01:00
Merge branch 'master' of https://github.com/kilobug42/lgogdownloader
This commit is contained in:
commit
bddde5b0da
@ -63,6 +63,11 @@ class Config
|
|||||||
std::string sLanguagePackSubdir;
|
std::string sLanguagePackSubdir;
|
||||||
std::string sDLCSubdir;
|
std::string sDLCSubdir;
|
||||||
std::string sGameSubdir;
|
std::string sGameSubdir;
|
||||||
|
std::string sLanguagePriority;
|
||||||
|
std::string sPlatformPriority;
|
||||||
|
std::vector<unsigned int> vLanguagePriority;
|
||||||
|
std::vector<unsigned int> vPlatformPriority;
|
||||||
|
|
||||||
unsigned int iInstallerType;
|
unsigned int iInstallerType;
|
||||||
unsigned int iInstallerLanguage;
|
unsigned int iInstallerLanguage;
|
||||||
int iRetries;
|
int iRetries;
|
||||||
|
@ -21,10 +21,12 @@ class gameDetails
|
|||||||
std::string gamename;
|
std::string gamename;
|
||||||
std::string title;
|
std::string title;
|
||||||
std::string icon;;
|
std::string icon;;
|
||||||
|
void filterWithPriorities(const Config& config);
|
||||||
void makeFilepaths(const Config& config);
|
void makeFilepaths(const Config& config);
|
||||||
Json::Value getDetailsAsJson();
|
Json::Value getDetailsAsJson();
|
||||||
virtual ~gameDetails();
|
virtual ~gameDetails();
|
||||||
protected:
|
protected:
|
||||||
|
void filterListWithPriorities(std::vector<gameFile>& list, const Config& config);
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ class gameFile
|
|||||||
std::string size;
|
std::string size;
|
||||||
unsigned int platform;
|
unsigned int platform;
|
||||||
unsigned int language;
|
unsigned int language;
|
||||||
|
int score;
|
||||||
int silent;
|
int silent;
|
||||||
void setFilepath(const std::string& path);
|
void setFilepath(const std::string& path);
|
||||||
std::string getFilepath();
|
std::string getFilepath();
|
||||||
|
46
main.cpp
46
main.cpp
@ -26,6 +26,40 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse the priority string, making it an array of numeric codes, and override the ORed type if required
|
||||||
|
void handle_priority(const std::string &what, const std::string &priority_string, std::vector<unsigned int> &priority, unsigned int &type)
|
||||||
|
{
|
||||||
|
size_t idx = 0, found;
|
||||||
|
|
||||||
|
while ((found = priority_string.find(',', idx)) != std::string::npos)
|
||||||
|
{
|
||||||
|
priority.push_back(std::stoi(priority_string.substr(idx, found - idx)));
|
||||||
|
idx = found + 1;
|
||||||
|
}
|
||||||
|
priority.push_back(std::stoi(priority_string.substr(idx)));
|
||||||
|
|
||||||
|
unsigned int wanted = 0;
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "DEBUG INFO (handle_priority): for " << what << " found ";
|
||||||
|
#endif
|
||||||
|
for (std::vector<unsigned int>::iterator it = priority.begin(); it != priority.end(); it++)
|
||||||
|
{
|
||||||
|
wanted += *it;
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << *it << " ";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (wanted != type)
|
||||||
|
{
|
||||||
|
type = wanted;
|
||||||
|
std::cout << "Warning: for " << what << " the priority string doesn't match the enabled installers, forcing enabled installers to " << type << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
Config config;
|
Config config;
|
||||||
@ -68,6 +102,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// Help text for subdir options
|
// Help text for subdir options
|
||||||
std::string subdir_help_text = "\nTemplates:\n- %platform%\n- %gamename%\n- %dlcname%";
|
std::string subdir_help_text = "\nTemplates:\n- %platform%\n- %gamename%\n- %dlcname%";
|
||||||
|
// Help text for priority options
|
||||||
|
std::string priority_help_text = "\nIf set, only the first matching one will be downloaded. If unset, all matching combinations will be downloaded.\nSyntax: use a string separated by \",\"";
|
||||||
|
|
||||||
std::vector<std::string> unrecognized_options_cfg;
|
std::vector<std::string> unrecognized_options_cfg;
|
||||||
bpo::variables_map vm;
|
bpo::variables_map vm;
|
||||||
@ -148,6 +184,9 @@ int main(int argc, char *argv[])
|
|||||||
("subdir-game", bpo::value<std::string>(&config.sGameSubdir)->default_value("%gamename%"), ("Set subdirectory for game" + subdir_help_text).c_str())
|
("subdir-game", bpo::value<std::string>(&config.sGameSubdir)->default_value("%gamename%"), ("Set subdirectory for game" + subdir_help_text).c_str())
|
||||||
("use-cache", bpo::value<bool>(&config.bUseCache)->zero_tokens()->default_value(false), ("Use game details cache"))
|
("use-cache", bpo::value<bool>(&config.bUseCache)->zero_tokens()->default_value(false), ("Use game details cache"))
|
||||||
("cache-valid", bpo::value<int>(&config.iCacheValid)->default_value(2880), ("Set how long cached game details are valid (in minutes)\nDefault: 2880 minutes (48 hours)"))
|
("cache-valid", bpo::value<int>(&config.iCacheValid)->default_value(2880), ("Set how long cached game details are valid (in minutes)\nDefault: 2880 minutes (48 hours)"))
|
||||||
|
("language-priority", bpo::value<std::string>(&config.sLanguagePriority)->default_value(""), ("Set priority of systems" + priority_help_text + ", like \"4,1\" for French first, then English if no French version").c_str())
|
||||||
|
("platform-priority", bpo::value<std::string>(&config.sPlatformPriority)->default_value(""), ("Set priority of platforms" + priority_help_text + ", like \"4,1\" for Linux first, then Windows if no Linux version").c_str())
|
||||||
|
|
||||||
;
|
;
|
||||||
// Options read from config file
|
// Options read from config file
|
||||||
options_cfg_only.add_options()
|
options_cfg_only.add_options()
|
||||||
@ -300,6 +339,13 @@ int main(int argc, char *argv[])
|
|||||||
// Override cover option
|
// Override cover option
|
||||||
if (bNoCover)
|
if (bNoCover)
|
||||||
config.bCover = false;
|
config.bCover = false;
|
||||||
|
|
||||||
|
// Handle priority business
|
||||||
|
if (!config.sLanguagePriority.empty())
|
||||||
|
handle_priority("languages", config.sLanguagePriority, config.vLanguagePriority, config.iInstallerLanguage);
|
||||||
|
if (!config.sPlatformPriority.empty())
|
||||||
|
handle_priority("platforms", config.sPlatformPriority, config.vPlatformPriority, config.iInstallerType);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -83,5 +83,16 @@ Must be in the following format:
|
|||||||
.br
|
.br
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[priorities]
|
||||||
|
For both languages and platforms, the default behavior is to download all enabled ones.
|
||||||
|
The \fBlanguage-priority\fB and \fBplatform-priority\fB switches enable a priority-based mode: only the first matching one will be downloaded.
|
||||||
|
.PP
|
||||||
|
For example, setting \fBlanguage\fB to 5 means both French and English will be downloaded (if available) for all games. Setting \fBlanguage-priority\fB to 4,1 means that the French version (and only that one) will be downloaded if available, and if not, the English version will be downloaded.
|
||||||
|
.PP
|
||||||
|
You're allowed to "stack" codes in the priority string if needed. If you set \fBlanguage-priority\fB 132,1 it means it'll download both Spanish (128) and French (4) versions if they are available, and the English (1) one only if none of French and Spanish are available.
|
||||||
|
.PP
|
||||||
|
Ideally the \fBlanguage\fB and \fBplatform\fB settings should match the sum of all enabled codes in the "priority" versions. If they don't, they'll be overrided with a warning.
|
||||||
|
|
||||||
[availability]
|
[availability]
|
||||||
The latest version of this distribution is available from \fIhttps://github.com/Sude-/lgogdownloader\fP
|
The latest version of this distribution is available from \fIhttps://github.com/Sude-/lgogdownloader\fP
|
||||||
|
|
||||||
|
@ -518,9 +518,9 @@ gameDetails API::getGameDetails(const std::string& game_name, const unsigned int
|
|||||||
|
|
||||||
if (!langpacknames.empty()) // found at least one language pack
|
if (!langpacknames.empty()) // found at least one language pack
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < langpacknames.size(); ++i)
|
for (unsigned int j = 0; j < langpacknames.size(); ++j)
|
||||||
{
|
{
|
||||||
Json::Value langpack = root["game"][langpacknames[i]];
|
Json::Value langpack = root["game"][langpacknames[j]];
|
||||||
game.languagepacks.push_back(
|
game.languagepacks.push_back(
|
||||||
gameFile( false, /* language packs don't have "updated" flag */
|
gameFile( false, /* language packs don't have "updated" flag */
|
||||||
langpack["id"].isInt() ? std::to_string(langpack["id"].asInt()) : langpack["id"].asString(),
|
langpack["id"].isInt() ? std::to_string(langpack["id"].asInt()) : langpack["id"].asString(),
|
||||||
|
@ -252,6 +252,8 @@ int Downloader::getGameDetails()
|
|||||||
game = gogAPI->getGameDetails(gameItems[i].name, conf.iInstallerType, conf.iInstallerLanguage, config.bDuplicateHandler);
|
game = gogAPI->getGameDetails(gameItems[i].name, conf.iInstallerType, conf.iInstallerLanguage, config.bDuplicateHandler);
|
||||||
if (!gogAPI->getError())
|
if (!gogAPI->getError())
|
||||||
{
|
{
|
||||||
|
game.filterWithPriorities(config);
|
||||||
|
|
||||||
if (game.extras.empty() && config.bExtras) // Try to get extras from account page if API didn't return any extras
|
if (game.extras.empty() && config.bExtras) // Try to get extras from account page if API didn't return any extras
|
||||||
{
|
{
|
||||||
game.extras = this->getExtras(gameItems[i].name, gameItems[i].id);
|
game.extras = this->getExtras(gameItems[i].name, gameItems[i].id);
|
||||||
@ -262,6 +264,7 @@ int Downloader::getGameDetails()
|
|||||||
{
|
{
|
||||||
gameDetails dlc;
|
gameDetails dlc;
|
||||||
dlc = gogAPI->getGameDetails(gameItems[i].dlcnames[j], conf.iInstallerType, conf.iInstallerLanguage, config.bDuplicateHandler);
|
dlc = gogAPI->getGameDetails(gameItems[i].dlcnames[j], conf.iInstallerType, conf.iInstallerLanguage, config.bDuplicateHandler);
|
||||||
|
dlc.filterWithPriorities(config);
|
||||||
if (dlc.extras.empty() && config.bExtras) // Try to get extras from account page if API didn't return any extras
|
if (dlc.extras.empty() && config.bExtras) // Try to get extras from account page if API didn't return any extras
|
||||||
{
|
{
|
||||||
dlc.extras = this->getExtras(gameItems[i].dlcnames[j], gameItems[i].id);
|
dlc.extras = this->getExtras(gameItems[i].dlcnames[j], gameItems[i].id);
|
||||||
@ -2817,7 +2820,10 @@ std::vector<gameDetails> Downloader::getGameDetailsFromJsonNode(Json::Value root
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!game.extras.empty() || !game.installers.empty() || !game.patches.empty() || !game.languagepacks.empty() || !game.dlcs.empty())
|
if (!game.extras.empty() || !game.installers.empty() || !game.patches.empty() || !game.languagepacks.empty() || !game.dlcs.empty())
|
||||||
details.push_back(game);
|
{
|
||||||
|
game.filterWithPriorities(config);
|
||||||
|
details.push_back(game);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
@ -2840,6 +2846,8 @@ void Downloader::updateCache()
|
|||||||
config.sGameRegex = ".*";
|
config.sGameRegex = ".*";
|
||||||
config.iInstallerLanguage = all_languages;
|
config.iInstallerLanguage = all_languages;
|
||||||
config.iInstallerType = all_platforms;
|
config.iInstallerType = all_platforms;
|
||||||
|
config.vLanguagePriority.clear();
|
||||||
|
config.vPlatformPriority.clear();
|
||||||
|
|
||||||
this->getGameList();
|
this->getGameList();
|
||||||
this->getGameDetails();
|
this->getGameDetails();
|
||||||
|
@ -11,6 +11,61 @@ gameDetails::~gameDetails()
|
|||||||
//dtor
|
//dtor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gameDetails::filterWithPriorities(const Config& config)
|
||||||
|
{
|
||||||
|
if (config.vPlatformPriority.empty() && config.vLanguagePriority.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
filterListWithPriorities(installers, config);
|
||||||
|
filterListWithPriorities(patches, config);
|
||||||
|
filterListWithPriorities(languagepacks, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gameDetails::filterListWithPriorities(std::vector<gameFile>& list, const Config& config)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Compute the score of each item - we use a scoring mechanism and we keep all ties
|
||||||
|
Like if someone asked French then English and Linux then Windows, but there are
|
||||||
|
only Windows French, Windows English and Linux English versions, we'll get the
|
||||||
|
Windows French and Linux English ones.
|
||||||
|
Score is inverted: lower is better.
|
||||||
|
*/
|
||||||
|
int bestscore = -1;
|
||||||
|
|
||||||
|
for (std::vector<gameFile>::iterator fileDetails = list.begin(); fileDetails != list.end(); fileDetails++)
|
||||||
|
{
|
||||||
|
fileDetails->score = 0;
|
||||||
|
if (!config.vPlatformPriority.empty())
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i != config.vPlatformPriority.size(); i++)
|
||||||
|
if (fileDetails->platform & config.vPlatformPriority[i])
|
||||||
|
{
|
||||||
|
fileDetails->score += i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!config.vLanguagePriority.empty())
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i != config.vLanguagePriority.size(); i++)
|
||||||
|
if (fileDetails->language & config.vLanguagePriority[i])
|
||||||
|
{
|
||||||
|
fileDetails->score += i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((fileDetails->score < bestscore) or (bestscore < 0))
|
||||||
|
bestscore = fileDetails->score;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<gameFile>::iterator fileDetails = list.begin(); fileDetails != list.end(); )
|
||||||
|
{
|
||||||
|
if (fileDetails->score > bestscore)
|
||||||
|
fileDetails = list.erase(fileDetails);
|
||||||
|
else
|
||||||
|
fileDetails++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void gameDetails::makeFilepaths(const Config& config)
|
void gameDetails::makeFilepaths(const Config& config)
|
||||||
{
|
{
|
||||||
std::string filepath;
|
std::string filepath;
|
||||||
|
Loading…
Reference in New Issue
Block a user