diff --git a/README.md b/README.md index d0ab1f4..10cefd9 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ - [ ] [Video chat support](https://github.com/polyphony-chat/chorus/issues/49) ### Permissions and Roles -- [ ] [Role management](https://github.com/polyphony-chat/chorus/issues/46) (creation, deletion, modification) +- [x] [Role management](https://github.com/polyphony-chat/chorus/issues/46) (creation, deletion, modification) - [ ] [Permission management](https://github.com/polyphony-chat/chorus/issues/46) (assigning and revoking permissions) - [ ] [Channel-specific permissions](https://github.com/polyphony-chat/chorus/issues/88) - [ ] Role-based access control diff --git a/src/api/guilds/roles.rs b/src/api/guilds/roles.rs index a65b36d..b2e9b31 100644 --- a/src/api/guilds/roles.rs +++ b/src/api/guilds/roles.rs @@ -30,7 +30,7 @@ impl types::RoleObject { let mut belongs_to = user.belongs_to.borrow_mut(); let url = format!("{}/guilds/{}/roles/", belongs_to.urls.get_api(), guild_id); let request = Client::new().get(url).bearer_auth(user.token()); - let requester = match LimitedRequester::new() + let result = match LimitedRequester::new() .await .send_request( request, @@ -43,7 +43,14 @@ impl types::RoleObject { Ok(request) => request, Err(e) => return Err(e), }; - let roles: Vec = from_str(&requester.text().await.unwrap()).unwrap(); + let roles: Vec = match from_str(&result.text().await.unwrap()) { + Ok(roles) => roles, + Err(e) => { + return Err(ChorusLibError::InvalidResponseError { + error: e.to_string(), + }) + } + }; if roles.is_empty() { return Ok(None); @@ -52,6 +59,59 @@ impl types::RoleObject { Ok(Some(roles)) } + /// Retrieves a single role for a given guild. + /// + /// # Arguments + /// + /// * `user` - A mutable reference to a [`UserMeta`] instance. + /// * `guild_id` - The ID of the guild to retrieve the role from. + /// * `role_id` - The ID of the role to retrieve. + /// + /// # Returns + /// + /// A `Result` containing the retrieved [`RoleObject`] if successful, or a [`ChorusLibError`] if the request fails or if the response is invalid. + /// + /// # Errors + /// + /// Returns a [`ChorusLibError`] if the request fails or if the response is invalid. + pub async fn get( + user: &mut UserMeta, + guild_id: &str, + role_id: &str, + ) -> Result { + let mut belongs_to = user.belongs_to.borrow_mut(); + let url = format!( + "{}/guilds/{}/roles/{}/", + belongs_to.urls.get_api(), + guild_id, + role_id + ); + let request = Client::new().get(url).bearer_auth(user.token()); + let result = match LimitedRequester::new() + .await + .send_request( + request, + crate::api::limits::LimitType::Guild, + &mut belongs_to.limits, + &mut user.limits, + ) + .await + { + Ok(request) => request, + Err(e) => return Err(e), + }; + let role: RoleObject = match from_str(&result.text().await.unwrap()) { + Ok(role) => role, + Err(e) => { + return Err(ChorusLibError::InvalidResponseError { + error: e.to_string(), + }) + } + }; + + Ok(role) + } + /// Creates a new role for a given guild. /// /// # Arguments @@ -161,4 +221,69 @@ impl types::RoleObject { }; Ok(role) } + + /// Updates a role in a guild. + /// + /// # Arguments + /// + /// * `user` - A mutable reference to a [`UserMeta`] instance. + /// * `guild_id` - The ID of the guild to update the role in. + /// * `role_id` - The ID of the role to update. + /// * `role_create_schema` - A [`RoleCreateModifySchema`] instance containing the new properties of the role. + /// + /// # Returns + /// + /// A `Result` containing the updated [`RoleObject`] if successful, or a [`ChorusLibError`] if the request fails or if the response is invalid. + /// + /// # Errors + /// + /// Returns a [`ChorusLibError`] if the request fails or if the response is invalid. + pub async fn update( + user: &mut UserMeta, + guild_id: &str, + role_id: &str, + role_create_schema: RoleCreateModifySchema, + ) -> Result { + let mut belongs_to = user.belongs_to.borrow_mut(); + let url = format!( + "{}/guilds/{}/roles/{}", + belongs_to.urls.get_api(), + guild_id, + role_id + ); + let body = match to_string::(&role_create_schema) { + Ok(string) => string, + Err(e) => { + return Err(ChorusLibError::FormCreationError { + error: e.to_string(), + }) + } + }; + let request = Client::new() + .patch(url) + .bearer_auth(user.token()) + .body(body); + let result = match LimitedRequester::new() + .await + .send_request( + request, + crate::api::limits::LimitType::Guild, + &mut belongs_to.limits, + &mut user.limits, + ) + .await + { + Ok(request) => request, + Err(e) => return Err(e), + }; + let role: RoleObject = match from_str(&result.text().await.unwrap()) { + Ok(role) => role, + Err(e) => { + return Err(ChorusLibError::InvalidResponseError { + error: e.to_string(), + }) + } + }; + Ok(role) + } } diff --git a/src/types/schema/role.rs b/src/types/schema/role.rs index 97ab248..65faa39 100644 --- a/src/types/schema/role.rs +++ b/src/types/schema/role.rs @@ -21,6 +21,6 @@ pub struct RoleCreateModifySchema { /// Represents the schema which needs to be sent to update a roles' position. /// See: [https://docs.spacebar.chat/routes/#cmp--schemas-rolepositionupdateschema](https://docs.spacebar.chat/routes/#cmp--schemas-rolepositionupdateschema) pub struct RolePositionUpdateSchema { - pub id: Snowflake, - pub position: i32, + pub id: String, + pub position: u16, } diff --git a/tests/roles.rs b/tests/roles.rs index 3eee2b8..2663d25 100644 --- a/tests/roles.rs +++ b/tests/roles.rs @@ -34,3 +34,16 @@ async fn create_and_get_roles() { assert_eq!(role, expected); common::teardown(bundle).await } + +#[tokio::test] +async fn get_singular_role() { + let mut bundle = common::setup().await; + let guild_id = &bundle.guild.id.to_string(); + let role_id = &bundle.role.id.to_string(); + let role = bundle.role.clone(); + let same_role = chorus::types::RoleObject::get(&mut bundle.user, guild_id, role_id) + .await + .unwrap(); + assert_eq!(role, same_role); + common::teardown(bundle).await +}