Play-/Source/ui_shared/BootablesProcesses.cpp

172 lines
4.4 KiB
C++
Raw Normal View History

#include <algorithm>
2019-01-16 20:00:10 +00:00
#include "AppConfig.h"
#include "BootablesProcesses.h"
2017-10-20 15:38:51 -04:00
#include "BootablesDbClient.h"
2017-10-23 07:27:42 -04:00
#include "TheGamesDbClient.h"
#include "DiskUtils.h"
2019-01-16 20:00:10 +00:00
#include "PathUtils.h"
2017-10-23 07:27:42 -04:00
#include "string_format.h"
2019-10-16 20:51:11 -04:00
#include "StdStreamUtils.h"
2019-01-16 20:00:10 +00:00
#include "http/HttpClientFactory.h"
//Jobs
// Scan for new games (from input directory)
// Remove games that might not be available anymore
// Extract game ids from disk images
// Pull disc cover URLs and titles from GamesDb/TheGamesDb
2019-10-16 20:51:11 -04:00
bool IsBootableExecutablePath(const fs::path& filePath)
{
auto extension = filePath.extension().string();
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
return (extension == ".elf");
}
2019-10-16 20:51:11 -04:00
bool IsBootableDiscImagePath(const fs::path& filePath)
{
auto extension = filePath.extension().string();
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
2018-08-29 13:53:51 -04:00
return (extension == ".iso") ||
(extension == ".isz") ||
(extension == ".cso") ||
(extension == ".bin");
}
2019-10-16 20:51:11 -04:00
void TryRegisteringBootable(const fs::path& path)
2019-01-16 19:57:55 +00:00
{
std::string serial;
if(
!IsBootableExecutablePath(path) &&
!(IsBootableDiscImagePath(path) && DiskUtils::TryGetDiskId(path, &serial)))
{
return;
}
BootablesDb::CClient::GetInstance().RegisterBootable(path, path.filename().string().c_str(), serial.c_str());
}
2019-10-16 20:51:11 -04:00
void ScanBootables(const fs::path& parentPath, bool recursive)
{
2019-10-16 20:51:11 -04:00
for(auto pathIterator = fs::directory_iterator(parentPath);
pathIterator != fs::directory_iterator(); pathIterator++)
{
auto& path = pathIterator->path();
try
{
2019-10-16 20:51:11 -04:00
if(recursive && fs::is_directory(path))
{
ScanBootables(path, recursive);
continue;
}
2019-01-16 19:57:55 +00:00
TryRegisteringBootable(path);
}
catch(const std::exception& exception)
2017-11-01 07:26:30 -04:00
{
//Failed to process a path, keep going
2017-11-01 07:26:30 -04:00
}
}
}
2019-10-16 20:51:11 -04:00
std::set<fs::path> GetActiveBootableDirectories()
{
2019-10-16 20:51:11 -04:00
std::set<fs::path> result;
auto bootables = BootablesDb::CClient::GetInstance().GetBootables();
for(const auto& bootable : bootables)
{
auto parentPath = bootable.path.parent_path();
2020-03-07 17:58:03 +00:00
static const char* s3ImagePathPrefix = "//s3/";
if(parentPath.string().find(s3ImagePathPrefix) == std::string::npos)
result.insert(parentPath);
}
return result;
}
2017-10-27 18:06:59 -04:00
void PurgeInexistingFiles()
{
auto bootables = BootablesDb::CClient::GetInstance().GetBootables();
for(const auto& bootable : bootables)
{
2019-10-16 20:51:11 -04:00
if(fs::exists(bootable.path)) continue;
2017-10-27 18:06:59 -04:00
BootablesDb::CClient::GetInstance().UnregisterBootable(bootable.path);
}
}
void FetchGameTitles()
{
2017-10-20 15:40:49 -04:00
auto bootables = BootablesDb::CClient::GetInstance().GetBootables();
2019-01-06 00:04:03 +00:00
std::vector<std::string> serials;
2017-10-20 15:40:49 -04:00
for(const auto& bootable : bootables)
{
2019-01-28 20:11:23 -05:00
if(bootable.discId.empty()) continue;
2019-01-06 00:04:03 +00:00
if(bootable.coverUrl.empty() || bootable.title.empty() || bootable.overview.empty())
2019-01-28 20:11:23 -05:00
{
2019-01-06 00:04:03 +00:00
serials.push_back(bootable.discId);
2019-01-28 20:11:23 -05:00
}
2019-01-06 00:04:03 +00:00
}
2019-01-28 20:11:23 -05:00
if(serials.empty()) return;
2019-01-06 00:04:03 +00:00
try
2019-01-06 00:04:03 +00:00
{
auto gamesList = TheGamesDb::CClient::GetInstance().GetGames(serials);
for(auto& game : gamesList)
2017-10-20 15:40:49 -04:00
{
for(const auto& bootable : bootables)
2019-01-06 00:04:03 +00:00
{
for(const auto& discId : game.discIds)
2019-01-06 00:04:03 +00:00
{
if(discId == bootable.discId)
2019-01-06 00:04:03 +00:00
{
BootablesDb::CClient::GetInstance().SetTitle(bootable.path, game.title.c_str());
2019-01-06 00:04:03 +00:00
if(!game.overview.empty())
{
BootablesDb::CClient::GetInstance().SetOverview(bootable.path, game.overview.c_str());
}
if(!game.boxArtUrl.empty())
{
auto coverUrl = string_format("%s%s", game.baseImgUrl.c_str(), game.boxArtUrl.c_str());
BootablesDb::CClient::GetInstance().SetCoverUrl(bootable.path, coverUrl.c_str());
}
break;
}
2019-01-06 00:04:03 +00:00
}
}
2017-10-20 15:40:49 -04:00
}
}
catch(...)
{
}
}
2019-01-16 20:00:10 +00:00
void FetchGameCovers()
{
2019-10-16 20:51:11 -04:00
auto coverpath(CAppConfig::GetBasePath() / fs::path("covers"));
2019-01-16 20:00:10 +00:00
Framework::PathUtils::EnsurePathExists(coverpath);
auto bootables = BootablesDb::CClient::GetInstance().GetBootables();
std::vector<std::string> serials;
for(const auto& bootable : bootables)
{
if(bootable.discId.empty() || bootable.coverUrl.empty())
continue;
auto path = coverpath / (bootable.discId + ".jpg");
2019-10-16 20:51:11 -04:00
if(fs::exists(path))
2019-01-16 20:00:10 +00:00
continue;
auto requestResult =
2019-01-17 12:26:47 +00:00
[&]() {
auto client = Framework::Http::CreateHttpClient();
client->SetUrl(bootable.coverUrl);
return client->SendRequest();
}();
2019-01-16 20:00:10 +00:00
if(requestResult.statusCode == Framework::Http::HTTP_STATUS_CODE::OK)
{
2019-10-16 20:51:11 -04:00
auto outputStream = Framework::CreateOutputStdStream(path.native());
outputStream.Write(requestResult.data.GetBuffer(), requestResult.data.GetSize());
2019-01-16 20:00:10 +00:00
}
}
}