Improved auto updating structs (#184)
This PR does the following things:
- Give `UserMeta` a `GatewayHandle`
- Change struct-fields which are supposed to be "shared" to
`Arc<RwLock<T>>`. "shared" struct-fields are things like a `Channel`
object, which may exist both on their own, and inside a `Guild`s struct
fields. Due to sharing this field, we only need to update a single
object to propagate the changes everywhere.
- Some light refactorings across the project. Example: change
`UserMeta::get()` to `UserMeta::get_user()`
- Add `Composite` trait and proc macro. `Composites` are `Updateable`
(uniquely identifiable) objects, which contain at least one other shared
(`Arc<RwLock<T>>`) field. This trait/macro provides functionality to not
only watch an object, but also all observable struct fields in that
object.
- Gets rid of tokio:⌚:channel in favor of Arc<RwLock<T>>
To-do before merging:
- [x] Properly test `Composite` functionality to ensure it works as
intended
I'd love a second pair of eyes over this, especially in case I forgot
something major ^^'
This commit is contained in:
commit
ecdab68677
|
@ -77,7 +77,7 @@ checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -220,8 +220,9 @@ dependencies = [
|
||||||
name = "chorus-macros"
|
name = "chorus-macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -361,7 +362,7 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"strsim",
|
"strsim",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -372,7 +373,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -569,7 +570,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1186,7 +1187,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1302,7 +1303,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1683,7 +1684,7 @@ checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1705,7 +1706,7 @@ checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1745,7 +1746,7 @@ dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1978,9 +1979,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.26"
|
version = "2.0.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
|
checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2018,7 +2019,7 @@ checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2102,7 +2103,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2206,7 +2207,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2384,7 +2385,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2418,7 +2419,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.26",
|
"syn 2.0.28",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,10 +2,22 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-trait"
|
||||||
|
version = "0.1.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chorus-macros"
|
name = "chorus-macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
|
@ -9,3 +9,4 @@ proc-macro = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quote = "1"
|
quote = "1"
|
||||||
syn = "2"
|
syn = "2"
|
||||||
|
async-trait = "0.1.71"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
use syn::{parse_macro_input, Data, DeriveInput, Field, Fields, FieldsNamed};
|
||||||
|
|
||||||
#[proc_macro_derive(Updateable)]
|
#[proc_macro_derive(Updateable)]
|
||||||
pub fn updateable_macro_derive(input: TokenStream) -> TokenStream {
|
pub fn updateable_macro_derive(input: TokenStream) -> TokenStream {
|
||||||
|
@ -16,3 +17,106 @@ pub fn updateable_macro_derive(input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(JsonField)]
|
||||||
|
pub fn jsonfield_macro_derive(input: TokenStream) -> TokenStream {
|
||||||
|
let ast: syn::DeriveInput = syn::parse(input).unwrap();
|
||||||
|
|
||||||
|
let name = &ast.ident;
|
||||||
|
// No need for macro hygiene, we're only using this in chorus
|
||||||
|
quote! {
|
||||||
|
impl JsonField for #name {
|
||||||
|
fn get_json(&self) -> String {
|
||||||
|
self.json.clone()
|
||||||
|
}
|
||||||
|
fn set_json(&mut self, json: String) {
|
||||||
|
self.json = json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn observe_option(_args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn observe_option_vec(_args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn observe(_args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn observe_vec(_args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(
|
||||||
|
Composite,
|
||||||
|
attributes(observe_option_vec, observe_option, observe, observe_vec)
|
||||||
|
)]
|
||||||
|
pub fn composite_derive(input: TokenStream) -> TokenStream {
|
||||||
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
|
let process_field = |field: &Field| {
|
||||||
|
let field_name = &field.ident;
|
||||||
|
let attrs = &field.attrs;
|
||||||
|
|
||||||
|
let observe_option = attrs
|
||||||
|
.iter()
|
||||||
|
.any(|attr| attr.path().is_ident("observe_option"));
|
||||||
|
let observe_option_vec = attrs
|
||||||
|
.iter()
|
||||||
|
.any(|attr| attr.path().is_ident("observe_option_vec"));
|
||||||
|
let observe = attrs.iter().any(|attr| attr.path().is_ident("observe"));
|
||||||
|
let observe_vec = attrs.iter().any(|attr| attr.path().is_ident("observe_vec"));
|
||||||
|
|
||||||
|
match (observe_option, observe_option_vec, observe, observe_vec) {
|
||||||
|
(true, _, _, _) => quote! {
|
||||||
|
#field_name: Self::option_observe_fn(self.#field_name, gateway).await
|
||||||
|
},
|
||||||
|
(_, true, _, _) => quote! {
|
||||||
|
#field_name: Self::option_vec_observe_fn(self.#field_name, gateway).await
|
||||||
|
},
|
||||||
|
(_, _, true, _) => quote! {
|
||||||
|
#field_name: Self::value_observe_fn(self.#field_name, gateway).await
|
||||||
|
},
|
||||||
|
(_, _, _, true) => quote! {
|
||||||
|
#field_name: Self::vec_observe_fn(self.#field_name, gateway).await
|
||||||
|
},
|
||||||
|
_ => quote! {
|
||||||
|
#field_name: self.#field_name
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match &input.data {
|
||||||
|
Data::Struct(data) => match &data.fields {
|
||||||
|
Fields::Named(FieldsNamed { named, .. }) => {
|
||||||
|
let field_exprs = named.iter().map(process_field);
|
||||||
|
|
||||||
|
let ident = &input.ident;
|
||||||
|
let expanded = quote! {
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl<T: Updateable + Clone + Debug> Composite<T> for #ident {
|
||||||
|
async fn watch_whole(self, gateway: &GatewayHandle) -> Self {
|
||||||
|
Self {
|
||||||
|
#(#field_exprs,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TokenStream::from(expanded)
|
||||||
|
}
|
||||||
|
_ => panic!("Composite derive macro only supports named fields"),
|
||||||
|
},
|
||||||
|
_ => panic!("Composite derive macro only supports structs"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
|
@ -46,7 +46,7 @@ impl Instance {
|
||||||
login_result.token,
|
login_result.token,
|
||||||
self.clone_limits_if_some(),
|
self.clone_limits_if_some(),
|
||||||
login_result.settings,
|
login_result.settings,
|
||||||
Arc::new(Mutex::new(object)),
|
Arc::new(RwLock::new(object)),
|
||||||
gateway,
|
gateway,
|
||||||
);
|
);
|
||||||
Ok(user)
|
Ok(user)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
@ -52,8 +52,8 @@ impl Instance {
|
||||||
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(),
|
||||||
Arc::new(Mutex::new(settings)),
|
Arc::new(RwLock::new(settings)),
|
||||||
Arc::new(Mutex::new(user_object)),
|
Arc::new(RwLock::new(user_object)),
|
||||||
gateway,
|
gateway,
|
||||||
);
|
);
|
||||||
Ok(user)
|
Ok(user)
|
||||||
|
|
|
@ -64,9 +64,9 @@ impl Channel {
|
||||||
pub async fn modify(
|
pub async fn modify(
|
||||||
&self,
|
&self,
|
||||||
modify_data: ChannelModifySchema,
|
modify_data: ChannelModifySchema,
|
||||||
channel_id: Snowflake,
|
|
||||||
user: &mut UserMeta,
|
user: &mut UserMeta,
|
||||||
) -> ChorusResult<Channel> {
|
) -> ChorusResult<Channel> {
|
||||||
|
let channel_id = self.id;
|
||||||
let chorus_request = ChorusRequest {
|
let chorus_request = ChorusRequest {
|
||||||
request: Client::new()
|
request: Client::new()
|
||||||
.patch(format!(
|
.patch(format!(
|
||||||
|
|
|
@ -120,13 +120,13 @@ impl types::RoleObject {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates a role in a guild.
|
/// Modifies a role in a guild.
|
||||||
///
|
///
|
||||||
/// Requires the [`MANAGE_ROLES`](crate::types::PermissionFlags::MANAGE_ROLES) permission.
|
/// Requires the [`MANAGE_ROLES`](crate::types::PermissionFlags::MANAGE_ROLES) permission.
|
||||||
///
|
///
|
||||||
/// # Reference
|
/// # Reference
|
||||||
/// See <https://discord-userdoccers.vercel.app/resources/guild#modify-guild-role>
|
/// See <https://discord-userdoccers.vercel.app/resources/guild#modify-guild-role>
|
||||||
pub async fn update(
|
pub async fn modify(
|
||||||
user: &mut UserMeta,
|
user: &mut UserMeta,
|
||||||
guild_id: Snowflake,
|
guild_id: Snowflake,
|
||||||
role_id: Snowflake,
|
role_id: Snowflake,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
@ -21,8 +20,8 @@ impl UserMeta {
|
||||||
/// # Reference
|
/// # Reference
|
||||||
/// See <https://discord-userdoccers.vercel.app/resources/user#get-user> and
|
/// See <https://discord-userdoccers.vercel.app/resources/user#get-user> and
|
||||||
/// <https://discord-userdoccers.vercel.app/resources/user#get-current-user>
|
/// <https://discord-userdoccers.vercel.app/resources/user#get-current-user>
|
||||||
pub async fn get(user: &mut UserMeta, id: Option<&String>) -> ChorusResult<User> {
|
pub async fn get_user(&mut self, id: Option<&String>) -> ChorusResult<User> {
|
||||||
User::get(user, id).await
|
User::get(self, id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the user's settings.
|
/// Gets the user's settings.
|
||||||
|
@ -56,12 +55,7 @@ impl UserMeta {
|
||||||
request,
|
request,
|
||||||
limit_type: LimitType::default(),
|
limit_type: LimitType::default(),
|
||||||
};
|
};
|
||||||
let user_updated = chorus_request
|
chorus_request.deserialize_response::<User>(self).await
|
||||||
.deserialize_response::<User>(self)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
self.object = Arc::new(Mutex::new(user_updated.clone()));
|
|
||||||
Ok(user_updated)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes the user from the Instance.
|
/// Deletes the user from the Instance.
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
use crate::errors::GatewayError;
|
use crate::errors::GatewayError;
|
||||||
use crate::gateway::events::Events;
|
use crate::gateway::events::Events;
|
||||||
use crate::types::{self, Channel, ChannelUpdate, Snowflake};
|
use crate::types::{
|
||||||
use crate::types::{UpdateMessage, WebSocketEvent};
|
self, Channel, ChannelUpdate, Composite, Guild, GuildRoleCreate, GuildRoleUpdate, JsonField,
|
||||||
|
RoleObject, Snowflake, UpdateMessage, WebSocketEvent,
|
||||||
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, RwLock};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::sync::watch;
|
|
||||||
use tokio::time::sleep_until;
|
use tokio::time::sleep_until;
|
||||||
|
|
||||||
use futures_util::stream::SplitSink;
|
use futures_util::stream::SplitSink;
|
||||||
|
@ -148,6 +149,8 @@ impl GatewayMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type ObservableObject = dyn Send + Sync + Any;
|
||||||
|
|
||||||
/// Represents a handle to a Gateway connection. A Gateway connection will create observable
|
/// Represents a handle to a Gateway connection. A Gateway connection will create observable
|
||||||
/// [`GatewayEvents`](GatewayEvent), which you can subscribe to. Gateway events include all currently
|
/// [`GatewayEvents`](GatewayEvent), which you can subscribe to. Gateway events include all currently
|
||||||
/// implemented types with the trait [`WebSocketEvent`]
|
/// implemented types with the trait [`WebSocketEvent`]
|
||||||
|
@ -167,7 +170,7 @@ pub struct GatewayHandle {
|
||||||
pub handle: JoinHandle<()>,
|
pub handle: JoinHandle<()>,
|
||||||
/// Tells gateway tasks to close
|
/// Tells gateway tasks to close
|
||||||
kill_send: tokio::sync::broadcast::Sender<()>,
|
kill_send: tokio::sync::broadcast::Sender<()>,
|
||||||
store: Arc<Mutex<HashMap<Snowflake, Box<dyn Send + Any>>>>,
|
pub(crate) store: Arc<Mutex<HashMap<Snowflake, Arc<RwLock<ObservableObject>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An entity type which is supposed to be updateable via the Gateway. This is implemented for all such types chorus supports, implementing it for your own types is likely a mistake.
|
/// An entity type which is supposed to be updateable via the Gateway. This is implemented for all such types chorus supports, implementing it for your own types is likely a mistake.
|
||||||
|
@ -196,27 +199,57 @@ impl GatewayHandle {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn observe<T: Updateable>(&self, object: T) -> watch::Receiver<T> {
|
pub async fn observe<T: Updateable + Clone + Debug + Composite<T>>(
|
||||||
|
&self,
|
||||||
|
object: Arc<RwLock<T>>,
|
||||||
|
) -> Arc<RwLock<T>> {
|
||||||
let mut store = self.store.lock().await;
|
let mut store = self.store.lock().await;
|
||||||
if let Some(channel) = store.get(&object.id()) {
|
let id = object.read().unwrap().id();
|
||||||
let (_, rx) = channel
|
if let Some(channel) = store.get(&id) {
|
||||||
.downcast_ref::<(watch::Sender<T>, watch::Receiver<T>)>()
|
let object = channel.clone();
|
||||||
|
drop(store);
|
||||||
|
object
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.downcast_ref::<T>()
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
panic!(
|
panic!(
|
||||||
"Snowflake {} already exists in the store, but it is not of type T.",
|
"Snowflake {} already exists in the store, but it is not of type T.",
|
||||||
object.id()
|
id
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
rx.clone()
|
let ptr = Arc::into_raw(object.clone());
|
||||||
|
// SAFETY:
|
||||||
|
// - We have just checked that the typeid of the `dyn Any ...` matches that of `T`.
|
||||||
|
// - This operation doesn't read or write any shared data, and thus cannot cause a data race
|
||||||
|
// - The reference count is not being modified
|
||||||
|
let downcasted = unsafe { Arc::from_raw(ptr as *const RwLock<T>).clone() };
|
||||||
|
let object = downcasted.read().unwrap().clone();
|
||||||
|
|
||||||
|
let watched_object = object.watch_whole(self).await;
|
||||||
|
*downcasted.write().unwrap() = watched_object;
|
||||||
|
downcasted
|
||||||
} else {
|
} else {
|
||||||
let id = object.id();
|
let id = object.read().unwrap().id();
|
||||||
let channel = watch::channel(object);
|
let object = object.read().unwrap().clone();
|
||||||
let receiver = channel.1.clone();
|
let object = object.clone().watch_whole(self).await;
|
||||||
store.insert(id, Box::new(channel));
|
let wrapped = Arc::new(RwLock::new(object));
|
||||||
receiver
|
store.insert(id, wrapped.clone());
|
||||||
|
wrapped
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Recursively observes and updates all updateable fields on the struct T. Returns an object `T`
|
||||||
|
/// with all of its observable fields being observed.
|
||||||
|
pub async fn observe_and_into_inner<T: Updateable + Clone + Debug + Composite<T>>(
|
||||||
|
&self,
|
||||||
|
object: Arc<RwLock<T>>,
|
||||||
|
) -> T {
|
||||||
|
let channel = self.observe(object.clone()).await;
|
||||||
|
let object = channel.read().unwrap().clone();
|
||||||
|
object
|
||||||
|
}
|
||||||
|
|
||||||
/// Sends an identify event to the gateway
|
/// Sends an identify event to the gateway
|
||||||
pub async fn send_identify(&self, to_send: types::GatewayIdentifyPayload) {
|
pub async fn send_identify(&self, to_send: types::GatewayIdentifyPayload) {
|
||||||
let to_send_value = serde_json::to_value(&to_send).unwrap();
|
let to_send_value = serde_json::to_value(&to_send).unwrap();
|
||||||
|
@ -306,7 +339,7 @@ pub struct Gateway {
|
||||||
>,
|
>,
|
||||||
websocket_receive: SplitStream<WebSocketStream<MaybeTlsStream<TcpStream>>>,
|
websocket_receive: SplitStream<WebSocketStream<MaybeTlsStream<TcpStream>>>,
|
||||||
kill_send: tokio::sync::broadcast::Sender<()>,
|
kill_send: tokio::sync::broadcast::Sender<()>,
|
||||||
store: Arc<Mutex<HashMap<Snowflake, Box<dyn Send + Any>>>>,
|
store: Arc<Mutex<HashMap<Snowflake, Arc<RwLock<ObservableObject>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gateway {
|
impl Gateway {
|
||||||
|
@ -472,14 +505,26 @@ impl Gateway {
|
||||||
match event_name.as_str() {
|
match event_name.as_str() {
|
||||||
$($name => {
|
$($name => {
|
||||||
let event = &mut self.events.lock().await.$($path).+;
|
let event = &mut self.events.lock().await.$($path).+;
|
||||||
match serde_json::from_str(gateway_payload.event_data.unwrap().get()) {
|
let json = gateway_payload.event_data.unwrap().get();
|
||||||
|
match serde_json::from_str(json) {
|
||||||
Err(err) => warn!("Failed to parse gateway event {event_name} ({err})"),
|
Err(err) => warn!("Failed to parse gateway event {event_name} ({err})"),
|
||||||
Ok(message) => {
|
Ok(message) => {
|
||||||
$(
|
$(
|
||||||
let message: $message_type = message;
|
let mut message: $message_type = message;
|
||||||
if let Some(to_update) = self.store.lock().await.get(&message.id()) {
|
let store = self.store.lock().await;
|
||||||
if let Some((tx, _)) = to_update.downcast_ref::<(watch::Sender<$update_type>, watch::Receiver<$update_type>)>() {
|
if let Some(to_update) = store.get(&message.id()) {
|
||||||
tx.send_modify(|object| message.update(object));
|
let object = to_update.clone();
|
||||||
|
let inner_object = object.read().unwrap();
|
||||||
|
if let Some(_) = inner_object.downcast_ref::<$update_type>() {
|
||||||
|
let ptr = Arc::into_raw(object.clone());
|
||||||
|
// SAFETY:
|
||||||
|
// - We have just checked that the typeid of the `dyn Any ...` matches that of `T`.
|
||||||
|
// - This operation doesn't read or write any shared data, and thus cannot cause a data race
|
||||||
|
// - The reference count is not being modified
|
||||||
|
let downcasted = unsafe { Arc::from_raw(ptr as *const RwLock<$update_type>).clone() };
|
||||||
|
drop(inner_object);
|
||||||
|
message.set_json(json.to_string());
|
||||||
|
message.update(downcasted.clone());
|
||||||
} else {
|
} else {
|
||||||
warn!("Received {} for {}, but it has been observed to be a different type!", $name, message.id())
|
warn!("Received {} for {}, but it has been observed to be a different type!", $name, message.id())
|
||||||
}
|
}
|
||||||
|
@ -553,8 +598,8 @@ impl Gateway {
|
||||||
"GUILD_MEMBER_REMOVE" => guild.member_remove,
|
"GUILD_MEMBER_REMOVE" => guild.member_remove,
|
||||||
"GUILD_MEMBER_UPDATE" => guild.member_update,
|
"GUILD_MEMBER_UPDATE" => guild.member_update,
|
||||||
"GUILD_MEMBERS_CHUNK" => guild.members_chunk,
|
"GUILD_MEMBERS_CHUNK" => guild.members_chunk,
|
||||||
"GUILD_ROLE_CREATE" => guild.role_create,
|
"GUILD_ROLE_CREATE" => guild.role_create GuildRoleCreate: Guild,
|
||||||
"GUILD_ROLE_UPDATE" => guild.role_update,
|
"GUILD_ROLE_UPDATE" => guild.role_update GuildRoleUpdate: RoleObject,
|
||||||
"GUILD_ROLE_DELETE" => guild.role_delete,
|
"GUILD_ROLE_DELETE" => guild.role_delete,
|
||||||
"GUILD_SCHEDULED_EVENT_CREATE" => guild.role_scheduled_event_create,
|
"GUILD_SCHEDULED_EVENT_CREATE" => guild.role_scheduled_event_create,
|
||||||
"GUILD_SCHEDULED_EVENT_UPDATE" => guild.role_scheduled_event_update,
|
"GUILD_SCHEDULED_EVENT_UPDATE" => guild.role_scheduled_event_update,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -91,8 +91,8 @@ 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: Arc<Mutex<UserSettings>>,
|
pub settings: Arc<RwLock<UserSettings>>,
|
||||||
pub object: Arc<Mutex<User>>,
|
pub object: Arc<RwLock<User>>,
|
||||||
pub gateway: GatewayHandle,
|
pub gateway: GatewayHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,8 +114,8 @@ impl UserMeta {
|
||||||
belongs_to: Rc<RefCell<Instance>>,
|
belongs_to: Rc<RefCell<Instance>>,
|
||||||
token: String,
|
token: String,
|
||||||
limits: Option<HashMap<LimitType, Limit>>,
|
limits: Option<HashMap<LimitType, Limit>>,
|
||||||
settings: Arc<Mutex<UserSettings>>,
|
settings: Arc<RwLock<UserSettings>>,
|
||||||
object: Arc<Mutex<User>>,
|
object: Arc<RwLock<User>>,
|
||||||
gateway: GatewayHandle,
|
gateway: GatewayHandle,
|
||||||
) -> UserMeta {
|
) -> UserMeta {
|
||||||
UserMeta {
|
UserMeta {
|
||||||
|
@ -134,8 +134,8 @@ impl UserMeta {
|
||||||
/// need to make a RateLimited request. To use the [`GatewayHandle`], you will have to identify
|
/// need to make a RateLimited request. To use the [`GatewayHandle`], you will have to identify
|
||||||
/// first.
|
/// first.
|
||||||
pub(crate) async fn shell(instance: Rc<RefCell<Instance>>, token: String) -> UserMeta {
|
pub(crate) async fn shell(instance: Rc<RefCell<Instance>>, token: String) -> UserMeta {
|
||||||
let settings = Arc::new(Mutex::new(UserSettings::default()));
|
let settings = Arc::new(RwLock::new(UserSettings::default()));
|
||||||
let object = Arc::new(Mutex::new(User::default()));
|
let object = Arc::new(RwLock::new(User::default()));
|
||||||
let wss_url = instance.borrow().urls.wss.clone();
|
let wss_url = instance.borrow().urls.wss.clone();
|
||||||
// Dummy gateway object
|
// Dummy gateway object
|
||||||
let gateway = Gateway::new(wss_url).await.unwrap();
|
let gateway = Gateway::new(wss_url).await.unwrap();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -27,7 +27,7 @@ pub struct Application {
|
||||||
pub bot_require_code_grant: bool,
|
pub bot_require_code_grant: bool,
|
||||||
pub verify_key: String,
|
pub verify_key: String,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub owner: Arc<Mutex<User>>,
|
pub owner: Arc<RwLock<User>>,
|
||||||
pub flags: u64,
|
pub flags: u64,
|
||||||
#[cfg(feature = "sqlx")]
|
#[cfg(feature = "sqlx")]
|
||||||
pub redirect_uris: Option<sqlx::types::Json<Vec<String>>>,
|
pub redirect_uris: Option<sqlx::types::Json<Vec<String>>>,
|
||||||
|
@ -49,7 +49,7 @@ pub struct Application {
|
||||||
#[cfg(feature = "sqlx")]
|
#[cfg(feature = "sqlx")]
|
||||||
pub install_params: Option<sqlx::types::Json<InstallParams>>,
|
pub install_params: Option<sqlx::types::Json<InstallParams>>,
|
||||||
#[cfg(not(feature = "sqlx"))]
|
#[cfg(not(feature = "sqlx"))]
|
||||||
pub install_params: Option<Arc<Mutex<InstallParams>>>,
|
pub install_params: Option<Arc<RwLock<InstallParams>>>,
|
||||||
pub terms_of_service_url: Option<String>,
|
pub terms_of_service_url: Option<String>,
|
||||||
pub privacy_policy_url: Option<String>,
|
pub privacy_policy_url: Option<String>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
|
@ -142,7 +142,7 @@ pub struct ApplicationCommand {
|
||||||
pub application_id: Snowflake,
|
pub application_id: Snowflake,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: String,
|
pub description: String,
|
||||||
pub options: Vec<Arc<Mutex<ApplicationCommandOption>>>,
|
pub options: Vec<Arc<RwLock<ApplicationCommandOption>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
@ -154,7 +154,7 @@ pub struct ApplicationCommandOption {
|
||||||
pub description: String,
|
pub description: String,
|
||||||
pub required: bool,
|
pub required: bool,
|
||||||
pub choices: Vec<ApplicationCommandOptionChoice>,
|
pub choices: Vec<ApplicationCommandOptionChoice>,
|
||||||
pub options: Arc<Mutex<Vec<ApplicationCommandOption>>>,
|
pub options: Arc<RwLock<Vec<ApplicationCommandOption>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
@ -190,14 +190,14 @@ pub enum ApplicationCommandOptionType {
|
||||||
pub struct ApplicationCommandInteractionData {
|
pub struct ApplicationCommandInteractionData {
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub options: Vec<Arc<Mutex<ApplicationCommandInteractionDataOption>>>,
|
pub options: Vec<Arc<RwLock<ApplicationCommandInteractionDataOption>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct ApplicationCommandInteractionDataOption {
|
pub struct ApplicationCommandInteractionDataOption {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: Value,
|
pub value: Value,
|
||||||
pub options: Vec<Arc<Mutex<ApplicationCommandInteractionDataOption>>>,
|
pub options: Vec<Arc<RwLock<ApplicationCommandInteractionDataOption>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
|
@ -206,7 +206,7 @@ pub struct GuildApplicationCommandPermissions {
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
pub application_id: Snowflake,
|
pub application_id: Snowflake,
|
||||||
pub guild_id: Snowflake,
|
pub guild_id: Snowflake,
|
||||||
pub permissions: Vec<Arc<Mutex<ApplicationCommandPermission>>>,
|
pub permissions: Vec<Arc<RwLock<ApplicationCommandPermission>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use crate::types::utils::Snowflake;
|
||||||
/// See <https://discord.com/developers/docs/resources/audit-log#audit-log-entry-object>
|
/// See <https://discord.com/developers/docs/resources/audit-log#audit-log-entry-object>
|
||||||
pub struct AuditLogEntry {
|
pub struct AuditLogEntry {
|
||||||
pub target_id: Option<String>,
|
pub target_id: Option<String>,
|
||||||
pub changes: Option<Vec<Arc<Mutex<AuditLogChange>>>>,
|
pub changes: Option<Vec<Arc<RwLock<AuditLogChange>>>>,
|
||||||
pub user_id: Option<Snowflake>,
|
pub user_id: Option<Snowflake>,
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
// to:do implement an enum for these types
|
// to:do implement an enum for these types
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
@ -14,8 +14,8 @@ pub struct AutoModerationRule {
|
||||||
pub creator_id: Snowflake,
|
pub creator_id: Snowflake,
|
||||||
pub event_type: AutoModerationRuleEventType,
|
pub event_type: AutoModerationRuleEventType,
|
||||||
pub trigger_type: AutoModerationRuleTriggerType,
|
pub trigger_type: AutoModerationRuleTriggerType,
|
||||||
pub trigger_metadata: Arc<Mutex<AutoModerationRuleTriggerMetadata>>,
|
pub trigger_metadata: Arc<RwLock<AutoModerationRuleTriggerMetadata>>,
|
||||||
pub actions: Vec<Arc<Mutex<AutoModerationAction>>>,
|
pub actions: Vec<Arc<RwLock<AutoModerationAction>>>,
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub exempt_roles: Vec<Snowflake>,
|
pub exempt_roles: Vec<Snowflake>,
|
||||||
pub exempt_channels: Vec<Snowflake>,
|
pub exempt_channels: Vec<Snowflake>,
|
||||||
|
@ -92,7 +92,7 @@ pub enum AutoModerationRuleKeywordPresetType {
|
||||||
pub struct AutoModerationAction {
|
pub struct AutoModerationAction {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub action_type: AutoModerationActionType,
|
pub action_type: AutoModerationActionType,
|
||||||
pub metadata: Option<Arc<Mutex<AutoModerationActionMetadata>>>,
|
pub metadata: Option<Arc<RwLock<AutoModerationActionMetadata>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default)]
|
#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default)]
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use chorus_macros::Updateable;
|
use chorus_macros::{observe_option_vec, Composite, Updateable};
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_aux::prelude::deserialize_string_from_number;
|
use serde_aux::prelude::deserialize_string_from_number;
|
||||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use crate::gateway::Updateable;
|
use crate::gateway::{GatewayHandle, Updateable};
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
entities::{GuildMember, User},
|
entities::{GuildMember, User},
|
||||||
utils::Snowflake,
|
utils::Snowflake,
|
||||||
|
Composite,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default, Debug, Serialize, Deserialize, Clone, Updateable)]
|
#[derive(Default, Debug, Serialize, Deserialize, Clone, Updateable, Composite)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
/// Represents a guild of private channel
|
/// Represents a guild of private channel
|
||||||
///
|
///
|
||||||
|
@ -48,7 +50,7 @@ pub struct Channel {
|
||||||
pub last_pin_timestamp: Option<String>,
|
pub last_pin_timestamp: Option<String>,
|
||||||
pub managed: Option<bool>,
|
pub managed: Option<bool>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub member: Option<Arc<Mutex<ThreadMember>>>,
|
pub member: Option<ThreadMember>,
|
||||||
pub member_count: Option<i32>,
|
pub member_count: Option<i32>,
|
||||||
pub message_count: Option<i32>,
|
pub message_count: Option<i32>,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
|
@ -58,12 +60,14 @@ pub struct Channel {
|
||||||
#[cfg(feature = "sqlx")]
|
#[cfg(feature = "sqlx")]
|
||||||
pub permission_overwrites: Option<sqlx::types::Json<Vec<PermissionOverwrite>>>,
|
pub permission_overwrites: Option<sqlx::types::Json<Vec<PermissionOverwrite>>>,
|
||||||
#[cfg(not(feature = "sqlx"))]
|
#[cfg(not(feature = "sqlx"))]
|
||||||
pub permission_overwrites: Option<Vec<Arc<Mutex<PermissionOverwrite>>>>,
|
#[observe_option_vec]
|
||||||
|
pub permission_overwrites: Option<Vec<Arc<RwLock<PermissionOverwrite>>>>,
|
||||||
pub permissions: Option<String>,
|
pub permissions: Option<String>,
|
||||||
pub position: Option<i32>,
|
pub position: Option<i32>,
|
||||||
pub rate_limit_per_user: Option<i32>,
|
pub rate_limit_per_user: Option<i32>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub recipients: Option<Vec<Arc<Mutex<User>>>>,
|
#[observe_option_vec]
|
||||||
|
pub recipients: Option<Vec<Arc<RwLock<User>>>>,
|
||||||
pub rtc_region: Option<String>,
|
pub rtc_region: Option<String>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub thread_metadata: Option<ThreadMetadata>,
|
pub thread_metadata: Option<ThreadMetadata>,
|
||||||
|
@ -122,7 +126,9 @@ pub struct Tag {
|
||||||
pub emoji_name: Option<String>,
|
pub emoji_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd)]
|
#[derive(
|
||||||
|
Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Updateable, Composite,
|
||||||
|
)]
|
||||||
pub struct PermissionOverwrite {
|
pub struct PermissionOverwrite {
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
|
@ -156,7 +162,7 @@ pub struct ThreadMember {
|
||||||
pub user_id: Option<Snowflake>,
|
pub user_id: Option<Snowflake>,
|
||||||
pub join_timestamp: Option<String>,
|
pub join_timestamp: Option<String>,
|
||||||
pub flags: Option<u64>,
|
pub flags: Option<u64>,
|
||||||
pub member: Option<Arc<Mutex<GuildMember>>>,
|
pub member: Option<Arc<RwLock<GuildMember>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
|
|
|
@ -1,23 +1,26 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::fmt::Debug;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use chorus_macros::{Composite, Updateable};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::gateway::{GatewayHandle, Updateable};
|
||||||
use crate::types::entities::User;
|
use crate::types::entities::User;
|
||||||
use crate::types::Snowflake;
|
use crate::types::{Composite, Snowflake};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
|
#[derive(Debug, Clone, Deserialize, Serialize, Default, Updateable, Composite)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
/// # Reference
|
/// # Reference
|
||||||
/// See <https://discord-userdoccers.vercel.app/resources/emoji#emoji-object>
|
/// See <https://discord-userdoccers.vercel.app/resources/emoji#emoji-object>
|
||||||
pub struct Emoji {
|
pub struct Emoji {
|
||||||
pub id: Option<Snowflake>,
|
pub id: Snowflake,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
#[cfg(feature = "sqlx")]
|
#[cfg(feature = "sqlx")]
|
||||||
pub roles: Option<sqlx::types::Json<Vec<Snowflake>>>,
|
pub roles: Option<sqlx::types::Json<Vec<Snowflake>>>,
|
||||||
#[cfg(not(feature = "sqlx"))]
|
#[cfg(not(feature = "sqlx"))]
|
||||||
pub roles: Option<Vec<Snowflake>>,
|
pub roles: Option<Vec<Snowflake>>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub user: Option<Arc<Mutex<User>>>,
|
pub user: Option<Arc<RwLock<User>>>,
|
||||||
pub require_colons: Option<bool>,
|
pub require_colons: Option<bool>,
|
||||||
pub managed: Option<bool>,
|
pub managed: Option<bool>,
|
||||||
pub animated: Option<bool>,
|
pub animated: Option<bool>,
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::fmt::Debug;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use chorus_macros::{observe_option_vec, observe_vec, Composite, Updateable};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
|
||||||
|
use crate::gateway::{GatewayHandle, Updateable};
|
||||||
use crate::types::types::guild_configuration::GuildFeaturesList;
|
use crate::types::types::guild_configuration::GuildFeaturesList;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
entities::{Channel, Emoji, RoleObject, Sticker, User, VoiceState, Webhook},
|
entities::{Channel, Emoji, RoleObject, Sticker, User, VoiceState, Webhook},
|
||||||
interfaces::WelcomeScreenObject,
|
interfaces::WelcomeScreenObject,
|
||||||
utils::Snowflake,
|
utils::Snowflake,
|
||||||
|
Composite,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// See <https://discord.com/developers/docs/resources/guild>
|
/// See <https://discord.com/developers/docs/resources/guild>
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable, Composite)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
pub struct Guild {
|
pub struct Guild {
|
||||||
pub afk_channel_id: Option<Snowflake>,
|
pub afk_channel_id: Option<Snowflake>,
|
||||||
|
@ -27,13 +31,15 @@ pub struct Guild {
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub bans: Option<Vec<GuildBan>>,
|
pub bans: Option<Vec<GuildBan>>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub channels: Option<Vec<Arc<Mutex<Channel>>>>,
|
#[observe_option_vec]
|
||||||
|
pub channels: Option<Vec<Arc<RwLock<Channel>>>>,
|
||||||
pub default_message_notifications: Option<i32>,
|
pub default_message_notifications: Option<i32>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub discovery_splash: Option<String>,
|
pub discovery_splash: Option<String>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub emojis: Vec<Arc<Mutex<Emoji>>>,
|
#[observe_vec]
|
||||||
|
pub emojis: Vec<Arc<RwLock<Emoji>>>,
|
||||||
pub explicit_content_filter: Option<i32>,
|
pub explicit_content_filter: Option<i32>,
|
||||||
//#[cfg_attr(feature = "sqlx", sqlx(try_from = "String"))]
|
//#[cfg_attr(feature = "sqlx", sqlx(try_from = "String"))]
|
||||||
pub features: Option<GuildFeaturesList>,
|
pub features: Option<GuildFeaturesList>,
|
||||||
|
@ -42,7 +48,7 @@ pub struct Guild {
|
||||||
pub icon_hash: Option<String>,
|
pub icon_hash: Option<String>,
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub invites: Option<Vec<Arc<Mutex<GuildInvite>>>>,
|
pub invites: Option<Vec<GuildInvite>>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub joined_at: Option<String>,
|
pub joined_at: Option<String>,
|
||||||
pub large: Option<bool>,
|
pub large: Option<bool>,
|
||||||
|
@ -68,7 +74,8 @@ pub struct Guild {
|
||||||
pub public_updates_channel_id: Option<Snowflake>,
|
pub public_updates_channel_id: Option<Snowflake>,
|
||||||
pub region: Option<String>,
|
pub region: Option<String>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub roles: Option<Vec<Arc<Mutex<RoleObject>>>>,
|
#[observe_option_vec]
|
||||||
|
pub roles: Option<Vec<Arc<RwLock<RoleObject>>>>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub rules_channel: Option<String>,
|
pub rules_channel: Option<String>,
|
||||||
pub rules_channel_id: Option<Snowflake>,
|
pub rules_channel_id: Option<Snowflake>,
|
||||||
|
@ -81,13 +88,15 @@ pub struct Guild {
|
||||||
pub vanity_url_code: Option<String>,
|
pub vanity_url_code: Option<String>,
|
||||||
pub verification_level: Option<i32>,
|
pub verification_level: Option<i32>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub voice_states: Option<Vec<Arc<Mutex<VoiceState>>>>,
|
#[observe_option_vec]
|
||||||
|
pub voice_states: Option<Vec<Arc<RwLock<VoiceState>>>>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub webhooks: Option<Vec<Arc<Mutex<Webhook>>>>,
|
#[observe_option_vec]
|
||||||
|
pub webhooks: Option<Vec<Arc<RwLock<Webhook>>>>,
|
||||||
#[cfg(feature = "sqlx")]
|
#[cfg(feature = "sqlx")]
|
||||||
pub welcome_screen: Option<sqlx::types::Json<WelcomeScreenObject>>,
|
pub welcome_screen: Option<sqlx::types::Json<WelcomeScreenObject>>,
|
||||||
#[cfg(not(feature = "sqlx"))]
|
#[cfg(not(feature = "sqlx"))]
|
||||||
pub welcome_screen: Option<Arc<Mutex<WelcomeScreenObject>>>,
|
pub welcome_screen: Option<WelcomeScreenObject>,
|
||||||
pub widget_channel_id: Option<Snowflake>,
|
pub widget_channel_id: Option<Snowflake>,
|
||||||
pub widget_enabled: Option<bool>,
|
pub widget_enabled: Option<bool>,
|
||||||
}
|
}
|
||||||
|
@ -113,11 +122,11 @@ pub struct GuildInvite {
|
||||||
pub created_at: DateTime<Utc>,
|
pub created_at: DateTime<Utc>,
|
||||||
pub expires_at: Option<DateTime<Utc>>,
|
pub expires_at: Option<DateTime<Utc>>,
|
||||||
pub guild_id: Snowflake,
|
pub guild_id: Snowflake,
|
||||||
pub guild: Option<Arc<Mutex<Guild>>>,
|
pub guild: Option<Arc<RwLock<Guild>>>,
|
||||||
pub channel_id: Snowflake,
|
pub channel_id: Snowflake,
|
||||||
pub channel: Option<Arc<Mutex<Channel>>>,
|
pub channel: Option<Arc<RwLock<Channel>>>,
|
||||||
pub inviter_id: Option<Snowflake>,
|
pub inviter_id: Option<Snowflake>,
|
||||||
pub inviter: Option<Arc<Mutex<User>>>,
|
pub inviter: Option<Arc<RwLock<User>>>,
|
||||||
pub target_user_id: Option<Snowflake>,
|
pub target_user_id: Option<Snowflake>,
|
||||||
pub target_user: Option<String>,
|
pub target_user: Option<String>,
|
||||||
pub target_user_type: Option<i32>,
|
pub target_user_type: Option<i32>,
|
||||||
|
@ -151,7 +160,7 @@ pub struct GuildScheduledEvent {
|
||||||
pub entity_type: GuildScheduledEventEntityType,
|
pub entity_type: GuildScheduledEventEntityType,
|
||||||
pub entity_id: Option<Snowflake>,
|
pub entity_id: Option<Snowflake>,
|
||||||
pub entity_metadata: Option<GuildScheduledEventEntityMetadata>,
|
pub entity_metadata: Option<GuildScheduledEventEntityMetadata>,
|
||||||
pub creator: Option<Arc<Mutex<User>>>,
|
pub creator: Option<Arc<RwLock<User>>>,
|
||||||
pub user_count: Option<u64>,
|
pub user_count: Option<u64>,
|
||||||
pub image: Option<String>,
|
pub image: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ use crate::types::{entities::PublicUser, Snowflake};
|
||||||
/// # Reference
|
/// # Reference
|
||||||
/// See <https://discord-userdoccers.vercel.app/resources/guild#guild-member-object>
|
/// See <https://discord-userdoccers.vercel.app/resources/guild#guild-member-object>
|
||||||
pub struct GuildMember {
|
pub struct GuildMember {
|
||||||
pub user: Option<Arc<Mutex<PublicUser>>>,
|
pub user: Option<Arc<RwLock<PublicUser>>>,
|
||||||
pub nick: Option<String>,
|
pub nick: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<String>,
|
||||||
pub roles: Vec<Snowflake>,
|
pub roles: Vec<Snowflake>,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -23,14 +23,14 @@ pub struct Integration {
|
||||||
pub expire_behaviour: Option<u8>,
|
pub expire_behaviour: Option<u8>,
|
||||||
pub expire_grace_period: Option<u16>,
|
pub expire_grace_period: Option<u16>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub user: Option<Arc<Mutex<User>>>,
|
pub user: Option<Arc<RwLock<User>>>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub account: IntegrationAccount,
|
pub account: IntegrationAccount,
|
||||||
pub synced_at: Option<DateTime<Utc>>,
|
pub synced_at: Option<DateTime<Utc>>,
|
||||||
pub subscriber_count: Option<f64>,
|
pub subscriber_count: Option<f64>,
|
||||||
pub revoked: Option<bool>,
|
pub revoked: Option<bool>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub application: Option<Arc<Mutex<Application>>>,
|
pub application: Option<Arc<RwLock<Application>>>,
|
||||||
pub scopes: Option<Vec<String>>,
|
pub scopes: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -70,7 +70,7 @@ pub enum NSFWLevel {
|
||||||
/// See <https://discord-userdoccers.vercel.app/resources/invite#invite-stage-instance-object>
|
/// See <https://discord-userdoccers.vercel.app/resources/invite#invite-stage-instance-object>
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct InviteStageInstance {
|
pub struct InviteStageInstance {
|
||||||
pub members: Vec<Arc<Mutex<GuildMember>>>,
|
pub members: Vec<Arc<RwLock<GuildMember>>>,
|
||||||
pub participant_count: i32,
|
pub participant_count: i32,
|
||||||
pub speaker_count: i32,
|
pub speaker_count: i32,
|
||||||
pub topic: String,
|
pub topic: String,
|
||||||
|
|
|
@ -22,6 +22,11 @@ pub use user_settings::*;
|
||||||
pub use voice_state::*;
|
pub use voice_state::*;
|
||||||
pub use webhook::*;
|
pub use webhook::*;
|
||||||
|
|
||||||
|
use crate::gateway::{GatewayHandle, Updateable};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
mod application;
|
mod application;
|
||||||
mod attachment;
|
mod attachment;
|
||||||
mod audit_log;
|
mod audit_log;
|
||||||
|
@ -45,3 +50,62 @@ mod user;
|
||||||
mod user_settings;
|
mod user_settings;
|
||||||
mod voice_state;
|
mod voice_state;
|
||||||
mod webhook;
|
mod webhook;
|
||||||
|
|
||||||
|
#[async_trait(?Send)]
|
||||||
|
pub trait Composite<T: Updateable + Clone + Debug> {
|
||||||
|
async fn watch_whole(self, gateway: &GatewayHandle) -> Self;
|
||||||
|
|
||||||
|
async fn option_observe_fn(
|
||||||
|
value: Option<Arc<RwLock<T>>>,
|
||||||
|
gateway: &GatewayHandle,
|
||||||
|
) -> Option<Arc<RwLock<T>>>
|
||||||
|
where
|
||||||
|
T: Composite<T> + Debug,
|
||||||
|
{
|
||||||
|
if let Some(value) = value {
|
||||||
|
let value = value.clone();
|
||||||
|
Some(gateway.observe(value).await)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn option_vec_observe_fn(
|
||||||
|
value: Option<Vec<Arc<RwLock<T>>>>,
|
||||||
|
gateway: &GatewayHandle,
|
||||||
|
) -> Option<Vec<Arc<RwLock<T>>>>
|
||||||
|
where
|
||||||
|
T: Composite<T>,
|
||||||
|
{
|
||||||
|
if let Some(value) = value {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
for component in value.into_iter() {
|
||||||
|
vec.push(gateway.observe(component).await);
|
||||||
|
}
|
||||||
|
Some(vec)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn value_observe_fn(value: Arc<RwLock<T>>, gateway: &GatewayHandle) -> Arc<RwLock<T>>
|
||||||
|
where
|
||||||
|
T: Composite<T>,
|
||||||
|
{
|
||||||
|
gateway.observe(value).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn vec_observe_fn(
|
||||||
|
value: Vec<Arc<RwLock<T>>>,
|
||||||
|
gateway: &GatewayHandle,
|
||||||
|
) -> Vec<Arc<RwLock<T>>>
|
||||||
|
where
|
||||||
|
T: Composite<T>,
|
||||||
|
{
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
for component in value.into_iter() {
|
||||||
|
vec.push(gateway.observe(component).await);
|
||||||
|
}
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -15,7 +15,7 @@ pub struct Relationship {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub relationship_type: RelationshipType,
|
pub relationship_type: RelationshipType,
|
||||||
pub nickname: Option<String>,
|
pub nickname: Option<String>,
|
||||||
pub user: Arc<Mutex<PublicUser>>,
|
pub user: Arc<RwLock<PublicUser>>,
|
||||||
pub since: Option<DateTime<Utc>>,
|
pub since: Option<DateTime<Utc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
use chorus_macros::{Composite, Updateable};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_aux::prelude::{deserialize_option_number_from_string, deserialize_string_from_number};
|
use serde_aux::prelude::{deserialize_option_number_from_string, deserialize_string_from_number};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use crate::types::utils::Snowflake;
|
use crate::gateway::{GatewayHandle, Updateable};
|
||||||
|
use crate::types::{utils::Snowflake, Composite};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Updateable, Composite)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
/// See <https://discord.com/developers/docs/topics/permissions#role-object>
|
/// See <https://discord.com/developers/docs/topics/permissions#role-object>
|
||||||
pub struct RoleObject {
|
pub struct RoleObject {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ pub struct Sticker {
|
||||||
pub available: Option<bool>,
|
pub available: Option<bool>,
|
||||||
pub guild_id: Option<Snowflake>,
|
pub guild_id: Option<Snowflake>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub user: Option<Arc<Mutex<User>>>,
|
pub user: Option<Arc<RwLock<User>>>,
|
||||||
pub sort_value: Option<u8>,
|
pub sort_value: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -21,5 +21,5 @@ pub struct TeamMember {
|
||||||
pub membership_state: u8,
|
pub membership_state: u8,
|
||||||
pub permissions: Vec<String>,
|
pub permissions: Vec<String>,
|
||||||
pub team_id: Snowflake,
|
pub team_id: Snowflake,
|
||||||
pub user: Arc<Mutex<User>>,
|
pub user: Arc<RwLock<User>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -18,13 +18,13 @@ pub struct GuildTemplate {
|
||||||
pub usage_count: Option<u64>,
|
pub usage_count: Option<u64>,
|
||||||
pub creator_id: Snowflake,
|
pub creator_id: Snowflake,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub creator: Arc<Mutex<User>>,
|
pub creator: Arc<RwLock<User>>,
|
||||||
pub created_at: DateTime<Utc>,
|
pub created_at: DateTime<Utc>,
|
||||||
pub updated_at: DateTime<Utc>,
|
pub updated_at: DateTime<Utc>,
|
||||||
pub source_guild_id: Snowflake,
|
pub source_guild_id: Snowflake,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub source_guild: Vec<Arc<Mutex<Guild>>>,
|
pub source_guild: Vec<Arc<RwLock<Guild>>>,
|
||||||
// Unsure how a {recursive: Guild} looks like, might be a Vec?
|
// Unsure how a {recursive: Guild} looks like, might be a Vec?
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub serialized_source_guild: Vec<Arc<Mutex<Guild>>>,
|
pub serialized_source_guild: Vec<Arc<RwLock<Guild>>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
use crate::types::utils::Snowflake;
|
use chorus_macros::{Composite, Updateable};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_aux::prelude::deserialize_option_number_from_string;
|
use serde_aux::prelude::deserialize_option_number_from_string;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
use crate::gateway::{GatewayHandle, Updateable};
|
||||||
|
use crate::types::{utils::Snowflake, Composite};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
|
||||||
|
@ -15,7 +19,7 @@ impl User {
|
||||||
PublicUser::from(self)
|
PublicUser::from(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Updateable, Composite)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use chrono::{serde::ts_milliseconds_option, Utc};
|
use chrono::{serde::ts_milliseconds_option, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -75,7 +75,7 @@ pub struct UserSettings {
|
||||||
#[cfg(not(feature = "sqlx"))]
|
#[cfg(not(feature = "sqlx"))]
|
||||||
pub restricted_guilds: Vec<String>,
|
pub restricted_guilds: Vec<String>,
|
||||||
pub show_current_game: bool,
|
pub show_current_game: bool,
|
||||||
pub status: Arc<Mutex<UserStatus>>,
|
pub status: Arc<RwLock<UserStatus>>,
|
||||||
pub stream_notifications_enabled: bool,
|
pub stream_notifications_enabled: bool,
|
||||||
pub theme: UserTheme,
|
pub theme: UserTheme,
|
||||||
pub timezone_offset: i16,
|
pub timezone_offset: i16,
|
||||||
|
@ -111,7 +111,7 @@ impl Default for UserSettings {
|
||||||
render_reactions: true,
|
render_reactions: true,
|
||||||
restricted_guilds: Default::default(),
|
restricted_guilds: Default::default(),
|
||||||
show_current_game: true,
|
show_current_game: true,
|
||||||
status: Arc::new(Mutex::new(UserStatus::Online)),
|
status: Arc::new(RwLock::new(UserStatus::Online)),
|
||||||
stream_notifications_enabled: false,
|
stream_notifications_enabled: false,
|
||||||
theme: UserTheme::Dark,
|
theme: UserTheme::Dark,
|
||||||
timezone_offset: 0,
|
timezone_offset: 0,
|
||||||
|
@ -151,5 +151,5 @@ pub struct GuildFolder {
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct LoginResult {
|
pub struct LoginResult {
|
||||||
pub token: String,
|
pub token: String,
|
||||||
pub settings: Arc<Mutex<UserSettings>>,
|
pub settings: Arc<RwLock<UserSettings>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use chorus_macros::{Composite, Updateable};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
use crate::gateway::{GatewayHandle, Updateable};
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
entities::{Guild, GuildMember},
|
entities::{Guild, GuildMember},
|
||||||
utils::Snowflake,
|
utils::Snowflake,
|
||||||
|
Composite,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// See <https://docs.spacebar.chat/routes/#cmp--schemas-voicestate>
|
/// See <https://docs.spacebar.chat/routes/#cmp--schemas-voicestate>
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable, Composite)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
pub struct VoiceState {
|
pub struct VoiceState {
|
||||||
pub guild_id: Option<Snowflake>,
|
pub guild_id: Option<Snowflake>,
|
||||||
pub guild: Option<Guild>,
|
pub guild: Option<Guild>,
|
||||||
pub channel_id: Option<Snowflake>,
|
pub channel_id: Option<Snowflake>,
|
||||||
pub user_id: Snowflake,
|
pub user_id: Snowflake,
|
||||||
pub member: Option<Arc<Mutex<GuildMember>>>,
|
pub member: Option<Arc<RwLock<GuildMember>>>,
|
||||||
pub session_id: Snowflake,
|
pub session_id: Snowflake,
|
||||||
pub token: Option<String>,
|
pub token: Option<String>,
|
||||||
pub deaf: bool,
|
pub deaf: bool,
|
||||||
|
@ -27,5 +31,5 @@ pub struct VoiceState {
|
||||||
pub self_video: bool,
|
pub self_video: bool,
|
||||||
pub suppress: bool,
|
pub suppress: bool,
|
||||||
pub request_to_speak_timestamp: Option<DateTime<Utc>>,
|
pub request_to_speak_timestamp: Option<DateTime<Utc>>,
|
||||||
pub id: Option<Snowflake>,
|
pub id: Snowflake,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::fmt::Debug;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use chorus_macros::{Composite, Updateable};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::gateway::{GatewayHandle, Updateable};
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
entities::{Guild, User},
|
entities::{Guild, User},
|
||||||
utils::Snowflake,
|
utils::Snowflake,
|
||||||
|
Composite,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// See <https://docs.spacebar.chat/routes/#cmp--schemas-webhook>
|
/// See <https://docs.spacebar.chat/routes/#cmp--schemas-webhook>
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable, Composite)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
pub struct Webhook {
|
pub struct Webhook {
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
|
@ -22,10 +26,10 @@ pub struct Webhook {
|
||||||
pub application_id: Snowflake,
|
pub application_id: Snowflake,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub user: Option<Arc<Mutex<User>>>,
|
pub user: Option<Arc<RwLock<User>>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub source_guild: Option<Arc<Mutex<Guild>>>,
|
pub source_guild: Option<Arc<RwLock<Guild>>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub url: Option<String>,
|
pub url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use crate::types::events::WebSocketEvent;
|
use crate::types::events::WebSocketEvent;
|
||||||
use crate::types::{entities::Channel, Snowflake};
|
use crate::types::{entities::Channel, JsonField, Snowflake};
|
||||||
|
use chorus_macros::JsonField;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -24,18 +27,21 @@ pub struct ChannelCreate {
|
||||||
|
|
||||||
impl WebSocketEvent for ChannelCreate {}
|
impl WebSocketEvent for ChannelCreate {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)]
|
||||||
/// See <https://discord.com/developers/docs/topics/gateway-events#channel-update>
|
/// See <https://discord.com/developers/docs/topics/gateway-events#channel-update>
|
||||||
pub struct ChannelUpdate {
|
pub struct ChannelUpdate {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub channel: Channel,
|
pub channel: Channel,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub json: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for ChannelUpdate {}
|
impl WebSocketEvent for ChannelUpdate {}
|
||||||
|
|
||||||
impl UpdateMessage<Channel> for ChannelUpdate {
|
impl UpdateMessage<Channel> for ChannelUpdate {
|
||||||
fn update(&self, object_to_update: &mut Channel) {
|
fn update(&mut self, object_to_update: Arc<RwLock<Channel>>) {
|
||||||
*object_to_update = self.channel.clone();
|
let mut write = object_to_update.write().unwrap();
|
||||||
|
*write = self.channel.clone();
|
||||||
}
|
}
|
||||||
fn id(&self) -> Snowflake {
|
fn id(&self) -> Snowflake {
|
||||||
self.channel.id
|
self.channel.id
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use chorus_macros::JsonField;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::entities::{Guild, PublicUser, UnavailableGuild};
|
use crate::types::entities::{Guild, PublicUser, UnavailableGuild};
|
||||||
use crate::types::events::WebSocketEvent;
|
use crate::types::events::WebSocketEvent;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
AuditLogEntry, Emoji, GuildMember, GuildScheduledEvent, RoleObject, Snowflake, Sticker,
|
AuditLogEntry, Emoji, GuildMember, GuildScheduledEvent, JsonField, RoleObject, Snowflake,
|
||||||
|
Sticker,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::PresenceUpdate;
|
use super::{PresenceUpdate, UpdateMessage};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
||||||
/// See <https://discord.com/developers/docs/topics/gateway-events#guild-create>;
|
/// See <https://discord.com/developers/docs/topics/gateway-events#guild-create>;
|
||||||
|
@ -164,24 +168,60 @@ pub struct GuildMembersChunk {
|
||||||
|
|
||||||
impl WebSocketEvent for GuildMembersChunk {}
|
impl WebSocketEvent for GuildMembersChunk {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)]
|
||||||
/// See <https://discord.com/developers/docs/topics/gateway-events#guild-role-create>
|
/// See <https://discord.com/developers/docs/topics/gateway-events#guild-role-create>
|
||||||
pub struct GuildRoleCreate {
|
pub struct GuildRoleCreate {
|
||||||
pub guild_id: Snowflake,
|
pub guild_id: Snowflake,
|
||||||
pub role: RoleObject,
|
pub role: RoleObject,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub json: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for GuildRoleCreate {}
|
impl WebSocketEvent for GuildRoleCreate {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
|
impl UpdateMessage<Guild> for GuildRoleCreate {
|
||||||
|
fn id(&self) -> Snowflake {
|
||||||
|
self.guild_id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, object_to_update: Arc<RwLock<Guild>>) {
|
||||||
|
let mut object_to_update = object_to_update.write().unwrap();
|
||||||
|
if object_to_update.roles.is_some() {
|
||||||
|
object_to_update
|
||||||
|
.roles
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.push(Arc::new(RwLock::new(self.role.clone())));
|
||||||
|
} else {
|
||||||
|
object_to_update.roles = Some(Vec::from([Arc::new(RwLock::new(self.role.clone()))]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)]
|
||||||
/// See <https://discord.com/developers/docs/topics/gateway-events#guild-role-update>
|
/// See <https://discord.com/developers/docs/topics/gateway-events#guild-role-update>
|
||||||
pub struct GuildRoleUpdate {
|
pub struct GuildRoleUpdate {
|
||||||
pub guild_id: Snowflake,
|
pub guild_id: Snowflake,
|
||||||
pub role: RoleObject,
|
pub role: RoleObject,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub json: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for GuildRoleUpdate {}
|
impl WebSocketEvent for GuildRoleUpdate {}
|
||||||
|
|
||||||
|
impl UpdateMessage<RoleObject> for GuildRoleUpdate {
|
||||||
|
fn id(&self) -> Snowflake {
|
||||||
|
self.role.id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, object_to_update: Arc<RwLock<RoleObject>>) {
|
||||||
|
println!("Processing Role Update. Name: {}", self.role.name);
|
||||||
|
let mut write = object_to_update.write().unwrap();
|
||||||
|
*write = self.role.clone();
|
||||||
|
println!("Updated role: Name: {}", write.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
|
||||||
/// See <https://discord.com/developers/docs/topics/gateway-events#guild-role-delete>
|
/// See <https://discord.com/developers/docs/topics/gateway-events#guild-role-delete>
|
||||||
pub struct GuildRoleDelete {
|
pub struct GuildRoleDelete {
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub use application::*;
|
pub use application::*;
|
||||||
|
@ -19,6 +24,7 @@ pub use ready::*;
|
||||||
pub use relationship::*;
|
pub use relationship::*;
|
||||||
pub use request_members::*;
|
pub use request_members::*;
|
||||||
pub use resume::*;
|
pub use resume::*;
|
||||||
|
use serde_json::{from_str, from_value, to_value, Value};
|
||||||
pub use session::*;
|
pub use session::*;
|
||||||
pub use stage_instance::*;
|
pub use stage_instance::*;
|
||||||
pub use thread::*;
|
pub use thread::*;
|
||||||
|
@ -109,10 +115,31 @@ impl<'a> WebSocketEvent for GatewayReceivePayload<'a> {}
|
||||||
/// This would imply, that the [`WebSocketEvent`] "[`ChannelUpdate`]" contains new/updated information
|
/// This would imply, that the [`WebSocketEvent`] "[`ChannelUpdate`]" contains new/updated information
|
||||||
/// about a [`Channel`]. The update method describes how this new information will be turned into
|
/// about a [`Channel`]. The update method describes how this new information will be turned into
|
||||||
/// a [`Channel`] object.
|
/// a [`Channel`] object.
|
||||||
pub(crate) trait UpdateMessage<T>: Clone
|
pub(crate) trait UpdateMessage<T>: Clone + JsonField
|
||||||
where
|
where
|
||||||
T: Updateable,
|
T: Updateable + Serialize + DeserializeOwned + Clone,
|
||||||
{
|
{
|
||||||
fn update(&self, object_to_update: &mut T);
|
fn update(&mut self, object_to_update: Arc<RwLock<T>>) {
|
||||||
|
update_object(self.get_json(), object_to_update)
|
||||||
|
}
|
||||||
fn id(&self) -> Snowflake;
|
fn id(&self) -> Snowflake;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) trait JsonField: Clone {
|
||||||
|
fn set_json(&mut self, json: String);
|
||||||
|
fn get_json(&self) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Only applicable for events where the Update struct is the same as the Entity struct
|
||||||
|
pub(crate) fn update_object(
|
||||||
|
value: String,
|
||||||
|
object: Arc<RwLock<(impl Updateable + Serialize + DeserializeOwned + Clone)>>,
|
||||||
|
) {
|
||||||
|
let data_from_event: HashMap<String, Value> = from_str(&value).unwrap();
|
||||||
|
let mut original_data: HashMap<String, Value> =
|
||||||
|
from_value(to_value(object.clone()).unwrap()).unwrap();
|
||||||
|
for (updated_entry_key, updated_entry_value) in data_from_event.into_iter() {
|
||||||
|
original_data.insert(updated_entry_key.clone(), updated_entry_value);
|
||||||
|
}
|
||||||
|
*object.write().unwrap() = from_value(to_value(original_data).unwrap()).unwrap();
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
/// Represents the schema which needs to be sent to create or modify a Role.
|
/// Represents the schema which needs to be sent to create or modify a Role.
|
||||||
/// See: [https://docs.spacebar.chat/routes/#cmp--schemas-rolemodifyschema](https://docs.spacebar.chat/routes/#cmp--schemas-rolemodifyschema)
|
/// See: [https://docs.spacebar.chat/routes/#cmp--schemas-rolemodifyschema](https://docs.spacebar.chat/routes/#cmp--schemas-rolemodifyschema)
|
||||||
|
|
|
@ -8,7 +8,7 @@ mod common;
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn get_channel() {
|
async fn get_channel() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let bundle_channel = bundle.channel.clone();
|
let bundle_channel = bundle.channel.read().unwrap().clone();
|
||||||
let bundle_user = &mut bundle.user;
|
let bundle_user = &mut bundle.user;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -21,7 +21,8 @@ async fn get_channel() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn delete_channel() {
|
async fn delete_channel() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let result = Channel::delete(bundle.channel.clone(), &mut bundle.user).await;
|
let channel_guard = bundle.channel.write().unwrap().clone();
|
||||||
|
let result = Channel::delete(channel_guard, &mut bundle.user).await;
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
common::teardown(bundle).await
|
common::teardown(bundle).await
|
||||||
}
|
}
|
||||||
|
@ -30,7 +31,7 @@ async fn delete_channel() {
|
||||||
async fn modify_channel() {
|
async fn modify_channel() {
|
||||||
const CHANNEL_NAME: &str = "beepboop";
|
const CHANNEL_NAME: &str = "beepboop";
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let channel = &mut bundle.channel;
|
let channel = &mut bundle.channel.read().unwrap().clone();
|
||||||
let modify_data: types::ChannelModifySchema = types::ChannelModifySchema {
|
let modify_data: types::ChannelModifySchema = types::ChannelModifySchema {
|
||||||
name: Some(CHANNEL_NAME.to_string()),
|
name: Some(CHANNEL_NAME.to_string()),
|
||||||
channel_type: None,
|
channel_type: None,
|
||||||
|
@ -50,32 +51,26 @@ async fn modify_channel() {
|
||||||
default_thread_rate_limit_per_user: None,
|
default_thread_rate_limit_per_user: None,
|
||||||
video_quality_mode: None,
|
video_quality_mode: None,
|
||||||
};
|
};
|
||||||
let modified_channel = Channel::modify(channel, modify_data, channel.id, &mut bundle.user)
|
let modified_channel = channel.modify(modify_data, &mut bundle.user).await.unwrap();
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(modified_channel.name, Some(CHANNEL_NAME.to_string()));
|
assert_eq!(modified_channel.name, Some(CHANNEL_NAME.to_string()));
|
||||||
|
|
||||||
let permission_override = PermissionFlags::from_vec(Vec::from([
|
let permission_override = PermissionFlags::from_vec(Vec::from([
|
||||||
PermissionFlags::MANAGE_CHANNELS,
|
PermissionFlags::MANAGE_CHANNELS,
|
||||||
PermissionFlags::MANAGE_MESSAGES,
|
PermissionFlags::MANAGE_MESSAGES,
|
||||||
]));
|
]));
|
||||||
let user_id: types::Snowflake = bundle.user.object.lock().unwrap().id;
|
let user_id: types::Snowflake = bundle.user.object.read().unwrap().id;
|
||||||
let permission_override = PermissionOverwrite {
|
let permission_override = PermissionOverwrite {
|
||||||
id: user_id,
|
id: user_id,
|
||||||
overwrite_type: "1".to_string(),
|
overwrite_type: "1".to_string(),
|
||||||
allow: permission_override,
|
allow: permission_override,
|
||||||
deny: "0".to_string(),
|
deny: "0".to_string(),
|
||||||
};
|
};
|
||||||
|
let channel_id: Snowflake = bundle.channel.read().unwrap().id;
|
||||||
|
Channel::edit_permissions(&mut bundle.user, channel_id, permission_override.clone())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
Channel::edit_permissions(
|
Channel::delete_permission(&mut bundle.user, channel_id, permission_override.id)
|
||||||
&mut bundle.user,
|
|
||||||
bundle.channel.id,
|
|
||||||
permission_override.clone(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Channel::delete_permission(&mut bundle.user, bundle.channel.id, permission_override.id)
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -85,7 +80,7 @@ async fn modify_channel() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn get_channel_messages() {
|
async fn get_channel_messages() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
|
let channel_id: Snowflake = bundle.channel.read().unwrap().id;
|
||||||
// First create some messages to read
|
// First create some messages to read
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
let _ = bundle
|
let _ = bundle
|
||||||
|
@ -95,7 +90,7 @@ async fn get_channel_messages() {
|
||||||
content: Some("A Message!".to_string()),
|
content: Some("A Message!".to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
bundle.channel.id,
|
channel_id,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -104,7 +99,7 @@ async fn get_channel_messages() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Channel::messages(
|
Channel::messages(
|
||||||
GetChannelMessagesSchema::before(Snowflake::generate()),
|
GetChannelMessagesSchema::before(Snowflake::generate()),
|
||||||
bundle.channel.id,
|
channel_id,
|
||||||
&mut bundle.user,
|
&mut bundle.user,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
@ -128,7 +123,7 @@ async fn get_channel_messages() {
|
||||||
|
|
||||||
assert!(Channel::messages(
|
assert!(Channel::messages(
|
||||||
GetChannelMessagesSchema::after(Snowflake::generate()),
|
GetChannelMessagesSchema::after(Snowflake::generate()),
|
||||||
bundle.channel.id,
|
channel_id,
|
||||||
&mut bundle.user,
|
&mut bundle.user,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
@ -144,7 +139,7 @@ async fn create_dm() {
|
||||||
let other_user = bundle.create_user("integrationtestuser2").await;
|
let other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let private_channel_create_schema = PrivateChannelCreateSchema {
|
let private_channel_create_schema = PrivateChannelCreateSchema {
|
||||||
recipients: Some(Vec::from([other_user.object.lock().unwrap().id])),
|
recipients: Some(Vec::from([other_user.object.read().unwrap().id])),
|
||||||
access_tokens: None,
|
access_tokens: None,
|
||||||
nicks: None,
|
nicks: None,
|
||||||
};
|
};
|
||||||
|
@ -160,11 +155,11 @@ async fn create_dm() {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(0)
|
.get(0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.lock()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.id
|
.id
|
||||||
.clone(),
|
.clone(),
|
||||||
other_user.object.lock().unwrap().id
|
other_user.object.read().unwrap().id
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
dm_channel
|
dm_channel
|
||||||
|
@ -173,11 +168,11 @@ async fn create_dm() {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(1)
|
.get(1)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.lock()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.id
|
.id
|
||||||
.clone(),
|
.clone(),
|
||||||
user.object.lock().unwrap().id.clone()
|
user.object.read().unwrap().id.clone()
|
||||||
);
|
);
|
||||||
common::teardown(bundle).await;
|
common::teardown(bundle).await;
|
||||||
}
|
}
|
||||||
|
@ -189,9 +184,9 @@ async fn remove_add_person_from_to_dm() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
let mut third_user = bundle.create_user("integrationtestuser3").await;
|
let mut third_user = bundle.create_user("integrationtestuser3").await;
|
||||||
let third_user_id = third_user.object.lock().unwrap().id;
|
let third_user_id = third_user.object.read().unwrap().id;
|
||||||
let other_user_id = other_user.object.lock().unwrap().id;
|
let other_user_id = other_user.object.read().unwrap().id;
|
||||||
let user_id = bundle.user.object.lock().unwrap().id;
|
let user_id = bundle.user.object.read().unwrap().id;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let private_channel_create_schema = PrivateChannelCreateSchema {
|
let private_channel_create_schema = PrivateChannelCreateSchema {
|
||||||
recipients: Some(Vec::from([other_user_id, third_user_id])),
|
recipients: Some(Vec::from([other_user_id, third_user_id])),
|
||||||
|
@ -234,7 +229,7 @@ async fn remove_add_person_from_to_dm() {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(0)
|
.get(0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.lock()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.id,
|
.id,
|
||||||
other_user_id
|
other_user_id
|
||||||
|
@ -246,7 +241,7 @@ async fn remove_add_person_from_to_dm() {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(1)
|
.get(1)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.lock()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.id,
|
.id,
|
||||||
user_id
|
user_id
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use chorus::gateway::Gateway;
|
use chorus::gateway::Gateway;
|
||||||
use chorus::{
|
use chorus::{
|
||||||
instance::{Instance, UserMeta},
|
instance::{Instance, UserMeta},
|
||||||
|
@ -14,9 +16,9 @@ pub(crate) struct TestBundle {
|
||||||
pub urls: UrlBundle,
|
pub urls: UrlBundle,
|
||||||
pub user: UserMeta,
|
pub user: UserMeta,
|
||||||
pub instance: Instance,
|
pub instance: Instance,
|
||||||
pub guild: Guild,
|
pub guild: Arc<RwLock<Guild>>,
|
||||||
pub role: RoleObject,
|
pub role: Arc<RwLock<RoleObject>>,
|
||||||
pub channel: Channel,
|
pub channel: Arc<RwLock<Channel>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -113,17 +115,16 @@ pub(crate) async fn setup() -> TestBundle {
|
||||||
urls,
|
urls,
|
||||||
user,
|
user,
|
||||||
instance,
|
instance,
|
||||||
guild,
|
guild: Arc::new(RwLock::new(guild)),
|
||||||
role,
|
role: Arc::new(RwLock::new(role)),
|
||||||
channel,
|
channel: Arc::new(RwLock::new(channel)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Teardown method to clean up after a test.
|
// Teardown method to clean up after a test.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) async fn teardown(mut bundle: TestBundle) {
|
pub(crate) async fn teardown(mut bundle: TestBundle) {
|
||||||
Guild::delete(&mut bundle.user, bundle.guild.id)
|
let id = bundle.guild.read().unwrap().id;
|
||||||
.await
|
Guild::delete(&mut bundle.user, id).await.unwrap();
|
||||||
.unwrap();
|
|
||||||
bundle.user.delete().await.unwrap()
|
bundle.user.delete().await.unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use chorus::gateway::*;
|
use chorus::gateway::*;
|
||||||
use chorus::types::{self, Channel};
|
use chorus::types::{self, ChannelModifySchema, RoleCreateModifySchema, RoleObject};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
/// Tests establishing a connection (hello and heartbeats) on the local gateway;
|
/// Tests establishing a connection (hello and heartbeats) on the local gateway;
|
||||||
|
@ -29,18 +31,88 @@ async fn test_gateway_authenticate() {
|
||||||
#[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 channel_updater = bundle.user.gateway.observe(bundle.channel.clone()).await;
|
let received_channel = bundle
|
||||||
let received_channel = channel_updater.borrow().clone();
|
.user
|
||||||
assert_eq!(received_channel, bundle.channel);
|
.gateway
|
||||||
let channel = &mut bundle.channel;
|
.observe_and_into_inner(bundle.channel.clone())
|
||||||
let modify_data = types::ChannelModifySchema {
|
.await;
|
||||||
name: Some("beepboop".to_string()),
|
|
||||||
|
assert_eq!(received_channel, bundle.channel.read().unwrap().clone());
|
||||||
|
|
||||||
|
let modify_schema = ChannelModifySchema {
|
||||||
|
name: Some("selfupdating".to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
Channel::modify(channel, modify_data, channel.id, &mut bundle.user)
|
received_channel
|
||||||
|
.modify(modify_schema, &mut bundle.user)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let received_channel = channel_updater.borrow();
|
assert_eq!(
|
||||||
assert_eq!(received_channel.name.as_ref().unwrap(), "beepboop");
|
bundle
|
||||||
|
.user
|
||||||
|
.gateway
|
||||||
|
.observe_and_into_inner(bundle.channel.clone())
|
||||||
|
.await
|
||||||
|
.name
|
||||||
|
.unwrap(),
|
||||||
|
"selfupdating".to_string()
|
||||||
|
);
|
||||||
|
|
||||||
common::teardown(bundle).await
|
common::teardown(bundle).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_recursive_self_updating_structs() {
|
||||||
|
// Setup
|
||||||
|
let mut bundle = common::setup().await;
|
||||||
|
let guild = bundle.guild.clone();
|
||||||
|
// Observe Guild, make sure it has no channels
|
||||||
|
let guild = bundle.user.gateway.observe(guild.clone()).await;
|
||||||
|
let inner_guild = guild.read().unwrap().clone();
|
||||||
|
assert!(inner_guild.roles.is_none());
|
||||||
|
// Create Role
|
||||||
|
let permissions = types::PermissionFlags::CONNECT | types::PermissionFlags::MANAGE_EVENTS;
|
||||||
|
let permissions = Some(permissions.to_string());
|
||||||
|
let mut role_create_schema: types::RoleCreateModifySchema = RoleCreateModifySchema {
|
||||||
|
name: Some("cool person".to_string()),
|
||||||
|
permissions,
|
||||||
|
hoist: Some(true),
|
||||||
|
icon: None,
|
||||||
|
unicode_emoji: Some("".to_string()),
|
||||||
|
mentionable: Some(true),
|
||||||
|
position: None,
|
||||||
|
color: None,
|
||||||
|
};
|
||||||
|
let guild_id = inner_guild.id;
|
||||||
|
let role = RoleObject::create(&mut bundle.user, guild_id, role_create_schema.clone())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
// Watch role;
|
||||||
|
bundle
|
||||||
|
.user
|
||||||
|
.gateway
|
||||||
|
.observe(Arc::new(RwLock::new(role.clone())))
|
||||||
|
.await;
|
||||||
|
// Update Guild and check for Guild
|
||||||
|
let inner_guild = guild.read().unwrap().clone();
|
||||||
|
assert!(inner_guild.roles.is_some());
|
||||||
|
// Update the Role
|
||||||
|
role_create_schema.name = Some("yippieee".to_string());
|
||||||
|
RoleObject::modify(&mut bundle.user, guild_id, role.id, role_create_schema)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let role_inner = bundle
|
||||||
|
.user
|
||||||
|
.gateway
|
||||||
|
.observe_and_into_inner(Arc::new(RwLock::new(role.clone())))
|
||||||
|
.await;
|
||||||
|
assert_eq!(role_inner.name, "yippieee");
|
||||||
|
// Check if the change propagated
|
||||||
|
let guild = bundle.user.gateway.observe(bundle.guild.clone()).await;
|
||||||
|
let inner_guild = guild.read().unwrap().clone();
|
||||||
|
let guild_roles = inner_guild.roles;
|
||||||
|
let guild_role = guild_roles.unwrap();
|
||||||
|
let guild_role_inner = guild_role.get(0).unwrap().read().unwrap().clone();
|
||||||
|
assert_eq!(guild_role_inner.name, "yippieee".to_string());
|
||||||
|
common::teardown(bundle).await;
|
||||||
|
}
|
||||||
|
|
|
@ -27,9 +27,7 @@ async fn guild_creation_deletion() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn get_channels() {
|
async fn get_channels() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
println!(
|
let guild = bundle.guild.read().unwrap().clone();
|
||||||
"{:?}",
|
println!("{:?}", guild.channels(&mut bundle.user).await.unwrap());
|
||||||
bundle.guild.channels(&mut bundle.user).await.unwrap()
|
|
||||||
);
|
|
||||||
common::teardown(bundle).await;
|
common::teardown(bundle).await;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,12 @@ 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.read().unwrap().clone();
|
||||||
let mut other_user = bundle.create_user("testuser1312").await;
|
let mut other_user = bundle.create_user("testuser1312").await;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let create_channel_invite_schema = CreateChannelInviteSchema::default();
|
let create_channel_invite_schema = CreateChannelInviteSchema::default();
|
||||||
assert!(chorus::types::Guild::get(bundle.guild.id, &mut other_user)
|
let guild = bundle.guild.read().unwrap().clone();
|
||||||
|
assert!(chorus::types::Guild::get(guild.id, &mut other_user)
|
||||||
.await
|
.await
|
||||||
.is_err());
|
.is_err());
|
||||||
let invite = user
|
let invite = user
|
||||||
|
@ -16,7 +17,7 @@ async fn create_accept_invite() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
other_user.accept_invite(&invite.code, None).await.unwrap();
|
other_user.accept_invite(&invite.code, None).await.unwrap();
|
||||||
assert!(chorus::types::Guild::get(bundle.guild.id, &mut other_user)
|
assert!(chorus::types::Guild::get(guild.id, &mut other_user)
|
||||||
.await
|
.await
|
||||||
.is_ok());
|
.is_ok());
|
||||||
common::teardown(bundle).await;
|
common::teardown(bundle).await;
|
||||||
|
|
|
@ -5,9 +5,9 @@ mod common;
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn add_remove_role() -> ChorusResult<()> {
|
async fn add_remove_role() -> ChorusResult<()> {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let guild = bundle.guild.id;
|
let guild = bundle.guild.read().unwrap().id;
|
||||||
let role = bundle.role.id;
|
let role = bundle.role.read().unwrap().id;
|
||||||
let member_id = bundle.user.object.lock().unwrap().id;
|
let member_id = bundle.user.object.read().unwrap().id;
|
||||||
GuildMember::add_role(&mut bundle.user, guild, member_id, role).await?;
|
GuildMember::add_role(&mut bundle.user, guild, member_id, role).await?;
|
||||||
let member = GuildMember::get(&mut bundle.user, guild, member_id)
|
let member = GuildMember::get(&mut bundle.user, guild, member_id)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -12,11 +12,8 @@ async fn send_message() {
|
||||||
content: Some("A Message!".to_string()),
|
content: Some("A Message!".to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let _ = bundle
|
let channel = bundle.channel.read().unwrap().clone();
|
||||||
.user
|
let _ = bundle.user.send_message(message, channel.id).await.unwrap();
|
||||||
.send_message(message, bundle.channel.id)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
common::teardown(bundle).await
|
common::teardown(bundle).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,13 +47,9 @@ async fn send_message_attachment() {
|
||||||
attachments: Some(vec![attachment.clone()]),
|
attachments: Some(vec![attachment.clone()]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
let channel = bundle.channel.read().unwrap().clone();
|
||||||
let vec_attach = vec![attachment.clone()];
|
let vec_attach = vec![attachment.clone()];
|
||||||
let _arg = Some(&vec_attach);
|
let _arg = Some(&vec_attach);
|
||||||
bundle
|
bundle.user.send_message(message, channel.id).await.unwrap();
|
||||||
.user
|
|
||||||
.send_message(message, bundle.channel.id)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
common::teardown(bundle).await
|
common::teardown(bundle).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ async fn test_get_mutual_relationships() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let username = user.object.lock().unwrap().username.clone();
|
let username = user.object.read().unwrap().username.clone();
|
||||||
let discriminator = user.object.lock().unwrap().discriminator.clone();
|
let discriminator = user.object.read().unwrap().discriminator.clone();
|
||||||
let other_user_id: types::Snowflake = other_user.object.lock().unwrap().id;
|
let other_user_id: types::Snowflake = other_user.object.read().unwrap().id;
|
||||||
let friend_request_schema = types::FriendRequestSendSchema {
|
let friend_request_schema = types::FriendRequestSendSchema {
|
||||||
username,
|
username,
|
||||||
discriminator: Some(discriminator),
|
discriminator: Some(discriminator),
|
||||||
|
@ -28,8 +28,8 @@ async fn test_get_relationships() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let username = user.object.lock().unwrap().username.clone();
|
let username = user.object.read().unwrap().username.clone();
|
||||||
let discriminator = user.object.lock().unwrap().discriminator.clone();
|
let discriminator = user.object.read().unwrap().discriminator.clone();
|
||||||
let friend_request_schema = types::FriendRequestSendSchema {
|
let friend_request_schema = types::FriendRequestSendSchema {
|
||||||
username,
|
username,
|
||||||
discriminator: Some(discriminator),
|
discriminator: Some(discriminator),
|
||||||
|
@ -41,7 +41,7 @@ async fn test_get_relationships() {
|
||||||
let relationships = user.get_relationships().await.unwrap();
|
let relationships = user.get_relationships().await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
relationships.get(0).unwrap().id,
|
relationships.get(0).unwrap().id,
|
||||||
other_user.object.lock().unwrap().id
|
other_user.object.read().unwrap().id
|
||||||
);
|
);
|
||||||
common::teardown(bundle).await
|
common::teardown(bundle).await
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,8 @@ async fn test_modify_relationship_friends() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let user_id: types::Snowflake = user.object.lock().unwrap().id;
|
let user_id: types::Snowflake = user.object.read().unwrap().id;
|
||||||
let other_user_id: types::Snowflake = other_user.object.lock().unwrap().id;
|
let other_user_id: types::Snowflake = other_user.object.read().unwrap().id;
|
||||||
|
|
||||||
other_user
|
other_user
|
||||||
.modify_user_relationship(user_id, types::RelationshipType::Friends)
|
.modify_user_relationship(user_id, types::RelationshipType::Friends)
|
||||||
|
@ -61,7 +61,7 @@ async fn test_modify_relationship_friends() {
|
||||||
let relationships = user.get_relationships().await.unwrap();
|
let relationships = user.get_relationships().await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
relationships.get(0).unwrap().id,
|
relationships.get(0).unwrap().id,
|
||||||
other_user.object.lock().unwrap().id
|
other_user.object.read().unwrap().id
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
relationships.get(0).unwrap().relationship_type,
|
relationships.get(0).unwrap().relationship_type,
|
||||||
|
@ -70,7 +70,7 @@ async fn test_modify_relationship_friends() {
|
||||||
let relationships = other_user.get_relationships().await.unwrap();
|
let relationships = other_user.get_relationships().await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
relationships.get(0).unwrap().id,
|
relationships.get(0).unwrap().id,
|
||||||
user.object.lock().unwrap().id
|
user.object.read().unwrap().id
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
relationships.get(0).unwrap().relationship_type,
|
relationships.get(0).unwrap().relationship_type,
|
||||||
|
@ -102,7 +102,7 @@ async fn test_modify_relationship_block() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let user_id: types::Snowflake = user.object.lock().unwrap().id;
|
let user_id: types::Snowflake = user.object.read().unwrap().id;
|
||||||
|
|
||||||
other_user
|
other_user
|
||||||
.modify_user_relationship(user_id, types::RelationshipType::Blocked)
|
.modify_user_relationship(user_id, types::RelationshipType::Blocked)
|
||||||
|
@ -113,7 +113,7 @@ async fn test_modify_relationship_block() {
|
||||||
let relationships = other_user.get_relationships().await.unwrap();
|
let relationships = other_user.get_relationships().await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
relationships.get(0).unwrap().id,
|
relationships.get(0).unwrap().id,
|
||||||
user.object.lock().unwrap().id
|
user.object.read().unwrap().id
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
relationships.get(0).unwrap().relationship_type,
|
relationships.get(0).unwrap().relationship_type,
|
||||||
|
|
|
@ -17,12 +17,12 @@ async fn create_and_get_roles() {
|
||||||
position: None,
|
position: None,
|
||||||
color: None,
|
color: None,
|
||||||
};
|
};
|
||||||
let guild = bundle.guild.id;
|
let guild_id = bundle.guild.read().unwrap().id;
|
||||||
let role = types::RoleObject::create(&mut bundle.user, guild, role_create_schema)
|
let role = types::RoleObject::create(&mut bundle.user, guild_id, role_create_schema)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let expected = types::RoleObject::get_all(&mut bundle.user, guild)
|
let expected = types::RoleObject::get_all(&mut bundle.user, guild_id)
|
||||||
.await
|
.await
|
||||||
.unwrap()[2]
|
.unwrap()[2]
|
||||||
.clone();
|
.clone();
|
||||||
|
@ -34,9 +34,9 @@ async fn create_and_get_roles() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn get_singular_role() {
|
async fn get_singular_role() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let guild_id = bundle.guild.id;
|
let guild_id = bundle.guild.read().unwrap().id;
|
||||||
let role_id = bundle.role.id;
|
let role_id = bundle.role.read().unwrap().id;
|
||||||
let role = bundle.role.clone();
|
let role = bundle.role.read().unwrap().clone();
|
||||||
let same_role = chorus::types::RoleObject::get(&mut bundle.user, guild_id, role_id)
|
let same_role = chorus::types::RoleObject::get(&mut bundle.user, guild_id, role_id)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
Loading…
Reference in New Issue