use crate::{
DeviceProperties,
api::{
endpoint::Requester,
login::{AuthToken, checkin, fetch_auth, toc, upload_device},
},
client::{Client, ClientRequester, async_doc},
error::{LoginError, PropsError},
};
pub struct LongLivedClient {
aas_token: String,
email: String,
props: DeviceProperties,
auth_token: AuthToken,
checkin_token: String,
config_token: String,
dfe_cookie: String,
gsf: i64,
}
impl LongLivedClient {
#[doc = async_doc!(r#"let mut props_map = gpipipi::PropsMap::parse_aurora_config(PROPS)?;
let props = props_map.remove("arm").ok_or("No 'arm' device props!")?;
let client = gpipipi::LongLivedClient::login(email, aas_token, props).await?;"#)]
pub async fn login<A: Into<String>, B: Into<String>>(
email: A,
aas_token: B,
props: DeviceProperties,
) -> Result<Self, LoginError> {
let email = email.into();
let aas_token = aas_token.into();
let checkin_response = checkin(&props).await?;
let gsf = checkin_response
.android_id
.ok_or(LoginError::NoAndroidId())?
.cast_signed();
let checkin_token = checkin_response
.device_checkin_consistency_token
.ok_or(LoginError::NoDeviceToken())?;
let upload_response = upload_device(&props, gsf, &checkin_token).await?;
let config_token = upload_response
.upload_device_config_token
.ok_or(LoginError::NoConfigToken())?;
let auth_token = fetch_auth(&props, &aas_token, &email, gsf).await?;
let dfe_cookie = toc(&auth_token, gsf, &checkin_token, &props).await?;
Ok(Self {
aas_token,
email,
props,
auth_token,
checkin_token,
config_token,
dfe_cookie,
gsf,
})
}
}
impl ClientRequester for LongLivedClient {
async fn requester(&self) -> Result<Requester<'_>, PropsError> {
Requester::new()
.checkin_token(&self.checkin_token)
.config_token(&self.config_token)
.auth_token(&self.auth_token)
.dfe_cookie(&self.dfe_cookie)
.aas_token(&self.aas_token)
.email(&self.email)
.props(&self.props)
.gsf(self.gsf)
.default_headers()
.await
}
}
impl Client for LongLivedClient {}