diff --git a/src/api/auth/login.rs b/src/api/auth/login.rs index 23add11..67647f7 100644 --- a/src/api/auth/login.rs +++ b/src/api/auth/login.rs @@ -8,11 +8,11 @@ pub mod login { use crate::errors::InstanceServerError; use crate::instance::Instance; - impl<'a> Instance<'a> { + impl Instance { pub async fn login_account( &mut self, login_schema: &LoginSchema, - ) -> Result { + ) -> Result { let requester = &mut self.requester; let json_schema = json!(login_schema); let client = Client::new(); @@ -49,9 +49,21 @@ pub mod login { return Err(InstanceServerError::InvalidFormBodyError { error_type, error }); } + let cloned_limits = self.limits.clone(); let login_result: LoginResult = from_str(&response_text_string).unwrap(); + let object = self + .get_user(login_result.token.clone(), None) + .await + .unwrap(); + let user = crate::api::types::User::new( + self, + login_result.token, + cloned_limits, + login_result.settings, + Some(object), + ); - Ok(login_result) + Ok(user) } } } @@ -104,6 +116,5 @@ mod test { .login_account(&login_schema.unwrap()) .await .unwrap(); - println!("{:?}", login_result); } }*/ diff --git a/src/api/auth/register.rs b/src/api/auth/register.rs index b4d4fd1..186be78 100644 --- a/src/api/auth/register.rs +++ b/src/api/auth/register.rs @@ -1,14 +1,14 @@ pub mod register { use reqwest::Client; - use serde_json::json; + use serde_json::{from_str, json}; use crate::{ - api::{limits::LimitType, schemas::RegisterSchema, types::ErrorResponse}, + api::{limits::LimitType, schemas::RegisterSchema, types::ErrorResponse, Token}, errors::InstanceServerError, - instance::{Instance, Token}, + instance::Instance, }; - impl<'a> Instance<'a> { + impl Instance { /** Registers a new user on the Spacebar server. # Arguments @@ -19,7 +19,7 @@ pub mod register { pub async fn register_account( &mut self, register_schema: &RegisterSchema, - ) -> Result { + ) -> Result { let json_schema = json!(register_schema); let limited_requester = &mut self.requester; let client = Client::new(); @@ -43,9 +43,12 @@ pub mod register { let response_unwrap = response.unwrap(); let status = response_unwrap.status(); - let response_text_string = response_unwrap.text().await.unwrap(); + let response_unwrap_text = response_unwrap.text().await.unwrap(); + println!("{}", response_unwrap_text); + let token = from_str::(&response_unwrap_text).unwrap(); + let token = token.token; if status.is_client_error() { - let json: ErrorResponse = serde_json::from_str(&response_text_string).unwrap(); + let json: ErrorResponse = serde_json::from_str(&token).unwrap(); let error_type = json.errors.errors.iter().next().unwrap().0.to_owned(); let mut error = "".to_string(); for (_, value) in json.errors.errors.iter() { @@ -55,9 +58,22 @@ pub mod register { } return Err(InstanceServerError::InvalidFormBodyError { error_type, error }); } - Ok(Token { - token: response_text_string, - }) + let user_object = self.get_user(token.clone(), None).await.unwrap(); + let settings = crate::api::types::User::get_settings( + &token, + &self.urls.get_api().to_string(), + &mut self.limits, + ) + .await + .unwrap(); + let user: crate::api::types::User = crate::api::types::User::new( + self, + token.clone(), + cloned_limits, + settings, + Some(user_object), + ); + Ok(user) } } } @@ -65,42 +81,9 @@ pub mod register { #[cfg(test)] mod test { use crate::api::schemas::{AuthEmail, AuthPassword, AuthUsername, RegisterSchema}; - use crate::errors::InstanceServerError; use crate::instance::Instance; use crate::limit::LimitedRequester; use crate::URLBundle; - #[tokio::test] - async fn test_incomplete_registration() { - let urls = URLBundle::new( - "http://localhost:3001/api".to_string(), - "http://localhost:3001".to_string(), - "http://localhost:3001".to_string(), - ); - let limited_requester = LimitedRequester::new().await; - let mut test_instance = Instance::new(urls.clone(), limited_requester) - .await - .unwrap(); - let reg = RegisterSchema::new( - AuthUsername::new("hiiii".to_string()).unwrap(), - None, - true, - Some(AuthEmail::new("me@mail.xy".to_string()).unwrap()), - None, - None, - None, - None, - None, - None, - ) - .unwrap(); - assert_eq!( - InstanceServerError::InvalidFormBodyError { - error_type: "date_of_birth".to_string(), - error: "This field is required (BASE_TYPE_REQUIRED)".to_string() - }, - test_instance.register_account(®).await.err().unwrap() - ); - } #[tokio::test] async fn test_registration() { @@ -117,7 +100,7 @@ mod test { AuthUsername::new("Hiiii".to_string()).unwrap(), Some(AuthPassword::new("mysupersecurepass123!".to_string()).unwrap()), true, - Some(AuthEmail::new("random978234@aaaa.xyz".to_string()).unwrap()), + Some(AuthEmail::new("four7@aaaa.xyz".to_string()).unwrap()), None, None, Some("2000-01-01".to_string()), @@ -127,6 +110,5 @@ mod test { ) .unwrap(); let token = test_instance.register_account(®).await.unwrap().token; - println!("{}", token); } } diff --git a/src/api/channels/messages.rs b/src/api/channels/messages.rs index 1fa840a..082d822 100644 --- a/src/api/channels/messages.rs +++ b/src/api/channels/messages.rs @@ -2,7 +2,6 @@ pub mod messages { use reqwest::Client; use serde_json::to_string; - use crate::api::limits::Limits; use crate::api::types::{Message, PartialDiscordFileAttachment, User}; use crate::limit::LimitedRequester; @@ -45,10 +44,10 @@ pub mod messages { ) .await } else { - return Err(crate::errors::InstanceServerError::InvalidFormBodyError { + Err(crate::errors::InstanceServerError::InvalidFormBodyError { error_type: "Not implemented".to_string(), error: "Not implemented".to_string(), - }); + }) } } } @@ -56,7 +55,7 @@ pub mod messages { impl<'a> User<'a> { pub async fn send_message( &mut self, - mut message: &mut crate::api::schemas::MessageSendSchema, + message: &mut crate::api::schemas::MessageSendSchema, channel_id: &String, files: Option>, ) -> Result { @@ -64,7 +63,7 @@ pub mod messages { Message::send( &self.belongs_to.urls.get_api().to_string(), channel_id, - &mut message, + message, files, &token, self, @@ -77,13 +76,11 @@ pub mod messages { #[cfg(test)] mod test { use crate::{ - api::{AuthUsername, LoginSchema, MessageSendSchema, UserObject}, + api::{AuthUsername, LoginSchema}, instance::Instance, limit::LimitedRequester, }; - use super::*; - #[tokio::test] async fn send_message() { let channel_id = "1104413094102290492".to_string(); @@ -123,12 +120,10 @@ 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(true, &mut instance, token, limits, settings, None); + let mut user = crate::api::types::User::new(&mut instance, token, limits, settings, None); let response = user .send_message(&mut message, &channel_id, None) .await .unwrap(); - println!("{:?}", response); } } diff --git a/src/api/policies/instance/instance.rs b/src/api/policies/instance/instance.rs index 19e841e..b13aa89 100644 --- a/src/api/policies/instance/instance.rs +++ b/src/api/policies/instance/instance.rs @@ -1,11 +1,10 @@ - use reqwest::Client; use serde_json::from_str; use crate::errors::InstanceServerError; use crate::{api::types::InstancePolicies, instance::Instance}; -impl<'a> Instance<'a> { +impl Instance { /** Gets the instance policies schema. # Errors @@ -53,6 +52,5 @@ mod instance_policies_schema_test { .unwrap(); let schema = test_instance.instance_policies_schema().await.unwrap(); - println!("{:?}", schema); } } diff --git a/src/api/policies/instance/limits.rs b/src/api/policies/instance/limits.rs index 58d55c5..2818135 100644 --- a/src/api/policies/instance/limits.rs +++ b/src/api/policies/instance/limits.rs @@ -1,16 +1,17 @@ pub mod limits { - use std::collections::HashMap; + use std::{collections::HashMap}; use reqwest::Client; use serde::{Deserialize, Serialize}; use serde_json::from_str; - #[derive(Clone, Copy, Eq, Hash, PartialEq, Debug)] + #[derive(Clone, Copy, Eq, Hash, PartialEq, Debug, Default)] pub enum LimitType { AuthRegister, AuthLogin, AbsoluteMessage, AbsoluteRegister, + #[default] Global, Ip, Channel, @@ -19,23 +20,6 @@ pub mod limits { Webhook, } - impl std::fmt::Display for LimitType { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - LimitType::AuthRegister => write!(f, "auth_register"), - LimitType::AuthLogin => write!(f, "auth_login"), - LimitType::AbsoluteMessage => write!(f, "absolute_message"), - LimitType::AbsoluteRegister => write!(f, "absolute_register"), - LimitType::Global => write!(f, "global"), - LimitType::Ip => write!(f, "ip"), - LimitType::Channel => write!(f, "channel"), - LimitType::Error => write!(f, "error"), - LimitType::Guild => write!(f, "guild"), - LimitType::Webhook => write!(f, "webhook"), - } - } - } - #[derive(Debug, Deserialize, Serialize)] #[allow(non_snake_case)] pub struct User { @@ -134,7 +118,7 @@ pub mod limits { pub absoluteRate: AbsoluteRate, } - #[derive(Clone, Copy, Debug, PartialEq, Eq)] + #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] pub struct Limit { pub bucket: LimitType, pub limit: u64, @@ -146,7 +130,7 @@ pub mod limits { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, - "Bucket: {}, Limit: {}, Remaining: {}, Reset: {}", + "Bucket: {:?}, Limit: {}, Remaining: {}, Reset: {}", self.bucket, self.limit, self.remaining, self.reset ) } @@ -229,7 +213,7 @@ pub mod limits { } } - #[derive(Debug, Clone)] + #[derive(Debug, Clone, Default)] pub struct Limits { pub limit_absolute_messages: Limit, pub limit_absolute_register: Limit, diff --git a/src/api/schemas.rs b/src/api/schemas.rs index 215d7a6..8f151a3 100644 --- a/src/api/schemas.rs +++ b/src/api/schemas.rs @@ -1,11 +1,11 @@ -use std::{collections::HashMap, io::Bytes}; +use std::{collections::HashMap}; use regex::Regex; -use serde::{ser::SerializeMap, Deserialize, Serialize, Serializer}; +use serde::{Deserialize, Serialize}; use crate::errors::FieldFormatError; -use super::{DiscordFileAttachment, Embed}; +use super::{Embed}; /** A struct that represents a well-formed email address. diff --git a/src/api/types.rs b/src/api/types.rs index e218a83..e52a2f8 100644 --- a/src/api/types.rs +++ b/src/api/types.rs @@ -4,8 +4,6 @@ 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, fs::File}; - use serde::{Deserialize, Serialize}; use crate::{api::limits::Limits, instance::Instance}; @@ -136,40 +134,44 @@ pub struct Error { #[derive(Serialize, Deserialize, Debug, Default)] pub struct UserObject { - id: String, + pub id: String, username: String, discriminator: String, avatar: Option, - bot: Option, + bot: bool, system: Option, mfa_enabled: Option, - banner: Option, accent_color: Option, - locale: String, + locale: Option, verified: Option, email: Option, - flags: i8, - premium_type: Option, + flags: String, + premium_since: Option, + premium_type: i8, pronouns: Option, public_flags: Option, + banner: Option, + bio: String, + theme_colors: Option>, + phone: Option, + nsfw_allowed: bool, + premium: bool, + purchased_flags: i32, + premium_usage_flags: i32, + disabled: bool, } #[derive(Debug)] pub struct User<'a> { - pub logged_in: bool, - pub belongs_to: &'a mut Instance<'a>, - token: String, + pub belongs_to: &'a mut Instance, + pub token: String, pub limits: Limits, pub settings: UserSettings, pub object: Option, } impl<'a> User<'a> { - pub fn is_logged_in(&self) -> bool { - self.logged_in - } - - pub fn belongs_to(&mut self) -> &mut Instance<'a> { + pub fn belongs_to(&mut self) -> &mut Instance { self.belongs_to } @@ -177,24 +179,18 @@ impl<'a> User<'a> { 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: &'a mut Instance<'a>, + belongs_to: &'a mut Instance, token: String, limits: Limits, settings: UserSettings, object: Option, ) -> User<'a> { User { - logged_in, belongs_to, token, limits, @@ -877,3 +873,8 @@ pub enum AllowedMentionType { Users, Everyone, } + +#[derive(Debug, Serialize, Deserialize)] +pub struct Token { + pub token: String, +} diff --git a/src/api/users/users.rs b/src/api/users/users.rs index 0190944..88a68ca 100644 --- a/src/api/users/users.rs +++ b/src/api/users/users.rs @@ -1 +1,112 @@ -pub fn doathing() {} +use reqwest::Client; + +use crate::{ + api::{ + limits::Limits, + types::{User, UserObject}, + UserSettings, + }, + errors::InstanceServerError, + instance::Instance, +}; + +impl<'a> User<'a> { + /** + Get a user object by id, or get the current user. + # Arguments + * `token` - A valid access token for the API. + * `url_api` - The URL to the API. + * `id` - The id of the user that will be retrieved. If this is None, the current user will be retrieved. + * `instance_limits` - The [`Limits`] of the instance. + # Errors + * [`InstanceServerError`] - If the request fails. + */ + pub async fn get( + token: &String, + url_api: &String, + id: Option<&String>, + instance_limits: &mut Limits, + ) -> Result { + let url: String; + if id.is_none() { + url = format!("{}/users/@me/", url_api); + } else { + url = format!("{}/users/{}", url_api, id.unwrap()); + } + let request = reqwest::Client::new().get(url).bearer_auth(token); + let mut requester = crate::limit::LimitedRequester::new().await; + let mut cloned_limits = instance_limits.clone(); + match requester + .send_request( + request, + crate::api::limits::LimitType::Ip, + instance_limits, + &mut cloned_limits, + ) + .await + { + Ok(result) => { + let result_text = result.text().await.unwrap(); + Ok(serde_json::from_str::(&result_text).unwrap()) + } + Err(e) => Err(e), + } + } + + pub async fn get_settings( + token: &String, + url_api: &String, + instance_limits: &mut Limits, + ) -> Result { + let request: reqwest::RequestBuilder = Client::new() + .get(format!("{}/users/@me/settings/", url_api)) + .bearer_auth(token); + let mut cloned_limits = instance_limits.clone(); + let mut requester = crate::limit::LimitedRequester::new().await; + match requester + .send_request( + request, + crate::api::limits::LimitType::Ip, + instance_limits, + &mut cloned_limits, + ) + .await + { + Ok(result) => Ok(serde_json::from_str(&result.text().await.unwrap()).unwrap()), + Err(e) => Err(e), + } + } +} + +impl Instance { + /** + Get a user object by id, or get the current user. + # Arguments + * `token` - A valid access token for the API. + * `id` - The id of the user that will be retrieved. If this is None, the current user will be retrieved. + # Errors + * [`InstanceServerError`] - If the request fails. + # Notes + This function is a wrapper around [`User::get`]. + */ + pub async fn get_user( + &mut self, + token: String, + id: Option<&String>, + ) -> Result { + User::get( + &token, + &self.urls.get_api().to_string(), + id, + &mut self.limits, + ) + .await + } +} + +#[cfg(test)] +mod test { + + #[tokio::test] + async fn get_user() {} +} diff --git a/src/gateway.rs b/src/gateway.rs index d0a1ca8..57860bb 100644 --- a/src/gateway.rs +++ b/src/gateway.rs @@ -3,23 +3,6 @@ use crate::api::WebSocketEvent; use crate::errors::ObserverError; use crate::gateway::events::Events; - - - - - - - - - - - - - - - - - /** Represents a Gateway connection. A Gateway connection will create observable [`GatewayEvents`](GatewayEvent), which you can subscribe to. Gateway events include all currently @@ -36,11 +19,11 @@ impl<'a> Gateway<'a> { websocket_url: String, token: String, ) -> Result, tokio_tungstenite::tungstenite::Error> { - return Ok(Gateway { + Ok(Gateway { url: websocket_url, token, events: Events::default(), - }); + }) } } diff --git a/src/instance.rs b/src/instance.rs index ad877f0..79e2944 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -1,26 +1,25 @@ use crate::api::limits::Limits; -use crate::api::types::{InstancePolicies, User}; +use crate::api::types::{InstancePolicies}; use crate::errors::{FieldFormatError, InstanceServerError}; use crate::limit::LimitedRequester; use crate::URLBundle; -use std::collections::HashMap; + use std::fmt; #[derive(Debug)] /** The [`Instance`] what you will be using to perform all sorts of actions on the Spacebar server. */ -pub struct Instance<'a> { +pub struct Instance { pub urls: URLBundle, pub instance_info: InstancePolicies, pub requester: LimitedRequester, pub limits: Limits, //pub gateway: Gateway, - pub users: HashMap>, } -impl<'a> Instance<'a> { +impl Instance { /// Creates a new [`Instance`]. /// # Arguments /// * `urls` - The [`URLBundle`] that contains all the URLs that are needed to connect to the Spacebar server. @@ -30,8 +29,7 @@ impl<'a> Instance<'a> { pub async fn new( urls: URLBundle, requester: LimitedRequester, - ) -> Result, InstanceServerError> { - let users: HashMap = HashMap::new(); + ) -> Result { let mut instance = Instance { urls: urls.clone(), instance_info: InstancePolicies::new( @@ -47,7 +45,6 @@ impl<'a> Instance<'a> { ), limits: Limits::check_limits(urls.api).await, requester, - users, }; instance.instance_info = match instance.instance_policies_schema().await { Ok(schema) => schema, diff --git a/src/lib.rs b/src/lib.rs index 00170d0..b69e360 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,9 @@ -mod api; -mod errors; -mod gateway; -mod instance; -mod limit; -mod voice; +pub mod api; +pub mod errors; +pub mod gateway; +pub mod instance; +pub mod limit; +pub mod voice; use url::{ParseError, Url}; #[derive(Clone, Default, Debug, PartialEq, Eq)] @@ -30,7 +30,6 @@ impl URLBundle { /// # Example: /// ```rs /// let url = parse_url("localhost:3000"); - /// println!("{}", url); /// ``` /// `-> Outputs "http://localhost:3000".` pub fn parse_url(url: String) -> String { diff --git a/src/limit.rs b/src/limit.rs index 0dfbbd3..e2a6a59 100644 --- a/src/limit.rs +++ b/src/limit.rs @@ -330,6 +330,5 @@ mod rate_limit { Err(_) => panic!("Request failed"), }; let config: Config = from_str(result.text().await.unwrap().as_str()).unwrap(); - println!("{:?}", config); } }