Merge pull request #17 from polyphony-chat/refactor/split-up-schemas
Refactor/split up schemas
This commit is contained in:
commit
19f96582bc
|
@ -3,7 +3,8 @@ pub mod login {
|
||||||
use serde_json::{from_str, json};
|
use serde_json::{from_str, json};
|
||||||
|
|
||||||
use crate::api::limits::LimitType;
|
use crate::api::limits::LimitType;
|
||||||
use crate::api::schemas::schemas::{ErrorResponse, LoginResult, LoginSchema};
|
use crate::api::schemas::LoginSchema;
|
||||||
|
use crate::api::types::{ErrorResponse, LoginResult};
|
||||||
use crate::errors::InstanceServerError;
|
use crate::errors::InstanceServerError;
|
||||||
use crate::instance::Instance;
|
use crate::instance::Instance;
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ pub mod login {
|
||||||
&mut cloned_limits,
|
&mut cloned_limits,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
if !response.is_ok() {
|
if response.is_err() {
|
||||||
return Err(InstanceServerError::NoResponse);
|
return Err(InstanceServerError::NoResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ pub mod login {
|
||||||
|
|
||||||
let login_result: LoginResult = from_str(&response_text_string).unwrap();
|
let login_result: LoginResult = from_str(&response_text_string).unwrap();
|
||||||
|
|
||||||
return Ok(login_result);
|
Ok(login_result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,7 @@ pub mod register {
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{
|
api::{limits::LimitType, schemas::RegisterSchema, types::ErrorResponse},
|
||||||
limits::LimitType,
|
|
||||||
schemas::schemas::{ErrorResponse, RegisterSchema},
|
|
||||||
},
|
|
||||||
errors::InstanceServerError,
|
errors::InstanceServerError,
|
||||||
instance::{Instance, Token},
|
instance::{Instance, Token},
|
||||||
};
|
};
|
||||||
|
@ -40,7 +37,7 @@ pub mod register {
|
||||||
&mut cloned_limits,
|
&mut cloned_limits,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
if !response.is_ok() {
|
if response.is_err() {
|
||||||
return Err(InstanceServerError::NoResponse);
|
return Err(InstanceServerError::NoResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,16 +55,16 @@ pub mod register {
|
||||||
}
|
}
|
||||||
return Err(InstanceServerError::InvalidFormBodyError { error_type, error });
|
return Err(InstanceServerError::InvalidFormBodyError { error_type, error });
|
||||||
}
|
}
|
||||||
return Ok(Token {
|
Ok(Token {
|
||||||
token: response_text_string,
|
token: response_text_string,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::api::schemas::schemas::{AuthEmail, AuthPassword, AuthUsername, RegisterSchema};
|
use crate::api::schemas::{AuthEmail, AuthPassword, AuthUsername, RegisterSchema};
|
||||||
use crate::errors::InstanceServerError;
|
use crate::errors::InstanceServerError;
|
||||||
use crate::instance::Instance;
|
use crate::instance::Instance;
|
||||||
use crate::limit::LimitedRequester;
|
use crate::limit::LimitedRequester;
|
||||||
|
@ -79,7 +76,7 @@ mod test {
|
||||||
"http://localhost:3001".to_string(),
|
"http://localhost:3001".to_string(),
|
||||||
"http://localhost:3001".to_string(),
|
"http://localhost:3001".to_string(),
|
||||||
);
|
);
|
||||||
let limited_requester = LimitedRequester::new(urls.get_api().to_string()).await;
|
let limited_requester = LimitedRequester::new().await;
|
||||||
let mut test_instance = Instance::new(urls.clone(), limited_requester)
|
let mut test_instance = Instance::new(urls.clone(), limited_requester)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -112,7 +109,7 @@ mod test {
|
||||||
"http://localhost:3001".to_string(),
|
"http://localhost:3001".to_string(),
|
||||||
"http://localhost:3001".to_string(),
|
"http://localhost:3001".to_string(),
|
||||||
);
|
);
|
||||||
let limited_requester = LimitedRequester::new(urls.get_api().to_string()).await;
|
let limited_requester = LimitedRequester::new().await;
|
||||||
let mut test_instance = Instance::new(urls.clone(), limited_requester)
|
let mut test_instance = Instance::new(urls.clone(), limited_requester)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod policies;
|
pub mod policies;
|
||||||
pub mod schemas;
|
pub mod schemas;
|
||||||
|
pub mod types;
|
||||||
|
|
||||||
pub use policies::instance::instance::*;
|
pub use policies::instance::instance::*;
|
||||||
pub use policies::instance::limits::*;
|
pub use policies::instance::limits::*;
|
||||||
pub use schemas::*;
|
pub use schemas::*;
|
||||||
|
pub use types::*;
|
||||||
|
|
|
@ -3,7 +3,7 @@ pub mod instance {
|
||||||
use serde_json::from_str;
|
use serde_json::from_str;
|
||||||
|
|
||||||
use crate::errors::InstanceServerError;
|
use crate::errors::InstanceServerError;
|
||||||
use crate::{api::schemas::schemas::InstancePoliciesSchema, instance::Instance};
|
use crate::{api::types::InstancePolicies, instance::Instance};
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
/**
|
/**
|
||||||
|
@ -13,7 +13,7 @@ pub mod instance {
|
||||||
*/
|
*/
|
||||||
pub async fn instance_policies_schema(
|
pub async fn instance_policies_schema(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<InstancePoliciesSchema, InstanceServerError> {
|
) -> Result<InstancePolicies, InstanceServerError> {
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
let endpoint_url = self.urls.get_api().to_string() + "/policies/instance/";
|
let endpoint_url = self.urls.get_api().to_string() + "/policies/instance/";
|
||||||
let request = match client.get(&endpoint_url).send().await {
|
let request = match client.get(&endpoint_url).send().await {
|
||||||
|
@ -26,14 +26,14 @@ pub mod instance {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if request.status().as_str().chars().next().unwrap() != '2' {
|
if !request.status().as_str().starts_with('2') {
|
||||||
return Err(InstanceServerError::ReceivedErrorCodeError {
|
return Err(InstanceServerError::ReceivedErrorCodeError {
|
||||||
error_code: request.status().to_string(),
|
error_code: request.status().to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = request.text().await.unwrap();
|
let body = request.text().await.unwrap();
|
||||||
let instance_policies_schema: InstancePoliciesSchema = from_str(&body).unwrap();
|
let instance_policies_schema: InstancePolicies = from_str(&body).unwrap();
|
||||||
Ok(instance_policies_schema)
|
Ok(instance_policies_schema)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ mod instance_policies_schema_test {
|
||||||
"http://localhost:3001".to_string(),
|
"http://localhost:3001".to_string(),
|
||||||
"http://localhost:3001".to_string(),
|
"http://localhost:3001".to_string(),
|
||||||
);
|
);
|
||||||
let limited_requester = LimitedRequester::new(urls.get_api().to_string()).await;
|
let limited_requester = LimitedRequester::new().await;
|
||||||
let test_instance = Instance::new(urls.clone(), limited_requester)
|
let test_instance = Instance::new(urls.clone(), limited_requester)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -155,14 +155,14 @@ pub mod limits {
|
||||||
impl Limit {
|
impl Limit {
|
||||||
pub fn add_remaining(&mut self, remaining: i64) {
|
pub fn add_remaining(&mut self, remaining: i64) {
|
||||||
if remaining < 0 {
|
if remaining < 0 {
|
||||||
if ((self.remaining as i64 + remaining) as i64) <= 0 {
|
if (self.remaining as i64 + remaining) <= 0 {
|
||||||
self.remaining = 0;
|
self.remaining = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.remaining -= remaining.abs() as u64;
|
self.remaining -= remaining.unsigned_abs();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.remaining += remaining.abs() as u64;
|
self.remaining += remaining.unsigned_abs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ pub mod limits {
|
||||||
instance_rate_limits: &'a mut Limits,
|
instance_rate_limits: &'a mut Limits,
|
||||||
user_rate_limits: &'a mut Limits,
|
user_rate_limits: &'a mut Limits,
|
||||||
) -> LimitsMutRef<'a> {
|
) -> LimitsMutRef<'a> {
|
||||||
return LimitsMutRef {
|
LimitsMutRef {
|
||||||
limit_absolute_messages: &mut instance_rate_limits.limit_absolute_messages,
|
limit_absolute_messages: &mut instance_rate_limits.limit_absolute_messages,
|
||||||
limit_absolute_register: &mut instance_rate_limits.limit_absolute_register,
|
limit_absolute_register: &mut instance_rate_limits.limit_absolute_register,
|
||||||
limit_auth_login: &mut instance_rate_limits.limit_auth_login,
|
limit_auth_login: &mut instance_rate_limits.limit_auth_login,
|
||||||
|
@ -195,36 +195,36 @@ pub mod limits {
|
||||||
limit_guild: &mut user_rate_limits.limit_guild,
|
limit_guild: &mut user_rate_limits.limit_guild,
|
||||||
limit_ip: &mut instance_rate_limits.limit_ip,
|
limit_ip: &mut instance_rate_limits.limit_ip,
|
||||||
limit_webhook: &mut user_rate_limits.limit_webhook,
|
limit_webhook: &mut user_rate_limits.limit_webhook,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_limit_ref(&self, limit_type: &LimitType) -> &Limit {
|
pub fn get_limit_ref(&self, limit_type: &LimitType) -> &Limit {
|
||||||
match limit_type {
|
match limit_type {
|
||||||
&LimitType::AbsoluteMessage => &self.limit_absolute_messages,
|
&LimitType::AbsoluteMessage => self.limit_absolute_messages,
|
||||||
&LimitType::AbsoluteRegister => &self.limit_absolute_register,
|
&LimitType::AbsoluteRegister => self.limit_absolute_register,
|
||||||
&LimitType::AuthLogin => &self.limit_auth_login,
|
&LimitType::AuthLogin => self.limit_auth_login,
|
||||||
&LimitType::AuthRegister => &self.limit_auth_register,
|
&LimitType::AuthRegister => self.limit_auth_register,
|
||||||
&LimitType::Channel => &self.limit_channel,
|
&LimitType::Channel => self.limit_channel,
|
||||||
&LimitType::Error => &self.limit_error,
|
&LimitType::Error => self.limit_error,
|
||||||
&LimitType::Global => &self.limit_global,
|
&LimitType::Global => self.limit_global,
|
||||||
&LimitType::Guild => &self.limit_guild,
|
&LimitType::Guild => self.limit_guild,
|
||||||
&LimitType::Ip => &self.limit_ip,
|
&LimitType::Ip => self.limit_ip,
|
||||||
&LimitType::Webhook => &self.limit_webhook,
|
&LimitType::Webhook => self.limit_webhook,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_limit_mut_ref(&mut self, limit_type: &LimitType) -> &mut Limit {
|
pub fn get_limit_mut_ref(&mut self, limit_type: &LimitType) -> &mut Limit {
|
||||||
match limit_type {
|
match limit_type {
|
||||||
&LimitType::AbsoluteMessage => &mut self.limit_absolute_messages,
|
&LimitType::AbsoluteMessage => self.limit_absolute_messages,
|
||||||
&LimitType::AbsoluteRegister => &mut self.limit_absolute_register,
|
&LimitType::AbsoluteRegister => self.limit_absolute_register,
|
||||||
&LimitType::AuthLogin => &mut self.limit_auth_login,
|
&LimitType::AuthLogin => self.limit_auth_login,
|
||||||
&LimitType::AuthRegister => &mut self.limit_auth_register,
|
&LimitType::AuthRegister => self.limit_auth_register,
|
||||||
&LimitType::Channel => &mut self.limit_channel,
|
&LimitType::Channel => self.limit_channel,
|
||||||
&LimitType::Error => &mut self.limit_error,
|
&LimitType::Error => self.limit_error,
|
||||||
&LimitType::Global => &mut self.limit_global,
|
&LimitType::Global => self.limit_global,
|
||||||
&LimitType::Guild => &mut self.limit_guild,
|
&LimitType::Guild => self.limit_guild,
|
||||||
&LimitType::Ip => &mut self.limit_ip,
|
&LimitType::Ip => self.limit_ip,
|
||||||
&LimitType::Webhook => &mut self.limit_webhook,
|
&LimitType::Webhook => self.limit_webhook,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ pub mod limits {
|
||||||
|
|
||||||
impl Limits {
|
impl Limits {
|
||||||
pub fn combine(instance_rate_limits: &Limits, user_rate_limits: &Limits) -> Limits {
|
pub fn combine(instance_rate_limits: &Limits, user_rate_limits: &Limits) -> Limits {
|
||||||
return Limits {
|
Limits {
|
||||||
limit_absolute_messages: instance_rate_limits.limit_absolute_messages,
|
limit_absolute_messages: instance_rate_limits.limit_absolute_messages,
|
||||||
limit_absolute_register: instance_rate_limits.limit_absolute_register,
|
limit_absolute_register: instance_rate_limits.limit_absolute_register,
|
||||||
limit_auth_login: instance_rate_limits.limit_auth_login,
|
limit_auth_login: instance_rate_limits.limit_auth_login,
|
||||||
|
@ -256,7 +256,7 @@ pub mod limits {
|
||||||
limit_guild: user_rate_limits.limit_guild,
|
limit_guild: user_rate_limits.limit_guild,
|
||||||
limit_ip: instance_rate_limits.limit_ip,
|
limit_ip: instance_rate_limits.limit_ip,
|
||||||
limit_webhook: user_rate_limits.limit_webhook,
|
limit_webhook: user_rate_limits.limit_webhook,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_limit_ref(&self, limit_type: &LimitType) -> &Limit {
|
pub fn get_limit_ref(&self, limit_type: &LimitType) -> &Limit {
|
||||||
|
@ -329,7 +329,7 @@ pub mod limits {
|
||||||
let config: Config = from_str(&result).unwrap();
|
let config: Config = from_str(&result).unwrap();
|
||||||
// If config.rate.enabled is false, then add return a Limits struct with all limits set to u64::MAX
|
// If config.rate.enabled is false, then add return a Limits struct with all limits set to u64::MAX
|
||||||
let mut limits: Limits;
|
let mut limits: Limits;
|
||||||
if config.rate.enabled == false {
|
if !config.rate.enabled {
|
||||||
limits = Limits {
|
limits = Limits {
|
||||||
limit_absolute_messages: Limit {
|
limit_absolute_messages: Limit {
|
||||||
bucket: LimitType::AbsoluteMessage,
|
bucket: LimitType::AbsoluteMessage,
|
||||||
|
@ -475,7 +475,7 @@ pub mod limits {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return limits;
|
limits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -493,8 +493,8 @@ mod instance_limits {
|
||||||
reset: 0,
|
reset: 0,
|
||||||
};
|
};
|
||||||
limit.add_remaining(-2);
|
limit.add_remaining(-2);
|
||||||
assert_eq!(0 as u64, limit.remaining);
|
assert_eq!(0_u64, limit.remaining);
|
||||||
limit.add_remaining(-2123123);
|
limit.add_remaining(-2123123);
|
||||||
assert_eq!(0 as u64, limit.remaining);
|
assert_eq!(0_u64, limit.remaining);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,465 +1,250 @@
|
||||||
pub mod schemas {
|
use regex::Regex;
|
||||||
use regex::Regex;
|
use serde::{Deserialize, Serialize};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::{collections::HashMap, fmt};
|
|
||||||
|
|
||||||
use crate::{api::limits::Limits, errors::FieldFormatError, URLBundle};
|
use crate::errors::FieldFormatError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
A struct that represents a well-formed email address.
|
||||||
|
*/
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct AuthEmail {
|
||||||
|
pub email: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuthEmail {
|
||||||
/**
|
/**
|
||||||
A struct that represents a well-formed email address.
|
Returns a new [`Result<AuthEmail, FieldFormatError>`].
|
||||||
*/
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
pub struct AuthEmail {
|
|
||||||
pub email: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthEmail {
|
|
||||||
/**
|
|
||||||
Returns a new [`Result<AuthEmail, FieldFormatError>`].
|
|
||||||
## Arguments
|
|
||||||
The email address you want to validate.
|
|
||||||
## Errors
|
|
||||||
You will receive a [`FieldFormatError`], if:
|
|
||||||
- The email address is not in a valid format.
|
|
||||||
|
|
||||||
*/
|
|
||||||
pub fn new(email: String) -> Result<AuthEmail, FieldFormatError> {
|
|
||||||
let regex = Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap();
|
|
||||||
if !regex.is_match(email.clone().as_str()) {
|
|
||||||
return Err(FieldFormatError::EmailError);
|
|
||||||
}
|
|
||||||
return Ok(AuthEmail { email });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
A struct that represents a well-formed username.
|
|
||||||
## Arguments
|
## Arguments
|
||||||
Please use new() to create a new instance of this struct.
|
The email address you want to validate.
|
||||||
|
## Errors
|
||||||
|
You will receive a [`FieldFormatError`], if:
|
||||||
|
- The email address is not in a valid format.
|
||||||
|
|
||||||
|
*/
|
||||||
|
pub fn new(email: String) -> Result<AuthEmail, FieldFormatError> {
|
||||||
|
let regex = Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap();
|
||||||
|
if !regex.is_match(email.as_str()) {
|
||||||
|
return Err(FieldFormatError::EmailError);
|
||||||
|
}
|
||||||
|
Ok(AuthEmail { email })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
A struct that represents a well-formed username.
|
||||||
|
## Arguments
|
||||||
|
Please use new() to create a new instance of this struct.
|
||||||
|
## Errors
|
||||||
|
You will receive a [`FieldFormatError`], if:
|
||||||
|
- The username is not between 2 and 32 characters.
|
||||||
|
*/
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct AuthUsername {
|
||||||
|
pub username: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuthUsername {
|
||||||
|
/**
|
||||||
|
Returns a new [`Result<AuthUsername, FieldFormatError>`].
|
||||||
|
## Arguments
|
||||||
|
The username you want to validate.
|
||||||
## Errors
|
## Errors
|
||||||
You will receive a [`FieldFormatError`], if:
|
You will receive a [`FieldFormatError`], if:
|
||||||
- The username is not between 2 and 32 characters.
|
- The username is not between 2 and 32 characters.
|
||||||
*/
|
*/
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
pub fn new(username: String) -> Result<AuthUsername, FieldFormatError> {
|
||||||
pub struct AuthUsername {
|
if username.len() < 2 || username.len() > 32 {
|
||||||
pub username: String,
|
Err(FieldFormatError::UsernameError)
|
||||||
}
|
} else {
|
||||||
|
Ok(AuthUsername { username })
|
||||||
impl AuthUsername {
|
|
||||||
/**
|
|
||||||
Returns a new [`Result<AuthUsername, FieldFormatError>`].
|
|
||||||
## Arguments
|
|
||||||
The username you want to validate.
|
|
||||||
## Errors
|
|
||||||
You will receive a [`FieldFormatError`], if:
|
|
||||||
- The username is not between 2 and 32 characters.
|
|
||||||
*/
|
|
||||||
pub fn new(username: String) -> Result<AuthUsername, FieldFormatError> {
|
|
||||||
if username.len() < 2 || username.len() > 32 {
|
|
||||||
return Err(FieldFormatError::UsernameError);
|
|
||||||
} else {
|
|
||||||
return Ok(AuthUsername { username });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
A struct that represents a well-formed password.
|
||||||
|
## Arguments
|
||||||
|
Please use new() to create a new instance of this struct.
|
||||||
|
## Errors
|
||||||
|
You will receive a [`FieldFormatError`], if:
|
||||||
|
- The password is not between 1 and 72 characters.
|
||||||
|
*/
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct AuthPassword {
|
||||||
|
pub password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuthPassword {
|
||||||
/**
|
/**
|
||||||
A struct that represents a well-formed password.
|
Returns a new [`Result<AuthPassword, FieldFormatError>`].
|
||||||
## Arguments
|
## Arguments
|
||||||
Please use new() to create a new instance of this struct.
|
The password you want to validate.
|
||||||
## Errors
|
## Errors
|
||||||
You will receive a [`FieldFormatError`], if:
|
You will receive a [`FieldFormatError`], if:
|
||||||
- The password is not between 1 and 72 characters.
|
- The password is not between 1 and 72 characters.
|
||||||
*/
|
*/
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
pub fn new(password: String) -> Result<AuthPassword, FieldFormatError> {
|
||||||
pub struct AuthPassword {
|
if password.is_empty() || password.len() > 72 {
|
||||||
pub password: String,
|
Err(FieldFormatError::PasswordError)
|
||||||
}
|
} else {
|
||||||
|
Ok(AuthPassword { password })
|
||||||
impl AuthPassword {
|
|
||||||
/**
|
|
||||||
Returns a new [`Result<AuthPassword, FieldFormatError>`].
|
|
||||||
## Arguments
|
|
||||||
The password you want to validate.
|
|
||||||
## Errors
|
|
||||||
You will receive a [`FieldFormatError`], if:
|
|
||||||
- The password is not between 1 and 72 characters.
|
|
||||||
*/
|
|
||||||
pub fn new(password: String) -> Result<AuthPassword, FieldFormatError> {
|
|
||||||
if password.len() < 1 || password.len() > 72 {
|
|
||||||
return Err(FieldFormatError::PasswordError);
|
|
||||||
} else {
|
|
||||||
return Ok(AuthPassword { password });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
A struct that represents a well-formed register request.
|
||||||
|
## Arguments
|
||||||
|
Please use new() to create a new instance of this struct.
|
||||||
|
## Errors
|
||||||
|
You will receive a [`FieldFormatError`], if:
|
||||||
|
- The username is not between 2 and 32 characters.
|
||||||
|
- The password is not between 1 and 72 characters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub struct RegisterSchema {
|
||||||
|
username: String,
|
||||||
|
password: Option<String>,
|
||||||
|
consent: bool,
|
||||||
|
email: Option<String>,
|
||||||
|
fingerprint: Option<String>,
|
||||||
|
invite: Option<String>,
|
||||||
|
date_of_birth: Option<String>,
|
||||||
|
gift_code_sku_id: Option<String>,
|
||||||
|
captcha_key: Option<String>,
|
||||||
|
promotional_email_opt_in: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterSchema {
|
||||||
/**
|
/**
|
||||||
A struct that represents a well-formed register request.
|
Returns a new [`Result<RegisterSchema, FieldFormatError>`].
|
||||||
## Arguments
|
## Arguments
|
||||||
Please use new() to create a new instance of this struct.
|
All but "String::username" and "bool::consent" are optional.
|
||||||
|
|
||||||
## Errors
|
## Errors
|
||||||
You will receive a [`FieldFormatError`], if:
|
You will receive a [`FieldFormatError`], if:
|
||||||
- The username is not between 2 and 32 characters.
|
- The username is less than 2 or more than 32 characters in length
|
||||||
- The password is not between 1 and 72 characters.
|
- You supply a `password` which is less than 1 or more than 72 characters in length.
|
||||||
*/
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
These constraints have been defined [in the Spacebar-API](https://docs.spacebar.chat/routes/)
|
||||||
#[serde(rename_all = "snake_case")]
|
*/
|
||||||
pub struct RegisterSchema {
|
pub fn new(
|
||||||
username: String,
|
username: AuthUsername,
|
||||||
password: Option<String>,
|
password: Option<AuthPassword>,
|
||||||
consent: bool,
|
consent: bool,
|
||||||
email: Option<String>,
|
email: Option<AuthEmail>,
|
||||||
fingerprint: Option<String>,
|
fingerprint: Option<String>,
|
||||||
invite: Option<String>,
|
invite: Option<String>,
|
||||||
date_of_birth: Option<String>,
|
date_of_birth: Option<String>,
|
||||||
gift_code_sku_id: Option<String>,
|
gift_code_sku_id: Option<String>,
|
||||||
captcha_key: Option<String>,
|
captcha_key: Option<String>,
|
||||||
promotional_email_opt_in: Option<bool>,
|
promotional_email_opt_in: Option<bool>,
|
||||||
}
|
) -> Result<RegisterSchema, FieldFormatError> {
|
||||||
|
let username = username.username;
|
||||||
|
|
||||||
impl RegisterSchema {
|
let email_addr;
|
||||||
/**
|
if email.is_some() {
|
||||||
Returns a new [`Result<RegisterSchema, FieldFormatError>`].
|
email_addr = Some(email.unwrap().email);
|
||||||
## Arguments
|
} else {
|
||||||
All but "String::username" and "bool::consent" are optional.
|
email_addr = None;
|
||||||
|
|
||||||
## Errors
|
|
||||||
You will receive a [`FieldFormatError`], if:
|
|
||||||
- The username is less than 2 or more than 32 characters in length
|
|
||||||
- You supply a `password` which is less than 1 or more than 72 characters in length.
|
|
||||||
|
|
||||||
These constraints have been defined [in the Spacebar-API](https://docs.spacebar.chat/routes/)
|
|
||||||
*/
|
|
||||||
pub fn new(
|
|
||||||
username: AuthUsername,
|
|
||||||
password: Option<AuthPassword>,
|
|
||||||
consent: bool,
|
|
||||||
email: Option<AuthEmail>,
|
|
||||||
fingerprint: Option<String>,
|
|
||||||
invite: Option<String>,
|
|
||||||
date_of_birth: Option<String>,
|
|
||||||
gift_code_sku_id: Option<String>,
|
|
||||||
captcha_key: Option<String>,
|
|
||||||
promotional_email_opt_in: Option<bool>,
|
|
||||||
) -> Result<RegisterSchema, FieldFormatError> {
|
|
||||||
let username = username.username;
|
|
||||||
|
|
||||||
let email_addr;
|
|
||||||
if email.is_some() {
|
|
||||||
email_addr = Some(email.unwrap().email);
|
|
||||||
} else {
|
|
||||||
email_addr = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let has_password;
|
|
||||||
if password.is_some() {
|
|
||||||
has_password = Some(password.unwrap().password);
|
|
||||||
} else {
|
|
||||||
has_password = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !consent {
|
|
||||||
return Err(FieldFormatError::ConsentError);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(RegisterSchema {
|
|
||||||
username,
|
|
||||||
password: has_password,
|
|
||||||
consent,
|
|
||||||
email: email_addr,
|
|
||||||
fingerprint,
|
|
||||||
invite,
|
|
||||||
date_of_birth,
|
|
||||||
gift_code_sku_id,
|
|
||||||
captcha_key,
|
|
||||||
promotional_email_opt_in,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
let has_password;
|
||||||
|
if password.is_some() {
|
||||||
|
has_password = Some(password.unwrap().password);
|
||||||
|
} else {
|
||||||
|
has_password = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !consent {
|
||||||
|
return Err(FieldFormatError::ConsentError);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(RegisterSchema {
|
||||||
|
username,
|
||||||
|
password: has_password,
|
||||||
|
consent,
|
||||||
|
email: email_addr,
|
||||||
|
fingerprint,
|
||||||
|
invite,
|
||||||
|
date_of_birth,
|
||||||
|
gift_code_sku_id,
|
||||||
|
captcha_key,
|
||||||
|
promotional_email_opt_in,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
A struct that represents a well-formed login request.
|
||||||
|
## Arguments
|
||||||
|
Please use new() to create a new instance of this struct.
|
||||||
|
## Errors
|
||||||
|
You will receive a [`FieldFormatError`], if:
|
||||||
|
- The username is not between 2 and 32 characters.
|
||||||
|
- The password is not between 1 and 72 characters.
|
||||||
|
*/
|
||||||
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub struct LoginSchema {
|
||||||
|
login: String,
|
||||||
|
password: String,
|
||||||
|
undelete: Option<bool>,
|
||||||
|
captcha_key: Option<String>,
|
||||||
|
login_source: Option<String>,
|
||||||
|
gift_code_sku_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LoginSchema {
|
||||||
/**
|
/**
|
||||||
A struct that represents a well-formed login request.
|
Returns a new [`Result<LoginSchema, FieldFormatError>`].
|
||||||
## Arguments
|
## Arguments
|
||||||
Please use new() to create a new instance of this struct.
|
login: The username you want to login with.
|
||||||
|
password: The password you want to login with.
|
||||||
|
undelete: Honestly no idea what this is for.
|
||||||
|
captcha_key: The captcha key you want to login with.
|
||||||
|
login_source: The login source.
|
||||||
|
gift_code_sku_id: The gift code sku id.
|
||||||
## Errors
|
## Errors
|
||||||
You will receive a [`FieldFormatError`], if:
|
You will receive a [`FieldFormatError`], if:
|
||||||
- The username is not between 2 and 32 characters.
|
- The username is less than 2 or more than 32 characters in length
|
||||||
- The password is not between 1 and 72 characters.
|
*/
|
||||||
*/
|
pub fn new(
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
login: AuthUsername,
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub struct LoginSchema {
|
|
||||||
login: String,
|
|
||||||
password: String,
|
password: String,
|
||||||
undelete: Option<bool>,
|
undelete: Option<bool>,
|
||||||
captcha_key: Option<String>,
|
captcha_key: Option<String>,
|
||||||
login_source: Option<String>,
|
login_source: Option<String>,
|
||||||
gift_code_sku_id: Option<String>,
|
gift_code_sku_id: Option<String>,
|
||||||
|
) -> Result<LoginSchema, FieldFormatError> {
|
||||||
|
let login = login.username;
|
||||||
|
Ok(LoginSchema {
|
||||||
|
login,
|
||||||
|
password,
|
||||||
|
undelete,
|
||||||
|
captcha_key,
|
||||||
|
login_source,
|
||||||
|
gift_code_sku_id,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LoginSchema {
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
/**
|
#[serde(rename_all = "snake_case")]
|
||||||
Returns a new [`Result<LoginSchema, FieldFormatError>`].
|
pub struct TotpSchema {
|
||||||
## Arguments
|
code: String,
|
||||||
login: The username you want to login with.
|
ticket: String,
|
||||||
password: The password you want to login with.
|
gift_code_sku_id: Option<String>,
|
||||||
undelete: Honestly no idea what this is for.
|
login_source: Option<String>,
|
||||||
captcha_key: The captcha key you want to login with.
|
|
||||||
login_source: The login source.
|
|
||||||
gift_code_sku_id: The gift code sku id.
|
|
||||||
## Errors
|
|
||||||
You will receive a [`FieldFormatError`], if:
|
|
||||||
- The username is less than 2 or more than 32 characters in length
|
|
||||||
*/
|
|
||||||
pub fn new(
|
|
||||||
login: AuthUsername,
|
|
||||||
password: String,
|
|
||||||
undelete: Option<bool>,
|
|
||||||
captcha_key: Option<String>,
|
|
||||||
login_source: Option<String>,
|
|
||||||
gift_code_sku_id: Option<String>,
|
|
||||||
) -> Result<LoginSchema, FieldFormatError> {
|
|
||||||
let login = login.username;
|
|
||||||
return Ok(LoginSchema {
|
|
||||||
login,
|
|
||||||
password,
|
|
||||||
undelete,
|
|
||||||
captcha_key,
|
|
||||||
login_source,
|
|
||||||
gift_code_sku_id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct LoginResult {
|
|
||||||
token: String,
|
|
||||||
settings: UserSettings,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct UserSettings {
|
|
||||||
afk_timeout: i32,
|
|
||||||
allow_accessibility_detection: bool,
|
|
||||||
animate_emoji: bool,
|
|
||||||
animate_stickers: i32,
|
|
||||||
contact_sync_enabled: bool,
|
|
||||||
convert_emoticons: bool,
|
|
||||||
custom_status: Option<String>,
|
|
||||||
default_guilds_restricted: bool,
|
|
||||||
detect_platform_accounts: bool,
|
|
||||||
developer_mode: bool,
|
|
||||||
disable_games_tab: bool,
|
|
||||||
enable_tts_command: bool,
|
|
||||||
explicit_content_filter: i32,
|
|
||||||
friend_source_flags: FriendSourceFlags,
|
|
||||||
friend_discovery_flags: Option<i32>,
|
|
||||||
gateway_connected: bool,
|
|
||||||
gif_auto_play: bool,
|
|
||||||
guild_folders: Vec<GuildFolder>,
|
|
||||||
guild_positions: Vec<i64>,
|
|
||||||
inline_attachment_media: bool,
|
|
||||||
inline_embed_media: bool,
|
|
||||||
locale: String,
|
|
||||||
message_display_compact: bool,
|
|
||||||
native_phone_integration_enabled: bool,
|
|
||||||
render_embeds: bool,
|
|
||||||
render_reactions: bool,
|
|
||||||
restricted_guilds: Vec<i64>,
|
|
||||||
show_current_game: bool,
|
|
||||||
status: String,
|
|
||||||
stream_notifications_enabled: bool,
|
|
||||||
theme: String,
|
|
||||||
timezone_offset: i32,
|
|
||||||
view_nsfw_guilds: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct FriendSourceFlags {
|
|
||||||
all: Option<bool>,
|
|
||||||
mutual_friends: Option<bool>,
|
|
||||||
mutual_guilds: Option<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct GuildFolder {
|
|
||||||
id: String,
|
|
||||||
guild_ids: Vec<i64>,
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub struct TotpSchema {
|
|
||||||
code: String,
|
|
||||||
ticket: String,
|
|
||||||
gift_code_sku_id: Option<String>,
|
|
||||||
login_source: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Represents the result you get from GET: /api/instance/policies/.
|
|
||||||
*/
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct InstancePoliciesSchema {
|
|
||||||
instance_name: String,
|
|
||||||
instance_description: Option<String>,
|
|
||||||
front_page: Option<String>,
|
|
||||||
tos_page: Option<String>,
|
|
||||||
correspondence_email: Option<String>,
|
|
||||||
correspondence_user_id: Option<String>,
|
|
||||||
image: Option<String>,
|
|
||||||
instance_id: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InstancePoliciesSchema {
|
|
||||||
pub fn new(
|
|
||||||
instance_name: String,
|
|
||||||
instance_description: Option<String>,
|
|
||||||
front_page: Option<String>,
|
|
||||||
tos_page: Option<String>,
|
|
||||||
correspondence_email: Option<String>,
|
|
||||||
correspondence_user_id: Option<String>,
|
|
||||||
image: Option<String>,
|
|
||||||
instance_id: Option<String>,
|
|
||||||
) -> Self {
|
|
||||||
InstancePoliciesSchema {
|
|
||||||
instance_name,
|
|
||||||
instance_description,
|
|
||||||
front_page,
|
|
||||||
tos_page,
|
|
||||||
correspondence_email,
|
|
||||||
correspondence_user_id,
|
|
||||||
image,
|
|
||||||
instance_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for InstancePoliciesSchema {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"InstancePoliciesSchema {{ instance_name: {}, instance_description: {}, front_page: {}, tos_page: {}, correspondence_email: {}, correspondence_user_id: {}, image: {}, instance_id: {} }}",
|
|
||||||
self.instance_name,
|
|
||||||
self.instance_description.clone().unwrap_or("None".to_string()),
|
|
||||||
self.front_page.clone().unwrap_or("None".to_string()),
|
|
||||||
self.tos_page.clone().unwrap_or("None".to_string()),
|
|
||||||
self.correspondence_email.clone().unwrap_or("None".to_string()),
|
|
||||||
self.correspondence_user_id.clone().unwrap_or("None".to_string()),
|
|
||||||
self.image.clone().unwrap_or("None".to_string()),
|
|
||||||
self.instance_id.clone().unwrap_or("None".to_string()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct ErrorResponse {
|
|
||||||
pub code: i32,
|
|
||||||
pub message: String,
|
|
||||||
pub errors: IntermittentError,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct IntermittentError {
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub errors: std::collections::HashMap<String, ErrorField>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
|
||||||
pub struct ErrorField {
|
|
||||||
#[serde(default)]
|
|
||||||
pub _errors: Vec<Error>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct Error {
|
|
||||||
pub message: String,
|
|
||||||
pub code: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct UserObject {
|
|
||||||
id: String,
|
|
||||||
username: String,
|
|
||||||
discriminator: String,
|
|
||||||
avatar: Option<String>,
|
|
||||||
bot: Option<bool>,
|
|
||||||
system: Option<bool>,
|
|
||||||
mfa_enabled: Option<bool>,
|
|
||||||
banner: Option<bool>,
|
|
||||||
accent_color: Option<String>,
|
|
||||||
locale: String,
|
|
||||||
verified: Option<bool>,
|
|
||||||
email: Option<String>,
|
|
||||||
flags: i8,
|
|
||||||
premium_type: Option<i8>,
|
|
||||||
public_flags: Option<i8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct User {
|
|
||||||
logged_in: bool,
|
|
||||||
belongs_to: URLBundle,
|
|
||||||
token: String,
|
|
||||||
rate_limits: Limits,
|
|
||||||
pub settings: UserSettings,
|
|
||||||
pub object: UserObject,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl User {
|
|
||||||
pub fn is_logged_in(&self) -> bool {
|
|
||||||
if self.logged_in == true {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn belongs_to(&self) -> URLBundle {
|
|
||||||
return self.belongs_to.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn token(&self) -> String {
|
|
||||||
return self.token.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_logged_in(&mut self, bool: bool) {
|
|
||||||
self.logged_in = bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_token(&mut self, token: String) {
|
|
||||||
self.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(
|
|
||||||
logged_in: bool,
|
|
||||||
belongs_to: URLBundle,
|
|
||||||
token: String,
|
|
||||||
rate_limits: Limits,
|
|
||||||
settings: UserSettings,
|
|
||||||
object: UserObject,
|
|
||||||
) -> User {
|
|
||||||
User {
|
|
||||||
logged_in,
|
|
||||||
belongs_to,
|
|
||||||
token,
|
|
||||||
rate_limits,
|
|
||||||
settings,
|
|
||||||
object,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// I know that some of these tests are... really really basic and unneccessary, but sometimes, I
|
// I know that some of these tests are... really really basic and unneccessary, but sometimes, I
|
||||||
// just feel like writing tests, so there you go :) -@bitfl0wer
|
// just feel like writing tests, so there you go :) -@bitfl0wer
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod schemas_tests {
|
mod schemas_tests {
|
||||||
use super::schemas::*;
|
use super::*;
|
||||||
use crate::errors::FieldFormatError;
|
use crate::errors::FieldFormatError;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -474,7 +259,7 @@ mod schemas_tests {
|
||||||
fn password_too_long() {
|
fn password_too_long() {
|
||||||
let mut long_pw = String::new();
|
let mut long_pw = String::new();
|
||||||
for _ in 0..73 {
|
for _ in 0..73 {
|
||||||
long_pw = long_pw + "a";
|
long_pw += "a";
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
AuthPassword::new(long_pw),
|
AuthPassword::new(long_pw),
|
||||||
|
@ -494,7 +279,7 @@ mod schemas_tests {
|
||||||
fn username_too_long() {
|
fn username_too_long() {
|
||||||
let mut long_un = String::new();
|
let mut long_un = String::new();
|
||||||
for _ in 0..33 {
|
for _ in 0..33 {
|
||||||
long_un = long_un + "a";
|
long_un += "a";
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
AuthUsername::new(long_un),
|
AuthUsername::new(long_un),
|
||||||
|
|
|
@ -0,0 +1,213 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{api::limits::Limits, URLBundle};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct LoginResult {
|
||||||
|
token: String,
|
||||||
|
settings: UserSettings,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct UserSettings {
|
||||||
|
afk_timeout: i32,
|
||||||
|
allow_accessibility_detection: bool,
|
||||||
|
animate_emoji: bool,
|
||||||
|
animate_stickers: i32,
|
||||||
|
contact_sync_enabled: bool,
|
||||||
|
convert_emoticons: bool,
|
||||||
|
custom_status: Option<String>,
|
||||||
|
default_guilds_restricted: bool,
|
||||||
|
detect_platform_accounts: bool,
|
||||||
|
developer_mode: bool,
|
||||||
|
disable_games_tab: bool,
|
||||||
|
enable_tts_command: bool,
|
||||||
|
explicit_content_filter: i32,
|
||||||
|
friend_source_flags: FriendSourceFlags,
|
||||||
|
friend_discovery_flags: Option<i32>,
|
||||||
|
gateway_connected: bool,
|
||||||
|
gif_auto_play: bool,
|
||||||
|
guild_folders: Vec<GuildFolder>,
|
||||||
|
guild_positions: Vec<i64>,
|
||||||
|
inline_attachment_media: bool,
|
||||||
|
inline_embed_media: bool,
|
||||||
|
locale: String,
|
||||||
|
message_display_compact: bool,
|
||||||
|
native_phone_integration_enabled: bool,
|
||||||
|
render_embeds: bool,
|
||||||
|
render_reactions: bool,
|
||||||
|
restricted_guilds: Vec<i64>,
|
||||||
|
show_current_game: bool,
|
||||||
|
status: String,
|
||||||
|
stream_notifications_enabled: bool,
|
||||||
|
theme: String,
|
||||||
|
timezone_offset: i32,
|
||||||
|
view_nsfw_guilds: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct FriendSourceFlags {
|
||||||
|
all: Option<bool>,
|
||||||
|
mutual_friends: Option<bool>,
|
||||||
|
mutual_guilds: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct GuildFolder {
|
||||||
|
id: String,
|
||||||
|
guild_ids: Vec<i64>,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Represents the result you get from GET: /api/instance/policies/.
|
||||||
|
*/
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct InstancePolicies {
|
||||||
|
instance_name: String,
|
||||||
|
instance_description: Option<String>,
|
||||||
|
front_page: Option<String>,
|
||||||
|
tos_page: Option<String>,
|
||||||
|
correspondence_email: Option<String>,
|
||||||
|
correspondence_user_id: Option<String>,
|
||||||
|
image: Option<String>,
|
||||||
|
instance_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InstancePolicies {
|
||||||
|
pub fn new(
|
||||||
|
instance_name: String,
|
||||||
|
instance_description: Option<String>,
|
||||||
|
front_page: Option<String>,
|
||||||
|
tos_page: Option<String>,
|
||||||
|
correspondence_email: Option<String>,
|
||||||
|
correspondence_user_id: Option<String>,
|
||||||
|
image: Option<String>,
|
||||||
|
instance_id: Option<String>,
|
||||||
|
) -> Self {
|
||||||
|
InstancePolicies {
|
||||||
|
instance_name,
|
||||||
|
instance_description,
|
||||||
|
front_page,
|
||||||
|
tos_page,
|
||||||
|
correspondence_email,
|
||||||
|
correspondence_user_id,
|
||||||
|
image,
|
||||||
|
instance_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for InstancePolicies {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"InstancePoliciesSchema {{ instance_name: {}, instance_description: {}, front_page: {}, tos_page: {}, correspondence_email: {}, correspondence_user_id: {}, image: {}, instance_id: {} }}",
|
||||||
|
self.instance_name,
|
||||||
|
self.instance_description.clone().unwrap_or("None".to_string()),
|
||||||
|
self.front_page.clone().unwrap_or("None".to_string()),
|
||||||
|
self.tos_page.clone().unwrap_or("None".to_string()),
|
||||||
|
self.correspondence_email.clone().unwrap_or("None".to_string()),
|
||||||
|
self.correspondence_user_id.clone().unwrap_or("None".to_string()),
|
||||||
|
self.image.clone().unwrap_or("None".to_string()),
|
||||||
|
self.instance_id.clone().unwrap_or("None".to_string()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct ErrorResponse {
|
||||||
|
pub code: i32,
|
||||||
|
pub message: String,
|
||||||
|
pub errors: IntermittentError,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct IntermittentError {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub errors: std::collections::HashMap<String, ErrorField>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
|
pub struct ErrorField {
|
||||||
|
#[serde(default)]
|
||||||
|
pub _errors: Vec<Error>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Error {
|
||||||
|
pub message: String,
|
||||||
|
pub code: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct UserObject {
|
||||||
|
id: String,
|
||||||
|
username: String,
|
||||||
|
discriminator: String,
|
||||||
|
avatar: Option<String>,
|
||||||
|
bot: Option<bool>,
|
||||||
|
system: Option<bool>,
|
||||||
|
mfa_enabled: Option<bool>,
|
||||||
|
banner: Option<bool>,
|
||||||
|
accent_color: Option<String>,
|
||||||
|
locale: String,
|
||||||
|
verified: Option<bool>,
|
||||||
|
email: Option<String>,
|
||||||
|
flags: i8,
|
||||||
|
premium_type: Option<i8>,
|
||||||
|
public_flags: Option<i8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct User {
|
||||||
|
logged_in: bool,
|
||||||
|
belongs_to: URLBundle,
|
||||||
|
token: String,
|
||||||
|
rate_limits: Limits,
|
||||||
|
pub settings: UserSettings,
|
||||||
|
pub object: UserObject,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl User {
|
||||||
|
pub fn is_logged_in(&self) -> bool {
|
||||||
|
self.logged_in
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn belongs_to(&self) -> URLBundle {
|
||||||
|
self.belongs_to.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn token(&self) -> String {
|
||||||
|
self.token.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_logged_in(&mut self, bool: bool) {
|
||||||
|
self.logged_in = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_token(&mut self, token: String) {
|
||||||
|
self.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
logged_in: bool,
|
||||||
|
belongs_to: URLBundle,
|
||||||
|
token: String,
|
||||||
|
rate_limits: Limits,
|
||||||
|
settings: UserSettings,
|
||||||
|
object: UserObject,
|
||||||
|
) -> User {
|
||||||
|
User {
|
||||||
|
logged_in,
|
||||||
|
belongs_to,
|
||||||
|
token,
|
||||||
|
rate_limits,
|
||||||
|
settings,
|
||||||
|
object,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::api::limits::{Limit, LimitType, Limits};
|
use crate::api::limits::Limits;
|
||||||
use crate::api::schemas::schemas::{InstancePoliciesSchema, User};
|
use crate::api::types::{InstancePolicies, User};
|
||||||
use crate::errors::{FieldFormatError, InstanceServerError};
|
use crate::errors::{FieldFormatError, InstanceServerError};
|
||||||
use crate::limit::LimitedRequester;
|
use crate::limit::LimitedRequester;
|
||||||
use crate::URLBundle;
|
use crate::URLBundle;
|
||||||
|
@ -13,7 +13,7 @@ The [`Instance`] what you will be using to perform all sorts of actions on the S
|
||||||
*/
|
*/
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
pub urls: URLBundle,
|
pub urls: URLBundle,
|
||||||
pub instance_info: InstancePoliciesSchema,
|
pub instance_info: InstancePolicies,
|
||||||
pub requester: LimitedRequester,
|
pub requester: LimitedRequester,
|
||||||
pub limits: Limits,
|
pub limits: Limits,
|
||||||
//pub gateway: Gateway,
|
//pub gateway: Gateway,
|
||||||
|
@ -34,7 +34,7 @@ impl Instance {
|
||||||
let users: HashMap<Token, User> = HashMap::new();
|
let users: HashMap<Token, User> = HashMap::new();
|
||||||
let mut instance = Instance {
|
let mut instance = Instance {
|
||||||
urls: urls.clone(),
|
urls: urls.clone(),
|
||||||
instance_info: InstancePoliciesSchema::new(
|
instance_info: InstancePolicies::new(
|
||||||
// This is okay, because the instance_info will be overwritten by the instance_policies_schema() function.
|
// This is okay, because the instance_info will be overwritten by the instance_policies_schema() function.
|
||||||
"".to_string(),
|
"".to_string(),
|
||||||
None,
|
None,
|
||||||
|
@ -87,6 +87,6 @@ impl Username {
|
||||||
if username.len() < 2 || username.len() > 32 {
|
if username.len() < 2 || username.len() > 32 {
|
||||||
return Err(FieldFormatError::UsernameError);
|
return Err(FieldFormatError::UsernameError);
|
||||||
}
|
}
|
||||||
return Ok(Username { username });
|
Ok(Username { username })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,10 +49,10 @@ impl URLBundle {
|
||||||
};
|
};
|
||||||
// if the last character of the string is a slash, remove it.
|
// if the last character of the string is a slash, remove it.
|
||||||
let mut url_string = url.to_string();
|
let mut url_string = url.to_string();
|
||||||
if url_string.chars().last().unwrap() == '/' {
|
if url_string.ends_with('/') {
|
||||||
url_string.pop();
|
url_string.pop();
|
||||||
}
|
}
|
||||||
return url_string;
|
url_string
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_api(&self) -> &str {
|
pub fn get_api(&self) -> &str {
|
||||||
|
|
22
src/limit.rs
22
src/limit.rs
|
@ -28,7 +28,7 @@ impl LimitedRequester {
|
||||||
/// be send within the `Limit` of an external API Ratelimiter, and looks at the returned request
|
/// be send within the `Limit` of an external API Ratelimiter, and looks at the returned request
|
||||||
/// headers to see if it can find Ratelimit info to update itself.
|
/// headers to see if it can find Ratelimit info to update itself.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn new(api_url: String) -> Self {
|
pub async fn new() -> Self {
|
||||||
LimitedRequester {
|
LimitedRequester {
|
||||||
http: Client::new(),
|
http: Client::new(),
|
||||||
requests: VecDeque::new(),
|
requests: VecDeque::new(),
|
||||||
|
@ -86,13 +86,13 @@ impl LimitedRequester {
|
||||||
instance_rate_limits,
|
instance_rate_limits,
|
||||||
user_rate_limits,
|
user_rate_limits,
|
||||||
);
|
);
|
||||||
return Ok(response);
|
Ok(response)
|
||||||
} else {
|
} else {
|
||||||
self.requests.push_back(TypedRequest {
|
self.requests.push_back(TypedRequest {
|
||||||
request: request,
|
request,
|
||||||
limit_type: limit_type,
|
limit_type,
|
||||||
});
|
});
|
||||||
return Err(InstanceServerError::RateLimited);
|
Err(InstanceServerError::RateLimited)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ impl LimitedRequester {
|
||||||
]
|
]
|
||||||
.to_vec();
|
.to_vec();
|
||||||
for limit in constant_limits.iter() {
|
for limit in constant_limits.iter() {
|
||||||
match rate_limits.to_hash_map().get(&limit) {
|
match rate_limits.to_hash_map().get(limit) {
|
||||||
Some(limit) => {
|
Some(limit) => {
|
||||||
if limit.remaining == 0 {
|
if limit.remaining == 0 {
|
||||||
return false;
|
return false;
|
||||||
|
@ -155,7 +155,7 @@ impl LimitedRequester {
|
||||||
None => return false,
|
None => return false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_limits(
|
fn update_limits(
|
||||||
|
@ -183,7 +183,7 @@ impl LimitedRequester {
|
||||||
let status = response.status();
|
let status = response.status();
|
||||||
let status_str = status.as_str();
|
let status_str = status.as_str();
|
||||||
|
|
||||||
if status_str.chars().next().unwrap() == '4' {
|
if status_str.starts_with('4') {
|
||||||
rate_limits
|
rate_limits
|
||||||
.get_limit_mut_ref(&LimitType::Error)
|
.get_limit_mut_ref(&LimitType::Error)
|
||||||
.add_remaining(-1);
|
.add_remaining(-1);
|
||||||
|
@ -266,7 +266,7 @@ mod rate_limit {
|
||||||
String::from("wss://localhost:3001/"),
|
String::from("wss://localhost:3001/"),
|
||||||
String::from("http://localhost:3001/cdn"),
|
String::from("http://localhost:3001/cdn"),
|
||||||
);
|
);
|
||||||
let requester = LimitedRequester::new(urls.api).await;
|
let _requester = LimitedRequester::new().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -276,7 +276,7 @@ mod rate_limit {
|
||||||
String::from("wss://localhost:3001/"),
|
String::from("wss://localhost:3001/"),
|
||||||
String::from("http://localhost:3001/cdn"),
|
String::from("http://localhost:3001/cdn"),
|
||||||
);
|
);
|
||||||
let mut requester = LimitedRequester::new(urls.api.clone()).await;
|
let mut requester = LimitedRequester::new().await;
|
||||||
let mut request: Option<Result<Response, InstanceServerError>> = None;
|
let mut request: Option<Result<Response, InstanceServerError>> = None;
|
||||||
let mut instance_rate_limits = Limits::check_limits(urls.api.clone()).await;
|
let mut instance_rate_limits = Limits::check_limits(urls.api.clone()).await;
|
||||||
let mut user_rate_limits = Limits::check_limits(urls.api.clone()).await;
|
let mut user_rate_limits = Limits::check_limits(urls.api.clone()).await;
|
||||||
|
@ -314,7 +314,7 @@ mod rate_limit {
|
||||||
);
|
);
|
||||||
let mut instance_rate_limits = Limits::check_limits(urls.api.clone()).await;
|
let mut instance_rate_limits = Limits::check_limits(urls.api.clone()).await;
|
||||||
let mut user_rate_limits = Limits::check_limits(urls.api.clone()).await;
|
let mut user_rate_limits = Limits::check_limits(urls.api.clone()).await;
|
||||||
let mut requester = LimitedRequester::new(urls.api.clone()).await;
|
let mut requester = LimitedRequester::new().await;
|
||||||
let request_path = urls.api.clone() + "/policies/instance/limits";
|
let request_path = urls.api.clone() + "/policies/instance/limits";
|
||||||
let request_builder = requester.http.get(request_path);
|
let request_builder = requester.http.get(request_path);
|
||||||
let request = requester
|
let request = requester
|
||||||
|
|
Loading…
Reference in New Issue