roblox_api/api/groups/
v1.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{DateTime, Error, Paging, client::Client};
4
5pub const URL: &str = "https://groups.roblox.com/v1";
6
7#[derive(Clone, Debug, Deserialize)]
8pub struct GroupUser {
9    #[serde(rename = "userId")]
10    pub id: u64,
11    #[serde(rename = "username")]
12    pub name: String,
13    #[serde(rename = "displayName")]
14    pub display_name: String,
15    #[serde(rename = "hasVerifiedBadge")]
16    pub is_verified: bool,
17}
18
19#[derive(Clone, Debug, Deserialize)]
20pub struct GroupRole {
21    pub id: u64,
22    pub name: String,
23    pub rank: u8,
24}
25
26#[derive(Clone, Debug, Deserialize)]
27pub struct GroupShout {
28    pub body: String,
29    pub poster: GroupUser,
30    pub created: DateTime,
31    pub updated: DateTime,
32}
33
34#[derive(Clone, Debug, Deserialize)]
35pub struct GroupInformation {
36    pub id: u64,
37    pub name: String,
38    pub description: String,
39
40    pub owner: Option<GroupUser>,
41    pub shout: Option<GroupShout>,
42
43    #[serde(rename = "memberCount")]
44    pub member_count: u64,
45    #[serde(rename = "isBuildersClubOnly")]
46    pub premium_only: bool,
47    #[serde(rename = "publicEntryAllowed")]
48    pub is_public: bool,
49    #[serde(rename = "hasVerifiedBadge")]
50    pub is_verified: bool,
51}
52
53pub struct GroupUsers {
54    pub users: Vec<(GroupUser, GroupRole)>,
55    pub next_cursor: Option<String>,
56    pub previous_cursor: Option<String>,
57}
58
59pub async fn information(client: &mut Client, id: u64) -> Result<GroupInformation, Error> {
60    let result = client
61        .requestor
62        .client
63        .get(format!("{URL}/groups/{id}"))
64        .headers(client.requestor.default_headers.clone())
65        .send()
66        .await;
67
68    let response = client.validate_response(result).await?;
69    client
70        .requestor
71        .parse_json::<GroupInformation>(response)
72        .await
73}
74
75pub async fn roles(client: &mut Client, id: u64) -> Result<Vec<GroupRole>, Error> {
76    let result = client
77        .requestor
78        .client
79        .get(format!("{URL}/groups/{id}/roles"))
80        .headers(client.requestor.default_headers.clone())
81        .send()
82        .await;
83
84    #[derive(Clone, Debug, Deserialize)]
85    struct Response {
86        roles: Vec<GroupRole>,
87    }
88
89    let response = client.validate_response(result).await?;
90    Ok(client
91        .requestor
92        .parse_json::<Response>(response)
93        .await?
94        .roles)
95}
96
97pub async fn user_roles(
98    client: &mut Client,
99    id: u64,
100) -> Result<Vec<(GroupInformation, GroupRole)>, Error> {
101    let result = client
102        .requestor
103        .client
104        .get(format!("{URL}/users/{id}/groups/roles"))
105        .headers(client.requestor.default_headers.clone())
106        .send()
107        .await;
108
109    #[derive(Clone, Debug, Deserialize)]
110    struct GroupAndRole {
111        group: GroupInformation,
112        role: GroupRole,
113    }
114
115    #[derive(Clone, Debug, Deserialize)]
116    struct Response {
117        #[serde(rename = "data")]
118        items: Vec<GroupAndRole>,
119    }
120
121    let response = client.validate_response(result).await?;
122    let response = client.requestor.parse_json::<Response>(response).await?;
123
124    let mut roles = Vec::new();
125    for item in &response.items {
126        roles.push((item.group.clone(), item.role.clone()));
127    }
128
129    Ok(roles)
130}
131
132pub async fn users(client: &mut Client, id: u64, paging: Paging<'_>) -> Result<GroupUsers, Error> {
133    let limit = paging.limit.unwrap_or(10).to_string();
134    let sort_order = paging.order.unwrap_or_default().to_string();
135    let cursor = match paging.cursor {
136        Some(cursor) => cursor.to_string(),
137        None => String::new(),
138    };
139
140    let result = client
141        .requestor
142        .client
143        .get(format!("{URL}/groups/{id}/users"))
144        .query(&[
145            ("limit", limit),
146            ("sortOrder", sort_order),
147            ("cursor", cursor),
148        ])
149        .headers(client.requestor.default_headers.clone())
150        .send()
151        .await;
152
153    #[derive(Clone, Debug, Deserialize)]
154    struct User {
155        user: GroupUser,
156        role: GroupRole,
157    }
158
159    #[derive(Clone, Debug, Deserialize)]
160    struct Response {
161        #[serde(rename = "data")]
162        users: Vec<User>,
163        #[serde(rename = "nextPageCursor")]
164        next_cursor: Option<String>,
165        #[serde(rename = "previousPageCursor")]
166        previous_cursor: Option<String>,
167    }
168
169    let response = client.validate_response(result).await?;
170    let response = client.requestor.parse_json::<Response>(response).await?;
171
172    let mut users = Vec::new();
173    for user in response.users {
174        users.push((user.user, user.role))
175    }
176
177    Ok(GroupUsers {
178        users,
179        next_cursor: response.next_cursor,
180        previous_cursor: response.previous_cursor,
181    })
182}
183
184pub async fn join(client: &mut Client, id: u64) -> Result<(), Error> {
185    #[derive(Serialize)]
186    struct Request<'a> {
187        #[serde(rename = "sessionId")]
188        session_id: &'a str,
189        #[serde(rename = "redemptionToken")]
190        redemption_token: &'a str,
191    }
192
193    let result = client
194        .requestor
195        .client
196        .post(format!("{URL}/groups/{id}/users"))
197        .headers(client.requestor.default_headers.clone())
198        .json(&Request {
199            session_id: "",
200            redemption_token: "",
201        })
202        .send()
203        .await;
204
205    client.validate_response(result).await?;
206    Ok(())
207}
208
209pub async fn remove_join_request(client: &mut Client, id: u64, user_id: u64) -> Result<(), Error> {
210    #[derive(Serialize)]
211    struct Request {}
212
213    let result = client
214        .requestor
215        .client
216        .delete(format!("{URL}/groups/{id}/join-requests/users/{user_id}"))
217        .json(&Request {})
218        .headers(client.requestor.default_headers.clone())
219        .send()
220        .await;
221
222    client.validate_response(result).await?;
223    Ok(())
224}
225
226pub async fn remove(client: &mut Client, id: u64, user_id: u64) -> Result<(), Error> {
227    #[derive(Serialize)]
228    struct Request {}
229
230    let result = client
231        .requestor
232        .client
233        .delete(format!("{URL}/groups/{id}/users/{user_id}"))
234        .headers(client.requestor.default_headers.clone())
235        .json(&Request {})
236        .send()
237        .await;
238
239    client.validate_response(result).await?;
240    Ok(())
241}