Added support for user accounts for ScreenScraper.

This commit is contained in:
Leon Styhre 2020-11-07 15:34:15 +01:00
parent 1af7e3eda4
commit f1f0596fe1
8 changed files with 144 additions and 11 deletions

View file

@ -22,6 +22,7 @@ Many bugs have been fixed, and numerous features that were only partially implem
* Game systems are now sorted by full names which makes much more sense from a user perspective
* New game media file logic using a media directory with files matching the ROM names instead of pointing to the media files in gamelist.xml
* Updated scraper to support additional media files, detailed configuration of what to scrape, semi-automatic mode etc.
* Added user account support when scraping using ScreenScraper
* In the metadata editor, any values updated by the single-game scraper or by the user are now highlighted using a different font color
* Files or folders can now be flagged for exclusion when scraping with the multi-scraper, and for folders it can be set to apply recursively
* Gamelist sorting is now working as expected and is persistent throughout the application session

View file

@ -495,6 +495,22 @@ Criteria for what games to include in the scraping. It can be set to 'All games'
A selection of which systems to scrape for. It's possible to automatically scrape several or all systems in one go.
#### Account settings
Setup of ScreenScraper account.
**Use this account for ScreenScraper**
Whether to use the account that has been setup here. If this is disabled, the username and password configured on this screen will be ignored during scraping. This can be useful if you have scraping issues and want to check whether it's related to your account or if it's a general problem. Note that screenscraper.fr does not seem to return a proper error message regarding incorrect username and password, but starting ES with the --debug flag will indicate in the log file whether the username was included in the server response.
**ScreenScraper username**
Username as registered on screenscraper.fr.
**ScreenScraper password**
The password as registered on screenscraper.fr. Note that the password is masked using asterisks on this screen, and the password input field will be blank when attempting to update an existing password. Entering a new password will of course work, and it will be saved accordingly. Be aware though that the es_settings.cfg file contains the password in clear text.
#### Content settings
Describes the content types to include in the scraping. Most users will probably not need to adjust so many of these.

View file

@ -72,6 +72,9 @@ GuiScraperMenu::GuiScraperMenu(Window* window, std::string title)
}
mMenu.addWithLabel("Systems", mSystems);
addEntry("ACCOUNT SETTINGS", 0x777777FF, true, [this] {
openAccountSettings();
});
addEntry("CONTENT SETTINGS", 0x777777FF, true, [this] {
// If the scraper service has been changed before entering this menu, then save the
// settings so that the specific options supported by the respective scrapers
@ -115,6 +118,61 @@ GuiScraperMenu::~GuiScraperMenu()
}
}
void GuiScraperMenu::openAccountSettings()
{
auto s = new GuiSettings(mWindow, "ACCOUNT SETTINGS");
// Whether to use the ScreenScraper account when scraping.
auto scraper_use_account_screenscraper = std::make_shared<SwitchComponent>(mWindow);
scraper_use_account_screenscraper->setState(Settings::getInstance()->
getBool("ScraperUseAccountScreenScraper"));
s->addWithLabel("USE THIS ACCOUNT FOR SCREENSCRAPER", scraper_use_account_screenscraper);
s->addSaveFunc([scraper_use_account_screenscraper, s] {
if (scraper_use_account_screenscraper->getState() !=
Settings::getInstance()->getBool("ScraperUseAccountScreenScraper")) {
Settings::getInstance()->setBool("ScraperUseAccountScreenScraper",
scraper_use_account_screenscraper->getState());
s->setNeedsSaving();
}
});
// ScreenScraper username.
auto scraper_username_screenscraper = std::make_shared<TextComponent>(mWindow, "",
Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_RIGHT);
s->addEditableTextComponent("SCREENSCRAPER USERNAME", scraper_username_screenscraper,
Settings::getInstance()->getString("ScraperUsernameScreenScraper"));
s->addSaveFunc([scraper_username_screenscraper, s] {
if (scraper_username_screenscraper->getValue() !=
Settings::getInstance()->getString("ScraperUsernameScreenScraper")) {
Settings::getInstance()->setString("ScraperUsernameScreenScraper",
scraper_username_screenscraper->getValue());
s->setNeedsSaving();
}
});
// ScreenScraper password.
auto scraper_password_screenscraper = std::make_shared<TextComponent>(mWindow, "",
Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_RIGHT);
std::string passwordMasked;
if (Settings::getInstance()->getString("ScraperPasswordScreenScraper") != "") {
passwordMasked = "********";
scraper_password_screenscraper->setHiddenValue(
Settings::getInstance()->getString("ScraperPasswordScreenScraper"));
}
s->addEditableTextComponent("SCREENSCRAPER PASSWORD",
scraper_password_screenscraper, passwordMasked, "", true);
s->addSaveFunc([scraper_password_screenscraper, s] {
if (scraper_password_screenscraper->getHiddenValue() !=
Settings::getInstance()->getString("ScraperPasswordScreenScraper")) {
Settings::getInstance()->setString("ScraperPasswordScreenScraper",
scraper_password_screenscraper->getHiddenValue());
s->setNeedsSaving();
}
});
mWindow->pushGui(s);
}
void GuiScraperMenu::openContentSettings()
{
auto s = new GuiSettings(mWindow, "SCRAPER CONTENT SETTINGS");

View file

@ -39,6 +39,7 @@ private:
void addEntry(const char* name, unsigned int color,
bool add_arrow, const std::function<void()>& func);
void openAccountSettings();
void openContentSettings();
void openOtherSettings();

View file

@ -92,8 +92,12 @@ void GuiSettings::save()
mWindow->invalidateCachedBackground();
}
void GuiSettings::addEditableTextComponent(const std::string label,
std::shared_ptr<GuiComponent> ed, std::string value, std::string defaultValue)
void GuiSettings::addEditableTextComponent(
const std::string label,
std::shared_ptr<GuiComponent> ed,
std::string value,
std::string defaultValue,
bool isPassword)
{
ComponentListRow row;
row.elements.clear();
@ -114,16 +118,33 @@ void GuiSettings::addEditableTextComponent(const std::string label,
row.addElement(bracket, false);
// OK callback (apply new value to ed).
auto updateVal = [ed, defaultValue](const std::string& newVal) {
auto updateVal = [ed, defaultValue, isPassword](const std::string& newVal) {
// If the field is blank, apply the default value if it's been passes as an argument.
if (defaultValue != "" && newVal == "")
if (defaultValue != "" && newVal == "") {
ed->setValue(defaultValue);
else
}
// If it's a password and actually set to something, then show a star mask.
else if (isPassword && newVal == "") {
ed->setValue("");
ed->setHiddenValue("");
}
else if (isPassword) {
ed->setValue("********");
ed->setHiddenValue(newVal);
}
else {
ed->setValue(newVal);
}
};
row.makeAcceptInputHandler([this, label, ed, updateVal] {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), label,
ed->getValue(), updateVal, false));
row.makeAcceptInputHandler([this, label, ed, updateVal, isPassword] {
// Never display the value if it's a password, instead set it to blank.
if (isPassword)
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), label,
"", updateVal, false));
else
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), label,
ed->getValue(), updateVal, false));
});
assert(ed);
addRow(row);

View file

@ -25,8 +25,12 @@ public:
inline void addRow(const ComponentListRow& row) { mMenu.addRow(row); };
inline void addWithLabel(const std::string& label,
const std::shared_ptr<GuiComponent>& comp) { mMenu.addWithLabel(label, comp); };
void addEditableTextComponent(const std::string label, std::shared_ptr<GuiComponent> ed,
std::string value, std::string defaultValue = "");
void addEditableTextComponent(
const std::string label,
std::shared_ptr<GuiComponent> ed,
std::string value,
std::string defaultValue = "",
bool isPassword = false);
inline void addSaveFunc(const std::function<void()>& func) { mSaveFuncs.push_back(func); };
void setNeedsSaving() { mNeedsSaving = true; };

View file

@ -358,6 +358,24 @@ void ScreenScraperRequest::processGame(const pugi::xml_document& xmldoc,
result.mdl.get("players");
}
// Username, if an account is used for scraping.
if (Settings::getInstance()->getBool("ScraperUseAccountScreenScraper") &&
Settings::getInstance()->getString("ScraperUsernameScreenScraper") != "" &&
Settings::getInstance()->getString("ScraperPasswordScreenScraper") != "") {
// Check if our username was included in the response.
std::string userID = data.child("ssuser").child("id").text().get();
if (userID != "") {
LOG(LogDebug) << "ScreenScraperRequest::processGame(): Scraping using account '" <<
userID << "'.";
}
else {
LOG(LogDebug) << "ScreenScraperRequest::processGame(): The configured account '" <<
Settings::getInstance()->getString("ScraperUsernameScreenScraper") <<
"' was not included in the scraper response, wrong username or password?";
}
}
// Scraping allowance.
if (maxRequestsPerDay > 0) {
LOG(LogDebug) << "ScreenScraperRequest::processGame(): Daily scraping allowance: " <<
requestsToday << "/" << maxRequestsPerDay << " (" <<
@ -487,10 +505,21 @@ void ScreenScraperRequest::processList(const pugi::xml_document& xmldoc,
std::string ScreenScraperRequest::ScreenScraperConfig::getGameSearchUrl(
const std::string gameName) const
{
return API_URL_BASE
std::string screenScraperURL = API_URL_BASE
+ "/jeuInfos.php?devid=" + Utils::String::scramble(API_DEV_U, API_DEV_KEY)
+ "&devpassword=" + Utils::String::scramble(API_DEV_P, API_DEV_KEY)
+ "&softname=" + HttpReq::urlEncode(API_SOFT_NAME)
+ "&output=xml"
+ "&romnom=" + HttpReq::urlEncode(gameName);
// Username / password, if this has been setup and activated.
if (Settings::getInstance()->getBool("ScraperUseAccountScreenScraper")) {
std::string username = Settings::getInstance()->getString("ScraperUsernameScreenScraper");
std::string password = Settings::getInstance()->getString("ScraperPasswordScreenScraper");
if (!username.empty() && !password.empty())
screenScraperURL += "&ssid=" + HttpReq::urlEncode(username) + "&sspassword=" +
HttpReq::urlEncode(password);
}
return screenScraperURL;
}

View file

@ -81,6 +81,9 @@ void Settings::setDefaults()
// Scraper.
mStringMap["Scraper"] = "screenscraper";
mBoolMap["ScraperUseAccountScreenScraper"] = false;
mStringMap["ScraperUsernameScreenScraper"] = "";
mStringMap["ScraperPasswordScreenScraper"] = "";
mBoolMap["ScrapeGameNames"] = true;
mBoolMap["ScrapeRatings"] = true;
mBoolMap["ScrapeMetadata"] = true;