Merge branch 'main'

This commit is contained in:
kozabrada123 2023-05-22 13:30:19 +02:00
commit 73a9e5b0fc
10 changed files with 184 additions and 129 deletions

View File

@ -18,3 +18,6 @@ native-tls = "0.2.11"
tokio-tungstenite = {version = "0.19.0", features = ["native-tls"]}
futures-util = "0.3.28"
http = "0.2.9"
[dev-dependencies]
lazy_static = "1.4.0"

View File

@ -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<crate::api::types::User, InstanceServerError> {
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,

View File

@ -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<crate::api::types::User, InstanceServerError> {
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,

View File

@ -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<Vec<PartialDiscordFileAttachment>>,
token: &String,
user: &mut User<'a>,
token: String,
limits_user: &mut Limits,
limits_instance: &mut Limits,
) -> Result<reqwest::Response, crate::errors::InstanceServerError> {
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,31 @@ 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<Vec<PartialDiscordFileAttachment>>,
) -> Result<reqwest::Response, crate::errors::InstanceServerError> {
let token = self.token().clone();
let mut belongs_to = self.belongs_to.borrow_mut();
Message::send(
&self.belongs_to.urls.get_api().to_string(),
belongs_to.urls.get_api().to_string(),
channel_id,
message,
files,
&token,
self,
token,
&mut self.limits,
&mut belongs_to.limits,
)
.await
}
@ -120,9 +122,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 +141,11 @@ mod test {
None,
None,
);
let mut instance = Instance::new(
crate::URLBundle {
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,
)
})
.await
.unwrap();
let login_schema: LoginSchema = LoginSchema::new(
@ -163,9 +162,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 +213,11 @@ mod test {
None,
Some(vec![attachment.clone()]),
);
let mut instance = Instance::new(
crate::URLBundle {
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,
)
})
.await
.unwrap();
let login_schema: LoginSchema = LoginSchema::new(
@ -231,11 +233,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());

View File

@ -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<String, crate::errors::InstanceServerError> {
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<InstanceServerError> {
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());
@ -114,56 +114,3 @@ impl<'a> types::Guild {
}
}
}
#[cfg(test)]
mod test {
use crate::api::schemas;
use crate::api::types;
use crate::instance::Instance;
#[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,
)
.await
.unwrap();
let login_schema: schemas::LoginSchema = schemas::LoginSchema::new(
schemas::AuthUsername::new("user@test.xyz".to_string()).unwrap(),
"transrights".to_string(),
None,
None,
None,
None,
)
.unwrap();
let mut user = instance.login_account(&login_schema).await.unwrap();
let guild_create_schema = schemas::GuildCreateSchema {
name: Some("test".to_string()),
region: None,
icon: None,
channels: None,
guild_template_code: None,
system_channel_id: None,
rules_channel_id: None,
};
let guild =
types::Guild::create(&mut user, "http://localhost:3001/api", guild_create_schema)
.await
.unwrap();
println!("{}", guild);
match types::Guild::delete(&mut user, "http://localhost:3001/api", guild).await {
None => assert!(true),
Some(_) => assert!(false),
}
}
}

View File

@ -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();
}

View File

@ -4,8 +4,7 @@ https://discord.com/developers/docs .
I do not feel like re-documenting all of this, as everything is already perfectly explained there.
*/
use std::collections::HashMap;
use std::{cell::RefCell, rc::Rc, collections::HashMap};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::from_value;
@ -394,19 +393,15 @@ pub struct UserObject {
}
#[derive(Debug)]
pub struct User<'a> {
pub belongs_to: &'a mut Instance,
pub struct User {
pub belongs_to: Rc<RefCell<Instance>>,
pub token: String,
pub limits: Limits,
pub settings: UserSettings,
pub object: Option<UserObject>,
}
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()
}
@ -416,12 +411,12 @@ impl<'a> User<'a> {
}
pub fn new(
belongs_to: &'a mut Instance,
belongs_to: Rc<RefCell<Instance>>,
token: String,
limits: Limits,
settings: UserSettings,
object: Option<UserObject>,
) -> User<'a> {
) -> User {
User {
belongs_to,
token,

View File

@ -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
@ -122,6 +125,35 @@ impl<'a> User<'a> {
);
Ok(user_updated)
}
/// Sends a request to the server which deletes the user from the Instance.
///
/// # Arguments
///
/// * `self` - The `User` object to delete.
///
/// # Returns
///
/// Returns `None` if the user was successfully deleted, or an `InstanceServerError` if an error occurred.
pub async fn delete(mut self) -> Option<InstanceServerError> {
let mut belongs_to = self.belongs_to.borrow_mut();
let request = Client::new()
.post(format!("{}/users/@me/delete/", belongs_to.urls.get_api()))
.bearer_auth(self.token);
match LimitedRequester::new()
.await
.send_request(
request,
crate::api::limits::LimitType::Global,
&mut belongs_to.limits,
&mut self.limits,
)
.await
{
Ok(_) => None,
Err(e) => Some(e),
}
}
}
impl Instance {

View File

@ -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<Instance, InstanceServerError> {
pub async fn new(urls: URLBundle) -> Result<Instance, InstanceServerError> {
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,

74
tests/integration.rs Normal file
View File

@ -0,0 +1,74 @@
use chorus::{
api::{AuthUsername, RegisterSchema, User},
instance::Instance,
URLBundle,
};
#[derive(Debug)]
struct TestBundle {
urls: URLBundle,
user: User,
}
// Set up a test by creating an Instance and a User. Reduces Test boilerplate.
async fn setup() -> TestBundle {
let urls = URLBundle::new(
"http://localhost:3001/api".to_string(),
"ws://localhost:3001".to_string(),
"http://localhost:3001".to_string(),
);
let mut instance = Instance::new(urls.clone()).await.unwrap();
// Requires the existance of the below user.
let reg = RegisterSchema::new(
AuthUsername::new("integrationtestuser".to_string()).unwrap(),
None,
true,
None,
None,
None,
Some("2000-01-01".to_string()),
None,
None,
None,
)
.unwrap();
let user = instance.register_account(&reg).await.unwrap();
TestBundle { urls, user }
}
// Teardown method to clean up after a test.
async fn teardown(bundle: TestBundle) {
bundle.user.delete().await;
}
mod guild {
use chorus::api::{schemas, types};
#[tokio::test]
async fn guild_creation_deletion() {
let mut bundle = crate::setup().await;
let guild_create_schema = schemas::GuildCreateSchema {
name: Some("test".to_string()),
region: None,
icon: None,
channels: None,
guild_template_code: None,
system_channel_id: None,
rules_channel_id: None,
};
let guild =
types::Guild::create(&mut bundle.user, bundle.urls.get_api(), guild_create_schema)
.await
.unwrap();
println!("{}", guild);
match types::Guild::delete(&mut bundle.user, bundle.urls.get_api(), guild).await {
None => assert!(true),
Some(_) => assert!(false),
}
}
}