Added DLC support

This commit is contained in:
Sude 2014-03-29 01:51:39 +02:00
parent 8435fb2566
commit 50cc5a2565
5 changed files with 500 additions and 33 deletions

View File

@ -37,6 +37,7 @@ class gameDetails {
std::vector<gameFile> installers; std::vector<gameFile> installers;
std::vector<gameFile> patches; std::vector<gameFile> patches;
std::vector<gameFile> languagepacks; std::vector<gameFile> languagepacks;
std::vector<gameDetails> dlcs;
std::string gamename; std::string gamename;
std::string title; std::string title;
std::string icon; std::string icon;

View File

@ -28,6 +28,7 @@ class Config
bool bExtras; bool bExtras;
bool bPatches; bool bPatches;
bool bLanguagePacks; bool bLanguagePacks;
bool bDLC;
bool bUnicode; // use Unicode in console output bool bUnicode; // use Unicode in console output
bool bColor; // use colors bool bColor; // use colors
bool bVerifyPeer; bool bVerifyPeer;

View File

@ -31,6 +31,13 @@ class Timer
struct timeval last_update; struct timeval last_update;
}; };
class gameItem {
public:
std::string name;
std::string id;
std::vector<std::string> dlcnames;
};
class Downloader class Downloader
{ {
public: public:
@ -62,8 +69,8 @@ class Downloader
std::string getRemoteFileHash(const std::string& gamename, const std::string& id); std::string getRemoteFileHash(const std::string& gamename, const std::string& id);
int HTTP_Login(const std::string& email, const std::string& password); int HTTP_Login(const std::string& email, const std::string& password);
std::vector< std::pair<std::string,std::string> > getGames(); std::vector<gameItem> getGames();
std::vector< std::pair<std::string,std::string> > getFreeGames(); std::vector<gameItem> getFreeGames();
std::vector<gameFile> getExtras(const std::string& gamename, const std::string& gameid); std::vector<gameFile> getExtras(const std::string& gamename, const std::string& gameid);
static int progressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); static int progressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
@ -73,7 +80,7 @@ class Downloader
API *gogAPI; API *gogAPI;
std::vector< std::pair<std::string,std::string> > gameNamesIds; std::vector<gameItem> gameItems;
std::vector<gameDetails> games; std::vector<gameDetails> games;
std::string coverXML; std::string coverXML;

View File

@ -110,6 +110,7 @@ int main(int argc, char *argv[])
bool bNoExtras = false; bool bNoExtras = false;
bool bNoPatches = false; bool bNoPatches = false;
bool bNoLanguagePacks = false; bool bNoLanguagePacks = false;
bool bNoDLC = false;
bool bNoRemoteXML = false; bool bNoRemoteXML = false;
bool bNoSubDirectories = false; bool bNoSubDirectories = false;
// Commandline options (no config file) // Commandline options (no config file)
@ -142,6 +143,7 @@ int main(int argc, char *argv[])
("no-extras", bpo::value<bool>(&bNoExtras)->zero_tokens()->default_value(false), "Don't download/list/repair extras") ("no-extras", bpo::value<bool>(&bNoExtras)->zero_tokens()->default_value(false), "Don't download/list/repair extras")
("no-patches", bpo::value<bool>(&bNoPatches)->zero_tokens()->default_value(false), "Don't download/list/repair patches") ("no-patches", bpo::value<bool>(&bNoPatches)->zero_tokens()->default_value(false), "Don't download/list/repair patches")
("no-language-packs", bpo::value<bool>(&bNoLanguagePacks)->zero_tokens()->default_value(false), "Don't download/list/repair language packs") ("no-language-packs", bpo::value<bool>(&bNoLanguagePacks)->zero_tokens()->default_value(false), "Don't download/list/repair language packs")
("no-dlc", bpo::value<bool>(&bNoDLC)->zero_tokens()->default_value(false), "Don't download/list/repair DLCs")
("no-cover", bpo::value<bool>(&bNoCover)->zero_tokens()->default_value(false), "Don't download cover images") ("no-cover", bpo::value<bool>(&bNoCover)->zero_tokens()->default_value(false), "Don't download cover images")
("no-remote-xml", bpo::value<bool>(&bNoRemoteXML)->zero_tokens()->default_value(false), "Don't use remote XML for repair") ("no-remote-xml", bpo::value<bool>(&bNoRemoteXML)->zero_tokens()->default_value(false), "Don't use remote XML for repair")
("no-unicode", bpo::value<bool>(&bNoUnicode)->zero_tokens()->default_value(false), "Don't use Unicode in the progress bar") ("no-unicode", bpo::value<bool>(&bNoUnicode)->zero_tokens()->default_value(false), "Don't use Unicode in the progress bar")
@ -213,6 +215,7 @@ int main(int argc, char *argv[])
config.bExtras = !bNoExtras; config.bExtras = !bNoExtras;
config.bPatches = !bNoPatches; config.bPatches = !bNoPatches;
config.bLanguagePacks = !bNoLanguagePacks; config.bLanguagePacks = !bNoLanguagePacks;
config.bDLC = !bNoDLC;
config.bRemoteXML = !bNoRemoteXML; config.bRemoteXML = !bNoRemoteXML;
config.bSubDirectories = !bNoSubDirectories; config.bSubDirectories = !bNoSubDirectories;
} }

View File

@ -180,7 +180,7 @@ void Downloader::updateCheck()
void Downloader::getGameList() void Downloader::getGameList()
{ {
gameNamesIds = this->getGames(); gameItems = this->getGames();
// Filter the game list // Filter the game list
if (!config.sGameRegex.empty()) if (!config.sGameRegex.empty())
@ -191,19 +191,19 @@ void Downloader::getGameList()
if (config.sGameRegex == "free") if (config.sGameRegex == "free")
{ {
gameNamesIds = this->getFreeGames(); gameItems = this->getFreeGames();
} }
else else
{ // Filter the names { // Filter the names
std::vector<std::pair<std::string,std::string>> gameNamesIdsFiltered; std::vector<gameItem> gameItemsFiltered;
boost::regex expression(config.sGameRegex); boost::regex expression(config.sGameRegex);
boost::match_results<std::string::const_iterator> what; boost::match_results<std::string::const_iterator> what;
for (unsigned int i = 0; i < gameNamesIds.size(); ++i) for (unsigned int i = 0; i < gameItems.size(); ++i)
{ {
if (boost::regex_search(gameNamesIds[i].first, what, expression)) // Check if name matches the specified regex if (boost::regex_search(gameItems[i].name, what, expression)) // Check if name matches the specified regex
gameNamesIdsFiltered.push_back(gameNamesIds[i]); gameItemsFiltered.push_back(gameItems[i]);
} }
gameNamesIds = gameNamesIdsFiltered; gameItems = gameItemsFiltered;
} }
} }
} }
@ -216,15 +216,29 @@ int Downloader::getGameDetails()
{ {
gameDetails game; gameDetails game;
int updated = 0; int updated = 0;
for (unsigned int i = 0; i < gameNamesIds.size(); ++i) for (unsigned int i = 0; i < gameItems.size(); ++i)
{ {
std::cout << "Getting game info " << i+1 << " / " << gameNamesIds.size() << "\r" << std::flush; std::cout << "Getting game info " << i+1 << " / " << gameItems.size() << "\r" << std::flush;
game = gogAPI->getGameDetails(gameNamesIds[i].first, config.iInstallerType, config.iInstallerLanguage, config.bDuplicateHandler); bool bHasDLC = !gameItems[i].dlcnames.empty();
game = gogAPI->getGameDetails(gameItems[i].name, config.iInstallerType, config.iInstallerLanguage, config.bDuplicateHandler);
if (!gogAPI->getError()) if (!gogAPI->getError())
{ {
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(gameNamesIds[i].first, gameNamesIds[i].second); game.extras = this->getExtras(gameItems[i].name, gameItems[i].id);
}
if (game.dlcs.empty() && bHasDLC && config.bDLC)
{
for (unsigned int j = 0; j < gameItems[i].dlcnames.size(); ++j)
{
gameDetails dlc;
dlc = gogAPI->getGameDetails(gameItems[i].dlcnames[j], config.iInstallerType, config.iInstallerLanguage, config.bDuplicateHandler);
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);
}
game.dlcs.push_back(dlc);
}
} }
if (!config.bUpdateCheck) if (!config.bUpdateCheck)
games.push_back(game); games.push_back(game);
@ -340,12 +354,50 @@ void Downloader::listGames()
<< std::endl; << std::endl;
} }
} }
if (config.bDLC && !games[i].dlcs.empty())
{
std::cout << "DLCs: " << std::endl;
for (unsigned int j = 0; j < games[i].dlcs.size(); ++j)
{
for (unsigned int k = 0; k < games[i].dlcs[j].installers.size(); ++k)
{
std::cout << "\tgamename: " << games[i].dlcs[j].gamename << std::endl
<< "\tid: " << games[i].dlcs[j].installers[k].id << std::endl
<< "\tname: " << games[i].dlcs[j].installers[k].name << std::endl
<< "\tpath: " << games[i].dlcs[j].installers[k].path << std::endl
<< "\tsize: " << games[i].dlcs[j].installers[k].size << std::endl
<< std::endl;
}
for (unsigned int k = 0; k < games[i].dlcs[j].patches.size(); ++k)
{
std::cout << "\tgamename: " << games[i].dlcs[j].gamename << std::endl
<< "\tid: " << games[i].dlcs[j].patches[k].id << std::endl
<< "\tname: " << games[i].dlcs[j].patches[k].name << std::endl
<< "\tpath: " << games[i].dlcs[j].patches[k].path << std::endl
<< "\tsize: " << games[i].dlcs[j].patches[k].size << std::endl
<< std::endl;
}
for (unsigned int k = 0; k < games[i].dlcs[j].extras.size(); ++k)
{
std::cout << "\tgamename: " << games[i].dlcs[j].gamename << std::endl
<< "\tid: " << games[i].dlcs[j].extras[k].id << std::endl
<< "\tname: " << games[i].dlcs[j].extras[k].name << std::endl
<< "\tpath: " << games[i].dlcs[j].extras[k].path << std::endl
<< "\tsize: " << games[i].dlcs[j].extras[k].size << std::endl
<< std::endl;
}
}
}
} }
} }
else else
{ // List game names { // List game names
for (unsigned int i = 0; i < gameNamesIds.size(); ++i) for (unsigned int i = 0; i < gameItems.size(); ++i)
std::cout << gameNamesIds[i].first << std::endl; {
std::cout << gameItems[i].name << std::endl;
for (unsigned int j = 0; j < gameItems[i].dlcnames.size(); ++j)
std::cout << "+> " << gameItems[i].dlcnames[j] << std::endl;
}
} }
} }
@ -454,7 +506,84 @@ void Downloader::repair()
std::cout << std::endl; std::cout << std::endl;
} }
} }
if (config.bDLC && !games[i].dlcs.empty())
{
for (unsigned int j = 0; j < games[i].dlcs.size(); ++j)
{
if (config.bInstallers)
{
for (unsigned int k = 0; k < games[i].dlcs[j].installers.size(); ++k)
{
std::string filepath = Util::makeFilepath(config.sDirectory, games[i].dlcs[j].installers[k].path, games[i].gamename, config.bSubDirectories ? "dlc" : "");
// Get XML data
std::string XML = "";
if (config.bRemoteXML)
{
XML = gogAPI->getXML(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id);
if (gogAPI->getError())
{
std::cout << gogAPI->getErrorMessage() << std::endl;
gogAPI->clearError();
continue;
}
}
// Repair
bool bUseLocalXML = !config.bRemoteXML;
if (!XML.empty() || bUseLocalXML)
{
std::string url = gogAPI->getInstallerLink(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id);
if (gogAPI->getError())
{
std::cout << gogAPI->getErrorMessage() << std::endl;
gogAPI->clearError();
continue;
}
std::cout << "Repairing file " << filepath << std::endl;
this->repairFile(url, filepath, XML, games[i].dlcs[j].gamename);
std::cout << std::endl;
}
}
}
if (config.bPatches)
{
for (unsigned int k = 0; k < games[i].dlcs[j].patches.size(); ++k)
{
std::string filepath = Util::makeFilepath(config.sDirectory, games[i].dlcs[j].patches[k].path, games[i].gamename, config.bSubDirectories ? "dlc/patches" : "");
std::string url = gogAPI->getPatchLink(games[i].dlcs[j].gamename, games[i].dlcs[j].patches[k].id);
if (gogAPI->getError())
{
std::cout << gogAPI->getErrorMessage() << std::endl;
gogAPI->clearError();
continue;
}
std::cout << "Repairing file " << filepath << std::endl;
this->repairFile(url, filepath, std::string(), games[i].dlcs[j].gamename);
std::cout << std::endl;
}
}
if (config.bExtras)
{
for (unsigned int k = 0; k < games[i].dlcs[j].extras.size(); ++k)
{
std::string filepath = Util::makeFilepath(config.sDirectory, games[i].dlcs[j].extras[k].path, games[i].gamename, config.bSubDirectories ? "dlc/extras" : "");
std::string url = gogAPI->getExtraLink(games[i].dlcs[j].gamename, games[i].dlcs[j].extras[k].id);
if (gogAPI->getError())
{
std::cout << gogAPI->getErrorMessage() << std::endl;
gogAPI->clearError();
continue;
}
std::cout << "Repairing file " << filepath << std::endl;
this->repairFile(url, filepath, std::string(), games[i].dlcs[j].gamename);
std::cout << std::endl;
}
}
}
}
} }
} }
@ -569,12 +698,14 @@ void Downloader::download()
// Download // Download
if (!url.empty()) if (!url.empty())
{ {
if (!games[i].patches[j].name.empty()) std::string XML;
std::cout << "Dowloading: " << games[i].gamename << " " << games[i].patches[j].name << std::endl; if (config.bRemoteXML)
std::cout << filepath << std::endl; XML = gogAPI->getXML(games[i].dlcs[j].gamename, games[i].patches[j].id);
CURLcode result = downloadFile(url, filepath); if (!games[i].dlcs[j].patches[j].name.empty())
std::cout << "Dowloading: " << games[i].patches[j].name << std::endl;
CURLcode result = this->downloadFile(url, filepath, XML, games[i].gamename);
std::cout << std::endl; std::cout << std::endl;
if (result==CURLE_OK && config.sXMLFile == "automatic") if (result==CURLE_OK && config.sXMLFile == "automatic" && XML.empty())
{ {
std::cout << "Starting automatic XML creation" << std::endl; std::cout << "Starting automatic XML creation" << std::endl;
std::string xml_dir = config.sXMLDirectory + "/" + games[i].gamename; std::string xml_dir = config.sXMLDirectory + "/" + games[i].gamename;
@ -618,6 +749,108 @@ void Downloader::download()
} }
} }
} }
if (config.bDLC && !games[i].dlcs.empty())
{
for (unsigned int j = 0; j < games[i].dlcs.size(); ++j)
{
if (config.bInstallers)
{
for (unsigned int k = 0; k < games[i].dlcs[j].installers.size(); ++k)
{
std::string filepath = Util::makeFilepath(config.sDirectory, games[i].dlcs[j].installers[k].path, games[i].gamename, config.bSubDirectories ? "dlc" : "");
// Get link
std::string url = gogAPI->getInstallerLink(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id);
if (gogAPI->getError())
{
std::cout << gogAPI->getErrorMessage() << std::endl;
gogAPI->clearError();
continue;
}
// Download
if (!url.empty())
{
std::string XML;
if (config.bRemoteXML)
XML = gogAPI->getXML(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id);
if (!games[i].dlcs[j].installers[k].name.empty())
std::cout << "Dowloading: " << games[i].dlcs[j].installers[k].name << std::endl;
std::cout << filepath << std::endl;
this->downloadFile(url, filepath, XML, games[i].dlcs[j].gamename);
std::cout << std::endl;
}
}
}
if (config.bPatches)
{
for (unsigned int k = 0; k < games[i].dlcs[j].patches.size(); ++k)
{
std::string filepath = Util::makeFilepath(config.sDirectory, games[i].dlcs[j].patches[k].path, games[i].gamename, config.bSubDirectories ? "dlc/patches" : "");
// Get link
std::string url = gogAPI->getPatchLink(games[i].dlcs[j].gamename, games[i].dlcs[j].patches[k].id);
if (gogAPI->getError())
{
std::cout << gogAPI->getErrorMessage() << std::endl;
gogAPI->clearError();
continue;
}
// Download
if (!url.empty())
{
std::string XML;
if (config.bRemoteXML)
XML = gogAPI->getXML(games[i].dlcs[j].gamename, games[i].dlcs[j].patches[k].id);
if (!games[i].dlcs[j].patches[k].name.empty())
std::cout << "Dowloading: " << games[i].dlcs[j].patches[k].name << std::endl;
CURLcode result = this->downloadFile(url, filepath, XML, games[i].dlcs[j].gamename);
std::cout << std::endl;
if (result==CURLE_OK && config.sXMLFile == "automatic" && XML.empty())
{
std::cout << "Starting automatic XML creation" << std::endl;
std::string xml_dir = config.sXMLDirectory + "/" + games[i].dlcs[j].gamename;
Util::createXML(filepath, config.iChunkSize, xml_dir);
std::cout << std::endl;
}
}
}
}
if (config.bExtras)
{
for (unsigned int k = 0; k < games[i].dlcs[j].extras.size(); ++k)
{
std::string filepath = Util::makeFilepath(config.sDirectory, games[i].dlcs[j].extras[k].path, games[i].gamename, config.bSubDirectories ? "dlc/extras" : "");
// Get link
std::string url = gogAPI->getExtraLink(games[i].dlcs[j].gamename, games[i].dlcs[j].extras[k].id);
if (gogAPI->getError())
{
std::cout << gogAPI->getErrorMessage() << std::endl;
gogAPI->clearError();
continue;
}
// Download
if (!url.empty())
{
if (!games[i].dlcs[j].extras[k].name.empty())
std::cout << "Dowloading: " << games[i].dlcs[j].extras[k].name << std::endl;
CURLcode result = this->downloadFile(url, filepath);
std::cout << std::endl;
if (result==CURLE_OK && config.sXMLFile == "automatic")
{
std::cout << "Starting automatic XML creation" << std::endl;
std::string xml_dir = config.sXMLDirectory + "/" + games[i].dlcs[j].gamename;
Util::createXML(filepath, config.iChunkSize, xml_dir);
std::cout << std::endl;
}
}
}
}
}
}
} }
} }
@ -1363,9 +1596,9 @@ int Downloader::HTTP_Login(const std::string& email, const std::string& password
} }
// Get list of games from account page // Get list of games from account page
std::vector< std::pair<std::string,std::string> > Downloader::getGames() std::vector<gameItem> Downloader::getGames()
{ {
std::vector< std::pair<std::string,std::string> > games; std::vector<gameItem> games;
Json::Value root; Json::Value root;
Json::Reader *jsonparser = new Json::Reader; Json::Reader *jsonparser = new Json::Reader;
int i = 1; int i = 1;
@ -1409,11 +1642,122 @@ std::vector< std::pair<std::string,std::string> > Downloader::getGames()
std::string classname = it->attribute("class").second; std::string classname = it->attribute("class").second;
if (classname=="shelf_game") if (classname=="shelf_game")
{ {
gameItem game;
// Game name is contained in data-gameindex attribute // Game name is contained in data-gameindex attribute
std::string game = it->attribute("data-gameindex").second; game.name = it->attribute("data-gameindex").second;
std::string gameid = it->attribute("data-gameid").second; game.id = it->attribute("data-gameid").second;
if (!game.empty() && !gameid.empty()) if (!game.name.empty() && !game.id.empty())
games.push_back(std::make_pair(game,gameid)); {
// Check for DLC
if (config.bDLC)
{
tree<htmlcxx::HTML::Node>::iterator dlc_it = it;
tree<htmlcxx::HTML::Node>::iterator dlc_end = it.end();
for (; dlc_it != dlc_end; ++dlc_it)
{
if (dlc_it->tagName()=="div")
{
dlc_it->parseAttributes();
std::string classname_dlc = dlc_it->attribute("class").second;
if (classname_dlc == "shelf-game-dlc-counter")
{
std::string content;
for (unsigned int i = 0; i < dom.number_of_children(dlc_it); ++i)
{
tree<htmlcxx::HTML::Node>::iterator it = dom.child(dlc_it, i);
if (!it->isTag() && !it->isComment())
content += it->text();
}
// Get game names if game has DLC
if (content.find("DLC")!=std::string::npos)
{
Json::Value root;
Json::Reader *jsonparser = new Json::Reader;
std::string gameDataUrl = "https://secure.gog.com/en/account/ajax?a=gamesListDetails&g=" + game.id;
std::string json = this->getResponse(gameDataUrl);
// Parse JSON
if (!jsonparser->parse(json, root))
{
#ifdef DEBUG
std::cerr << "DEBUG INFO (Downloader::getGames)" << std::endl << json << std::endl;
#endif
std::cout << jsonparser->getFormatedErrorMessages();
delete jsonparser;
exit(1);
}
#ifdef DEBUG
std::cerr << "DEBUG INFO (Downloader::getGames)" << std::endl << root << std::endl;
#endif
std::string html = root["details"]["html"].asString();
delete jsonparser;
// Parse HTML to get game names for DLC
htmlcxx::HTML::ParserDom parser;
tree<htmlcxx::HTML::Node> dom = parser.parseTree(html);
tree<htmlcxx::HTML::Node>::iterator it = dom.begin();
tree<htmlcxx::HTML::Node>::iterator end = dom.end();
for (; it != end; ++it)
{
if (it->tagName()=="div")
{
it->parseAttributes();
std::string gamename = it->attribute("data-gameindex").second;
if (!gamename.empty() && gamename!=game.name)
{
bool bDuplicate = false;
for (unsigned int i = 0; i < game.dlcnames.size(); ++i)
{
if (gamename == game.dlcnames[i])
{
bDuplicate = true;
break;
}
}
if (!bDuplicate)
game.dlcnames.push_back(gamename);
}
}
}
// Try getting game names for DLCs from extra links. Catches game names for DLCs that don't have installers.
it = dom.begin();
end = dom.end();
for (; it != end; ++it)
{
if (it->tagName()=="a")
{
it->parseAttributes();
std::string href = it->attribute("href").second;
std::string search_string = "/downlink/file/"; // Extra links: https://secure.gog.com/downlink/file/gamename/id_number
if (href.find(search_string)!=std::string::npos)
{
std::string gamename;
gamename.assign(href.begin()+href.find(search_string)+search_string.length(), href.begin()+href.find_last_of("/"));
if (!gamename.empty() && gamename!=game.name)
{
bool bDuplicate = false;
for (unsigned int i = 0; i < game.dlcnames.size(); ++i)
{
if (gamename == game.dlcnames[i])
{
bDuplicate = true;
break;
}
}
if (!bDuplicate)
game.dlcnames.push_back(gamename);
}
}
}
}
}
}
}
}
}
games.push_back(game);
}
} }
} }
} }
@ -1422,11 +1766,11 @@ std::vector< std::pair<std::string,std::string> > Downloader::getGames()
} }
// Get list of free games // Get list of free games
std::vector< std::pair<std::string,std::string> > Downloader::getFreeGames() std::vector<gameItem> Downloader::getFreeGames()
{ {
Json::Value root; Json::Value root;
Json::Reader *jsonparser = new Json::Reader; Json::Reader *jsonparser = new Json::Reader;
std::vector< std::pair<std::string,std::string> > games; std::vector<gameItem> games;
std::string json = this->getResponse("https://secure.gog.com/games/ajax?a=search&f={\"price\":[\"free\"],\"sort\":\"title\"}&p=1&t=all"); std::string json = this->getResponse("https://secure.gog.com/games/ajax?a=search&f={\"price\":[\"free\"],\"sort\":\"title\"}&p=1&t=all");
// Parse JSON // Parse JSON
@ -1458,11 +1802,12 @@ std::vector< std::pair<std::string,std::string> > Downloader::getFreeGames()
std::string classname = it->attribute("class").second; std::string classname = it->attribute("class").second;
if (classname=="gog-price game-owned") if (classname=="gog-price game-owned")
{ {
gameItem game;
// Game name is contained in data-gameindex attribute // Game name is contained in data-gameindex attribute
std::string game = it->attribute("data-gameindex").second; game.name = it->attribute("data-gameindex").second;
std::string id = it->attribute("data-gameid").second; game.id = it->attribute("data-gameid").second;
if (!game.empty() && !id.empty()) if (!game.name.empty() && !game.id.empty())
games.push_back(std::make_pair(game,id)); games.push_back(game);
} }
} }
} }
@ -1639,6 +1984,38 @@ void Downloader::checkOrphans()
} }
} }
} }
if (!bFoundFile)
{ // Check dlcs
for (unsigned int k = 0; k < games[i].dlcs.size(); ++k)
{
for (unsigned int index = 0; index < games[i].dlcs[k].installers.size(); ++index)
{
if (games[i].dlcs[k].installers[index].path.find(filepath_vector[j].filename().string()) != std::string::npos)
{
bFoundFile = true;
break;
}
}
if (bFoundFile) break;
for (unsigned int index = 0; index < games[i].dlcs[k].patches.size(); ++index)
{
if (games[i].dlcs[k].patches[index].path.find(filepath_vector[j].filename().string()) != std::string::npos)
{
bFoundFile = true;
break;
}
}
for (unsigned int index = 0; index < games[i].dlcs[k].extras.size(); ++index)
{
if (games[i].dlcs[k].extras[index].path.find(filepath_vector[j].filename().string()) != std::string::npos)
{
bFoundFile = true;
break;
}
}
if (bFoundFile) break;
}
}
if (!bFoundFile) if (!bFoundFile)
orphans.push_back(filepath_vector[j].string()); orphans.push_back(filepath_vector[j].string());
} }
@ -1761,6 +2138,84 @@ void Downloader::checkStatus()
} }
} }
} }
if (config.bDLC)
{
for (unsigned int j = 0; j < games[i].dlcs.size(); ++j)
{
if (config.bInstallers)
{
for (unsigned int k = 0; k < games[i].dlcs[j].installers.size(); ++k)
{
boost::filesystem::path filepath = Util::makeFilepath(config.sDirectory, games[i].dlcs[j].installers[k].path, games[i].gamename, config.bSubDirectories ? "dlc" : "");
std::string remoteHash;
std::string localHash;
bool bHashOK = true; // assume hash OK
size_t filesize;
localHash = this->getLocalFileHash(filepath.string(), games[i].dlcs[j].gamename);
remoteHash = this->getRemoteFileHash(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id);
if (boost::filesystem::exists(filepath))
{
filesize = boost::filesystem::file_size(filepath);
if (remoteHash != localHash)
bHashOK = false;
std::cout << (bHashOK ? "OK " : "MD5 ") << games[i].gamename << " " << filepath.filename().string() << " " << filesize << " " << localHash << std::endl;
}
else
{
std::cout << "ND " << games[i].gamename << " " << filepath.filename().string() << std::endl;
}
}
}
if (config.bPatches)
{
for (unsigned int k = 0; k < games[i].dlcs[j].patches.size(); ++k)
{
boost::filesystem::path filepath = Util::makeFilepath(config.sDirectory, games[i].dlcs[j].patches[k].path, games[i].gamename, config.bSubDirectories ? "dlc/patches" : "");
std::string localHash = this->getLocalFileHash(filepath.string(), games[i].dlcs[j].gamename);
size_t filesize;
if (boost::filesystem::exists(filepath))
{
filesize = boost::filesystem::file_size(filepath);
std::cout << "OK " << games[i].gamename << " " << filepath.filename().string() << " " << filesize << " " << localHash << std::endl;
}
else
{
std::cout << "ND " << games[i].gamename << " " << filepath.filename().string() << std::endl;
}
}
}
if (config.bExtras)
{
for (unsigned int k = 0; k < games[i].dlcs[j].extras.size(); ++k)
{
boost::filesystem::path filepath = Util::makeFilepath(config.sDirectory, games[i].dlcs[j].extras[k].path, games[i].gamename, config.bSubDirectories ? "dlc/extras" : "");
std::string localHash = this->getLocalFileHash(filepath.string(), games[i].dlcs[j].gamename);
size_t filesize;
if (boost::filesystem::exists(filepath))
{
filesize = boost::filesystem::file_size(filepath);
std::cout << "OK " << games[i].gamename << " " << filepath.filename().string() << " " << filesize << " " << localHash << std::endl;
}
else
{
std::cout << "ND " << games[i].gamename << " " << filepath.filename().string() << std::endl;
}
}
}
}
}
} }
return; return;