Skip to main content

rbxapi/
api.rs

1use reqwest::header;
2
3use crate::{User, UserBuilder};
4use crate::{Game, GameBuilder};
5
6pub(crate) const BASE: &str = "https://api.roblox.com";
7#[allow(dead_code)]
8pub(crate) const AUTH: &str = "https://auth.roblox.com/v1/account/pin/unlock";
9#[allow(dead_code)]
10pub(crate) const ACCOUNT: &str = "https://accountinformation.roblox.com/v1";
11#[allow(dead_code)]
12pub(crate) const MESSAGES: &str = "https://privatemessages.roblox.com/v1";
13pub(crate) const USER: &str = "https://users.roblox.com/v1";
14pub(crate) const GAMES: &str = "https://games.roblox.com/v1";
15#[allow(dead_code)]
16pub(crate) const GROUPS: &str = "https://groups.roblox.com/v1";
17#[allow(dead_code)]
18pub(crate) const PRESENCE: &str = "https://presence.roblox.com/v1/presence/users";
19#[allow(dead_code)]
20pub(crate) const ECONOMY: &str = "https://economy.roblox.com/v1/assets";
21#[allow(dead_code)]
22pub(crate) const INVENTORY: &str = "https://inventory.roblox.com";
23
24#[derive(Debug)]
25pub struct Client {
26    pub session: reqwest::Client
27}
28
29impl Default for Client {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34
35impl Client {
36    pub fn new() -> Self {
37        Self {
38            session: reqwest::Client::builder().cookie_store(true).build().unwrap()
39        }
40    }
41
42    pub async fn cookie(mut self, cookie: &str) -> Self {
43        let mut headers = header::HeaderMap::new();
44        headers.insert(header::COOKIE,
45                       header::HeaderValue::from_str(&*(".ROBLOSECURITY=".to_owned() + cookie)).unwrap());
46        headers.insert(header::CONTENT_LENGTH,
47                       header::HeaderValue::from_static("0"));
48
49        let resp = reqwest::Client::new().post("https://catalog.roblox.com/v1/catalog/items/details")
50            .header("content-length", "0").send().await.expect("Failed to get X-CSRF-TOKEN");
51
52        headers.insert(header::HeaderName::from_static("x-csrf-token"),
53                       header::HeaderValue::from(
54                           resp.headers().get("x-csrf-token")
55                               .unwrap_or(&header::HeaderValue::from_static(""))));
56
57        self.session = reqwest::Client::builder().cookie_store(true).user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.152 Safari/537.36")
58            .default_headers(headers).build().expect("Failed to build new client from headers");
59
60        self.validate_cookie().await;
61        self
62    }
63
64    pub async fn user(&self, builder: impl UserBuilder) -> User {
65        builder.new(&self.session).await
66    }
67
68    pub async fn current_user(&self) -> User {
69        let data = self.session.get("https://www.roblox.com/mobileapi/userinfo")
70            .send().await.expect("Failed to get user info")
71            .json::<serde_json::Value>().await.expect("Failed to get user json");
72
73        let builder = data.get("UserID").unwrap().as_u64().unwrap();
74        UserBuilder::new(builder, &self.session).await
75    }
76
77    pub async fn game(&self, builder: impl GameBuilder) -> Game {
78        builder.new(&self.session).await
79    }
80
81    async fn validate_cookie(&self) {
82        let resp = self.session.get("https://www.roblox.com/mobileapi/userinfo")
83            .send().await.expect("Failed to get user info");
84        let _: serde_json::Value = resp.json().await.expect("Failed to get json");
85    }
86}