use crate::{Client, Limit, RoboatError, User};
use serde::{Deserialize, Serialize};
mod request_types;
const GROUP_ROLES_API: &str = "https://groups.roblox.com/v1/groups/{group_id}/roles";
const GROUP_ROLE_MEMBERS_SORT_ORDER: &str = "Desc";
const GROUP_ROLE_MEMBERS_API: &str =
"https://groups.roblox.com/v1/groups/{group_id}/roles/{role_id}/users?cursor={cursor}&limit={limit}&sortOrder={sort_order}";
const CHANGE_GROUP_MEMBER_ROLE_API: &str =
"https://groups.roblox.com/v1/groups/{group_id}/users/{user_id}";
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
pub struct Role {
pub id: u64,
pub name: String,
pub rank: u8,
#[serde(alias = "memberCount")]
pub member_count: u64,
}
impl Client {
pub async fn group_roles(&self, group_id: u64) -> Result<Vec<Role>, RoboatError> {
let formatted_url = GROUP_ROLES_API.replace("{group_id}", &group_id.to_string());
let request_result = self.reqwest_client.get(formatted_url).send().await;
let response = Self::validate_request_result(request_result).await?;
let raw = Self::parse_to_raw::<request_types::RolesResponse>(response).await?;
let mut roles = raw.roles;
roles.sort_by(|a, b| a.rank.cmp(&b.rank));
Ok(roles)
}
pub async fn group_role_members(
&self,
group_id: u64,
role_id: u64,
limit: Limit,
cursor: Option<String>,
) -> Result<(Vec<User>, Option<String>), RoboatError> {
let formatted_url = GROUP_ROLE_MEMBERS_API
.replace("{group_id}", &group_id.to_string())
.replace("{role_id}", &role_id.to_string())
.replace("{cursor}", &cursor.unwrap_or_default())
.replace("{limit}", &limit.to_u64().to_string())
.replace("{sort_order}", GROUP_ROLE_MEMBERS_SORT_ORDER);
let request_result = self.reqwest_client.get(formatted_url).send().await;
let response = Self::validate_request_result(request_result).await?;
let raw = Self::parse_to_raw::<request_types::RoleMembersResponse>(response).await?;
let mut users = Vec::new();
for member in raw.data {
users.push(User {
user_id: member.user_id,
username: member.username,
display_name: member.display_name,
});
}
let next_cursor = raw.next_page_cursor;
Ok((users, next_cursor))
}
pub async fn set_group_member_role(
&self,
user_id: u64,
group_id: u64,
role_id: u64,
) -> Result<(), RoboatError> {
match self
.set_group_member_role_internal(user_id, group_id, role_id)
.await
{
Ok(x) => Ok(x),
Err(e) => match e {
RoboatError::InvalidXcsrf(new_xcsrf) => {
self.set_xcsrf(new_xcsrf).await;
self.set_group_member_role_internal(user_id, group_id, role_id)
.await
}
_ => Err(e),
},
}
}
}
mod internal {
use super::CHANGE_GROUP_MEMBER_ROLE_API;
use crate::{Client, RoboatError, XCSRF_HEADER};
use reqwest::header;
impl Client {
pub(super) async fn set_group_member_role_internal(
&self,
user_id: u64,
group_id: u64,
role_id: u64,
) -> Result<(), RoboatError> {
let formatted_url = CHANGE_GROUP_MEMBER_ROLE_API
.replace("{group_id}", &group_id.to_string())
.replace("{user_id}", &user_id.to_string());
let cookie = self.cookie_string()?;
let xcsrf = self.xcsrf().await;
let json = serde_json::json!({ "roleId": role_id });
let request_result = self
.reqwest_client
.patch(formatted_url)
.json(&json)
.header(header::COOKIE, cookie)
.header(XCSRF_HEADER, xcsrf)
.send()
.await;
let _ = Self::validate_request_result(request_result).await?;
Ok(())
}
}
}