From 8a1c1f0a41417a71303d893372560d454ffa1d73 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 20 May 2023 23:10:25 +0200 Subject: [PATCH 1/2] Replace &mut Instance with Rc> Replace &mut Instance with Rc> on the User struct to represent the 1:n relation of Instance:User --- src/api/auth/login.rs | 8 ++- src/api/auth/register.rs | 11 ++-- src/api/channels/messages.rs | 81 +++++++++++++++------------ src/api/guilds/guilds.rs | 21 +++---- src/api/policies/instance/instance.rs | 4 +- src/api/types.rs | 16 +++--- src/api/users/users.rs | 9 ++- src/instance.rs | 13 +---- 8 files changed, 82 insertions(+), 81 deletions(-) diff --git a/src/api/auth/login.rs b/src/api/auth/login.rs index 67647f7..453ff1b 100644 --- a/src/api/auth/login.rs +++ b/src/api/auth/login.rs @@ -1,4 +1,7 @@ pub mod login { + use std::cell::RefCell; + use std::rc::Rc; + use reqwest::Client; use serde_json::{from_str, json}; @@ -7,13 +10,14 @@ pub mod login { use crate::api::types::{ErrorResponse, LoginResult}; use crate::errors::InstanceServerError; use crate::instance::Instance; + use crate::limit::LimitedRequester; impl Instance { pub async fn login_account( &mut self, login_schema: &LoginSchema, ) -> Result { - let requester = &mut self.requester; + let mut requester = LimitedRequester::new().await; let json_schema = json!(login_schema); let client = Client::new(); let endpoint_url = self.urls.get_api().to_string() + "/auth/login"; @@ -56,7 +60,7 @@ pub mod login { .await .unwrap(); let user = crate::api::types::User::new( - self, + Rc::new(RefCell::new(self.clone())), login_result.token, cloned_limits, login_result.settings, diff --git a/src/api/auth/register.rs b/src/api/auth/register.rs index 28c9c96..edafc5d 100644 --- a/src/api/auth/register.rs +++ b/src/api/auth/register.rs @@ -1,4 +1,6 @@ pub mod register { + use std::{cell::RefCell, rc::Rc}; + use reqwest::Client; use serde_json::{from_str, json}; @@ -6,6 +8,7 @@ pub mod register { api::{limits::LimitType, schemas::RegisterSchema, types::ErrorResponse, Token}, errors::InstanceServerError, instance::Instance, + limit::LimitedRequester, }; impl Instance { @@ -21,7 +24,7 @@ pub mod register { register_schema: &RegisterSchema, ) -> Result { let json_schema = json!(register_schema); - let limited_requester = &mut self.requester; + let mut limited_requester = LimitedRequester::new().await; let client = Client::new(); let endpoint_url = self.urls.get_api().to_string() + "/auth/register"; let request_builder = client.post(endpoint_url).body(json_schema.to_string()); @@ -67,7 +70,7 @@ pub mod register { .await .unwrap(); let user: crate::api::types::User = crate::api::types::User::new( - self, + Rc::new(RefCell::new(self.clone())), token.clone(), cloned_limits, settings, @@ -93,9 +96,7 @@ mod test { "http://localhost:3001".to_string(), ); let limited_requester = LimitedRequester::new().await; - let mut test_instance = Instance::new(urls.clone(), limited_requester) - .await - .unwrap(); + let mut test_instance = Instance::new(urls.clone()).await.unwrap(); let reg = RegisterSchema::new( AuthUsername::new("Hiiii".to_string()).unwrap(), None, diff --git a/src/api/channels/messages.rs b/src/api/channels/messages.rs index ffa3f06..9c27201 100644 --- a/src/api/channels/messages.rs +++ b/src/api/channels/messages.rs @@ -4,6 +4,7 @@ pub mod messages { use reqwest::{multipart, Client}; use serde_json::to_string; + use crate::api::limits::Limits; use crate::api::types::{Message, PartialDiscordFileAttachment, User}; use crate::limit::LimitedRequester; @@ -20,16 +21,15 @@ pub mod messages { * [`InstanceServerError`] - If the message cannot be sent. */ pub async fn send<'a>( - url_api: &String, - channel_id: &String, + url_api: String, + channel_id: String, message: &mut crate::api::schemas::MessageSendSchema, files: Option>, - token: &String, - user: &mut User<'a>, + token: String, + limits_user: &mut Limits, + limits_instance: &mut Limits, ) -> Result { let mut requester = LimitedRequester::new().await; - let user_rate_limits = &mut user.limits; - let instance_rate_limits = &mut user.belongs_to.limits; if files.is_none() { let message_request = Client::new() @@ -40,8 +40,8 @@ pub mod messages { .send_request( message_request, crate::api::limits::LimitType::Channel, - instance_rate_limits, - user_rate_limits, + limits_instance, + limits_user, ) .await } else { @@ -83,29 +83,30 @@ pub mod messages { .send_request( message_request, crate::api::limits::LimitType::Channel, - instance_rate_limits, - user_rate_limits, + limits_instance, + limits_user, ) .await } } } - impl<'a> User<'a> { + impl User { pub async fn send_message( &mut self, message: &mut crate::api::schemas::MessageSendSchema, - channel_id: &String, + channel_id: String, files: Option>, ) -> Result { let token = self.token().clone(); Message::send( - &self.belongs_to.urls.get_api().to_string(), + self.belongs_to.borrow_mut().urls.get_api().to_string(), channel_id, message, files, - &token, - self, + token, + &mut self.limits, + &mut self.belongs_to.borrow_mut().limits, ) .await } @@ -120,9 +121,9 @@ mod test { limit::LimitedRequester, }; - use std::fs::File; - use std::io::BufReader; use std::io::Read; + use std::{cell::RefCell, fs::File}; + use std::{io::BufReader, rc::Rc}; #[tokio::test] async fn send_message() { @@ -139,14 +140,11 @@ mod test { None, None, ); - let mut instance = Instance::new( - crate::URLBundle { - api: "http://localhost:3001/api".to_string(), - wss: "ws://localhost:3001/".to_string(), - cdn: "http://localhost:3001".to_string(), - }, - LimitedRequester::new().await, - ) + let mut instance = Instance::new(crate::URLBundle { + api: "http://localhost:3001/api".to_string(), + wss: "ws://localhost:3001/".to_string(), + cdn: "http://localhost:3001".to_string(), + }) .await .unwrap(); let login_schema: LoginSchema = LoginSchema::new( @@ -163,9 +161,15 @@ mod test { println!("TOKEN: {}", token); let settings = login_result.settings; let limits = instance.limits.clone(); - let mut user = crate::api::types::User::new(&mut instance, token, limits, settings, None); + let mut user = crate::api::types::User::new( + Rc::new(RefCell::new(instance)), + token, + limits, + settings, + None, + ); let _ = user - .send_message(&mut message, &channel_id, None) + .send_message(&mut message, channel_id, None) .await .unwrap(); } @@ -208,14 +212,11 @@ mod test { None, Some(vec![attachment.clone()]), ); - let mut instance = Instance::new( - crate::URLBundle { - api: "http://localhost:3001/api".to_string(), - wss: "ws://localhost:3001/".to_string(), - cdn: "http://localhost:3001".to_string(), - }, - LimitedRequester::new().await, - ) + let mut instance = Instance::new(crate::URLBundle { + api: "http://localhost:3001/api".to_string(), + wss: "ws://localhost:3001/".to_string(), + cdn: "http://localhost:3001".to_string(), + }) .await .unwrap(); let login_schema: LoginSchema = LoginSchema::new( @@ -231,11 +232,17 @@ mod test { let token = login_result.token; let settings = login_result.settings; let limits = instance.limits.clone(); - let mut user = crate::api::types::User::new(&mut instance, token, limits, settings, None); + let mut user = crate::api::types::User::new( + Rc::new(RefCell::new(instance)), + token, + limits, + settings, + None, + ); let vec_attach = vec![attachment.clone()]; let _arg = Some(&vec_attach); let response = user - .send_message(&mut message, &channel_id, Some(vec![attachment.clone()])) + .send_message(&mut message, channel_id, Some(vec![attachment.clone()])) .await .unwrap(); println!("[Response:] {}", response.text().await.unwrap()); diff --git a/src/api/guilds/guilds.rs b/src/api/guilds/guilds.rs index 23249b9..0c0137f 100644 --- a/src/api/guilds/guilds.rs +++ b/src/api/guilds/guilds.rs @@ -35,13 +35,13 @@ impl<'a> types::Guild { /// } /// ``` pub async fn create( - user: &mut types::User<'a>, + user: &mut types::User, url_api: &str, guild_create_schema: schemas::GuildCreateSchema, ) -> Result { let url = format!("{}/guilds/", url_api); let limits_user = user.limits.get_as_mut(); - let limits_instance = &mut user.belongs_to.limits; + let limits_instance = &mut user.belongs_to.borrow_mut().limits; let request = reqwest::Client::new() .post(url.clone()) .bearer_auth(user.token.clone()) @@ -88,13 +88,13 @@ impl<'a> types::Guild { /// } /// ``` pub async fn delete( - user: &mut types::User<'a>, + user: &mut types::User, url_api: &str, guild_id: String, ) -> Option { let url = format!("{}/guilds/{}/delete/", url_api, guild_id); let limits_user = user.limits.get_as_mut(); - let limits_instance = &mut user.belongs_to.limits; + let limits_instance = &mut user.belongs_to.borrow_mut().limits; let request = reqwest::Client::new() .post(url.clone()) .bearer_auth(user.token.clone()); @@ -123,14 +123,11 @@ mod test { #[tokio::test] async fn guild_creation_deletion() { - let mut instance = Instance::new( - crate::URLBundle { - api: "http://localhost:3001/api".to_string(), - wss: "ws://localhost:3001/".to_string(), - cdn: "http://localhost:3001".to_string(), - }, - crate::limit::LimitedRequester::new().await, - ) + let mut instance = Instance::new(crate::URLBundle { + api: "http://localhost:3001/api".to_string(), + wss: "ws://localhost:3001/".to_string(), + cdn: "http://localhost:3001".to_string(), + }) .await .unwrap(); let login_schema: schemas::LoginSchema = schemas::LoginSchema::new( diff --git a/src/api/policies/instance/instance.rs b/src/api/policies/instance/instance.rs index b864e54..2196b80 100644 --- a/src/api/policies/instance/instance.rs +++ b/src/api/policies/instance/instance.rs @@ -47,9 +47,7 @@ mod instance_policies_schema_test { "http://localhost:3001".to_string(), ); let limited_requester = LimitedRequester::new().await; - let test_instance = Instance::new(urls.clone(), limited_requester) - .await - .unwrap(); + let test_instance = Instance::new(urls.clone()).await.unwrap(); let _schema = test_instance.instance_policies_schema().await.unwrap(); } diff --git a/src/api/types.rs b/src/api/types.rs index bfb6861..5631130 100644 --- a/src/api/types.rs +++ b/src/api/types.rs @@ -4,6 +4,8 @@ https://discord.com/developers/docs . I do not feel like re-documenting all of this, as everything is already perfectly explained there. */ +use std::{cell::RefCell, rc::Rc}; + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_json::from_value; @@ -347,19 +349,15 @@ pub struct UserObject { } #[derive(Debug)] -pub struct User<'a> { - pub belongs_to: &'a mut Instance, +pub struct User { + pub belongs_to: Rc>, pub token: String, pub limits: Limits, pub settings: UserSettings, pub object: Option, } -impl<'a> User<'a> { - pub fn belongs_to(&mut self) -> &mut Instance { - self.belongs_to - } - +impl User { pub fn token(&self) -> String { self.token.clone() } @@ -369,12 +367,12 @@ impl<'a> User<'a> { } pub fn new( - belongs_to: &'a mut Instance, + belongs_to: Rc>, token: String, limits: Limits, settings: UserSettings, object: Option, - ) -> User<'a> { + ) -> User { User { belongs_to, token, diff --git a/src/api/users/users.rs b/src/api/users/users.rs index 7d97734..bc80bca 100644 --- a/src/api/users/users.rs +++ b/src/api/users/users.rs @@ -12,7 +12,7 @@ use crate::{ limit::LimitedRequester, }; -impl<'a> User<'a> { +impl User { /** Get a user object by id, or get the current user. # Arguments @@ -99,7 +99,10 @@ impl<'a> User<'a> { return Err(InstanceServerError::PasswordRequiredError); } let request = Client::new() - .patch(format!("{}/users/@me/", self.belongs_to.urls.get_api())) + .patch(format!( + "{}/users/@me/", + self.belongs_to.borrow_mut().urls.get_api() + )) .body(to_string(&modify_schema).unwrap()) .bearer_auth(self.token()); let result = match LimitedRequester::new() @@ -107,7 +110,7 @@ impl<'a> User<'a> { .send_request( request, crate::api::limits::LimitType::Global, - &mut self.belongs_to.limits, + &mut self.belongs_to.borrow_mut().limits, &mut self.limits, ) .await diff --git a/src/instance.rs b/src/instance.rs index ee33961..ab4b4b2 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -1,20 +1,17 @@ use crate::api::limits::Limits; -use crate::api::types::{InstancePolicies}; +use crate::api::types::InstancePolicies; use crate::errors::{FieldFormatError, InstanceServerError}; -use crate::limit::LimitedRequester; use crate::URLBundle; - use std::fmt; -#[derive(Debug)] +#[derive(Debug, Clone)] /** The [`Instance`] what you will be using to perform all sorts of actions on the Spacebar server. */ pub struct Instance { pub urls: URLBundle, pub instance_info: InstancePolicies, - pub requester: LimitedRequester, pub limits: Limits, } @@ -25,10 +22,7 @@ impl Instance { /// * `requester` - The [`LimitedRequester`] that will be used to make requests to the Spacebar server. /// # Errors /// * [`InstanceError`] - If the instance cannot be created. - pub async fn new( - urls: URLBundle, - requester: LimitedRequester, - ) -> Result { + pub async fn new(urls: URLBundle) -> Result { let mut instance = Instance { urls: urls.clone(), instance_info: InstancePolicies::new( @@ -43,7 +37,6 @@ impl Instance { None, ), limits: Limits::check_limits(urls.api).await, - requester, }; instance.instance_info = match instance.instance_policies_schema().await { Ok(schema) => schema, From 8aa4dea9c44093e6a39c96db33d8447a0974fc46 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 20 May 2023 23:21:24 +0200 Subject: [PATCH 2/2] Fix 'already borrowed: BorrowMutError' --- src/api/channels/messages.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/api/channels/messages.rs b/src/api/channels/messages.rs index 9c27201..0aaf8d1 100644 --- a/src/api/channels/messages.rs +++ b/src/api/channels/messages.rs @@ -99,14 +99,15 @@ pub mod messages { files: Option>, ) -> Result { let token = self.token().clone(); + let mut belongs_to = self.belongs_to.borrow_mut(); Message::send( - self.belongs_to.borrow_mut().urls.get_api().to_string(), + belongs_to.urls.get_api().to_string(), channel_id, message, files, token, &mut self.limits, - &mut self.belongs_to.borrow_mut().limits, + &mut belongs_to.limits, ) .await }