robloxapi_s/games/mod.rs
1pub mod models;
2
3use self::models::{DevProduct, Game, Server};
4use crate::ApiResult;
5
6use async_trait::async_trait;
7use reqwest::Method;
8
9#[async_trait]
10pub trait GameBuilder {
11 async fn new(self, client: &mut crate::Https) -> ApiResult<Game>;
12}
13
14#[async_trait]
15impl GameBuilder for u64 {
16 async fn new(self: u64, client: &mut crate::Https) -> ApiResult<Game> {
17 let udata: _ = client
18 .request::<serde_json::Value>(
19 Method::GET,
20 &format!(
21 "{}/games/multiget-place-details?placeIds={}",
22 crate::GAMES,
23 self
24 ),
25 )
26 .await
27 .expect("Failed to get game universe info");
28
29 let fdata = client
30 .request::<serde_json::Value>(
31 Method::GET,
32 &format!(
33 "{}/games?universeIds={}",
34 crate::GAMES,
35 udata[0]
36 .get("universeId")
37 .expect("Failed to find game universe ID")
38 ),
39 )
40 .await
41 .expect("Failed to get game root info");
42
43 Ok(Game {
44 client: client.clone(),
45 ..serde_json::from_value(
46 fdata.get("data").expect("Failed to get game root data")[0].clone(),
47 )
48 .expect("Failed to parse into Game")
49 })
50 // client.request::<Game>(Method::GET,
51 // &format!(
52 // "{}/games/multiget-place-details?placeIds={}",
53 // crate::GAMES,
54 // self
55 // )).await
56 }
57}
58
59impl Game {
60 /// Get a list of servers from the Game
61 /// # Example
62 /// ```
63 ///
64 /// #[tokio::main]
65 /// async fn main() {
66 ///
67 /// // Place ID
68 /// let game_id = 7415484311;
69 /// let mut client = robloxapi::Client::new();
70 /// // List of servers
71 /// let servers = client.game(game_id)
72 /// .await
73 /// .unwrap()
74 /// .servers();
75 /// }
76 ///
77 /// ```
78 pub async fn servers(&mut self) -> Vec<Server> {
79 if let Some(servers) = self.servers.clone() {
80 servers
81 } else {
82 let mut servers: Vec<Server> = vec![];
83 let mut data = self
84 .client
85 .request::<serde_json::Value>(
86 Method::GET,
87 &format!(
88 "{}/games/{}/servers/Public?limit=100",
89 crate::GAMES,
90 self.place_id
91 ),
92 )
93 .await
94 .expect("Failed to get server list");
95
96 while let Some(cursor) = data.clone().get("nextPageCursor") {
97 if cursor.is_null() {
98 break;
99 }
100
101 if let Some(info) = data.get("data") {
102 let data_servers: Vec<Server> =
103 serde_json::from_value(info.clone()).unwrap_or_default();
104 servers.extend_from_slice(&data_servers[..]);
105 }
106
107 data = self
108 .client
109 .request(
110 Method::GET,
111 &format!(
112 "{}/games/{}/servers/Public?limit=100&cursor={}",
113 crate::GAMES,
114 self.place_id,
115 cursor.as_str().unwrap()
116 ),
117 )
118 .await
119 .expect("Failed to get server list");
120
121 if let Some(error) = data.get("errors") {
122 if let Some(message) = error[0].get("message") {
123 if message.as_str().unwrap() == "TooManyRequests" {
124 println!("Rate limited, sleeping for 3 seconds");
125 tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
126
127 data = self
128 .client
129 .request(
130 Method::GET,
131 &format!(
132 "{}/games/{}/servers/Public?limit=100&cursor={}",
133 crate::GAMES,
134 self.place_id,
135 cursor.as_str().unwrap()
136 ),
137 )
138 .await
139 .expect("Failed to get server list");
140 }
141 }
142
143 continue;
144 }
145 }
146
147 self.servers = Some(servers.clone());
148 servers
149 }
150 }
151
152 /// Create a developer product given name and price.
153 /// # Example
154 /// ```
155 /// #[tokio::main]
156 /// async fn main() {
157 /// let mut client = robloxapi::Client::new();
158 /// client.set_cookie(COOKIE).await;
159 ///
160 /// // Create a new game with place id 100000
161 /// let mut game = client.game(100000).await.unwrap();
162 /// // Requires client to be logged in with a cookie
163 /// match game.create_dev_product(
164 /// "devproduct1", // Name of the devproduct
165 /// 500, // Price of the devproduct
166 /// ).await {
167 /// Err(_err) => {
168 /// todo!() // Handle the error
169 /// }
170 /// Ok(dev_product) => {
171 /// todo!() // Use the DevProduct
172 /// }
173 /// };
174 /// }
175 /// ```
176 ///
177 pub async fn create_dev_product(&mut self, name: &str, price: u32) -> ApiResult<DevProduct> {
178 // Make Request To DeveloperProducts
179 self.client
180 .request::<DevProduct>(
181 Method::POST,
182 &format!(
183 "{}/{}/developerproducts?name={}&description={}&priceInRobux={}",
184 crate::DEVPAGE,
185 self.universe_id,
186 name,
187 name,
188 price
189 ),
190 )
191 .await
192 }
193}