roblox_api/api/auth_token_service/
v1.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{DateTime, Error, client::Client};
4
5pub const URL: &str = "https://apis.roblox.com/auth-token-service/v1";
6
7// TODO: look into `qr-code-image`, `entercode`, `validatecode`, `metadata`
8
9#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
10pub enum LoginStatus {
11    Created,
12    Validated,
13}
14
15#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
16#[serde(rename_all = "camelCase")]
17pub struct LoginToken {
18    pub code: String,
19    pub status: String,
20    pub private_key: String,
21    pub expiration_time: DateTime,
22    pub image_path: String,
23}
24
25#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
26#[serde(rename_all = "camelCase")]
27pub struct LoginTokenStatus {
28    pub status: LoginStatus,
29    pub account_name: Option<String>,
30    pub account_picture_url: Option<String>,
31    pub expiration_time: String,
32}
33
34#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
35#[serde(rename_all = "camelCase")]
36pub struct InspectionInfo {
37    pub location: String,
38    pub device_info: String,
39}
40
41pub async fn login_create(client: &mut Client) -> Result<LoginToken, Error> {
42    let result = client
43        .requestor
44        .client
45        .post(format!("{URL}/login/create"))
46        .headers(client.requestor.default_headers.clone())
47        .send()
48        .await;
49
50    let response = client.validate_response(result).await?;
51    client.requestor.parse_json::<LoginToken>(response).await
52}
53
54pub async fn login_cancel(client: &mut Client, code: &str) -> Result<(), Error> {
55    #[derive(Serialize)]
56    struct Request<'a> {
57        code: &'a str,
58    }
59
60    let result = client
61        .requestor
62        .client
63        .post(format!("{URL}/login/cancel"))
64        .json(&Request { code })
65        .headers(client.requestor.default_headers.clone())
66        .send()
67        .await;
68
69    client.validate_response(result).await?;
70    Ok(())
71}
72
73pub async fn login_status(
74    client: &mut Client,
75    code: &str,
76    key: &str,
77) -> Result<LoginTokenStatus, Error> {
78    #[derive(Serialize)]
79    struct Request<'a> {
80        code: &'a str,
81        #[serde(rename = "privateKey")]
82        key: &'a str,
83    }
84
85    let result = client
86        .requestor
87        .client
88        .post(format!("{URL}/login/status"))
89        .json(&Request { code, key })
90        .headers(client.requestor.default_headers.clone())
91        .send()
92        .await;
93
94    let response = client.validate_response(result).await?;
95    client
96        .requestor
97        .parse_json::<LoginTokenStatus>(response)
98        .await
99}
100
101pub async fn inspect_code(client: &mut Client, code: &str) -> Result<InspectionInfo, Error> {
102    #[derive(Serialize)]
103    struct Request<'a> {
104        code: &'a str,
105    }
106
107    let result = client
108        .requestor
109        .client
110        .post(format!("{URL}/login/enterCode"))
111        .json(&Request { code })
112        .headers(client.requestor.default_headers.clone())
113        .send()
114        .await;
115
116    let response = client.validate_response(result).await?;
117    client
118        .requestor
119        .parse_json::<InspectionInfo>(response)
120        .await
121}
122
123pub async fn validate_code(client: &mut Client, code: &str) -> Result<(), Error> {
124    #[derive(Serialize)]
125    struct Request<'a> {
126        code: &'a str,
127    }
128
129    let result = client
130        .requestor
131        .client
132        .post(format!("{URL}/login/validateCode"))
133        .json(&Request { code })
134        .headers(client.requestor.default_headers.clone())
135        .send()
136        .await;
137
138    client.validate_response(result).await?;
139    Ok(())
140}