diff options
author | Nick Siakas <nikos.siakas@gmail.com> | 2020-08-23 13:12:29 +0300 |
---|---|---|
committer | NickSiak <nikos.siakas@gmail.com> | 2022-03-23 20:44:54 +0200 |
commit | 0d91930f19527923949d484f9008f87651bd7e86 (patch) | |
tree | 50d3099c87772eb5311c7d58cfefc36c5f895dd4 | |
parent | a17f77719bd8b5cc85cae82dfc0365851d9f2c8e (diff) |
Game Settings: Add login to RetroAchievements
-rw-r--r-- | addons/resource.language.en_gb/resources/strings.po | 70 | ||||
-rwxr-xr-x | system/settings/settings.xml | 36 | ||||
-rw-r--r-- | xbmc/games/GameSettings.cpp | 150 | ||||
-rw-r--r-- | xbmc/games/GameSettings.h | 9 |
4 files changed, 259 insertions, 6 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index 17e91bdfd6..8d1b9a5fab 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -8710,7 +8710,17 @@ msgctxt "#15311" msgid "Path:" msgstr "" -#empty strings from id 15312 to 15999 +#. Game settings category name +#: system/settings/settings.xml +msgctxt "#15312" +msgid "Achievements" +msgstr "" + +#. Group label for Achievements category in game settings +#: system/settings/settings.xml +msgctxt "#15313" +msgid "Login to RetroAchievements" +msgstr "" #. Label for button in the in-game savestate manager #: xbmc/games/dialogs/osd/DialogInGameSaves.cpp @@ -18366,7 +18376,63 @@ msgctxt "#35261" msgid "New game" msgstr "" -#empty strings from id 35262 to 35504 +#. Help text for RetroAchievements username input setting +#: system/settings/settings.xml +msgctxt "#35262" +msgid "Enter your RetroAchievements account username" +msgstr "" + +#. Help text for RetroAchievements password input setting +#: system/settings/settings.xml +msgctxt "#35263" +msgid "Enter your RetroAchievements account password" +msgstr "" + +#. Label for notification events regarding RetroAchievements login +#: xbmc/games/GameSettings.cpp +msgctxt "#35264" +msgid "RetroAchievements" +msgstr "" + +#. Description for notification event regarding unsuccessful RetroAchievements login +#: xbmc/games/GameSettings.cpp +msgctxt "#35265" +msgid "Incorrect User/Password!" +msgstr "" + +#. Description for notification event regarding unsuccessful RetroAchievements login +#: xbmc/games/GameSettings.cpp +msgctxt "#35266" +msgid "Failed to contact server" +msgstr "" + +#. Description for notification event regarding unsuccessful RetroAchievements login +#: xbmc/games/GameSettings.cpp +msgctxt "#35267" +msgid "Invalid response from server" +msgstr "" + +#. Setting to show if the user is logged in to RetroAchievements +#. Settings -> Games -> Achievements -> Logged in +#: system/settings/settings.xml +msgctxt "#35268" +msgid "Logged in" +msgstr "" + +#. Help text for the setting that shows if the user is logged in to RetroAchievements +#. Settings -> Games -> Achievements -> Logged in +#: system/settings/settings.xml +msgctxt "#35269" +msgid "Toggle this setting to log in or out of RetroAchievemts." +msgstr "" + +#. Description for notification event regarding unsuccessful RetroAchievements login +#: xbmc/games/GameSettings.cpp +msgctxt "#35270" +msgid "Your account is not verified. Please check your email to complete your sign up." +msgstr "" + +#empty strings from id 35271 to 35504 #. connection state "host unreachable" #: xbmc/pvr/addons/PVRClients.cpp diff --git a/system/settings/settings.xml b/system/settings/settings.xml index 36b2f7fa47..549cd40af6 100755 --- a/system/settings/settings.xml +++ b/system/settings/settings.xml @@ -2416,6 +2416,42 @@ </setting> </group> </category> + <category id="gamesachievements" label="15312"> + <group id="1" label="15313"> + <setting id="gamesachievements.username" type="string" label="1048" help="35262"> + <level>0</level> + <default></default> + <constraints> + <allowempty>true</allowempty> + </constraints> + <control type="edit" format="string"/> + </setting> + <setting id="gamesachievements.password" type="string" label="733" help="35263"> + <level>0</level> + <default></default> + <constraints> + <allowempty>true</allowempty> + </constraints> + <control type="edit" format="string"> + <hidden>true</hidden> + </control> + </setting> + <setting id="gamesachievements.token" type="string"> + <visible>false</visible> + <default></default> + <constraints> + <allowempty>true</allowempty> + </constraints> + <control type="edit" format="string"/> + </setting> + <setting id="gamesachievements.loggedin" type="boolean" label="35268" help="35269"> + <visible>true</visible> + <level>0</level> + <default>false</default> + <control type="toggle" /> + </setting> + </group> + </category> </section> <section id="system" label="13000" help="36349"> <category id="display" label="14220" help="36603"> diff --git a/xbmc/games/GameSettings.cpp b/xbmc/games/GameSettings.cpp index fb57b815a3..acbccdc6fb 100644 --- a/xbmc/games/GameSettings.cpp +++ b/xbmc/games/GameSettings.cpp @@ -9,11 +9,20 @@ #include "GameSettings.h" #include "ServiceBroker.h" +#include "URL.h" +#include "events/EventLog.h" +#include "events/NotificationEvent.h" +#include "filesystem/File.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "settings/lib/Setting.h" +#include "utils/JSONVariantParser.h" +#include "utils/StringUtils.h" +#include "utils/Variant.h" +#include "utils/log.h" #include <algorithm> +#include <vector> using namespace KODI; using namespace GAME; @@ -25,16 +34,27 @@ const std::string SETTING_GAMES_SHOW_OSD_HELP = "gamesgeneral.showosdhelp"; const std::string SETTING_GAMES_ENABLEAUTOSAVE = "gamesgeneral.enableautosave"; const std::string SETTING_GAMES_ENABLEREWIND = "gamesgeneral.enablerewind"; const std::string SETTING_GAMES_REWINDTIME = "gamesgeneral.rewindtime"; +const std::string SETTING_GAMES_ACHIEVEMENTS_USERNAME = "gamesachievements.username"; +const std::string SETTING_GAMES_ACHIEVEMENTS_PASSWORD = "gamesachievements.password"; +const std::string SETTING_GAMES_ACHIEVEMENTS_TOKEN = "gamesachievements.token"; +const std::string SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN = "gamesachievements.loggedin"; + +constexpr auto LOGIN_TO_RETRO_ACHIEVEMENTS_URL_TEMPLATE = + "http://retroachievements.org/dorequest.php?r=login&u={}&p={}"; +constexpr auto GET_PATCH_DATA_URL_TEMPLATE = + "http://retroachievements.org/dorequest.php?r=patch&u={}&t={}&g=0"; +constexpr auto SUCCESS = "Success"; +constexpr auto TOKEN = "Token"; } // namespace CGameSettings::CGameSettings() { m_settings = CServiceBroker::GetSettingsComponent()->GetSettings(); - m_settings->RegisterCallback(this, { - SETTING_GAMES_ENABLEREWIND, - SETTING_GAMES_REWINDTIME, - }); + m_settings->RegisterCallback(this, {SETTING_GAMES_ENABLEREWIND, SETTING_GAMES_REWINDTIME, + SETTING_GAMES_ACHIEVEMENTS_USERNAME, + SETTING_GAMES_ACHIEVEMENTS_PASSWORD, + SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN}); } CGameSettings::~CGameSettings() @@ -85,6 +105,16 @@ unsigned int CGameSettings::MaxRewindTimeSec() return static_cast<unsigned int>(std::max(rewindTimeSec, 0)); } +std::string CGameSettings::GetRAUsername() const +{ + return m_settings->GetString(SETTING_GAMES_ACHIEVEMENTS_USERNAME); +} + +std::string CGameSettings::GetRAToken() const +{ + return m_settings->GetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN); +} + void CGameSettings::OnSettingChanged(const std::shared_ptr<const CSetting>& setting) { if (setting == nullptr) @@ -97,4 +127,116 @@ void CGameSettings::OnSettingChanged(const std::shared_ptr<const CSetting>& sett SetChanged(); NotifyObservers(ObservableMessageSettingsChanged); } + else if (settingId == SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN && + std::dynamic_pointer_cast<const CSettingBool>(setting)->GetValue()) + { + const std::string username = m_settings->GetString(SETTING_GAMES_ACHIEVEMENTS_USERNAME); + const std::string password = m_settings->GetString(SETTING_GAMES_ACHIEVEMENTS_PASSWORD); + std::string token = m_settings->GetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN); + + token = LoginToRA(username, password, std::move(token)); + + m_settings->SetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN, token); + + if (!token.empty()) + { + m_settings->SetBool(SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN, true); + } + else + { + if (settingId == SETTING_GAMES_ACHIEVEMENTS_PASSWORD) + m_settings->SetString(SETTING_GAMES_ACHIEVEMENTS_PASSWORD, ""); + m_settings->SetBool(SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN, false); + } + + m_settings->Save(); + } + else if (settingId == SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN && + !std::dynamic_pointer_cast<const CSettingBool>(setting)->GetValue()) + { + m_settings->SetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN, ""); + m_settings->Save(); + } + else if (settingId == SETTING_GAMES_ACHIEVEMENTS_USERNAME || + settingId == SETTING_GAMES_ACHIEVEMENTS_PASSWORD) + { + m_settings->SetBool(SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN, false); + m_settings->SetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN, ""); + m_settings->Save(); + } +} + +std::string CGameSettings::LoginToRA(const std::string& username, + const std::string& password, + std::string token) const +{ + if (username.empty() || password.empty()) + return token; + + XFILE::CFile request; + const CURL loginUrl( + StringUtils::Format(LOGIN_TO_RETRO_ACHIEVEMENTS_URL_TEMPLATE, username, password)); + + std::vector<uint8_t> response; + if (request.LoadFile(loginUrl, response) > 0) + { + std::string strResponse(response.begin(), response.end()); + CVariant data(CVariant::VariantTypeObject); + if (CJSONVariantParser::Parse(strResponse, data)) + { + if (data[SUCCESS].asBoolean()) + { + token = data[TOKEN].asString(); + if (!IsAccountVerified(username, token)) + { + token.clear(); + // "RetroAchievements", "Your account is not verified, please check your emails to complete your sign up" + CServiceBroker::GetEventLog()->AddWithNotification( + EventPtr(new CNotificationEvent(35264, 35270, EventLevel::Error))); + } + } + else + { + token.clear(); + + // "RetroAchievements", "Incorrect User/Password!" + CServiceBroker::GetEventLog()->AddWithNotification( + EventPtr(new CNotificationEvent(35264, 35265, EventLevel::Error))); + } + } + else + { + // "RetroAchievements", "Invalid response from server" + CServiceBroker::GetEventLog()->AddWithNotification( + EventPtr(new CNotificationEvent(35264, 35267, EventLevel::Error))); + + CLog::Log(LOGERROR, "Invalid server response: {}", strResponse); + } + } + else + { + // "RetroAchievements", "Failed to contact server" + CServiceBroker::GetEventLog()->AddWithNotification( + EventPtr(new CNotificationEvent(35264, 35266, EventLevel::Error))); + } + return token; +} + +bool CGameSettings::IsAccountVerified(const std::string& username, const std::string& token) const +{ + XFILE::CFile request; + const CURL getPatchFileUrl(StringUtils::Format(GET_PATCH_DATA_URL_TEMPLATE, username, token)); + std::vector<uint8_t> response; + if (request.LoadFile(getPatchFileUrl, response) > 0) + { + std::string strResponse(response.begin(), response.end()); + CVariant data(CVariant::VariantTypeObject); + + if (CJSONVariantParser::Parse(strResponse, data)) + { + return data[SUCCESS].asBoolean(); + } + } + + return false; } diff --git a/xbmc/games/GameSettings.h b/xbmc/games/GameSettings.h index 59acac1975..63ee67b379 100644 --- a/xbmc/games/GameSettings.h +++ b/xbmc/games/GameSettings.h @@ -11,6 +11,8 @@ #include "settings/lib/ISettingCallback.h" #include "utils/Observer.h" +#include <string> + class CSetting; class CSettings; @@ -33,11 +35,18 @@ public: bool AutosaveEnabled(); bool RewindEnabled(); unsigned int MaxRewindTimeSec(); + std::string GetRAUsername() const; + std::string GetRAToken() const; // Inherited from ISettingCallback void OnSettingChanged(const std::shared_ptr<const CSetting>& setting) override; private: + std::string LoginToRA(const std::string& username, + const std::string& password, + std::string token) const; + bool IsAccountVerified(const std::string& username, const std::string& token) const; + // Construction parameters std::shared_ptr<CSettings> m_settings; }; |