diff --git a/src/api/auth/login.rs b/src/api/auth/login.rs index baae4ae..68604d9 100644 --- a/src/api/auth/login.rs +++ b/src/api/auth/login.rs @@ -6,9 +6,10 @@ use serde_json::to_string; use crate::api::LimitType; use crate::errors::ChorusResult; +use crate::gateway::Gateway; use crate::instance::{Instance, UserMeta}; use crate::ratelimiter::ChorusRequest; -use crate::types::{LoginResult, LoginSchema}; +use crate::types::{GatewayIdentifyPayload, LoginResult, LoginSchema}; impl Instance { pub async fn login_account(&mut self, login_schema: &LoginSchema) -> ChorusResult { @@ -22,7 +23,8 @@ impl Instance { // We do not have a user yet, and the UserRateLimits will not be affected by a login // request (since login is an instance wide limit), which is why we are just cloning the // instances' limits to pass them on as user_rate_limits later. - let mut shell = UserMeta::shell(Rc::new(RefCell::new(self.clone())), "None".to_string()); + let mut shell = + UserMeta::shell(Rc::new(RefCell::new(self.clone())), "None".to_string()).await; let login_result = chorus_request .deserialize_response::(&mut shell) .await?; @@ -30,12 +32,17 @@ impl Instance { if self.limits_information.is_some() { self.limits_information.as_mut().unwrap().ratelimits = shell.limits.clone().unwrap(); } + let mut identify = GatewayIdentifyPayload::common(); + let gateway = Gateway::new(self.urls.wss.clone()).await.unwrap(); + identify.token = login_result.token.clone(); + gateway.send_identify(identify).await; let user = UserMeta::new( Rc::new(RefCell::new(self.clone())), login_result.token, self.clone_limits_if_some(), login_result.settings, object, + gateway, ); Ok(user) } diff --git a/src/api/auth/register.rs b/src/api/auth/register.rs index a6849cc..e818d82 100644 --- a/src/api/auth/register.rs +++ b/src/api/auth/register.rs @@ -3,6 +3,8 @@ use std::{cell::RefCell, rc::Rc}; use reqwest::Client; use serde_json::to_string; +use crate::gateway::Gateway; +use crate::types::GatewayIdentifyPayload; use crate::{ api::policies::instance::LimitType, errors::ChorusResult, @@ -35,7 +37,8 @@ impl Instance { // We do not have a user yet, and the UserRateLimits will not be affected by a login // request (since register is an instance wide limit), which is why we are just cloning // the instances' limits to pass them on as user_rate_limits later. - let mut shell = UserMeta::shell(Rc::new(RefCell::new(self.clone())), "None".to_string()); + let mut shell = + UserMeta::shell(Rc::new(RefCell::new(self.clone())), "None".to_string()).await; let token = chorus_request .deserialize_response::(&mut shell) .await? @@ -45,12 +48,17 @@ impl Instance { } let user_object = self.get_user(token.clone(), None).await.unwrap(); let settings = UserMeta::get_settings(&token, &self.urls.api.clone(), self).await?; + let mut identify = GatewayIdentifyPayload::common(); + let gateway = Gateway::new(self.urls.wss.clone()).await.unwrap(); + identify.token = token.clone(); + gateway.send_identify(identify).await; let user = UserMeta::new( Rc::new(RefCell::new(self.clone())), token.clone(), self.clone_limits_if_some(), settings, user_object, + gateway, ); Ok(user) } diff --git a/src/api/users/users.rs b/src/api/users/users.rs index bd46a36..af6d2ce 100644 --- a/src/api/users/users.rs +++ b/src/api/users/users.rs @@ -122,7 +122,8 @@ impl User { let request: reqwest::RequestBuilder = Client::new() .get(format!("{}/users/@me/settings/", url_api)) .bearer_auth(token); - let mut user = UserMeta::shell(Rc::new(RefCell::new(instance.clone())), token.clone()); + let mut user = + UserMeta::shell(Rc::new(RefCell::new(instance.clone())), token.clone()).await; let chorus_request = ChorusRequest { request, limit_type: LimitType::Global, @@ -151,7 +152,7 @@ impl Instance { This function is a wrapper around [`User::get`]. */ pub async fn get_user(&mut self, token: String, id: Option<&String>) -> ChorusResult { - let mut user = UserMeta::shell(Rc::new(RefCell::new(self.clone())), token); + let mut user = UserMeta::shell(Rc::new(RefCell::new(self.clone())), token).await; let result = User::get(&mut user, id).await; if self.limits_information.is_some() { self.limits_information.as_mut().unwrap().ratelimits = diff --git a/src/instance.rs b/src/instance.rs index 0cd65f4..9795557 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize}; use crate::api::{Limit, LimitType}; use crate::errors::ChorusResult; +use crate::gateway::{Gateway, GatewayHandle}; use crate::ratelimiter::ChorusRequest; use crate::types::types::subconfigs::limits::rates::RateLimits; use crate::types::{GeneralConfiguration, User, UserSettings}; @@ -88,13 +89,14 @@ impl fmt::Display for Token { } } -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct UserMeta { pub belongs_to: Rc>, pub token: String, pub limits: Option>, pub settings: UserSettings, pub object: User, + pub gateway: GatewayHandle, } impl UserMeta { @@ -112,6 +114,7 @@ impl UserMeta { limits: Option>, settings: UserSettings, object: User, + gateway: GatewayHandle, ) -> UserMeta { UserMeta { belongs_to, @@ -119,19 +122,24 @@ impl UserMeta { limits, settings, object, + gateway, } } /// Creates a new 'shell' of a user. The user does not exist as an object, and exists so that you have /// a UserMeta object to make Rate Limited requests with. This is useful in scenarios like /// registering or logging in to the Instance, where you do not yet have a User object, but still - /// need to make a RateLimited request. - pub(crate) fn shell(instance: Rc>, token: String) -> UserMeta { + /// need to make a RateLimited request. To use the [`GatewayHandle`], you will have to identify + /// first. + pub(crate) async fn shell(instance: Rc>, token: String) -> UserMeta { let settings = UserSettings::default(); let object = User::default(); + let wss_url = instance.borrow().urls.wss.clone(); + // Dummy gateway object + let gateway = Gateway::new(wss_url).await.unwrap(); UserMeta { - belongs_to: instance.clone(), token, + belongs_to: instance.clone(), limits: instance .borrow() .limits_information @@ -139,6 +147,7 @@ impl UserMeta { .map(|info| info.ratelimits.clone()), settings, object, + gateway, } } } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index fc4a19c..747a8cd 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,3 +1,4 @@ +use chorus::gateway::Gateway; use chorus::{ instance::{Instance, UserMeta}, types::{ @@ -18,8 +19,8 @@ pub(crate) struct TestBundle { pub channel: Channel, } +#[allow(unused)] impl TestBundle { - #[allow(unused)] pub(crate) async fn create_user(&mut self, username: &str) -> UserMeta { let register_schema = RegisterSchema { username: username.to_string(), @@ -32,6 +33,16 @@ impl TestBundle { .await .unwrap() } + pub(crate) async fn clone_user_without_gateway(&self) -> UserMeta { + UserMeta { + belongs_to: self.user.belongs_to.clone(), + token: self.user.token.clone(), + limits: self.user.limits.clone(), + settings: self.user.settings.clone(), + object: self.user.object.clone(), + gateway: Gateway::new(self.instance.urls.wss.clone()).await.unwrap(), + } + } } // Set up a test by creating an Instance and a User. Reduces Test boilerplate. diff --git a/tests/gateway.rs b/tests/gateway.rs index 199e14b..21a2018 100644 --- a/tests/gateway.rs +++ b/tests/gateway.rs @@ -8,7 +8,8 @@ use chorus::types::{self, Channel}; async fn test_gateway_establish() { let bundle = common::setup().await; - Gateway::new(bundle.urls.wss).await.unwrap(); + Gateway::new(bundle.urls.wss.clone()).await.unwrap(); + common::teardown(bundle).await } #[tokio::test] @@ -16,25 +17,21 @@ async fn test_gateway_establish() { async fn test_gateway_authenticate() { let bundle = common::setup().await; - let gateway = Gateway::new(bundle.urls.wss).await.unwrap(); + let gateway = Gateway::new(bundle.urls.wss.clone()).await.unwrap(); let mut identify = types::GatewayIdentifyPayload::common(); - identify.token = bundle.user.token; + identify.token = bundle.user.token.clone(); gateway.send_identify(identify).await; + common::teardown(bundle).await } #[tokio::test] async fn test_self_updating_structs() { let mut bundle = common::setup().await; - let gateway = Gateway::new(bundle.urls.wss).await.unwrap(); - let mut identify = types::GatewayIdentifyPayload::common(); - identify.token = bundle.user.token.clone(); - gateway.send_identify(identify).await; - let channel_receiver = gateway.observe(bundle.channel.clone()).await; - let received_channel = channel_receiver.borrow(); - assert_eq!(*received_channel, bundle.channel); - drop(received_channel); + let channel_updater = bundle.user.gateway.observe(bundle.channel.clone()).await; + let received_channel = channel_updater.borrow().clone(); + assert_eq!(received_channel, bundle.channel); let channel = &mut bundle.channel; let modify_data = types::ChannelModifySchema { name: Some("beepboop".to_string()), @@ -43,6 +40,7 @@ async fn test_self_updating_structs() { Channel::modify(channel, modify_data, channel.id, &mut bundle.user) .await .unwrap(); - let received_channel = channel_receiver.borrow(); + let received_channel = channel_updater.borrow(); assert_eq!(received_channel.name.as_ref().unwrap(), "beepboop"); + common::teardown(bundle).await } diff --git a/tests/invites.rs b/tests/invites.rs index b6206b9..d19be61 100644 --- a/tests/invites.rs +++ b/tests/invites.rs @@ -1,14 +1,12 @@ -use chorus::types::CreateChannelInviteSchema; - mod common; - +use chorus::types::CreateChannelInviteSchema; #[tokio::test] async fn create_accept_invite() { let mut bundle = common::setup().await; let channel = bundle.channel.clone(); - let mut user = bundle.user.clone(); - let create_channel_invite_schema = CreateChannelInviteSchema::default(); let mut other_user = bundle.create_user("testuser1312").await; + let user = &mut bundle.user; + let create_channel_invite_schema = CreateChannelInviteSchema::default(); assert!(chorus::types::Guild::get(bundle.guild.id, &mut other_user) .await .is_err());