From 3bf8b5fb9075fa8e339c85b3aa9125de9eaea137 Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Tue, 19 Mar 2024 12:41:18 -0400 Subject: [PATCH] Refactored Achievement Manager Login to use rc_client LoginCallback was created to handle the results of the asynchronous client login calls; VerifyCredentials was deleted as no longer necessary. --- Source/Core/Core/AchievementManager.cpp | 116 ++++++++++-------- Source/Core/Core/AchievementManager.h | 7 +- .../Achievements/AchievementHeaderWidget.cpp | 2 +- .../AchievementSettingsWidget.cpp | 3 +- .../Achievements/AchievementsWindow.cpp | 2 +- 5 files changed, 73 insertions(+), 57 deletions(-) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 097fdb9b5d..2eeec7bd5a 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -5,6 +5,7 @@ #include "Core/AchievementManager.h" +#include #include #include @@ -48,8 +49,8 @@ void AchievementManager::Init() m_queue.Reset("AchievementManagerQueue", [](const std::function& func) { func(); }); m_image_queue.Reset("AchievementManagerImageQueue", [](const std::function& func) { func(); }); - if (IsLoggedIn()) - Login("", [](ResponseType r_type) {}); + if (HasAPIToken()) + Login(""); INFO_LOG_FMT(ACHIEVEMENTS, "Achievement Manager Initialized"); } } @@ -64,30 +65,36 @@ void AchievementManager::SetUpdateCallback(UpdateCallback callback) m_update_callback(); } -void AchievementManager::Login(const std::string& password, const ResponseCallback& callback) +void AchievementManager::Login(const std::string& password) { - if (!m_is_runtime_initialized) + if (!m_client) { - ERROR_LOG_FMT(ACHIEVEMENTS, "Attempted login (async) to RetroAchievements server without " - "Achievement Manager initialized."); - callback(ResponseType::MANAGER_NOT_INITIALIZED); + ERROR_LOG_FMT( + ACHIEVEMENTS, + "Attempted login to RetroAchievements server without achievement client initialized."); return; } - m_queue.EmplaceItem([this, password, callback] { - callback(VerifyCredentials(password)); - FetchBadges(); - m_update_callback(); - }); + if (password.empty()) + { + rc_client_begin_login_with_token(m_client, Config::Get(Config::RA_USERNAME).c_str(), + Config::Get(Config::RA_API_TOKEN).c_str(), LoginCallback, + nullptr); + } + else + { + rc_client_begin_login_with_password(m_client, Config::Get(Config::RA_USERNAME).c_str(), + password.c_str(), LoginCallback, nullptr); + } } -bool AchievementManager::IsLoggedIn() const +bool AchievementManager::HasAPIToken() const { return !Config::Get(Config::RA_API_TOKEN).empty(); } void AchievementManager::HashGame(const std::string& file_path, const ResponseCallback& callback) { - if (!Config::Get(Config::RA_ENABLED) || !IsLoggedIn()) + if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) { callback(ResponseType::NOT_ENABLED); return; @@ -142,7 +149,7 @@ void AchievementManager::HashGame(const std::string& file_path, const ResponseCa void AchievementManager::HashGame(const DiscIO::Volume* volume, const ResponseCallback& callback) { - if (!Config::Get(Config::RA_ENABLED) || !IsLoggedIn()) + if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) { callback(ResponseType::NOT_ENABLED); return; @@ -220,7 +227,7 @@ void AchievementManager::HashGame(const DiscIO::Volume* volume, const ResponseCa void AchievementManager::LoadGameSync(const ResponseCallback& callback) { - if (!Config::Get(Config::RA_ENABLED) || !IsLoggedIn()) + if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) { callback(ResponseType::NOT_ENABLED); return; @@ -316,7 +323,7 @@ bool AchievementManager::IsGameLoaded() const void AchievementManager::LoadUnlockData(const ResponseCallback& callback) { - if (!Config::Get(Config::RA_ENABLED) || !IsLoggedIn()) + if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) { callback(ResponseType::NOT_ENABLED); return; @@ -339,7 +346,7 @@ void AchievementManager::LoadUnlockData(const ResponseCallback& callback) void AchievementManager::ActivateDeactivateAchievements() { std::lock_guard lg{m_lock}; - if (!Config::Get(Config::RA_ENABLED) || !IsLoggedIn()) + if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) return; bool enabled = Config::Get(Config::RA_ACHIEVEMENTS_ENABLED); bool unofficial = Config::Get(Config::RA_UNOFFICIAL_ENABLED); @@ -359,7 +366,7 @@ void AchievementManager::ActivateDeactivateAchievements() void AchievementManager::ActivateDeactivateLeaderboards() { std::lock_guard lg{m_lock}; - if (!Config::Get(Config::RA_ENABLED) || !IsLoggedIn()) + if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) return; bool leaderboards_enabled = Config::Get(Config::RA_LEADERBOARDS_ENABLED) && Config::Get(Config::RA_HARDCORE_ENABLED); @@ -386,7 +393,7 @@ void AchievementManager::ActivateDeactivateLeaderboards() void AchievementManager::ActivateDeactivateRichPresence() { std::lock_guard lg{m_lock}; - if (!Config::Get(Config::RA_ENABLED) || !IsLoggedIn()) + if (!Config::Get(Config::RA_ENABLED) || !HasAPIToken()) return; rc_runtime_activate_richpresence( &m_runtime, @@ -399,7 +406,7 @@ void AchievementManager::ActivateDeactivateRichPresence() void AchievementManager::FetchBadges() { - if (!m_is_runtime_initialized || !IsLoggedIn() || !Config::Get(Config::RA_BADGES_ENABLED)) + if (!m_is_runtime_initialized || !HasAPIToken() || !Config::Get(Config::RA_BADGES_ENABLED)) { m_update_callback(); return; @@ -761,12 +768,12 @@ bool AchievementManager::IsHardcoreModeActive() const std::string AchievementManager::GetPlayerDisplayName() const { - return IsLoggedIn() ? m_display_name : ""; + return HasAPIToken() ? m_display_name : ""; } u32 AchievementManager::GetPlayerScore() const { - return IsLoggedIn() ? m_player_score : 0; + return HasAPIToken() ? m_player_score : 0; } const AchievementManager::BadgeStatus& AchievementManager::GetPlayerBadge() const @@ -1007,40 +1014,49 @@ void AchievementManager::FilereaderClose(void* file_handle) delete static_cast(file_handle); } -AchievementManager::ResponseType AchievementManager::VerifyCredentials(const std::string& password) +void AchievementManager::LoginCallback(int result, const char* error_message, rc_client_t* client, + void* userdata) { - rc_api_login_response_t login_data{}; - std::string username, api_token; + if (result != RC_OK) { - std::lock_guard lg{m_lock}; - username = Config::Get(Config::RA_USERNAME); - api_token = Config::Get(Config::RA_API_TOKEN); + WARN_LOG_FMT(ACHIEVEMENTS, "Failed to login {} to RetroAchievements server.", + Config::Get(Config::RA_USERNAME)); + return; } - rc_api_login_request_t login_request = { - .username = username.c_str(), .api_token = api_token.c_str(), .password = password.c_str()}; - ResponseType r_type = Request( - login_request, &login_data, rc_api_init_login_request, rc_api_process_login_response); - if (r_type == ResponseType::SUCCESS) + + const rc_client_user_t* user; { - INFO_LOG_FMT(ACHIEVEMENTS, "Successfully logged in {} to RetroAchievements server.", username); - std::lock_guard lg{m_lock}; - if (username != Config::Get(Config::RA_USERNAME)) + std::lock_guard lg{AchievementManager::GetInstance().GetLock()}; + user = rc_client_get_user_info(client); + } + if (!user) + { + WARN_LOG_FMT(ACHIEVEMENTS, "Failed to retrieve user information from client."); + return; + } + + std::string config_username = Config::Get(Config::RA_USERNAME); + if (config_username != user->username) + { + if (Common::CaseInsensitiveEquals(config_username, user->username)) { - INFO_LOG_FMT(ACHIEVEMENTS, "Attempted to login prior user {}; current user is {}.", username, - Config::Get(Config::RA_USERNAME)); - Config::SetBaseOrCurrent(Config::RA_API_TOKEN, ""); - return ResponseType::EXPIRED_CONTEXT; + INFO_LOG_FMT(ACHIEVEMENTS, + "Case mismatch between site {} and local {}; updating local config.", + user->username, Config::Get(Config::RA_USERNAME)); + Config::SetBaseOrCurrent(Config::RA_USERNAME, user->username); + } + else + { + INFO_LOG_FMT(ACHIEVEMENTS, "Attempted to login prior user {}; current user is {}.", + user->username, Config::Get(Config::RA_USERNAME)); + rc_client_logout(client); + return; } - Config::SetBaseOrCurrent(Config::RA_API_TOKEN, login_data.api_token); - m_display_name = login_data.display_name; - m_player_score = login_data.score; } - else - { - WARN_LOG_FMT(ACHIEVEMENTS, "Failed to login {} to RetroAchievements server.", username); - } - rc_api_destroy_login_response(&login_data); - return r_type; + INFO_LOG_FMT(ACHIEVEMENTS, "Successfully logged in {} to RetroAchievements server.", + user->username); + std::lock_guard lg{AchievementManager::GetInstance().GetLock()}; + Config::SetBaseOrCurrent(Config::RA_API_TOKEN, user->token); } AchievementManager::ResponseType AchievementManager::ResolveHash(const Hash& game_hash, diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index f819610729..3f4c3d88cf 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -117,8 +117,8 @@ public: static AchievementManager& GetInstance(); void Init(); void SetUpdateCallback(UpdateCallback callback); - void Login(const std::string& password, const ResponseCallback& callback); - bool IsLoggedIn() const; + void Login(const std::string& password); + bool HasAPIToken() const; void HashGame(const std::string& file_path, const ResponseCallback& callback); void HashGame(const DiscIO::Volume* volume, const ResponseCallback& callback); bool IsGameLoaded() const; @@ -171,7 +171,8 @@ private: static size_t FilereaderRead(void* file_handle, void* buffer, size_t requested_bytes); static void FilereaderClose(void* file_handle); - ResponseType VerifyCredentials(const std::string& password); + static void LoginCallback(int result, const char* error_message, rc_client_t* client, + void* userdata); ResponseType ResolveHash(const Hash& game_hash, u32* game_id); void LoadGameSync(const ResponseCallback& callback); ResponseType StartRASession(); diff --git a/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.cpp b/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.cpp index e844d22d39..0aea31d5bf 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.cpp +++ b/Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.cpp @@ -69,7 +69,7 @@ AchievementHeaderWidget::AchievementHeaderWidget(QWidget* parent) : QWidget(pare void AchievementHeaderWidget::UpdateData() { auto& instance = AchievementManager::GetInstance(); - if (!instance.IsLoggedIn()) + if (!instance.HasAPIToken()) { m_header_box->setVisible(false); return; diff --git a/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp b/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp index ec8fde6293..01e1470175 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp +++ b/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp @@ -254,8 +254,7 @@ void AchievementSettingsWidget::ToggleRAIntegration() void AchievementSettingsWidget::Login() { Config::SetBaseOrCurrent(Config::RA_USERNAME, m_common_username_input->text().toStdString()); - AchievementManager::GetInstance().Login(m_common_password_input->text().toStdString(), - [](AchievementManager::ResponseType r_type) {}); + AchievementManager::GetInstance().Login(m_common_password_input->text().toStdString()); m_common_password_input->setText(QString()); SaveSettings(); } diff --git a/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp b/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp index 3704884a2b..f8dcda0a25 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp +++ b/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp @@ -79,7 +79,7 @@ void AchievementsWindow::UpdateData() const bool is_game_loaded = instance.IsGameLoaded(); m_header_widget->UpdateData(); - m_header_widget->setVisible(instance.IsLoggedIn()); + m_header_widget->setVisible(instance.HasAPIToken()); m_settings_widget->UpdateData(); m_progress_widget->UpdateData(); m_tab_widget->setTabVisible(1, is_game_loaded);