2 * Copyright (C) 2012-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "GameSettings.h"
11 #include "ServiceBroker.h"
13 #include "events/EventLog.h"
14 #include "events/NotificationEvent.h"
15 #include "filesystem/File.h"
16 #include "settings/Settings.h"
17 #include "settings/SettingsComponent.h"
18 #include "settings/lib/Setting.h"
19 #include "utils/JSONVariantParser.h"
20 #include "utils/StringUtils.h"
21 #include "utils/Variant.h"
22 #include "utils/log.h"
32 const std::string SETTING_GAMES_ENABLE
= "gamesgeneral.enable";
33 const std::string SETTING_GAMES_SHOW_OSD_HELP
= "gamesgeneral.showosdhelp";
34 const std::string SETTING_GAMES_ENABLEAUTOSAVE
= "gamesgeneral.enableautosave";
35 const std::string SETTING_GAMES_ENABLEREWIND
= "gamesgeneral.enablerewind";
36 const std::string SETTING_GAMES_REWINDTIME
= "gamesgeneral.rewindtime";
37 const std::string SETTING_GAMES_ACHIEVEMENTS_USERNAME
= "gamesachievements.username";
38 const std::string SETTING_GAMES_ACHIEVEMENTS_PASSWORD
= "gamesachievements.password";
39 const std::string SETTING_GAMES_ACHIEVEMENTS_TOKEN
= "gamesachievements.token";
40 const std::string SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN
= "gamesachievements.loggedin";
42 constexpr auto LOGIN_TO_RETRO_ACHIEVEMENTS_URL_TEMPLATE
=
43 "http://retroachievements.org/dorequest.php?r=login&u={}&p={}";
44 constexpr auto GET_PATCH_DATA_URL_TEMPLATE
=
45 "http://retroachievements.org/dorequest.php?r=patch&u={}&t={}&g=0";
46 constexpr auto SUCCESS
= "Success";
47 constexpr auto TOKEN
= "Token";
50 CGameSettings::CGameSettings()
52 m_settings
= CServiceBroker::GetSettingsComponent()->GetSettings();
54 m_settings
->RegisterCallback(this, {SETTING_GAMES_ENABLEREWIND
, SETTING_GAMES_REWINDTIME
,
55 SETTING_GAMES_ACHIEVEMENTS_USERNAME
,
56 SETTING_GAMES_ACHIEVEMENTS_PASSWORD
,
57 SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN
});
60 CGameSettings::~CGameSettings()
62 m_settings
->UnregisterCallback(this);
65 bool CGameSettings::GamesEnabled()
67 return m_settings
->GetBool(SETTING_GAMES_ENABLE
);
70 bool CGameSettings::ShowOSDHelp()
72 return m_settings
->GetBool(SETTING_GAMES_SHOW_OSD_HELP
);
75 void CGameSettings::SetShowOSDHelp(bool bShow
)
77 if (m_settings
->GetBool(SETTING_GAMES_SHOW_OSD_HELP
) != bShow
)
79 m_settings
->SetBool(SETTING_GAMES_SHOW_OSD_HELP
, bShow
);
81 //! @todo Asynchronous save
86 void CGameSettings::ToggleGames()
88 m_settings
->ToggleBool(SETTING_GAMES_ENABLE
);
91 bool CGameSettings::AutosaveEnabled()
93 return m_settings
->GetBool(SETTING_GAMES_ENABLEAUTOSAVE
);
96 bool CGameSettings::RewindEnabled()
98 return m_settings
->GetBool(SETTING_GAMES_ENABLEREWIND
);
101 unsigned int CGameSettings::MaxRewindTimeSec()
103 int rewindTimeSec
= m_settings
->GetInt(SETTING_GAMES_REWINDTIME
);
105 return static_cast<unsigned int>(std::max(rewindTimeSec
, 0));
108 std::string
CGameSettings::GetRAUsername() const
110 return m_settings
->GetString(SETTING_GAMES_ACHIEVEMENTS_USERNAME
);
113 std::string
CGameSettings::GetRAToken() const
115 return m_settings
->GetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN
);
118 void CGameSettings::OnSettingChanged(const std::shared_ptr
<const CSetting
>& setting
)
120 if (setting
== nullptr)
123 const std::string
& settingId
= setting
->GetId();
125 if (settingId
== SETTING_GAMES_ENABLEREWIND
|| settingId
== SETTING_GAMES_REWINDTIME
)
128 NotifyObservers(ObservableMessageSettingsChanged
);
130 else if (settingId
== SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN
&&
131 std::dynamic_pointer_cast
<const CSettingBool
>(setting
)->GetValue())
133 const std::string username
= m_settings
->GetString(SETTING_GAMES_ACHIEVEMENTS_USERNAME
);
134 const std::string password
= m_settings
->GetString(SETTING_GAMES_ACHIEVEMENTS_PASSWORD
);
135 std::string token
= m_settings
->GetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN
);
137 token
= LoginToRA(username
, password
, std::move(token
));
139 m_settings
->SetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN
, token
);
143 m_settings
->SetBool(SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN
, true);
147 if (settingId
== SETTING_GAMES_ACHIEVEMENTS_PASSWORD
)
148 m_settings
->SetString(SETTING_GAMES_ACHIEVEMENTS_PASSWORD
, "");
149 m_settings
->SetBool(SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN
, false);
154 else if (settingId
== SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN
&&
155 !std::dynamic_pointer_cast
<const CSettingBool
>(setting
)->GetValue())
157 m_settings
->SetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN
, "");
160 else if (settingId
== SETTING_GAMES_ACHIEVEMENTS_USERNAME
||
161 settingId
== SETTING_GAMES_ACHIEVEMENTS_PASSWORD
)
163 m_settings
->SetBool(SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN
, false);
164 m_settings
->SetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN
, "");
169 std::string
CGameSettings::LoginToRA(const std::string
& username
,
170 const std::string
& password
,
171 std::string token
) const
173 if (username
.empty() || password
.empty())
176 XFILE::CFile request
;
178 StringUtils::Format(LOGIN_TO_RETRO_ACHIEVEMENTS_URL_TEMPLATE
, username
, password
));
180 std::vector
<uint8_t> response
;
181 if (request
.LoadFile(loginUrl
, response
) > 0)
183 std::string
strResponse(response
.begin(), response
.end());
184 CVariant
data(CVariant::VariantTypeObject
);
185 if (CJSONVariantParser::Parse(strResponse
, data
))
187 if (data
[SUCCESS
].asBoolean())
189 token
= data
[TOKEN
].asString();
190 if (!IsAccountVerified(username
, token
))
193 // "RetroAchievements", "Your account is not verified, please check your emails to complete your sign up"
194 CServiceBroker::GetEventLog()->AddWithNotification(
195 EventPtr(new CNotificationEvent(35264, 35270, EventLevel::Error
)));
202 // "RetroAchievements", "Incorrect User/Password!"
203 CServiceBroker::GetEventLog()->AddWithNotification(
204 EventPtr(new CNotificationEvent(35264, 35265, EventLevel::Error
)));
209 // "RetroAchievements", "Invalid response from server"
210 CServiceBroker::GetEventLog()->AddWithNotification(
211 EventPtr(new CNotificationEvent(35264, 35267, EventLevel::Error
)));
213 CLog::Log(LOGERROR
, "Invalid server response: {}", strResponse
);
218 // "RetroAchievements", "Failed to contact server"
219 CServiceBroker::GetEventLog()->AddWithNotification(
220 EventPtr(new CNotificationEvent(35264, 35266, EventLevel::Error
)));
225 bool CGameSettings::IsAccountVerified(const std::string
& username
, const std::string
& token
) const
227 XFILE::CFile request
;
228 const CURL
getPatchFileUrl(StringUtils::Format(GET_PATCH_DATA_URL_TEMPLATE
, username
, token
));
229 std::vector
<uint8_t> response
;
230 if (request
.LoadFile(getPatchFileUrl
, response
) > 0)
232 std::string
strResponse(response
.begin(), response
.end());
233 CVariant
data(CVariant::VariantTypeObject
);
235 if (CJSONVariantParser::Parse(strResponse
, data
))
237 return data
[SUCCESS
].asBoolean();