use scraper::{Html, Selector};
use serde_json::Value;
use crate::{
client::SteamUser,
endpoint::steam_endpoint,
error::SteamUserError,
types::{AddPhoneNumberResponse, ConfirmPhoneCodeResponse, RemovePhoneResult},
};
impl SteamUser {
#[steam_endpoint(GET, host = Store, path = "/phone/manage", kind = Read)]
pub async fn get_phone_number_status(&self) -> Result<Option<String>, SteamUserError> {
let response = self.get_path("/phone/manage").send().await?.text().await?;
let document = Html::parse_document(&response);
let header_selector = Selector::parse("h2.pageheader").expect("valid CSS selector");
if let Some(header) = document.select(&header_selector).next() {
let header_text = header.text().collect::<String>().trim().to_string();
if header_text == "Add a phone number to your account" {
return Ok(Some("none".to_string()));
} else if header_text == "Manage phone number" {
let desc_selector = Selector::parse(".phone_header_description > span").expect("valid CSS selector");
if let Some(desc) = document.select(&desc_selector).next() {
return Ok(Some(desc.text().collect::<String>().trim().to_string()));
}
}
}
Ok(None)
}
#[steam_endpoint(POST, host = Store, path = "/phone/add_ajaxop", kind = Write)]
pub async fn add_phone_number(&self, phone: &str) -> Result<AddPhoneNumberResponse, SteamUserError> {
let response: AddPhoneNumberResponse = self.post_path("/phone/add_ajaxop").header("referer", "https://store.steampowered.com/phone/add").form(&[("op", "get_phone_number"), ("input", phone), ("confirmed", "1"), ("checkfortos", "1"), ("bisediting", "0"), ("token", "0")]).send().await?.json().await?;
Ok(response)
}
#[steam_endpoint(POST, host = Store, path = "/phone/add_ajaxop", kind = Write)]
pub async fn confirm_phone_code_for_add(&self, code: &str) -> Result<ConfirmPhoneCodeResponse, SteamUserError> {
let response: ConfirmPhoneCodeResponse = self.post_path("/phone/add_ajaxop").form(&[("op", "get_sms_code"), ("input", code), ("confirmed", "1"), ("checkfortos", "1"), ("bisediting", "0"), ("token", "0")]).send().await?.json().await?;
Ok(response)
}
#[steam_endpoint(POST, host = Store, path = "/phone/add_ajaxop", kind = Write)]
pub async fn resend_phone_verification_code(&self) -> Result<Value, SteamUserError> {
let response: Value = self.post_path("/phone/add_ajaxop").form(&[("op", "retry_email_verification"), ("input", ""), ("confirmed", "1"), ("checkfortos", "1"), ("bisediting", "0"), ("token", "0")]).send().await?.json().await?;
Ok(response)
}
#[steam_endpoint(GET, host = Help, path = "/en/wizard/HelpRemovePhoneNumber", kind = Recovery)]
pub async fn get_remove_phone_number_type(&self) -> Result<Option<RemovePhoneResult>, SteamUserError> {
let response = self.get_path("/en/wizard/HelpRemovePhoneNumber?redir=store/account").send().await?.text().await?;
let document = Html::parse_document(&response);
let button_selector = Selector::parse("a.help_wizard_button").expect("valid CSS selector");
for button in document.select(&button_selector) {
let text = button.text().collect::<String>().trim().to_string();
let link = button.value().attr("href").map(|l| if l.starts_with("http") { l.to_string() } else { format!("https://help.steampowered.com{}", l) });
let mut wizard_param = None;
if let Some(ref l) = link {
if let Ok(url) = url::Url::parse(l) {
let map: std::collections::HashMap<_, _> = url.query_pairs().into_owned().collect();
if !map.is_empty() {
wizard_param = serde_json::to_value(map).ok();
}
}
}
if text == "Send a confirmation to my Steam Mobile app" {
return Ok(Some(RemovePhoneResult { success: true, method: Some(8), confirm_type: Some("SteamAppConfirm".into()), link, wizard_param }));
}
if text.starts_with("Text an account verification code to my phone number ending in") {
return Ok(Some(RemovePhoneResult { success: true, method: Some(4), confirm_type: Some("PhoneTextingConfirm".into()), link, wizard_param }));
}
if text.starts_with("Email an account verification code to") {
return Ok(Some(RemovePhoneResult { success: true, method: Some(2), confirm_type: Some("EmailConfirm".into()), link, wizard_param }));
}
}
Ok(None)
}
#[steam_endpoint(POST, host = Help, path = "/en/wizard/AjaxSendAccountRecoveryCode", kind = Recovery)]
pub async fn send_account_recovery_code(&self, wizard_param: Value, method: i32) -> Result<Value, SteamUserError> {
let mut params = wizard_param;
if let Some(obj) = params.as_object_mut() {
obj.insert("method".to_string(), Value::Number(method.into()));
obj.insert("n".to_string(), Value::Number(1.into()));
obj.insert("wizard_ajax".to_string(), Value::String("1".into()));
obj.insert("gamepad".to_string(), Value::String("0".into()));
}
let response: Value = self.post_path("/en/wizard/AjaxSendAccountRecoveryCode").form(¶ms).send().await?.json().await?;
Ok(response)
}
#[steam_endpoint(GET, host = Help, path = "/en/wizard/AjaxVerifyAccountRecoveryCode", kind = Recovery)]
pub async fn confirm_remove_phone_number_code(&self, wizard_param: Value, code: &str) -> Result<Value, SteamUserError> {
let mut params = wizard_param;
if let Some(obj) = params.as_object_mut() {
obj.insert("code".to_string(), Value::String(code.to_string()));
obj.insert("wizard_ajax".to_string(), Value::String("1".into()));
obj.insert("gamepad".to_string(), Value::String("0".into()));
}
let response: Value = self.get_path("/en/wizard/AjaxVerifyAccountRecoveryCode").query(¶ms).send().await?.json().await?;
Ok(response)
}
#[steam_endpoint(POST, host = Help, path = "/en/wizard/AjaxSendConfirmation2SteamMobileApp", kind = Recovery)]
pub async fn send_confirmation_2_steam_mobile_app(&self, wizard_param: Value) -> Result<Value, SteamUserError> {
let mut params = wizard_param;
if let Some(obj) = params.as_object_mut() {
obj.insert("wizard_ajax".to_string(), Value::String("1".into()));
obj.insert("gamepad".to_string(), Value::String("0".into()));
}
let response: Value = self.post_path("/en/wizard/AjaxSendConfirmation2SteamMobileApp").form(¶ms).send().await?.json().await?;
Ok(response)
}
#[steam_endpoint(POST, host = Help, path = "/en/wizard/AjaxSendConfirmation2SteamMobileAppFinal", kind = Recovery)]
pub async fn send_confirmation_2_steam_mobile_app_final(&self, wizard_param: Value) -> Result<Value, SteamUserError> {
let mut params = wizard_param;
if let Some(obj) = params.as_object_mut() {
obj.insert("wizard_ajax".to_string(), Value::String("1".into()));
obj.insert("gamepad".to_string(), Value::String("0".into()));
}
let response: Value = self.post_path("/en/wizard/AjaxSendConfirmation2SteamMobileAppFinal").form(¶ms).send().await?.json().await?;
Ok(response)
}
}