From 3bf911745fd3be0a40cdb799cdd6b63ac5f6c9a9 Mon Sep 17 00:00:00 2001 From: Flori Weber Date: Sun, 18 Jun 2023 13:59:11 +0200 Subject: [PATCH 01/10] Send a friend request --- tests/relationships.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/relationships.rs b/tests/relationships.rs index 08f7efb..44de72d 100644 --- a/tests/relationships.rs +++ b/tests/relationships.rs @@ -21,7 +21,12 @@ async fn test_get_mutual_relationships() { let bundle = common::setup().await; let mut belongs_to = bundle.instance; let mut user = bundle.user; - let other_user = belongs_to.register_account(®ister_schema).await.unwrap(); + let mut other_user = belongs_to.register_account(®ister_schema).await.unwrap(); + let friend_request_schema = types::FriendRequestSendSchema { + username: user.object.username.clone(), + discriminator: Some(user.object.discriminator.clone()), + }; + other_user.send_friend_request(friend_request_schema).await; let relationships = user .get_mutual_relationships(&other_user.object.id.to_string()) .await From 94ae449f7d9d923e33c924b009e0fa490cacd495 Mon Sep 17 00:00:00 2001 From: Flori Weber Date: Sun, 18 Jun 2023 14:00:12 +0200 Subject: [PATCH 02/10] Start implementing get_relationship --- src/api/users/relationships.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/api/users/relationships.rs b/src/api/users/relationships.rs index ede39f0..563b846 100644 --- a/src/api/users/relationships.rs +++ b/src/api/users/relationships.rs @@ -37,6 +37,19 @@ impl UserMeta { .await } + pub async fn get_relationships(&mut self) -> Result, ChorusLibError> { + let belongs_to = self.belongs_to.borrow(); + let url = format!("{}/users/@me/relationships/", belongs_to.urls.get_api(),); + drop(belongs_to); + let request = Client::new().get(url).bearer_auth(self.token()); + deserialize_response::>( + request, + self, + crate::api::limits::LimitType::Global, + ) + .await + } + /// Sends a friend request to a user. /// /// # Arguments From 5d6aab7d36a745bf848368d34b59bee570006db5 Mon Sep 17 00:00:00 2001 From: Flori Weber Date: Sun, 18 Jun 2023 15:39:40 +0200 Subject: [PATCH 03/10] Modift get_mutual, add get_relationships --- tests/relationships.rs | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/tests/relationships.rs b/tests/relationships.rs index 44de72d..b575046 100644 --- a/tests/relationships.rs +++ b/tests/relationships.rs @@ -18,9 +18,9 @@ async fn test_get_mutual_relationships() { ) .unwrap(); - let bundle = common::setup().await; - let mut belongs_to = bundle.instance; - let mut user = bundle.user; + let mut bundle = common::setup().await; + let belongs_to = &mut bundle.instance; + let user = &mut bundle.user; let mut other_user = belongs_to.register_account(®ister_schema).await.unwrap(); let friend_request_schema = types::FriendRequestSendSchema { username: user.object.username.clone(), @@ -31,5 +31,36 @@ async fn test_get_mutual_relationships() { .get_mutual_relationships(&other_user.object.id.to_string()) .await .unwrap(); - println!("{:?}", relationships.unwrap()); + println!("{:?}", relationships); + common::teardown(bundle).await +} + +#[tokio::test] +async fn test_get_relationships() { + let register_schema = types::RegisterSchema::new( + "integrationtestuser2".to_string(), + None, + true, + None, + None, + None, + Some("2000-01-01".to_string()), + None, + None, + None, + ) + .unwrap(); + + let mut bundle = common::setup().await; + let belongs_to = &mut bundle.instance; + let user = &mut bundle.user; + let mut other_user = belongs_to.register_account(®ister_schema).await.unwrap(); + let friend_request_schema = types::FriendRequestSendSchema { + username: user.object.username.clone(), + discriminator: Some(user.object.discriminator.clone()), + }; + other_user.send_friend_request(friend_request_schema).await; + let relationships = user.get_relationships().await.unwrap(); + println!("{:?}", relationships); + common::teardown(bundle).await } From 9b52ceab4b4c71f768cff6db355a1b3e232ccb3f Mon Sep 17 00:00:00 2001 From: Flori Weber Date: Sun, 18 Jun 2023 15:39:52 +0200 Subject: [PATCH 04/10] Change returns, add documentation --- src/api/users/relationships.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/api/users/relationships.rs b/src/api/users/relationships.rs index 563b846..a678da9 100644 --- a/src/api/users/relationships.rs +++ b/src/api/users/relationships.rs @@ -16,11 +16,11 @@ impl UserMeta { /// * `user_id` - A string slice that holds the ID of the user to retrieve the mutual relationships with. /// /// # Returns - /// This function returns a [`Option>>`]. + /// This function returns a [`Result, ChorusLibError>`]. pub async fn get_mutual_relationships( &mut self, user_id: &str, - ) -> Result>, ChorusLibError> { + ) -> Result, ChorusLibError> { let belongs_to = self.belongs_to.borrow(); let url = format!( "{}/users/{}/relationships/", @@ -29,7 +29,7 @@ impl UserMeta { ); drop(belongs_to); let request = Client::new().get(url).bearer_auth(self.token()); - deserialize_response::>>( + deserialize_response::>( request, self, crate::api::limits::LimitType::Global, @@ -37,6 +37,10 @@ impl UserMeta { .await } + /// Retrieves the authenticated user's relationships. + /// + /// # Returns + /// This function returns a [`Result, ChorusLibError>`]. pub async fn get_relationships(&mut self) -> Result, ChorusLibError> { let belongs_to = self.belongs_to.borrow(); let url = format!("{}/users/@me/relationships/", belongs_to.urls.get_api(),); From 3102ea80571a0b5f839ba967c55607ccbef07cb2 Mon Sep 17 00:00:00 2001 From: Flori Weber Date: Sun, 18 Jun 2023 19:04:55 +0200 Subject: [PATCH 05/10] Create relationship schemes --- src/types/schema/relationship.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/types/schema/relationship.rs b/src/types/schema/relationship.rs index 8b13789..b0a60d6 100644 --- a/src/types/schema/relationship.rs +++ b/src/types/schema/relationship.rs @@ -1 +1,25 @@ +use serde::{Deserialize, Serialize}; +use crate::types::RelationshipType; + +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct FriendRequestSendSchema { + pub username: String, + pub discriminator: Option, +} + +/// Represents the schema for the Create User Relationship route. +/// # Arguments +/// +/// * relationship_type: The [`RelationshipType`] to create (defaults to -1, which accepts an existing or creates a new friend request) +/// * from_friend_suggestion: Whether the relationship was created from a friend suggestion (default false) +/// * friend_token: The friend token of the user to add a direct friend relationship to +/// +/// See: [https://discord-userdoccers.vercel.app/resources/user#create-user-relationship](https://discord-userdoccers.vercel.app/resources/user#create-user-relationship) +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct CreateUserRelationshipSchema { + #[serde(rename = "type")] + pub relationship_type: Option, + pub from_friend_suggestion: Option, + pub friend_token: Option, +} From 3aa162cfc7192971fecb30a592f173a21517dcdf Mon Sep 17 00:00:00 2001 From: Flori Weber Date: Sun, 18 Jun 2023 19:05:09 +0200 Subject: [PATCH 06/10] Move FriendRequestSchema to schemas --- src/types/entities/relationship.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/types/entities/relationship.rs b/src/types/entities/relationship.rs index fb8acee..b965907 100644 --- a/src/types/entities/relationship.rs +++ b/src/types/entities/relationship.rs @@ -30,9 +30,3 @@ pub enum RelationshipType { Friends = 1, None = 0, } - -#[derive(Deserialize, Serialize, Debug)] -pub struct FriendRequestSendSchema { - pub username: String, - pub discriminator: Option, -} From fa524b179197859e01f584f633e78afecf33138d Mon Sep 17 00:00:00 2001 From: Flori Weber Date: Sun, 18 Jun 2023 23:01:38 +0200 Subject: [PATCH 07/10] Fix errors not displayed, add InvalidArgumentsErr --- src/errors.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index 0f65669..057f57f 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -18,13 +18,14 @@ custom_error! { CantGetInfoError{error:String} = "Something seems to be wrong with the instance. Cannot get information about the instance: {error}", InvalidFormBodyError{error_type: String, error:String} = "The server responded with: {error_type}: {error}", RateLimited{bucket:String} = "Ratelimited on Bucket {bucket}", - MultipartCreationError{error: String} = "Got an error whilst creating the form: {}", - FormCreationError{error: String} = "Got an error whilst creating the form: {}", + MultipartCreationError{error: String} = "Got an error whilst creating the form: {error}", + FormCreationError{error: String} = "Got an error whilst creating the form: {error}", TokenExpired = "Token expired, invalid or not found.", NoPermission = "You do not have the permissions needed to perform this action.", - NotFound{error: String} = "The provided resource hasn't been found: {}", + NotFound{error: String} = "The provided resource hasn't been found: {error}", PasswordRequiredError = "You need to provide your current password to authenticate for this action.", - InvalidResponseError{error: String} = "The response is malformed and cannot be processed. Error: {}", + InvalidResponseError{error: String} = "The response is malformed and cannot be processed. Error: {error}", + InvalidArgumentsError{error: String} = "Invalid arguments were provided. Error: {error}" } custom_error! { From 8c68e8bd77dee1d3d1e858ad665914e2bf011d98 Mon Sep 17 00:00:00 2001 From: Flori Weber Date: Sun, 18 Jun 2023 23:02:49 +0200 Subject: [PATCH 08/10] Add modify_user_relationship --- src/api/users/relationships.rs | 61 ++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/api/users/relationships.rs b/src/api/users/relationships.rs index a678da9..bab9a58 100644 --- a/src/api/users/relationships.rs +++ b/src/api/users/relationships.rs @@ -1,11 +1,11 @@ -use reqwest::Client; +use reqwest::{Client, RequestBuilder}; use serde_json::to_string; use crate::{ api::{deserialize_response, handle_request_as_option}, errors::ChorusLibError, instance::UserMeta, - types, + types::{self, CreateUserRelationshipSchema, RelationshipType}, }; impl UserMeta { @@ -73,4 +73,61 @@ impl UserMeta { let request = Client::new().post(url).bearer_auth(self.token()).body(body); handle_request_as_option(request, self, crate::api::limits::LimitType::Global).await } + + /// Modifies the relationship between the authenticated user and the specified user. + /// + /// # Arguments + /// + /// * `user_id` - A string slice that holds the ID of the user to modify the relationship with. + /// * `relationship_type` - A [`RelationshipType`] enum that specifies the type of relationship to modify. + /// * [`RelationshipType::None`]: Removes the relationship between the two users. + /// * [`RelationshipType::Friends`] | [`RelationshipType::Incoming`] | [`RelationshipType::Outgoing`]: + /// Either accepts an incoming friend request, or sends a new friend request, if there is no + /// incoming friend request from the specified `user_id`. + /// * [`RelationshipType::Blocked`]: Blocks the specified user_id. + /// + /// # Returns + /// This function returns an [`Option`] that holds a [`ChorusLibError`] if the request fails. + pub async fn modify_user_relationship( + &mut self, + user_id: &str, + relationship_type: RelationshipType, + ) -> Option { + let belongs_to = self.belongs_to.borrow(); + let api_url = belongs_to.urls.api.clone(); + drop(belongs_to); + match relationship_type { + RelationshipType::None => { + let request = Client::new() + .delete(format!("{}/users/@me/relationships/{}/", api_url, user_id)) + .bearer_auth(self.token()); + handle_request_as_option(request, self, crate::api::limits::LimitType::Global).await + } + RelationshipType::Friends | RelationshipType::Incoming | RelationshipType::Outgoing => { + let body = CreateUserRelationshipSchema { + relationship_type: None, // Selecting 'None' here will accept an incoming FR or send a new FR. + from_friend_suggestion: None, + friend_token: None, + }; + let request = Client::new() + .put(format!("{}/users/@me/relationships/{}/", api_url, user_id)) + .bearer_auth(self.token()) + .body(to_string(&body).unwrap()); + handle_request_as_option(request, self, crate::api::limits::LimitType::Global).await + } + RelationshipType::Blocked => { + let body = CreateUserRelationshipSchema { + relationship_type: Some(RelationshipType::Blocked), + from_friend_suggestion: None, + friend_token: None, + }; + let request = Client::new() + .put(format!("{}/users/@me/relationships/{}/", api_url, user_id)) + .bearer_auth(self.token()) + .body(to_string(&body).unwrap()); + handle_request_as_option(request, self, crate::api::limits::LimitType::Global).await + } + RelationshipType::Suggestion | RelationshipType::Implicit => None, + } + } } From f658f3fe61fa29bb3216d136d9c4a1608e6cf75b Mon Sep 17 00:00:00 2001 From: Flori Weber Date: Sun, 18 Jun 2023 23:04:25 +0200 Subject: [PATCH 09/10] Remove unneccessary imports --- src/api/users/relationships.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/users/relationships.rs b/src/api/users/relationships.rs index bab9a58..7ad76fe 100644 --- a/src/api/users/relationships.rs +++ b/src/api/users/relationships.rs @@ -1,4 +1,4 @@ -use reqwest::{Client, RequestBuilder}; +use reqwest::Client; use serde_json::to_string; use crate::{ From 1cb672faa60c6a914b177c550a396c707d5ef470 Mon Sep 17 00:00:00 2001 From: Flori Weber Date: Sun, 18 Jun 2023 23:10:29 +0200 Subject: [PATCH 10/10] Add remove_relationship --- src/api/users/relationships.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/api/users/relationships.rs b/src/api/users/relationships.rs index 7ad76fe..65c044e 100644 --- a/src/api/users/relationships.rs +++ b/src/api/users/relationships.rs @@ -130,4 +130,24 @@ impl UserMeta { RelationshipType::Suggestion | RelationshipType::Implicit => None, } } + + /// Removes the relationship between the authenticated user and the specified user. + /// + /// # Arguments + /// + /// * `user_id` - A string slice that holds the ID of the user to remove the relationship with. + /// + /// # Returns + /// This function returns an [`Option`] that holds a [`ChorusLibError`] if the request fails. + pub async fn remove_relationship(&mut self, user_id: &str) -> Option { + let belongs_to = self.belongs_to.borrow(); + let url = format!( + "{}/users/@me/relationships/{}/", + belongs_to.urls.get_api(), + user_id + ); + drop(belongs_to); + let request = Client::new().post(url).bearer_auth(self.token()); + handle_request_as_option(request, self, crate::api::limits::LimitType::Global).await + } }