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}