1use crate::{error::SteamError, SteamClient};
7
8#[derive(Debug, Clone)]
10pub struct SteamGuardDetails {
11 pub is_steamguard_enabled: bool,
13 pub is_email_auth_enabled: bool,
15 pub is_mobile_auth_enabled: bool,
17 pub timestamp_steamguard_enabled: Option<u64>,
19 pub timestamp_two_factor_enabled: Option<u64>,
21 pub machine_sessions: Vec<MachineSession>,
23}
24
25#[derive(Debug, Clone)]
27pub struct MachineSession {
28 pub machine_name: String,
30 pub first_login: u64,
32 pub last_login: u64,
34 pub last_ip: Option<String>,
36}
37
38#[derive(Debug, Clone)]
40pub struct PrivacySettings {
41 pub privacy_state: u32,
43 pub privacy_state_inventory: u32,
45 pub privacy_state_gifts: u32,
47 pub privacy_state_owned_games: u32,
49 pub privacy_state_playtime: u32,
51 pub privacy_state_friends_list: u32,
53}
54
55#[derive(Debug, Clone)]
57pub struct AccountLimitations {
58 pub is_limited: bool,
60 pub is_community_banned: bool,
62 pub is_locked: bool,
64 pub can_invite_friends: bool,
66}
67
68#[derive(Debug, Clone)]
70pub struct EmailInfo {
71 pub address: String,
73 pub validated: bool,
75}
76
77#[derive(Debug, Clone)]
79pub struct VacBans {
80 pub num_bans: u32,
82 pub app_ids: Vec<u32>,
84}
85
86#[derive(Debug, Clone)]
88pub struct WalletInfo {
89 pub has_wallet: bool,
91 pub balance: i32,
93 pub currency: i32,
95}
96
97impl SteamClient {
98 pub async fn request_validation_email(&mut self) -> Result<(), SteamError> {
107 if !self.is_logged_in() {
108 return Err(SteamError::NotLoggedOn);
109 }
110
111 let request = steam_protos::CMsgClientRequestValidationEmail {};
112 self.send_message(steam_enums::EMsg::ClientRequestValidationMail, &request).await
113 }
114
115 pub async fn get_steam_guard_details(&mut self) -> Result<SteamGuardDetails, SteamError> {
126 if !self.is_logged_in() {
127 return Err(SteamError::NotLoggedOn);
128 }
129
130 let request = steam_protos::CCredentialsGetSteamGuardDetailsRequest::default();
131 self.send_service_method("Credentials.GetSteamGuardDetails#1", &request).await?;
132
133 Ok(SteamGuardDetails {
136 is_steamguard_enabled: false,
137 is_email_auth_enabled: false,
138 is_mobile_auth_enabled: false,
139 timestamp_steamguard_enabled: None,
140 timestamp_two_factor_enabled: None,
141 machine_sessions: Vec::new(),
142 })
143 }
144
145 pub async fn get_privacy_settings(&mut self) -> Result<PrivacySettings, SteamError> {
156 if !self.is_logged_in() {
157 return Err(SteamError::NotLoggedOn);
158 }
159
160 let request = steam_protos::CPlayerGetPrivacySettingsRequest {};
162 let response: steam_protos::CPlayerGetPrivacySettingsResponse = self.send_unified_request_and_wait("Player.GetPrivacySettings#1", &request).await?;
163
164 if let Some(settings) = response.privacy_settings {
165 Ok(PrivacySettings {
166 privacy_state: settings.privacy_state.unwrap_or(0) as u32,
167 privacy_state_inventory: settings.privacy_state_inventory.unwrap_or(0) as u32,
168 privacy_state_gifts: settings.privacy_state_gifts.unwrap_or(0) as u32,
169 privacy_state_owned_games: settings.privacy_state_ownedgames.unwrap_or(0) as u32,
170 privacy_state_playtime: settings.privacy_state_playtime.unwrap_or(0) as u32,
171 privacy_state_friends_list: settings.privacy_state_friendslist.unwrap_or(0) as u32,
172 })
173 } else {
174 Err(SteamError::Other("No privacy settings returned".into()))
175 }
176 }
177
178 pub fn get_account_limitations(&self) -> Result<AccountLimitations, SteamError> {
184 if let Some(limitations) = self.account.read().limitations.clone() {
185 Ok(AccountLimitations {
186 is_limited: limitations.limited,
187 is_community_banned: limitations.community_banned,
188 is_locked: limitations.locked,
189 can_invite_friends: limitations.can_invite_friends,
190 })
191 } else {
192 Err(SteamError::Other("Account limitations not available yet".into()))
193 }
194 }
195
196 pub fn get_vac_bans(&self) -> Result<VacBans, SteamError> {
202 if let Some(vac) = self.account.read().vac.clone() {
203 Ok(VacBans { num_bans: vac.num_bans, app_ids: vac.appids.clone() })
204 } else {
205 Err(SteamError::Other("VAC status not available yet".into()))
206 }
207 }
208
209 pub async fn get_credential_change_times(&mut self) -> Result<CredentialChangeTimes, SteamError> {
219 if !self.is_logged_in() {
220 return Err(SteamError::NotLoggedOn);
221 }
222
223 let request = steam_protos::CCredentialsLastCredentialChangeTimeRequest { user_changes_only: Some(true) };
224 let response: steam_protos::CCredentialsLastCredentialChangeTimeResponse = self.send_unified_request_and_wait("Credentials.GetCredentialChangeTimeDetails#1", &request).await?;
225
226 Ok(CredentialChangeTimes {
227 password_last_changed: response.timestamp_last_password_change.map(|t| t as u64),
228 email_last_changed: response.timestamp_last_email_change.map(|t| t as u64),
229 })
230 }
231
232 pub async fn get_auth_secret(&mut self) -> Result<(i32, Vec<u8>), SteamError> {
238 if !self.is_logged_in() {
239 return Err(SteamError::NotLoggedOn);
240 }
241
242 let request = steam_protos::CCredentialsGetAccountAuthSecretRequest::default();
243 let response: steam_protos::CCredentialsGetAccountAuthSecretResponse = self.send_unified_request_and_wait("Credentials.GetAccountAuthSecret#1", &request).await?;
244
245 Ok((response.secret_id.unwrap_or(0), response.secret.unwrap_or_default()))
246 }
247}
248
249#[derive(Debug, Clone)]
251pub struct CredentialChangeTimes {
252 pub password_last_changed: Option<u64>,
254 pub email_last_changed: Option<u64>,
256}
257
258#[derive(Debug, Clone)]
260pub struct AccountInfo {
261 pub name: String,
263 pub country: String,
265 pub authed_machines: i32,
267 pub flags: u32,
269 pub facebook_id: Option<u64>,
271 pub facebook_name: Option<String>,
273 pub phone_verified: bool,
275 pub two_factor_state: u32,
277}
278
279impl From<&steam_protos::CMsgClientAccountInfo> for AccountInfo {
280 fn from(msg: &steam_protos::CMsgClientAccountInfo) -> Self {
281 Self {
282 name: msg.persona_name.clone().unwrap_or_default(),
283 country: msg.ip_country.clone().unwrap_or_default(),
284 authed_machines: msg.count_authed_computers.unwrap_or(0),
285 flags: msg.account_flags.unwrap_or(0),
286 facebook_id: msg.facebook_id,
287 facebook_name: msg.facebook_name.clone(),
288 phone_verified: msg.is_phone_verified.unwrap_or(false),
289 two_factor_state: msg.two_factor_state.unwrap_or(0),
290 }
291 }
292}