1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
mod errors;
mod games;
mod https;
mod users;

pub use errors::ApiResult;
pub use games::models::{DevProduct, Game, Server};
pub use games::GameBuilder;
pub use https::Https;
pub use users::models::User;
pub use users::UserBuilder;

use reqwest::Method;

// STATIC URLS
pub(crate) const BASE: &str = "https://api.roblox.com";
#[allow(dead_code)]
pub(crate) const AUTH: &str = "https://auth.roblox.com/v1/account/pin/unlock";
#[allow(dead_code)]
pub(crate) const ACCOUNT: &str = "https://accountinformation.roblox.com/v1";
#[allow(dead_code)]
pub(crate) const MESSAGES: &str = "https://privatemessages.roblox.com/v1";
pub(crate) const USER: &str = "https://users.roblox.com/v1";
pub(crate) const GAMES: &str = "https://games.roblox.com/v1";
#[allow(dead_code)]
pub(crate) const GROUPS: &str = "https://groups.roblox.com/v1";
#[allow(dead_code)]
pub(crate) const PRESENCE: &str = "https://presence.roblox.com/v1/presence/users";
#[allow(dead_code)]
pub(crate) const ECONOMY: &str = "https://economy.roblox.com/v1/assets";
#[allow(dead_code)]
pub(crate) const INVENTORY: &str = "https://inventory.roblox.com";
#[allow(dead_code)]
pub(crate) const DEVPAGE: &str = "https://develop.roblox.com/v1/universes";

#[derive(Debug, Clone)]
pub struct Client {
    pub session: crate::Https,
}

impl Default for Client {
    fn default() -> Self {
        Self::new()
    }
}

impl Client {
    /// Create a new client instance
    pub fn new() -> Self {
        Self {
            session: crate::Https::new(),
        }
    }

    /// Create a new user given user_id
    /// ## Example
    /// ```
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let mut client = robloxapi::Client::new();
    ///     let user = client.user(242872495).await;
    /// }
    /// ```
    pub async fn user(&mut self, builder: impl UserBuilder) -> User {
        builder.new(&mut self.session).await
    }

    /// Get the current user. Must be logged in with a cookie to get current_user
    /// # Example
    /// ```
    /// #[tokio::main]
    /// async fn main() {
    ///     let COOKIE: &str = "";
    ///     let mut client = robloxapi::Client::new();
    ///     client.set_cookie(COOKIE).await;
    ///     let current_user = client.current_user().await;
    /// }
    //
    pub async fn current_user(self: &mut Client) -> User {
        let data = self
            .session
            .request::<serde_json::Value>(Method::GET, "https://www.roblox.com/mobileapi/userinfo")
            .await
            .expect("Failed to get user info");

        let builder = data.get("UserID").unwrap().as_u64().unwrap();
        UserBuilder::new(builder, &mut self.session).await
    }

    /// Returns a Game struct given the place ID. Get information about a game.
    /// ## Example
    /// ```
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let place_id = 7415484311; // Place ID for game
    ///     let mut client = robloxapi::Client::new(); // Initialize a new client instance
    ///
    ///     // Create a new game given place id
    ///     let game = client.game(place_id).await;
    /// }
    /// ````
    pub async fn game(&self, builder: impl GameBuilder) -> ApiResult<Game> {
        builder.new(&mut self.session.clone()).await
    }
}