Merge pull request #108 from polyphony-chat/feature/relationships

Feature/relationships
This commit is contained in:
Flori 2023-06-18 23:16:45 +02:00 committed by GitHub
commit 0ff57601f1
5 changed files with 168 additions and 19 deletions

View File

@ -5,7 +5,7 @@ use crate::{
api::{deserialize_response, handle_request_as_option},
errors::ChorusLibError,
instance::UserMeta,
types,
types::{self, CreateUserRelationshipSchema, RelationshipType},
};
impl UserMeta {
@ -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<Vec<Result<PublicUser, ChorusLibError>>>`].
/// This function returns a [`Result<Vec<PublicUser>, ChorusLibError>`].
pub async fn get_mutual_relationships(
&mut self,
user_id: &str,
) -> Result<Option<Vec<types::PublicUser>>, ChorusLibError> {
) -> Result<Vec<types::PublicUser>, ChorusLibError> {
let belongs_to = self.belongs_to.borrow();
let url = format!(
"{}/users/{}/relationships/",
@ -29,7 +29,24 @@ impl UserMeta {
);
drop(belongs_to);
let request = Client::new().get(url).bearer_auth(self.token());
deserialize_response::<Option<Vec<types::PublicUser>>>(
deserialize_response::<Vec<types::PublicUser>>(
request,
self,
crate::api::limits::LimitType::Global,
)
.await
}
/// Retrieves the authenticated user's relationships.
///
/// # Returns
/// This function returns a [`Result<Vec<types::Relationship>, ChorusLibError>`].
pub async fn get_relationships(&mut self) -> Result<Vec<types::Relationship>, 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::<Vec<types::Relationship>>(
request,
self,
crate::api::limits::LimitType::Global,
@ -56,4 +73,81 @@ 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<ChorusLibError> {
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,
}
}
/// 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<ChorusLibError> {
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
}
}

View File

@ -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! {

View File

@ -30,9 +30,3 @@ pub enum RelationshipType {
Friends = 1,
None = 0,
}
#[derive(Deserialize, Serialize, Debug)]
pub struct FriendRequestSendSchema {
pub username: String,
pub discriminator: Option<String>,
}

View File

@ -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<String>,
}
/// 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<RelationshipType>,
pub from_friend_suggestion: Option<bool>,
pub friend_token: Option<String>,
}

View File

@ -18,13 +18,49 @@ async fn test_get_mutual_relationships() {
)
.unwrap();
let bundle = common::setup().await;
let mut belongs_to = bundle.instance;
let mut user = bundle.user;
let other_user = belongs_to.register_account(&register_schema).await.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(&register_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
.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(&register_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
}