Improve auto updating structs usage (#168)
* Add `GatewayHandle` to `UserMeta` * Make user::shell async due to gateway add
This commit is contained in:
parent
9ebe72a7dc
commit
07f283a205
|
@ -6,9 +6,10 @@ use serde_json::to_string;
|
||||||
|
|
||||||
use crate::api::LimitType;
|
use crate::api::LimitType;
|
||||||
use crate::errors::ChorusResult;
|
use crate::errors::ChorusResult;
|
||||||
|
use crate::gateway::Gateway;
|
||||||
use crate::instance::{Instance, UserMeta};
|
use crate::instance::{Instance, UserMeta};
|
||||||
use crate::ratelimiter::ChorusRequest;
|
use crate::ratelimiter::ChorusRequest;
|
||||||
use crate::types::{LoginResult, LoginSchema};
|
use crate::types::{GatewayIdentifyPayload, LoginResult, LoginSchema};
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub async fn login_account(&mut self, login_schema: &LoginSchema) -> ChorusResult<UserMeta> {
|
pub async fn login_account(&mut self, login_schema: &LoginSchema) -> ChorusResult<UserMeta> {
|
||||||
|
@ -22,7 +23,8 @@ impl Instance {
|
||||||
// We do not have a user yet, and the UserRateLimits will not be affected by a login
|
// 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
|
// 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.
|
// 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
|
let login_result = chorus_request
|
||||||
.deserialize_response::<LoginResult>(&mut shell)
|
.deserialize_response::<LoginResult>(&mut shell)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -30,12 +32,17 @@ impl Instance {
|
||||||
if self.limits_information.is_some() {
|
if self.limits_information.is_some() {
|
||||||
self.limits_information.as_mut().unwrap().ratelimits = shell.limits.clone().unwrap();
|
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(
|
let user = UserMeta::new(
|
||||||
Rc::new(RefCell::new(self.clone())),
|
Rc::new(RefCell::new(self.clone())),
|
||||||
login_result.token,
|
login_result.token,
|
||||||
self.clone_limits_if_some(),
|
self.clone_limits_if_some(),
|
||||||
login_result.settings,
|
login_result.settings,
|
||||||
object,
|
object,
|
||||||
|
gateway,
|
||||||
);
|
);
|
||||||
Ok(user)
|
Ok(user)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ use std::{cell::RefCell, rc::Rc};
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
|
|
||||||
|
use crate::gateway::Gateway;
|
||||||
|
use crate::types::GatewayIdentifyPayload;
|
||||||
use crate::{
|
use crate::{
|
||||||
api::policies::instance::LimitType,
|
api::policies::instance::LimitType,
|
||||||
errors::ChorusResult,
|
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
|
// 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
|
// 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.
|
// 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
|
let token = chorus_request
|
||||||
.deserialize_response::<Token>(&mut shell)
|
.deserialize_response::<Token>(&mut shell)
|
||||||
.await?
|
.await?
|
||||||
|
@ -45,12 +48,17 @@ impl Instance {
|
||||||
}
|
}
|
||||||
let user_object = self.get_user(token.clone(), None).await.unwrap();
|
let user_object = self.get_user(token.clone(), None).await.unwrap();
|
||||||
let settings = UserMeta::get_settings(&token, &self.urls.api.clone(), self).await?;
|
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(
|
let user = UserMeta::new(
|
||||||
Rc::new(RefCell::new(self.clone())),
|
Rc::new(RefCell::new(self.clone())),
|
||||||
token.clone(),
|
token.clone(),
|
||||||
self.clone_limits_if_some(),
|
self.clone_limits_if_some(),
|
||||||
settings,
|
settings,
|
||||||
user_object,
|
user_object,
|
||||||
|
gateway,
|
||||||
);
|
);
|
||||||
Ok(user)
|
Ok(user)
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,8 @@ impl User {
|
||||||
let request: reqwest::RequestBuilder = Client::new()
|
let request: reqwest::RequestBuilder = Client::new()
|
||||||
.get(format!("{}/users/@me/settings/", url_api))
|
.get(format!("{}/users/@me/settings/", url_api))
|
||||||
.bearer_auth(token);
|
.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 {
|
let chorus_request = ChorusRequest {
|
||||||
request,
|
request,
|
||||||
limit_type: LimitType::Global,
|
limit_type: LimitType::Global,
|
||||||
|
@ -151,7 +152,7 @@ impl Instance {
|
||||||
This function is a wrapper around [`User::get`].
|
This function is a wrapper around [`User::get`].
|
||||||
*/
|
*/
|
||||||
pub async fn get_user(&mut self, token: String, id: Option<&String>) -> ChorusResult<User> {
|
pub async fn get_user(&mut self, token: String, id: Option<&String>) -> ChorusResult<User> {
|
||||||
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;
|
let result = User::get(&mut user, id).await;
|
||||||
if self.limits_information.is_some() {
|
if self.limits_information.is_some() {
|
||||||
self.limits_information.as_mut().unwrap().ratelimits =
|
self.limits_information.as_mut().unwrap().ratelimits =
|
||||||
|
|
|
@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::api::{Limit, LimitType};
|
use crate::api::{Limit, LimitType};
|
||||||
use crate::errors::ChorusResult;
|
use crate::errors::ChorusResult;
|
||||||
|
use crate::gateway::{Gateway, GatewayHandle};
|
||||||
use crate::ratelimiter::ChorusRequest;
|
use crate::ratelimiter::ChorusRequest;
|
||||||
use crate::types::types::subconfigs::limits::rates::RateLimits;
|
use crate::types::types::subconfigs::limits::rates::RateLimits;
|
||||||
use crate::types::{GeneralConfiguration, User, UserSettings};
|
use crate::types::{GeneralConfiguration, User, UserSettings};
|
||||||
|
@ -88,13 +89,14 @@ impl fmt::Display for Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct UserMeta {
|
pub struct UserMeta {
|
||||||
pub belongs_to: Rc<RefCell<Instance>>,
|
pub belongs_to: Rc<RefCell<Instance>>,
|
||||||
pub token: String,
|
pub token: String,
|
||||||
pub limits: Option<HashMap<LimitType, Limit>>,
|
pub limits: Option<HashMap<LimitType, Limit>>,
|
||||||
pub settings: UserSettings,
|
pub settings: UserSettings,
|
||||||
pub object: User,
|
pub object: User,
|
||||||
|
pub gateway: GatewayHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserMeta {
|
impl UserMeta {
|
||||||
|
@ -112,6 +114,7 @@ impl UserMeta {
|
||||||
limits: Option<HashMap<LimitType, Limit>>,
|
limits: Option<HashMap<LimitType, Limit>>,
|
||||||
settings: UserSettings,
|
settings: UserSettings,
|
||||||
object: User,
|
object: User,
|
||||||
|
gateway: GatewayHandle,
|
||||||
) -> UserMeta {
|
) -> UserMeta {
|
||||||
UserMeta {
|
UserMeta {
|
||||||
belongs_to,
|
belongs_to,
|
||||||
|
@ -119,19 +122,24 @@ impl UserMeta {
|
||||||
limits,
|
limits,
|
||||||
settings,
|
settings,
|
||||||
object,
|
object,
|
||||||
|
gateway,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new 'shell' of a user. The user does not exist as an object, and exists so that you have
|
/// 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
|
/// 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
|
/// registering or logging in to the Instance, where you do not yet have a User object, but still
|
||||||
/// need to make a RateLimited request.
|
/// need to make a RateLimited request. To use the [`GatewayHandle`], you will have to identify
|
||||||
pub(crate) fn shell(instance: Rc<RefCell<Instance>>, token: String) -> UserMeta {
|
/// first.
|
||||||
|
pub(crate) async fn shell(instance: Rc<RefCell<Instance>>, token: String) -> UserMeta {
|
||||||
let settings = UserSettings::default();
|
let settings = UserSettings::default();
|
||||||
let object = User::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 {
|
UserMeta {
|
||||||
belongs_to: instance.clone(),
|
|
||||||
token,
|
token,
|
||||||
|
belongs_to: instance.clone(),
|
||||||
limits: instance
|
limits: instance
|
||||||
.borrow()
|
.borrow()
|
||||||
.limits_information
|
.limits_information
|
||||||
|
@ -139,6 +147,7 @@ impl UserMeta {
|
||||||
.map(|info| info.ratelimits.clone()),
|
.map(|info| info.ratelimits.clone()),
|
||||||
settings,
|
settings,
|
||||||
object,
|
object,
|
||||||
|
gateway,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use chorus::gateway::Gateway;
|
||||||
use chorus::{
|
use chorus::{
|
||||||
instance::{Instance, UserMeta},
|
instance::{Instance, UserMeta},
|
||||||
types::{
|
types::{
|
||||||
|
@ -18,8 +19,8 @@ pub(crate) struct TestBundle {
|
||||||
pub channel: Channel,
|
pub channel: Channel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
impl TestBundle {
|
impl TestBundle {
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) async fn create_user(&mut self, username: &str) -> UserMeta {
|
pub(crate) async fn create_user(&mut self, username: &str) -> UserMeta {
|
||||||
let register_schema = RegisterSchema {
|
let register_schema = RegisterSchema {
|
||||||
username: username.to_string(),
|
username: username.to_string(),
|
||||||
|
@ -32,6 +33,16 @@ impl TestBundle {
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.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.
|
// Set up a test by creating an Instance and a User. Reduces Test boilerplate.
|
||||||
|
|
|
@ -8,7 +8,8 @@ use chorus::types::{self, Channel};
|
||||||
async fn test_gateway_establish() {
|
async fn test_gateway_establish() {
|
||||||
let bundle = common::setup().await;
|
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]
|
#[tokio::test]
|
||||||
|
@ -16,25 +17,21 @@ async fn test_gateway_establish() {
|
||||||
async fn test_gateway_authenticate() {
|
async fn test_gateway_authenticate() {
|
||||||
let bundle = common::setup().await;
|
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();
|
let mut identify = types::GatewayIdentifyPayload::common();
|
||||||
identify.token = bundle.user.token;
|
identify.token = bundle.user.token.clone();
|
||||||
|
|
||||||
gateway.send_identify(identify).await;
|
gateway.send_identify(identify).await;
|
||||||
|
common::teardown(bundle).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_self_updating_structs() {
|
async fn test_self_updating_structs() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let gateway = Gateway::new(bundle.urls.wss).await.unwrap();
|
let channel_updater = bundle.user.gateway.observe(bundle.channel.clone()).await;
|
||||||
let mut identify = types::GatewayIdentifyPayload::common();
|
let received_channel = channel_updater.borrow().clone();
|
||||||
identify.token = bundle.user.token.clone();
|
assert_eq!(received_channel, bundle.channel);
|
||||||
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 = &mut bundle.channel;
|
let channel = &mut bundle.channel;
|
||||||
let modify_data = types::ChannelModifySchema {
|
let modify_data = types::ChannelModifySchema {
|
||||||
name: Some("beepboop".to_string()),
|
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)
|
Channel::modify(channel, modify_data, channel.id, &mut bundle.user)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let received_channel = channel_receiver.borrow();
|
let received_channel = channel_updater.borrow();
|
||||||
assert_eq!(received_channel.name.as_ref().unwrap(), "beepboop");
|
assert_eq!(received_channel.name.as_ref().unwrap(), "beepboop");
|
||||||
|
common::teardown(bundle).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
use chorus::types::CreateChannelInviteSchema;
|
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
use chorus::types::CreateChannelInviteSchema;
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn create_accept_invite() {
|
async fn create_accept_invite() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let channel = bundle.channel.clone();
|
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 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)
|
assert!(chorus::types::Guild::get(bundle.guild.id, &mut other_user)
|
||||||
.await
|
.await
|
||||||
.is_err());
|
.is_err());
|
||||||
|
|
Loading…
Reference in New Issue