1use serde::{Deserialize, Serialize};
2
3use crate::{DateTime, Paging, endpoint};
4
5pub const URL: &str = "https://groups.roblox.com/v1";
6
7#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
8#[serde(rename_all = "camelCase")]
9pub struct GroupUser {
10 #[serde(rename = "userId")]
11 pub id: u64,
12 #[serde(rename = "username")]
13 pub name: String,
14 pub display_name: String,
15 #[serde(rename = "hasVerifiedBadge")]
16 pub is_verified: bool,
17}
18
19#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
20#[serde(rename_all = "camelCase")]
21pub struct GroupRole {
22 pub id: u64,
23 pub name: String,
24 pub rank: u8,
25
26 pub member_count: Option<u64>,
28 pub description: Option<String>,
29}
30
31#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
32pub struct UserRole {
33 pub user: GroupUser,
34 pub role: GroupRole,
35}
36
37#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
38pub struct GroupShout {
39 pub body: String,
40 pub poster: GroupUser,
41 pub created: DateTime,
42 pub updated: DateTime,
43}
44
45#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
46#[serde(rename_all = "camelCase")]
47pub struct NameHistory {
48 pub names: Vec<(String, DateTime)>,
49 pub next_cursor: Option<String>,
50 pub previous_cursor: Option<String>,
51}
52
53#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
54pub struct WallPost {
55 pub id: u64,
56 pub body: String,
57 pub created: DateTime,
58 pub updated: DateTime,
59 pub poster: GroupUser,
60}
61
62#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
63#[serde(rename_all = "camelCase")]
64pub struct WallPosts {
65 #[serde(rename = "data")]
66 pub posts: Vec<WallPost>,
67 pub next_cursor: Option<String>,
68 pub previous_cursor: Option<String>,
69}
70
71#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
72#[serde(rename_all = "camelCase")]
73pub struct PostPermissions {
74 pub view_wall: bool,
75 pub post_to_wall: bool,
76 pub delete_from_wall: bool,
77
78 pub view_status: bool,
79 pub post_to_status: bool,
80}
81
82#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
83#[serde(rename_all = "camelCase")]
84pub struct ForumsPermissions {
85 pub pin_posts: bool,
86 pub lock_posts: bool,
87 pub create_posts: bool,
88 pub remove_posts: bool,
89
90 pub create_comments: bool,
91 pub remove_comments: bool,
92
93 pub manage_categories: bool,
94}
95
96#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
97#[serde(rename_all = "camelCase")]
98pub struct ContentModerationPermissions {
99 pub manage_keyword_block_list: bool,
100 pub view_keyword_block_list: bool,
101}
102
103#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
104#[serde(rename_all = "camelCase")]
105pub struct MembershipPermissions {
106 pub change_rank: bool,
107 pub ban_members: bool,
108 pub invite_members: bool,
109 pub remove_members: bool,
110}
111
112#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
113#[serde(rename_all = "camelCase")]
114pub struct ManagementPermissions {
115 pub manage_clan: bool,
116 pub manage_relationships: bool,
117 pub view_audit_logs: bool,
118}
119
120#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
121#[serde(rename_all = "camelCase")]
122pub struct EconomyPermissions {
123 pub create_items: bool,
124 pub manage_items: bool,
125 pub advertise_group: bool,
126 pub add_group_places: bool,
127 pub spend_group_funds: bool,
128 pub manage_group_games: bool,
129
130 pub view_group_payouts: bool,
131 pub view_analytics: bool,
132}
133
134#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
135#[serde(rename_all = "camelCase")]
136pub struct OpenCloudPermissions {
137 pub use_cloud_authentication: bool,
138 pub administer_cloud_authentication: bool,
139}
140
141#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
142#[serde(rename_all = "camelCase")]
143pub struct Permissions {
144 #[serde(rename = "groupPostsPermissions")]
146 pub posts: PostPermissions,
147 #[serde(rename = "groupForumsPermissions")]
148 pub forums: ForumsPermissions,
149 #[serde(rename = "groupContentModerationPermissions")]
150 pub content_moderation: ContentModerationPermissions,
151 #[serde(rename = "groupMembershipPermissions")]
152 pub membership: MembershipPermissions,
153 #[serde(rename = "groupManagementPermissions")]
154 pub management: ManagementPermissions,
155 #[serde(rename = "groupEconomyPermissions")]
156 pub economy: EconomyPermissions,
157 #[serde(rename = "groupOpenCloudPermissions")]
158 pub open_cloud: OpenCloudPermissions,
159}
160
161#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
162#[serde(rename_all = "camelCase")]
163pub struct GroupInformation {
164 pub id: u64,
165 pub name: String,
166 pub description: String,
167
168 pub owner: Option<GroupUser>,
169 pub shout: Option<GroupShout>,
170
171 pub member_count: Option<u64>,
172 #[serde(rename = "isBuildersClubOnly")]
173 pub premium_only: bool,
174 #[serde(rename = "publicEntryAllowed")]
175 pub is_public: bool,
176 #[serde(rename = "hasVerifiedBadge")]
177 pub is_verified: bool,
178}
179
180#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
181pub struct NotificationPreference {
182 #[serde(rename = "type")]
183 pub name: String,
184 pub description: String,
185
186 pub kind: String,
187 pub enabled: bool,
188}
189
190#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
191#[serde(rename_all = "camelCase")]
192pub struct Membership {
193 #[serde(rename = "groupId")]
194 pub id: u64,
195
196 pub user_role: UserRole,
198 pub permissions: Permissions,
199
200 pub is_primary: bool,
201 pub is_pending_join: bool,
202
203 pub are_enemies_allowed: bool,
204 pub are_group_games_visible: bool,
205 pub are_group_funds_visible: bool,
206
207 pub can_configure: bool,
208
209 pub notification_preferences: Option<Vec<NotificationPreference>>,
210}
211
212#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
213pub struct RolePermissions {
214 #[serde(rename = "groupId")]
215 pub id: u64,
216 pub role: GroupRole,
217 pub permissions: Permissions,
218}
219
220#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
221#[serde(rename_all = "camelCase")]
222pub struct GroupUsers {
223 pub users: Vec<(GroupUser, GroupRole)>,
224 pub next_cursor: Option<String>,
225 pub previous_cursor: Option<String>,
226}
227
228endpoint! {
229 information(id: u64) -> GroupInformation {
230 GET "{URL}/groups/{id}";
231 }
232
233 membership(id: u64, notification_preferences: bool) -> Membership {
235 GET "{URL}/groups/{id}/membership";
236 prelude {
237 let notification_preferences = notification_preferences.to_string();
238 }
239 query {
240 "includeNotificationPreferences" => ¬ification_preferences,
241 }
242 }
243
244 name_history(id: u64) -> NameHistory {
246 GET "{URL}/groups/{id}/name-history";
247 types {
248 NameHistoryItem {
249 name: String,
250 created: DateTime,
251 }
252 Response {
253 items("data"): Vec<NameHistoryItem>,
254 next_cursor("nextPageCursor"): Option<String>,
255 previous_cursor("previousPageCursor"): Option<String>,
256 }
257 }
258 map |r: Response| NameHistory {
259 names: r.items.into_iter().map(|x| (x.name, x.created)).collect(),
260 next_cursor: r.next_cursor,
261 previous_cursor: r.previous_cursor,
262 }
263 }
264
265 pending_join_requests() -> Vec<GroupInformation> {
267 GET "{URL}/user/groups/pending";
268 types {
269 Response {
270 groups("data"): Vec<GroupInformation>,
271 }
272 }
273 map |r: Response| r.groups
274 }
275
276 roles(id: u64) -> Vec<GroupRole> {
277 GET "{URL}/groups/{id}/roles";
278 types {
279 Response {
280 roles: Vec<GroupRole>,
281 }
282 }
283 map |r: Response| r.roles
284 }
285
286 user_roles(id: u64) -> Vec<(GroupInformation, GroupRole)> {
287 GET "{URL}/users/{id}/groups/roles";
288 types {
289 GroupAndRole {
290 group: GroupInformation,
291 role: GroupRole,
292 }
293 Response {
294 items("data"): Vec<GroupAndRole>,
295 }
296 }
297 map |r: Response| r.items.into_iter().map(|x| (x.group, x.role)).collect()
298 }
299
300 roleset_permissions(id: u64, roleset_id: u64) -> RolePermissions {
302 GET "{URL}/groups/{id}/roles/{roleset_id}/permissions";
303 }
304
305 role_permissions(id: u64) -> Vec<RolePermissions> {
307 GET "{URL}/groups/{id}/roles/permissions";
308 types {
309 Response {
310 items("data"): Vec<RolePermissions>,
311 }
312 }
313 map |r: Response| r.items
314 }
315
316 users(id: u64, paging: Paging<'_>) -> GroupUsers {
317 GET "{URL}/groups/{id}/users";
318 paging_query { paging, limit = 10 }
319 types {
320 User {
321 user: GroupUser,
322 role: GroupRole,
323 }
324 Response {
325 users("data"): Vec<User>,
326 next_cursor("nextPageCursor"): Option<String>,
327 previous_cursor("previousPageCursor"): Option<String>,
328 }
329 }
330 map |r: Response| GroupUsers {
331 users: r.users.into_iter().map(|u| (u.user, u.role)).collect(),
332 next_cursor: r.next_cursor,
333 previous_cursor: r.previous_cursor,
334 }
335 }
336
337 wall_posts(id: u64, paging: Paging<'_>) -> WallPosts {
339 GET "{URL}/groups/{id}/wall/posts";
340 paging_query { paging, limit = 10 }
341 }
342
343 join(id: u64) -> () {
344 POST "{URL}/groups/{id}/users";
345 types {
346 Request<'a> {
347 session_id: &'a str,
348 redemption_token: &'a str,
349 }
350 }
351 body_serialize { Request { session_id: "", redemption_token: "" } }
352 }
353
354 remove_join_request(id: u64, user_id: u64) -> () {
355 DELETE "{URL}/groups/{id}/join-requests/users/{user_id}";
356 types { Request {} }
357 body_serialize { Request {} }
358 }
359
360 remove(id: u64, user_id: u64) -> () {
361 DELETE "{URL}/groups/{id}/users/{user_id}";
362 types { Request {} }
363 body_serialize { Request {} }
364 }
365}