diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml
index 398c52f..b192a3c 100644
--- a/.github/workflows/build_and_test.yml
+++ b/.github/workflows/build_and_test.yml
@@ -2,7 +2,7 @@ name: Build and Test
on:
push:
- branches: [ "main" ]
+ branches: [ "main", "dev" ]
pull_request:
branches: [ "main" ]
diff --git a/.github/workflows/rust-clippy.yml b/.github/workflows/rust-clippy.yml
index dbbba76..0c3840f 100644
--- a/.github/workflows/rust-clippy.yml
+++ b/.github/workflows/rust-clippy.yml
@@ -11,7 +11,7 @@ name: rust-clippy analyze
on:
push:
- branches: [ "main", "preserve/*" ]
+ branches: [ "main", "preserve/*", "dev" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
diff --git a/Cargo.lock b/Cargo.lock
index 8c8c26e..df89f42 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -31,9 +31,9 @@ dependencies = [
[[package]]
name = "aho-corasick"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a"
+checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783"
dependencies = [
"memchr",
]
@@ -67,7 +67,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -177,7 +177,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chorus"
-version = "0.4.0"
+version = "0.9.0"
dependencies = [
"async-trait",
"base64 0.21.3",
@@ -211,18 +211,20 @@ dependencies = [
[[package]]
name = "chorus-macros"
-version = "0.1.0"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a81545a60b926f815517dadbbd40cd502294ae2baea25fa8194d854d607512b0"
dependencies = [
"async-trait",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
name = "chrono"
-version = "0.4.26"
+version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
+checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f"
dependencies = [
"android-tzdata",
"iana-time-zone",
@@ -231,7 +233,7 @@ dependencies = [
"serde",
"time 0.1.45",
"wasm-bindgen",
- "winapi",
+ "windows-targets",
]
[[package]]
@@ -345,7 +347,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -356,7 +358,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [
"darling_core",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -439,9 +441,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
+checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd"
dependencies = [
"errno-dragonfly",
"libc",
@@ -581,7 +583,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -686,21 +688,20 @@ dependencies = [
[[package]]
name = "hashlink"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f"
+checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
dependencies = [
"hashbrown 0.14.0",
]
[[package]]
name = "headers"
-version = "0.3.8"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584"
+checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270"
dependencies = [
- "base64 0.13.1",
- "bitflags 1.3.2",
+ "base64 0.21.3",
"bytes",
"headers-core",
"http",
@@ -1033,9 +1034,9 @@ dependencies = [
[[package]]
name = "memchr"
-version = "2.5.0"
+version = "2.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
[[package]]
name = "mime"
@@ -1184,9 +1185,9 @@ dependencies = [
[[package]]
name = "object"
-version = "0.32.0"
+version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
+checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
@@ -1199,11 +1200,11 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "openssl"
-version = "0.10.56"
+version = "0.10.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e"
+checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.4.0",
"cfg-if",
"foreign-types",
"libc",
@@ -1220,7 +1221,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -1231,9 +1232,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
-version = "0.9.91"
+version = "0.9.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac"
+checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b"
dependencies = [
"cc",
"libc",
@@ -1311,7 +1312,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -1355,9 +1356,9 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "poem"
-version = "1.3.57"
+version = "1.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0d92c532a37a9e98c0e9a0411e6852b8acccf9ec07d5e6e450b01cbf947d90b"
+checksum = "ebc7ae19f3e791ae8108b08801abb3708d64d3a16490c720e0b81040cae87b5d"
dependencies = [
"async-trait",
"bytes",
@@ -1384,14 +1385,14 @@ dependencies = [
[[package]]
name = "poem-derive"
-version = "1.3.57"
+version = "1.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5dd58846a1f582215370384c3090c62c9ef188e9d798ffc67ea90d0a1a8a3b8"
+checksum = "2550a0bce7273b278894ef3ccc5a6869e7031b6870042f3cc6826ed9faa980a6"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -1469,9 +1470,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.9.4"
+version = "1.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29"
+checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
dependencies = [
"aho-corasick",
"memchr",
@@ -1481,9 +1482,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.3.7"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629"
+checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
dependencies = [
"aho-corasick",
"memchr",
@@ -1588,9 +1589,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustix"
-version = "0.38.9"
+version = "0.38.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bfe0f2582b4931a45d1fa608f8a8722e8b3c7ac54dd6d5f3b3212791fedef49"
+checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453"
dependencies = [
"bitflags 2.4.0",
"errno",
@@ -1683,7 +1684,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -1705,7 +1706,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -1734,7 +1735,7 @@ dependencies = [
"serde",
"serde_json",
"serde_with_macros",
- "time 0.3.27",
+ "time 0.3.28",
]
[[package]]
@@ -1746,7 +1747,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -1799,7 +1800,7 @@ dependencies = [
"num-bigint",
"num-traits",
"thiserror",
- "time 0.3.27",
+ "time 0.3.28",
]
[[package]]
@@ -2110,9 +2111,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.29"
+version = "2.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
+checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
dependencies = [
"proc-macro2",
"quote",
@@ -2134,22 +2135,22 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.47"
+version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
+checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.47"
+version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
+checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -2165,9 +2166,9 @@ dependencies = [
[[package]]
name = "time"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bb39ee79a6d8de55f48f2293a830e040392f1c5f16e336bdd1788cd0aadce07"
+checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48"
dependencies = [
"deranged",
"itoa",
@@ -2184,9 +2185,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
[[package]]
name = "time-macros"
-version = "0.2.13"
+version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "733d258752e9303d392b94b75230d07b0b9c489350c69b851fc6c065fde3e8f9"
+checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572"
dependencies = [
"time-core",
]
@@ -2233,7 +2234,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -2338,7 +2339,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
]
[[package]]
@@ -2447,9 +2448,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "url"
-version = "2.4.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
+checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
dependencies = [
"form_urlencoded",
"idna",
@@ -2516,7 +2517,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
"wasm-bindgen-shared",
]
@@ -2550,7 +2551,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.29",
+ "syn 2.0.31",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
diff --git a/Cargo.toml b/Cargo.toml
index 3d2732b..42a5130 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "chorus"
description = "A library for interacting with multiple Spacebar-compatible Instances at once."
-version = "0.4.0"
+version = "0.9.0"
license = "AGPL-3.0"
edition = "2021"
repository = "https://github.com/polyphony-chat/chorus"
@@ -50,7 +50,7 @@ thiserror = "1.0.47"
jsonwebtoken = "8.3.0"
log = "0.4.20"
async-trait = "0.1.73"
-chorus-macros = { path = "chorus-macros", version = "0.1.0" }
+chorus-macros = "0.2.0"
[dev-dependencies]
tokio = { version = "1.32.0", features = ["full"] }
diff --git a/chorus-macros/Cargo.toml b/chorus-macros/Cargo.toml
index 098159f..272d99f 100644
--- a/chorus-macros/Cargo.toml
+++ b/chorus-macros/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "chorus-macros"
-version = "0.1.0"
+version = "0.2.0"
edition = "2021"
license = "AGPL-3.0"
description = "Macros for the chorus crate."
diff --git a/chorus-macros/src/lib.rs b/chorus-macros/src/lib.rs
index f825568..fd68df0 100644
--- a/chorus-macros/src/lib.rs
+++ b/chorus-macros/src/lib.rs
@@ -37,6 +37,25 @@ pub fn jsonfield_macro_derive(input: TokenStream) -> TokenStream {
.into()
}
+#[proc_macro_derive(SourceUrlField)]
+pub fn source_url_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 SourceUrlField for #name {
+ fn get_source_url(&self) -> String {
+ self.source_url.clone()
+ }
+ fn set_source_url(&mut self, url: String) {
+ self.source_url = url;
+ }
+ }
+ }
+ .into()
+}
+
#[proc_macro_attribute]
pub fn observe_option(_args: TokenStream, input: TokenStream) -> TokenStream {
input
diff --git a/src/api/auth/login.rs b/src/api/auth/login.rs
index 46951be..272ee04 100644
--- a/src/api/auth/login.rs
+++ b/src/api/auth/login.rs
@@ -3,24 +3,23 @@ use std::sync::{Arc, RwLock};
use reqwest::Client;
use serde_json::to_string;
-use crate::api::LimitType;
use crate::errors::ChorusResult;
use crate::gateway::Gateway;
use crate::instance::{ChorusUser, Instance};
use crate::ratelimiter::ChorusRequest;
-use crate::types::{GatewayIdentifyPayload, LoginResult, LoginSchema};
+use crate::types::{GatewayIdentifyPayload, LimitType, LoginResult, LoginSchema};
impl Instance {
/// Logs into an existing account on the spacebar server.
///
/// # Reference
/// See
- pub async fn login_account(&mut self, login_schema: &LoginSchema) -> ChorusResult {
+ pub async fn login_account(mut self, login_schema: LoginSchema) -> ChorusResult {
let endpoint_url = self.urls.api.clone() + "/auth/login";
let chorus_request = ChorusRequest {
request: Client::new()
.post(endpoint_url)
- .body(to_string(login_schema).unwrap())
+ .body(to_string(&login_schema).unwrap())
.header("Content-Type", "application/json"),
limit_type: LimitType::AuthLogin,
};
@@ -46,7 +45,7 @@ impl Instance {
self.clone_limits_if_some(),
login_result.settings,
Arc::new(RwLock::new(object)),
- Arc::new(gateway),
+ gateway,
);
Ok(user)
}
diff --git a/src/api/auth/mod.rs b/src/api/auth/mod.rs
index 663bf5e..3ad4a60 100644
--- a/src/api/auth/mod.rs
+++ b/src/api/auth/mod.rs
@@ -1,5 +1,41 @@
+use std::sync::{Arc, RwLock};
+
pub use login::*;
pub use register::*;
+use crate::{
+ errors::ChorusResult,
+ gateway::Gateway,
+ instance::{ChorusUser, Instance},
+ types::{GatewayIdentifyPayload, User},
+};
+
pub mod login;
pub mod register;
+
+impl Instance {
+ /// Logs into an existing account on the spacebar server, using only a token.
+ pub async fn login_with_token(&mut self, token: String) -> ChorusResult {
+ let object_result = self.get_user(token.clone(), None).await;
+ if let Err(e) = object_result {
+ return Result::Err(e);
+ }
+
+ let user_settings = User::get_settings(&token, &self.urls.api, &mut self.clone())
+ .await
+ .unwrap();
+ let mut identify = GatewayIdentifyPayload::common();
+ let gateway = Gateway::new(self.urls.wss.clone()).await.unwrap();
+ identify.token = token.clone();
+ gateway.send_identify(identify).await;
+ let user = ChorusUser::new(
+ Arc::new(RwLock::new(self.clone())),
+ token.clone(),
+ self.clone_limits_if_some(),
+ Arc::new(RwLock::new(user_settings)),
+ Arc::new(RwLock::new(object_result.unwrap())),
+ gateway,
+ );
+ Ok(user)
+ }
+}
diff --git a/src/api/auth/register.rs b/src/api/auth/register.rs
index 44c29d8..d10915e 100644
--- a/src/api/auth/register.rs
+++ b/src/api/auth/register.rs
@@ -6,10 +6,10 @@ use serde_json::to_string;
use crate::gateway::Gateway;
use crate::types::GatewayIdentifyPayload;
use crate::{
- api::policies::instance::LimitType,
errors::ChorusResult,
instance::{ChorusUser, Instance, Token},
ratelimiter::ChorusRequest,
+ types::LimitType,
types::RegisterSchema,
};
@@ -19,14 +19,14 @@ impl Instance {
/// # Reference
/// See
pub async fn register_account(
- &mut self,
- register_schema: &RegisterSchema,
+ mut self,
+ register_schema: RegisterSchema,
) -> ChorusResult {
let endpoint_url = self.urls.api.clone() + "/auth/register";
let chorus_request = ChorusRequest {
request: Client::new()
.post(endpoint_url)
- .body(to_string(register_schema).unwrap())
+ .body(to_string(®ister_schema).unwrap())
.header("Content-Type", "application/json"),
limit_type: LimitType::AuthRegister,
};
@@ -43,7 +43,7 @@ impl Instance {
self.limits_information.as_mut().unwrap().ratelimits = shell.limits.unwrap();
}
let user_object = self.get_user(token.clone(), None).await.unwrap();
- let settings = ChorusUser::get_settings(&token, &self.urls.api.clone(), self).await?;
+ let settings = ChorusUser::get_settings(&token, &self.urls.api.clone(), &mut self).await?;
let mut identify = GatewayIdentifyPayload::common();
let gateway = Gateway::new(self.urls.wss.clone()).await.unwrap();
identify.token = token.clone();
@@ -54,7 +54,7 @@ impl Instance {
self.clone_limits_if_some(),
Arc::new(RwLock::new(settings)),
Arc::new(RwLock::new(user_object)),
- Arc::new(gateway),
+ gateway,
);
Ok(user)
}
diff --git a/src/api/channels/channels.rs b/src/api/channels/channels.rs
index 7250b0e..9560d74 100644
--- a/src/api/channels/channels.rs
+++ b/src/api/channels/channels.rs
@@ -3,11 +3,12 @@ use serde_json::to_string;
use crate::types::{AddChannelRecipientSchema, ModifyChannelPositionsSchema};
use crate::{
- api::LimitType,
errors::{ChorusError, ChorusResult},
instance::ChorusUser,
ratelimiter::ChorusRequest,
- types::{Channel, ChannelModifySchema, GetChannelMessagesSchema, Message, Snowflake},
+ types::{
+ Channel, ChannelModifySchema, GetChannelMessagesSchema, LimitType, Message, Snowflake,
+ },
};
impl Channel {
diff --git a/src/api/channels/messages.rs b/src/api/channels/messages.rs
index 960e492..6dfdfbf 100644
--- a/src/api/channels/messages.rs
+++ b/src/api/channels/messages.rs
@@ -3,13 +3,12 @@ use http::HeaderMap;
use reqwest::{multipart, Client};
use serde_json::{from_value, to_string, Value};
-use crate::api::LimitType;
use crate::errors::{ChorusError, ChorusResult};
use crate::instance::ChorusUser;
use crate::ratelimiter::ChorusRequest;
use crate::types::{
- Channel, CreateGreetMessage, Message, MessageAck, MessageModifySchema, MessageSearchEndpoint,
- MessageSearchQuery, MessageSendSchema, Snowflake,
+ Channel, CreateGreetMessage, LimitType, Message, MessageAck, MessageModifySchema,
+ MessageSearchEndpoint, MessageSearchQuery, MessageSendSchema, Snowflake,
};
impl Message {
diff --git a/src/api/channels/permissions.rs b/src/api/channels/permissions.rs
index 7fa8edd..5360890 100644
--- a/src/api/channels/permissions.rs
+++ b/src/api/channels/permissions.rs
@@ -2,11 +2,10 @@ use reqwest::Client;
use serde_json::to_string;
use crate::{
- api::LimitType,
errors::{ChorusError, ChorusResult},
instance::ChorusUser,
ratelimiter::ChorusRequest,
- types::{self, PermissionOverwrite, Snowflake},
+ types::{self, LimitType, PermissionOverwrite, Snowflake},
};
impl types::Channel {
diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs
index 81c0366..94d3087 100644
--- a/src/api/channels/reactions.rs
+++ b/src/api/channels/reactions.rs
@@ -1,9 +1,8 @@
use crate::{
- api::LimitType,
errors::ChorusResult,
instance::ChorusUser,
ratelimiter::ChorusRequest,
- types::{self, PublicUser, Snowflake},
+ types::{self, LimitType, PublicUser, Snowflake},
};
/// Useful metadata for working with [`types::Reaction`], bundled together nicely.
diff --git a/src/api/guilds/guilds.rs b/src/api/guilds/guilds.rs
index 8d5f0d6..b433c84 100644
--- a/src/api/guilds/guilds.rs
+++ b/src/api/guilds/guilds.rs
@@ -2,14 +2,13 @@ use reqwest::Client;
use serde_json::from_str;
use serde_json::to_string;
-use crate::api::LimitType;
use crate::errors::ChorusError;
use crate::errors::ChorusResult;
use crate::instance::ChorusUser;
use crate::ratelimiter::ChorusRequest;
use crate::types::{
Channel, ChannelCreateSchema, Guild, GuildBanCreateSchema, GuildBansQuery, GuildCreateSchema,
- GuildMember, GuildMemberSearchSchema, GuildModifySchema, GuildPreview,
+ GuildMember, GuildMemberSearchSchema, GuildModifySchema, GuildPreview, LimitType,
ModifyGuildMemberProfileSchema, ModifyGuildMemberSchema, UserProfileMetadata,
};
use crate::types::{GuildBan, Snowflake};
diff --git a/src/api/guilds/member.rs b/src/api/guilds/member.rs
index 01294bd..885ddf9 100644
--- a/src/api/guilds/member.rs
+++ b/src/api/guilds/member.rs
@@ -1,11 +1,10 @@
use reqwest::Client;
use crate::{
- api::LimitType,
errors::ChorusResult,
instance::ChorusUser,
ratelimiter::ChorusRequest,
- types::{self, GuildMember, Snowflake},
+ types::{self, GuildMember, LimitType, Snowflake},
};
impl types::GuildMember {
diff --git a/src/api/guilds/roles.rs b/src/api/guilds/roles.rs
index 17d6f7b..f131367 100644
--- a/src/api/guilds/roles.rs
+++ b/src/api/guilds/roles.rs
@@ -2,11 +2,12 @@ use reqwest::Client;
use serde_json::to_string;
use crate::{
- api::LimitType,
errors::{ChorusError, ChorusResult},
instance::ChorusUser,
ratelimiter::ChorusRequest,
- types::{self, RoleCreateModifySchema, RoleObject, RolePositionUpdateSchema, Snowflake},
+ types::{
+ self, LimitType, RoleCreateModifySchema, RoleObject, RolePositionUpdateSchema, Snowflake,
+ },
};
impl types::RoleObject {
diff --git a/src/api/invites/mod.rs b/src/api/invites/mod.rs
index 658fb22..332570b 100644
--- a/src/api/invites/mod.rs
+++ b/src/api/invites/mod.rs
@@ -4,7 +4,7 @@ use serde_json::to_string;
use crate::errors::ChorusResult;
use crate::instance::ChorusUser;
use crate::ratelimiter::ChorusRequest;
-use crate::types::{CreateChannelInviteSchema, GuildInvite, Invite, Snowflake};
+use crate::types::{CreateChannelInviteSchema, GuildInvite, Invite, LimitType, Snowflake};
impl ChorusUser {
/// Accepts an invite to a guild, group DM, or DM.
@@ -26,7 +26,7 @@ impl ChorusUser {
invite_code
))
.header("Authorization", self.token()),
- limit_type: super::LimitType::Global,
+ limit_type: LimitType::Global,
};
if session_id.is_some() {
request.request = request
@@ -53,7 +53,7 @@ impl ChorusUser {
.body(to_string(&code).unwrap())
.header("Authorization", self.token())
.header("Content-Type", "application/json"),
- limit_type: super::LimitType::Global,
+ limit_type: LimitType::Global,
}
.deserialize_response::(self)
.await
@@ -81,7 +81,7 @@ impl ChorusUser {
.header("Authorization", self.token())
.header("Content-Type", "application/json")
.body(to_string(&create_channel_invite_schema).unwrap()),
- limit_type: super::LimitType::Channel(channel_id),
+ limit_type: LimitType::Channel(channel_id),
}
.deserialize_response::(self)
.await
diff --git a/src/api/mod.rs b/src/api/mod.rs
index 7329c50..ab3f9b9 100644
--- a/src/api/mod.rs
+++ b/src/api/mod.rs
@@ -3,7 +3,6 @@ pub use channels::messages::*;
pub use guilds::*;
pub use invites::*;
pub use policies::instance::instance::*;
-pub use policies::instance::ratelimits::*;
pub use users::*;
pub mod auth;
diff --git a/src/api/policies/instance/instance.rs b/src/api/policies/instance/instance.rs
index aa529ad..4de5fd8 100644
--- a/src/api/policies/instance/instance.rs
+++ b/src/api/policies/instance/instance.rs
@@ -19,7 +19,7 @@ impl Instance {
Err(e) => {
return Err(ChorusError::RequestFailed {
url: endpoint_url,
- error: e,
+ error: e.to_string(),
});
}
};
diff --git a/src/api/policies/instance/mod.rs b/src/api/policies/instance/mod.rs
index 0a1f245..b3a9148 100644
--- a/src/api/policies/instance/mod.rs
+++ b/src/api/policies/instance/mod.rs
@@ -1,5 +1,3 @@
pub use instance::*;
-pub use ratelimits::*;
pub mod instance;
-pub mod ratelimits;
diff --git a/src/api/policies/mod.rs b/src/api/policies/mod.rs
index d0c29f1..1d5ea99 100644
--- a/src/api/policies/mod.rs
+++ b/src/api/policies/mod.rs
@@ -1,3 +1 @@
-pub use instance::ratelimits::*;
-
pub mod instance;
diff --git a/src/api/users/channels.rs b/src/api/users/channels.rs
index 8d5f063..330b3e3 100644
--- a/src/api/users/channels.rs
+++ b/src/api/users/channels.rs
@@ -2,11 +2,10 @@ use reqwest::Client;
use serde_json::to_string;
use crate::{
- api::LimitType,
errors::ChorusResult,
instance::ChorusUser,
ratelimiter::ChorusRequest,
- types::{Channel, PrivateChannelCreateSchema},
+ types::{Channel, LimitType, PrivateChannelCreateSchema},
};
impl ChorusUser {
diff --git a/src/api/users/guilds.rs b/src/api/users/guilds.rs
index d2d5b9e..6ffcdfc 100644
--- a/src/api/users/guilds.rs
+++ b/src/api/users/guilds.rs
@@ -1,11 +1,10 @@
use reqwest::Client;
use serde_json::to_string;
-use crate::api::LimitType;
use crate::errors::ChorusResult;
use crate::instance::ChorusUser;
use crate::ratelimiter::ChorusRequest;
-use crate::types::{GetUserGuildSchema, Guild, Snowflake};
+use crate::types::{GetUserGuildSchema, Guild, LimitType, Snowflake};
impl ChorusUser {
/// Leaves a given guild.
@@ -26,7 +25,7 @@ impl ChorusUser {
.header("Authorization", self.token())
.header("Content-Type", "application/json")
.body(to_string(&lurking).unwrap()),
- limit_type: crate::api::LimitType::Guild(*guild_id),
+ limit_type: LimitType::Guild(*guild_id),
}
.handle_request_as_result(self)
.await
diff --git a/src/api/users/relationships.rs b/src/api/users/relationships.rs
index 8988871..4f9602c 100644
--- a/src/api/users/relationships.rs
+++ b/src/api/users/relationships.rs
@@ -2,12 +2,12 @@ use reqwest::Client;
use serde_json::to_string;
use crate::{
- api::LimitType,
errors::ChorusResult,
instance::ChorusUser,
ratelimiter::ChorusRequest,
types::{
- self, CreateUserRelationshipSchema, FriendRequestSendSchema, RelationshipType, Snowflake,
+ self, CreateUserRelationshipSchema, FriendRequestSendSchema, LimitType, RelationshipType,
+ Snowflake,
},
};
diff --git a/src/api/users/users.rs b/src/api/users/users.rs
index 25ac6cd..0f31d6f 100644
--- a/src/api/users/users.rs
+++ b/src/api/users/users.rs
@@ -4,11 +4,10 @@ use reqwest::Client;
use serde_json::to_string;
use crate::{
- api::LimitType,
errors::{ChorusError, ChorusResult},
instance::{ChorusUser, Instance},
ratelimiter::ChorusRequest,
- types::{User, UserModifySchema, UserSettings},
+ types::{LimitType, User, UserModifySchema, UserSettings},
};
impl ChorusUser {
diff --git a/src/errors.rs b/src/errors.rs
index 642a3ba..4099a6b 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -1,11 +1,10 @@
//! Contains all the errors that can be returned by the library.
use custom_error::custom_error;
-use reqwest::Error;
use crate::types::WebSocketEvent;
custom_error! {
- #[derive(PartialEq, Eq)]
+ #[derive(PartialEq, Eq, Clone, Hash)]
pub RegistrationError
Consent = "Consent must be 'true' to register.",
}
@@ -13,11 +12,12 @@ custom_error! {
pub type ChorusResult = std::result::Result;
custom_error! {
+ #[derive(Clone, Hash, PartialEq, Eq)]
pub ChorusError
/// Server did not respond.
NoResponse = "Did not receive a response from the Server.",
/// Reqwest returned an Error instead of a Response object.
- RequestFailed{url:String, error: Error} = "An error occured while trying to GET from {url}: {error}",
+ RequestFailed{url:String, error: String} = "An error occured while trying to GET from {url}: {error}",
/// Response received, however, it was not of the successful responses type. Used when no other, special case applies.
ReceivedErrorCode{error_code: u16, error: String} = "Received the following error code while requesting from the route: {error_code}",
/// Used when there is likely something wrong with the instance, the request was directed to.
diff --git a/src/gateway.rs b/src/gateway.rs
index 6913e6a..8689406 100644
--- a/src/gateway.rs
+++ b/src/gateway.rs
@@ -5,7 +5,7 @@ use crate::gateway::events::Events;
use crate::types::{
self, AutoModerationRule, AutoModerationRuleUpdate, Channel, ChannelCreate, ChannelDelete,
ChannelUpdate, Composite, Guild, GuildRoleCreate, GuildRoleUpdate, JsonField, RoleObject,
- Snowflake, ThreadUpdate, UpdateMessage, WebSocketEvent,
+ Snowflake, SourceUrlField, ThreadUpdate, UpdateMessage, WebSocketEvent,
};
use async_trait::async_trait;
use std::any::Any;
@@ -158,7 +158,7 @@ pub type ObservableObject = dyn Send + Sync + Any;
/// [`GatewayEvents`](GatewayEvent), which you can subscribe to. Gateway events include all currently
/// implemented types with the trait [`WebSocketEvent`]
/// Using this handle you can also send Gateway Events directly.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct GatewayHandle {
pub url: String,
pub events: Arc>,
@@ -170,7 +170,6 @@ pub struct GatewayHandle {
>,
>,
>,
- pub handle: JoinHandle<()>,
/// Tells gateway tasks to close
kill_send: tokio::sync::broadcast::Sender<()>,
pub(crate) store: Arc>>>>,
@@ -293,7 +292,7 @@ impl GatewayHandle {
/// Sends an update voice state to the server
pub async fn send_update_voice_state(&self, to_send: types::UpdateVoiceState) {
- let to_send_value = serde_json::to_value(&to_send).unwrap();
+ let to_send_value = serde_json::to_value(to_send).unwrap();
trace!("GW: Sending Update Voice State..");
@@ -344,6 +343,7 @@ pub struct Gateway {
websocket_receive: SplitStream>>,
kill_send: tokio::sync::broadcast::Sender<()>,
store: Arc>>>>,
+ url: String,
}
impl Gateway {
@@ -407,10 +407,11 @@ impl Gateway {
websocket_receive,
kill_send: kill_send.clone(),
store: store.clone(),
+ url: websocket_url.clone(),
};
// Now we can continuously check for messages in a different task, since we aren't going to receive another hello
- let handle: JoinHandle<()> = task::spawn(async move {
+ task::spawn(async move {
gateway.gateway_listen_task().await;
});
@@ -418,7 +419,6 @@ impl Gateway {
url: websocket_url.clone(),
events: shared_events,
websocket_send: shared_websocket_send.clone(),
- handle,
kill_send: kill_send.clone(),
store,
})
@@ -501,7 +501,7 @@ impl Gateway {
GATEWAY_DISPATCH => {
let Some(event_name) = gateway_payload.event_name else {
warn!("Gateway dispatch op without event_name");
- return
+ return;
};
trace!("Gateway: Received {event_name}");
@@ -536,6 +536,7 @@ impl Gateway {
let downcasted = unsafe { Arc::from_raw(ptr as *const RwLock<$update_type>).clone() };
drop(inner_object);
message.set_json(json.to_string());
+ message.set_source_url(self.url.clone());
message.update(downcasted.clone());
} else {
warn!("Received {} for {}, but it has been observed to be a different type!", $name, id)
@@ -916,7 +917,7 @@ impl GatewayEvent {
}
}
-mod events {
+pub mod events {
use super::*;
#[derive(Default, Debug)]
diff --git a/src/instance.rs b/src/instance.rs
index a3b5325..72bf350 100644
--- a/src/instance.rs
+++ b/src/instance.rs
@@ -8,15 +8,14 @@ use std::sync::{Arc, RwLock};
use reqwest::Client;
use serde::{Deserialize, Serialize};
-use crate::api::{Limit, LimitType};
use crate::errors::ChorusResult;
use crate::gateway::{Gateway, GatewayHandle};
use crate::ratelimiter::ChorusRequest;
use crate::types::types::subconfigs::limits::rates::RateLimits;
-use crate::types::{GeneralConfiguration, User, UserSettings};
+use crate::types::{GeneralConfiguration, Limit, LimitType, User, UserSettings};
use crate::UrlBundle;
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Default)]
/// The [`Instance`]; what you will be using to perform all sorts of actions on the Spacebar server.
/// If `limits_information` is `None`, then the instance will not be rate limited.
pub struct Instance {
@@ -26,7 +25,7 @@ pub struct Instance {
pub client: Client,
}
-#[derive(Debug, Clone, Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LimitsInformation {
pub ratelimits: HashMap,
pub configuration: RateLimits,
@@ -94,7 +93,7 @@ pub struct ChorusUser {
pub limits: Option>,
pub settings: Arc>,
pub object: Arc>,
- pub gateway: Arc, // TODO: Can this be an Arc? That way we could have Clone implemented on ChorusUser
+ pub gateway: GatewayHandle,
}
impl ChorusUser {
@@ -117,7 +116,7 @@ impl ChorusUser {
limits: Option>,
settings: Arc>,
object: Arc>,
- gateway: Arc,
+ gateway: GatewayHandle,
) -> ChorusUser {
ChorusUser {
belongs_to,
@@ -139,7 +138,7 @@ impl ChorusUser {
let object = Arc::new(RwLock::new(User::default()));
let wss_url = instance.read().unwrap().urls.wss.clone();
// Dummy gateway object
- let gateway = Arc::new(Gateway::new(wss_url).await.unwrap());
+ let gateway = Gateway::new(wss_url).await.unwrap();
ChorusUser {
token,
belongs_to: instance.clone(),
diff --git a/src/lib.rs b/src/lib.rs
index 2edecc2..e63c41d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -30,7 +30,7 @@ pub mod types;
#[cfg(feature = "client")]
pub mod voice;
-#[derive(Clone, Default, Debug, PartialEq, Eq)]
+#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
/// A URLBundle bundles together the API-, Gateway- and CDN-URLs of a Spacebar instance.
///
/// # Notes
diff --git a/src/ratelimiter.rs b/src/ratelimiter.rs
index 84bd641..88d4a02 100644
--- a/src/ratelimiter.rs
+++ b/src/ratelimiter.rs
@@ -8,10 +8,9 @@ use serde::Deserialize;
use serde_json::from_str;
use crate::{
- api::{Limit, LimitType},
errors::{ChorusError, ChorusResult},
instance::ChorusUser,
- types::{types::subconfigs::limits::rates::RateLimits, LimitsConfiguration},
+ types::{types::subconfigs::limits::rates::RateLimits, Limit, LimitType, LimitsConfiguration},
};
/// Chorus' request struct. This struct is used to send rate-limited requests to the Spacebar server.
@@ -92,7 +91,7 @@ impl ChorusRequest {
log::warn!("Request failed: {:?}", error);
return Err(ChorusError::RequestFailed {
url: error.url().unwrap().to_string(),
- error,
+ error: error.to_string(),
});
}
};
@@ -360,7 +359,7 @@ impl ChorusRequest {
Err(e) => {
return Err(ChorusError::RequestFailed {
url: url_api.to_string(),
- error: e,
+ error: e.to_string(),
})
}
};
diff --git a/src/types/config/types/guild_configuration.rs b/src/types/config/types/guild_configuration.rs
index 96e6ea8..65897ea 100644
--- a/src/types/config/types/guild_configuration.rs
+++ b/src/types/config/types/guild_configuration.rs
@@ -18,7 +18,7 @@ use crate::types::config::types::subconfigs::guild::{
};
use crate::types::{Error, GuildError};
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Hash)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum GuildFeatures {
ActivitiesAlpha,
@@ -139,7 +139,7 @@ pub enum GuildFeatures {
InvitesClosed,
}
-#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, Eq)]
+#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, Eq, Hash)]
pub struct GuildFeaturesList(Vec);
impl Deref for GuildFeaturesList {
diff --git a/src/types/config/types/subconfigs/limits/rates.rs b/src/types/config/types/subconfigs/limits/rates.rs
index ce1ea60..8fdd183 100644
--- a/src/types/config/types/subconfigs/limits/rates.rs
+++ b/src/types/config/types/subconfigs/limits/rates.rs
@@ -2,11 +2,9 @@ use std::collections::HashMap;
use serde::{Deserialize, Serialize};
-use crate::{
- api::LimitType,
- types::config::types::subconfigs::limits::ratelimits::{
- route::RouteRateLimit, RateLimitOptions,
- },
+use crate::types::{
+ config::types::subconfigs::limits::ratelimits::{route::RouteRateLimit, RateLimitOptions},
+ LimitType,
};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
diff --git a/src/types/entities/auto_moderation.rs b/src/types/entities/auto_moderation.rs
index eaec2b0..a8910b1 100644
--- a/src/types/entities/auto_moderation.rs
+++ b/src/types/entities/auto_moderation.rs
@@ -1,13 +1,18 @@
use std::sync::{Arc, RwLock};
+#[cfg(feature = "client")]
use crate::gateway::Updateable;
+
+#[cfg(feature = "client")]
use chorus_macros::Updateable;
+
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use crate::types::utils::Snowflake;
-#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable)]
+#[cfg_attr(feature = "client", derive(Updateable))]
+#[derive(Serialize, Deserialize, Debug, Default, Clone)]
/// See
pub struct AutoModerationRule {
pub id: Snowflake,
diff --git a/src/types/entities/channel.rs b/src/types/entities/channel.rs
index 84530c9..280401c 100644
--- a/src/types/entities/channel.rs
+++ b/src/types/entities/channel.rs
@@ -1,21 +1,28 @@
use std::sync::{Arc, RwLock};
-use chorus_macros::{observe_option_vec, Composite, Updateable};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_aux::prelude::deserialize_string_from_number;
use serde_repr::{Deserialize_repr, Serialize_repr};
use std::fmt::Debug;
-use crate::gateway::{GatewayHandle, Updateable};
use crate::types::{
entities::{GuildMember, User},
utils::Snowflake,
- Composite,
};
-#[derive(Default, Debug, Serialize, Deserialize, Clone, Updateable, Composite)]
+#[cfg(feature = "client")]
+use crate::types::Composite;
+
+#[cfg(feature = "client")]
+use crate::gateway::{GatewayHandle, Updateable};
+
+#[cfg(feature = "client")]
+use chorus_macros::{observe_option_vec, Composite, Updateable};
+
+#[derive(Default, Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
+#[cfg_attr(feature = "client", derive(Updateable, Composite))]
/// Represents a guild or private channel
///
/// # Reference
@@ -60,13 +67,13 @@ pub struct Channel {
#[cfg(feature = "sqlx")]
pub permission_overwrites: Option>>,
#[cfg(not(feature = "sqlx"))]
- #[observe_option_vec]
+ #[cfg_attr(feature = "client", observe_option_vec)]
pub permission_overwrites: Option>>>,
pub permissions: Option,
pub position: Option,
pub rate_limit_per_user: Option,
#[cfg_attr(feature = "sqlx", sqlx(skip))]
- #[observe_option_vec]
+ #[cfg_attr(feature = "client", observe_option_vec)]
pub recipients: Option>>>,
pub rtc_region: Option,
#[cfg_attr(feature = "sqlx", sqlx(skip))]
@@ -126,9 +133,8 @@ pub struct Tag {
pub emoji_name: Option,
}
-#[derive(
- Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Updateable, Composite,
-)]
+#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd)]
+#[cfg_attr(feature = "client", derive(Updateable, Composite))]
pub struct PermissionOverwrite {
pub id: Snowflake,
#[serde(rename = "type")]
diff --git a/src/types/entities/emoji.rs b/src/types/entities/emoji.rs
index d80e487..4f56af5 100644
--- a/src/types/entities/emoji.rs
+++ b/src/types/entities/emoji.rs
@@ -1,14 +1,22 @@
use std::fmt::Debug;
use std::sync::{Arc, RwLock};
-use chorus_macros::{Composite, Updateable};
use serde::{Deserialize, Serialize};
-use crate::gateway::{GatewayHandle, Updateable};
use crate::types::entities::User;
-use crate::types::{Composite, Snowflake};
+use crate::types::Snowflake;
-#[derive(Debug, Clone, Deserialize, Serialize, Default, Updateable, Composite)]
+#[cfg(feature = "client")]
+use crate::types::Composite;
+
+#[cfg(feature = "client")]
+use crate::gateway::{GatewayHandle, Updateable};
+
+#[cfg(feature = "client")]
+use chorus_macros::{Composite, Updateable};
+
+#[derive(Debug, Clone, Deserialize, Serialize, Default)]
+#[cfg_attr(feature = "client", derive(Updateable, Composite))]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
/// # Reference
/// See
@@ -27,6 +35,19 @@ pub struct Emoji {
pub available: Option,
}
+impl std::hash::Hash for Emoji {
+ fn hash(&self, state: &mut H) {
+ self.id.hash(state);
+ self.name.hash(state);
+ self.roles.hash(state);
+ self.roles.hash(state);
+ self.require_colons.hash(state);
+ self.managed.hash(state);
+ self.animated.hash(state);
+ self.available.hash(state);
+ }
+}
+
impl PartialEq for Emoji {
fn eq(&self, other: &Self) -> bool {
!(self.id != other.id
diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs
index 93b13fc..bb4db0c 100644
--- a/src/types/entities/guild.rs
+++ b/src/types/entities/guild.rs
@@ -1,25 +1,32 @@
use std::fmt::Debug;
use std::sync::{Arc, RwLock};
-use chorus_macros::{observe_option_vec, observe_vec, Composite, Updateable};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
-use crate::gateway::{GatewayHandle, Updateable};
use crate::types::types::guild_configuration::GuildFeaturesList;
use crate::types::{
entities::{Channel, Emoji, RoleObject, Sticker, User, VoiceState, Webhook},
interfaces::WelcomeScreenObject,
utils::Snowflake,
- Composite,
};
use bitflags::bitflags;
use super::PublicUser;
+#[cfg(feature = "client")]
+use crate::gateway::{GatewayHandle, Updateable};
+
+#[cfg(feature = "client")]
+use chorus_macros::{observe_option_vec, observe_vec, Composite, Updateable};
+
+#[cfg(feature = "client")]
+use crate::types::Composite;
+
/// See
-#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable, Composite)]
+#[derive(Serialize, Deserialize, Debug, Default, Clone)]
+#[cfg_attr(feature = "client", derive(Updateable, Composite))]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
pub struct Guild {
pub afk_channel_id: Option,
@@ -34,14 +41,14 @@ pub struct Guild {
#[cfg_attr(feature = "sqlx", sqlx(skip))]
pub bans: Option>,
#[cfg_attr(feature = "sqlx", sqlx(skip))]
- #[observe_option_vec]
+ #[cfg_attr(feature = "client", observe_option_vec)]
pub channels: Option>>>,
pub default_message_notifications: Option,
pub description: Option,
pub discovery_splash: Option,
#[cfg_attr(feature = "sqlx", sqlx(skip))]
+ #[cfg_attr(feature = "client", observe_vec)]
#[serde(default)]
- #[observe_vec]
pub emojis: Vec>>,
pub explicit_content_filter: Option,
//#[cfg_attr(feature = "sqlx", sqlx(try_from = "String"))]
@@ -77,7 +84,7 @@ pub struct Guild {
pub public_updates_channel_id: Option,
pub region: Option,
#[cfg_attr(feature = "sqlx", sqlx(skip))]
- #[observe_option_vec]
+ #[cfg_attr(feature = "client", observe_option_vec)]
pub roles: Option>>>,
#[cfg_attr(feature = "sqlx", sqlx(skip))]
pub rules_channel: Option,
@@ -91,10 +98,10 @@ pub struct Guild {
pub vanity_url_code: Option,
pub verification_level: Option,
#[cfg_attr(feature = "sqlx", sqlx(skip))]
- #[observe_option_vec]
+ #[cfg_attr(feature = "client", observe_option_vec)]
pub voice_states: Option>>>,
#[cfg_attr(feature = "sqlx", sqlx(skip))]
- #[observe_option_vec]
+ #[cfg_attr(feature = "client", observe_option_vec)]
pub webhooks: Option>>>,
#[cfg(feature = "sqlx")]
pub welcome_screen: Option>,
@@ -104,8 +111,113 @@ pub struct Guild {
pub widget_enabled: Option,
}
+impl std::hash::Hash for Guild {
+ fn hash(&self, state: &mut H) {
+ self.afk_channel_id.hash(state);
+ self.afk_timeout.hash(state);
+ self.application_id.hash(state);
+ self.approximate_member_count.hash(state);
+ self.approximate_presence_count.hash(state);
+ self.banner.hash(state);
+ self.bans.hash(state);
+ self.default_message_notifications.hash(state);
+ self.description.hash(state);
+ self.discovery_splash.hash(state);
+ self.explicit_content_filter.hash(state);
+ self.features.hash(state);
+ self.icon.hash(state);
+ self.icon_hash.hash(state);
+ self.id.hash(state);
+ self.invites.hash(state);
+ self.joined_at.hash(state);
+ self.large.hash(state);
+ self.max_members.hash(state);
+ self.max_presences.hash(state);
+ self.max_stage_video_channel_users.hash(state);
+ self.max_video_channel_users.hash(state);
+ self.mfa_level.hash(state);
+ self.name.hash(state);
+ self.nsfw_level.hash(state);
+ self.owner.hash(state);
+ self.owner_id.hash(state);
+ self.permissions.hash(state);
+ self.preferred_locale.hash(state);
+ self.premium_progress_bar_enabled.hash(state);
+ self.premium_subscription_count.hash(state);
+ self.premium_tier.hash(state);
+ self.primary_category_id.hash(state);
+ self.public_updates_channel_id.hash(state);
+ self.region.hash(state);
+ self.rules_channel.hash(state);
+ self.rules_channel_id.hash(state);
+ self.splash.hash(state);
+ self.stickers.hash(state);
+ self.system_channel_flags.hash(state);
+ self.system_channel_id.hash(state);
+ self.vanity_url_code.hash(state);
+ self.verification_level.hash(state);
+ self.welcome_screen.hash(state);
+ self.welcome_screen.hash(state);
+ self.widget_channel_id.hash(state);
+ self.widget_enabled.hash(state);
+ }
+}
+
+impl std::cmp::PartialEq for Guild {
+ fn eq(&self, other: &Self) -> bool {
+ self.afk_channel_id == other.afk_channel_id
+ && self.afk_timeout == other.afk_timeout
+ && self.application_id == other.application_id
+ && self.approximate_member_count == other.approximate_member_count
+ && self.approximate_presence_count == other.approximate_presence_count
+ && self.banner == other.banner
+ && self.bans == other.bans
+ && self.default_message_notifications == other.default_message_notifications
+ && self.description == other.description
+ && self.discovery_splash == other.discovery_splash
+ && self.explicit_content_filter == other.explicit_content_filter
+ && self.features == other.features
+ && self.icon == other.icon
+ && self.icon_hash == other.icon_hash
+ && self.id == other.id
+ && self.joined_at == other.joined_at
+ && self.large == other.large
+ && self.max_members == other.max_members
+ && self.max_presences == other.max_presences
+ && self.max_stage_video_channel_users == other.max_stage_video_channel_users
+ && self.max_video_channel_users == other.max_video_channel_users
+ && self.mfa_level == other.mfa_level
+ && self.name == other.name
+ && self.nsfw_level == other.nsfw_level
+ && self.owner == other.owner
+ && self.owner_id == other.owner_id
+ && self.permissions == other.permissions
+ && self.preferred_locale == other.preferred_locale
+ && self.premium_progress_bar_enabled == other.premium_progress_bar_enabled
+ && self.premium_subscription_count == other.premium_subscription_count
+ && self.premium_tier == other.premium_tier
+ && self.primary_category_id == other.primary_category_id
+ && self.public_updates_channel_id == other.public_updates_channel_id
+ && self.region == other.region
+ && self.rules_channel == other.rules_channel
+ && self.rules_channel_id == other.rules_channel_id
+ && self.splash == other.splash
+ && self.stickers == other.stickers
+ && self.system_channel_flags == other.system_channel_flags
+ && self.system_channel_id == other.system_channel_id
+ && self.vanity_url_code == other.vanity_url_code
+ && self.verification_level == other.verification_level
+ && self.welcome_screen == other.welcome_screen
+ && self.welcome_screen == other.welcome_screen
+ && self.widget_channel_id == other.widget_channel_id
+ && self.widget_enabled == other.widget_enabled
+ }
+}
+
+impl std::cmp::Eq for Guild {}
+
/// See
-#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
+#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
pub struct GuildBan {
pub user: PublicUser,
@@ -135,10 +247,29 @@ pub struct GuildInvite {
pub vanity_url: Option,
}
-#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
+impl std::hash::Hash for GuildInvite {
+ fn hash(&self, state: &mut H) {
+ self.code.hash(state);
+ self.temporary.hash(state);
+ self.uses.hash(state);
+ self.max_uses.hash(state);
+ self.max_age.hash(state);
+ self.created_at.hash(state);
+ self.expires_at.hash(state);
+ self.guild_id.hash(state);
+ self.channel_id.hash(state);
+ self.inviter_id.hash(state);
+ self.target_user_id.hash(state);
+ self.target_user.hash(state);
+ self.target_user_type.hash(state);
+ self.vanity_url.hash(state);
+ }
+}
+
+#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Hash)]
pub struct UnavailableGuild {
- id: Snowflake,
- unavailable: bool,
+ pub id: Snowflake,
+ pub unavailable: bool,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
@@ -202,7 +333,7 @@ pub struct GuildScheduledEventEntityMetadata {
pub location: Option,
}
-#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
+#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq, Hash)]
pub struct VoiceRegion {
id: String,
name: String,
@@ -211,7 +342,7 @@ pub struct VoiceRegion {
custom: bool,
}
-#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)]
+#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)]
#[repr(u8)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// See
@@ -221,7 +352,7 @@ pub enum MessageNotificationLevel {
OnlyMentions = 1,
}
-#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)]
+#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)]
#[repr(u8)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// See
@@ -232,7 +363,7 @@ pub enum ExplicitContentFilterLevel {
AllMembers = 2,
}
-#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)]
+#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)]
#[repr(u8)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// See
@@ -245,7 +376,7 @@ pub enum VerificationLevel {
VeryHigh = 4,
}
-#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)]
+#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)]
#[repr(u8)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// See
@@ -255,7 +386,7 @@ pub enum MFALevel {
Elevated = 1,
}
-#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)]
+#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)]
#[repr(u8)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// See
@@ -267,7 +398,7 @@ pub enum NSFWLevel {
AgeRestricted = 3,
}
-#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)]
+#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)]
#[repr(u8)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// See
@@ -280,7 +411,7 @@ pub enum PremiumTier {
}
bitflags! {
- #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
+ #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
/// # Reference
/// See
pub struct SystemChannelFlags: u64 {
diff --git a/src/types/entities/mod.rs b/src/types/entities/mod.rs
index abdf976..a14ef2c 100644
--- a/src/types/entities/mod.rs
+++ b/src/types/entities/mod.rs
@@ -10,6 +10,7 @@ pub use guild_member::*;
pub use integration::*;
pub use invite::*;
pub use message::*;
+pub use ratelimits::*;
pub use relationship::*;
pub use role::*;
pub use security_key::*;
@@ -22,9 +23,16 @@ pub use user_settings::*;
pub use voice_state::*;
pub use webhook::*;
+#[cfg(feature = "client")]
use crate::gateway::{GatewayHandle, Updateable};
+
+#[cfg(feature = "client")]
use async_trait::async_trait;
+
+#[cfg(feature = "client")]
use std::fmt::Debug;
+
+#[cfg(feature = "client")]
use std::sync::{Arc, RwLock};
mod application;
@@ -39,6 +47,7 @@ mod guild_member;
mod integration;
mod invite;
mod message;
+mod ratelimits;
mod relationship;
mod role;
mod security_key;
@@ -51,6 +60,7 @@ mod user_settings;
mod voice_state;
mod webhook;
+#[cfg(feature = "client")]
#[async_trait(?Send)]
pub trait Composite {
async fn watch_whole(self, gateway: &GatewayHandle) -> Self;
diff --git a/src/api/policies/instance/ratelimits.rs b/src/types/entities/ratelimits.rs
similarity index 100%
rename from src/api/policies/instance/ratelimits.rs
rename to src/types/entities/ratelimits.rs
diff --git a/src/types/entities/role.rs b/src/types/entities/role.rs
index 22dceff..087a775 100644
--- a/src/types/entities/role.rs
+++ b/src/types/entities/role.rs
@@ -1,13 +1,21 @@
use bitflags::bitflags;
-use chorus_macros::{Composite, Updateable};
use serde::{Deserialize, Serialize};
use serde_aux::prelude::{deserialize_option_number_from_string, deserialize_string_from_number};
use std::fmt::Debug;
-use crate::gateway::{GatewayHandle, Updateable};
-use crate::types::{utils::Snowflake, Composite};
+use crate::types::utils::Snowflake;
-#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Updateable, Composite)]
+#[cfg(feature = "client")]
+use chorus_macros::{Composite, Updateable};
+
+#[cfg(feature = "client")]
+use crate::gateway::{GatewayHandle, Updateable};
+
+#[cfg(feature = "client")]
+use crate::types::Composite;
+
+#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
+#[cfg_attr(feature = "client", derive(Updateable, Composite))]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
/// See
pub struct RoleObject {
diff --git a/src/types/entities/sticker.rs b/src/types/entities/sticker.rs
index c2cdb46..593206d 100644
--- a/src/types/entities/sticker.rs
+++ b/src/types/entities/sticker.rs
@@ -28,6 +28,22 @@ pub struct Sticker {
pub sort_value: Option,
}
+impl std::hash::Hash for Sticker {
+ fn hash(&self, state: &mut H) {
+ self.id.hash(state);
+ self.pack_id.hash(state);
+ self.name.hash(state);
+ self.description.hash(state);
+ self.tags.hash(state);
+ self.asset.hash(state);
+ self.sticker_type.hash(state);
+ self.format_type.hash(state);
+ self.available.hash(state);
+ self.guild_id.hash(state);
+ self.sort_value.hash(state);
+ }
+}
+
impl PartialEq for Sticker {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
diff --git a/src/types/entities/user.rs b/src/types/entities/user.rs
index 64334ff..eca5344 100644
--- a/src/types/entities/user.rs
+++ b/src/types/entities/user.rs
@@ -1,11 +1,17 @@
-use chorus_macros::{Composite, Updateable};
+use crate::types::utils::Snowflake;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_aux::prelude::deserialize_option_number_from_string;
use std::fmt::Debug;
+#[cfg(feature = "client")]
use crate::gateway::{GatewayHandle, Updateable};
-use crate::types::{utils::Snowflake, Composite};
+
+#[cfg(feature = "client")]
+use crate::types::Composite;
+
+#[cfg(feature = "client")]
+use chorus_macros::{Composite, Updateable};
use super::Emoji;
@@ -21,7 +27,8 @@ impl User {
PublicUser::from(self)
}
}
-#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Updateable, Composite)]
+#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "client", derive(Updateable, Composite))]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
pub struct User {
pub id: Snowflake,
@@ -56,7 +63,7 @@ pub struct User {
pub disabled: Option,
}
-#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct PublicUser {
pub id: Snowflake,
pub username: Option,
diff --git a/src/types/entities/user_settings.rs b/src/types/entities/user_settings.rs
index 1be2c0a..e6db7e7 100644
--- a/src/types/entities/user_settings.rs
+++ b/src/types/entities/user_settings.rs
@@ -53,15 +53,17 @@ pub struct UserSettings {
pub friend_source_flags: sqlx::types::Json,
#[cfg(not(feature = "sqlx"))]
pub friend_source_flags: FriendSourceFlags,
- pub gateway_connected: bool,
+ pub gateway_connected: Option,
pub gif_auto_play: bool,
#[cfg(feature = "sqlx")]
pub guild_folders: sqlx::types::Json>,
#[cfg(not(feature = "sqlx"))]
pub guild_folders: Vec,
#[cfg(feature = "sqlx")]
+ #[serde(default)]
pub guild_positions: sqlx::types::Json>,
#[cfg(not(feature = "sqlx"))]
+ #[serde(default)]
pub guild_positions: Vec,
pub inline_attachment_media: bool,
pub inline_embed_media: bool,
@@ -98,7 +100,7 @@ impl Default for UserSettings {
enable_tts_command: false,
explicit_content_filter: 0,
friend_source_flags: Default::default(),
- gateway_connected: false,
+ gateway_connected: Some(false),
gif_auto_play: false,
guild_folders: Default::default(),
guild_positions: Default::default(),
diff --git a/src/types/entities/voice_state.rs b/src/types/entities/voice_state.rs
index c879c8e..e764296 100644
--- a/src/types/entities/voice_state.rs
+++ b/src/types/entities/voice_state.rs
@@ -1,20 +1,27 @@
use std::sync::{Arc, RwLock};
+#[cfg(feature = "client")]
use chorus_macros::{Composite, Updateable};
+
+#[cfg(feature = "client")]
+use crate::types::Composite;
+
+#[cfg(feature = "client")]
+use crate::gateway::{GatewayHandle, Updateable};
+
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
-use crate::gateway::{GatewayHandle, Updateable};
use crate::types::{
entities::{Guild, GuildMember},
utils::Snowflake,
- Composite,
};
/// See
-#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable, Composite)]
+#[derive(Serialize, Deserialize, Debug, Default, Clone)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
+#[cfg_attr(feature = "client", derive(Updateable, Composite))]
pub struct VoiceState {
pub guild_id: Option,
pub guild: Option,
diff --git a/src/types/entities/webhook.rs b/src/types/entities/webhook.rs
index 7771dbf..b544ec9 100644
--- a/src/types/entities/webhook.rs
+++ b/src/types/entities/webhook.rs
@@ -1,18 +1,25 @@
use std::fmt::Debug;
use std::sync::{Arc, RwLock};
-use chorus_macros::{Composite, Updateable};
use serde::{Deserialize, Serialize};
+#[cfg(feature = "client")]
use crate::gateway::{GatewayHandle, Updateable};
+
+#[cfg(feature = "client")]
+use chorus_macros::{Composite, Updateable};
+
+#[cfg(feature = "client")]
+use crate::types::Composite;
+
use crate::types::{
entities::{Guild, User},
utils::Snowflake,
- Composite,
};
/// See
-#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable, Composite)]
+#[derive(Serialize, Deserialize, Debug, Default, Clone)]
+#[cfg_attr(feature = "client", derive(Updateable, Composite))]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
pub struct Webhook {
pub id: Snowflake,
diff --git a/src/types/events/auto_moderation.rs b/src/types/events/auto_moderation.rs
index 376e523..2a2eb6b 100644
--- a/src/types/events/auto_moderation.rs
+++ b/src/types/events/auto_moderation.rs
@@ -1,5 +1,5 @@
-use crate::types::JsonField;
-use chorus_macros::JsonField;
+use crate::types::{JsonField, SourceUrlField};
+use chorus_macros::{JsonField, SourceUrlField};
use serde::{Deserialize, Serialize};
use crate::types::{
@@ -7,6 +7,7 @@ use crate::types::{
WebSocketEvent,
};
+#[cfg(feature = "client")]
use super::UpdateMessage;
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
@@ -18,15 +19,18 @@ pub struct AutoModerationRuleCreate {
impl WebSocketEvent for AutoModerationRuleCreate {}
-#[derive(Debug, Deserialize, Serialize, Default, Clone, JsonField)]
+#[derive(Debug, Deserialize, Serialize, Default, Clone, JsonField, SourceUrlField)]
/// See
pub struct AutoModerationRuleUpdate {
#[serde(flatten)]
pub rule: AutoModerationRule,
#[serde(skip)]
pub json: String,
+ #[serde(skip)]
+ pub source_url: String,
}
+#[cfg(feature = "client")]
impl UpdateMessage for AutoModerationRuleUpdate {
fn id(&self) -> Option {
Some(self.rule.id)
diff --git a/src/types/events/channel.rs b/src/types/events/channel.rs
index ae84b79..eb557d7 100644
--- a/src/types/events/channel.rs
+++ b/src/types/events/channel.rs
@@ -1,14 +1,18 @@
-use std::sync::{Arc, RwLock};
-
use crate::types::events::WebSocketEvent;
-use crate::types::Guild;
-use crate::types::{entities::Channel, JsonField, Snowflake};
-use chorus_macros::JsonField;
+use crate::types::{entities::Channel, JsonField, Snowflake, SourceUrlField};
+use chorus_macros::{JsonField, SourceUrlField};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
+#[cfg(feature = "client")]
use super::UpdateMessage;
+#[cfg(feature = "client")]
+use std::sync::{Arc, RwLock};
+
+#[cfg(feature = "client")]
+use crate::types::Guild;
+
#[derive(Debug, Default, Deserialize, Serialize)]
/// See
pub struct ChannelPinsUpdate {
@@ -19,17 +23,20 @@ pub struct ChannelPinsUpdate {
impl WebSocketEvent for ChannelPinsUpdate {}
-#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)]
+#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)]
/// See
pub struct ChannelCreate {
#[serde(flatten)]
pub channel: Channel,
#[serde(skip)]
pub json: String,
+ #[serde(skip)]
+ pub source_url: String,
}
impl WebSocketEvent for ChannelCreate {}
+#[cfg(feature = "client")]
impl UpdateMessage for ChannelCreate {
fn id(&self) -> Option {
self.channel.guild_id
@@ -46,17 +53,20 @@ impl UpdateMessage for ChannelCreate {
}
}
-#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)]
+#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)]
/// See
pub struct ChannelUpdate {
#[serde(flatten)]
pub channel: Channel,
#[serde(skip)]
pub json: String,
+ #[serde(skip)]
+ pub source_url: String,
}
impl WebSocketEvent for ChannelUpdate {}
+#[cfg(feature = "client")]
impl UpdateMessage for ChannelUpdate {
fn update(&mut self, object_to_update: Arc>) {
let mut write = object_to_update.write().unwrap();
@@ -87,15 +97,18 @@ pub struct ChannelUnreadUpdateObject {
impl WebSocketEvent for ChannelUnreadUpdate {}
-#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)]
+#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)]
/// See
pub struct ChannelDelete {
#[serde(flatten)]
pub channel: Channel,
#[serde(skip)]
pub json: String,
+ #[serde(skip)]
+ pub source_url: String,
}
+#[cfg(feature = "client")]
impl UpdateMessage for ChannelDelete {
fn id(&self) -> Option {
self.channel.guild_id
@@ -111,11 +124,7 @@ impl UpdateMessage for ChannelDelete {
}
for (iteration, item) in (0_u32..).zip(write.channels.as_mut().unwrap().iter()) {
if item.read().unwrap().id == self.id().unwrap() {
- write
- .channels
- .as_mut()
- .unwrap()
- .swap_remove(iteration as usize);
+ write.channels.as_mut().unwrap().remove(iteration as usize);
return;
}
}
diff --git a/src/types/events/guild.rs b/src/types/events/guild.rs
index 0afa9d6..0c6bb05 100644
--- a/src/types/events/guild.rs
+++ b/src/types/events/guild.rs
@@ -1,6 +1,4 @@
-use std::sync::{Arc, RwLock};
-
-use chorus_macros::JsonField;
+use chorus_macros::{JsonField, SourceUrlField};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
@@ -8,18 +6,38 @@ use crate::types::entities::{Guild, PublicUser, UnavailableGuild};
use crate::types::events::WebSocketEvent;
use crate::types::{
AuditLogEntry, Emoji, GuildMember, GuildScheduledEvent, JsonField, RoleObject, Snowflake,
- Sticker,
+ SourceUrlField, Sticker,
};
-use super::{PresenceUpdate, UpdateMessage};
+use super::PresenceUpdate;
-#[derive(Debug, Deserialize, Serialize, Default, Clone)]
+#[cfg(feature = "client")]
+use super::UpdateMessage;
+#[cfg(feature = "client")]
+use std::sync::{Arc, RwLock};
+
+#[derive(Debug, Deserialize, Serialize, Default, Clone, SourceUrlField, JsonField)]
/// See ;
/// Received to give data about a guild;
// This one is particularly painful, it can be a Guild object with an extra field or an unavailable guild object
pub struct GuildCreate {
#[serde(flatten)]
pub d: GuildCreateDataOption,
+ #[serde(skip)]
+ pub source_url: String,
+ #[serde(skip)]
+ pub json: String,
+}
+
+impl UpdateMessage for GuildCreate {
+ fn id(&self) -> Option {
+ match &self.d {
+ GuildCreateDataOption::UnavailableGuild(unavailable) => Some(unavailable.id),
+ GuildCreateDataOption::Guild(guild) => Some(guild.id),
+ }
+ }
+
+ fn update(&mut self, _: Arc>) {}
}
#[derive(Debug, Deserialize, Serialize, Clone)]
@@ -57,22 +75,43 @@ pub struct GuildBanRemove {
impl WebSocketEvent for GuildBanRemove {}
-#[derive(Debug, Default, Deserialize, Serialize, Clone)]
+#[derive(Debug, Default, Deserialize, Serialize, Clone, SourceUrlField, JsonField)]
/// See ;
/// Received to give info about a guild being updated;
pub struct GuildUpdate {
#[serde(flatten)]
pub guild: Guild,
+ #[serde(skip)]
+ pub source_url: String,
+ #[serde(skip)]
+ pub json: String,
}
impl WebSocketEvent for GuildUpdate {}
-#[derive(Debug, Default, Deserialize, Serialize, Clone)]
+impl UpdateMessage for GuildUpdate {
+ fn id(&self) -> Option {
+ Some(self.guild.id)
+ }
+}
+
+#[derive(Debug, Default, Deserialize, Serialize, Clone, SourceUrlField, JsonField)]
/// See ;
/// Received to tell the client about a guild being deleted;
pub struct GuildDelete {
#[serde(flatten)]
pub guild: UnavailableGuild,
+ #[serde(skip)]
+ pub source_url: String,
+ #[serde(skip)]
+ pub json: String,
+}
+
+impl UpdateMessage for GuildDelete {
+ fn id(&self) -> Option {
+ Some(self.guild.id)
+ }
+ fn update(&mut self, _: Arc>) {}
}
impl WebSocketEvent for GuildDelete {}
@@ -168,17 +207,20 @@ pub struct GuildMembersChunk {
impl WebSocketEvent for GuildMembersChunk {}
-#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)]
+#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)]
/// See
pub struct GuildRoleCreate {
pub guild_id: Snowflake,
pub role: RoleObject,
#[serde(skip)]
pub json: String,
+ #[serde(skip)]
+ pub source_url: String,
}
impl WebSocketEvent for GuildRoleCreate {}
+#[cfg(feature = "client")]
impl UpdateMessage for GuildRoleCreate {
fn id(&self) -> Option {
Some(self.guild_id)
@@ -198,17 +240,20 @@ impl UpdateMessage for GuildRoleCreate {
}
}
-#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)]
+#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)]
/// See
pub struct GuildRoleUpdate {
pub guild_id: Snowflake,
pub role: RoleObject,
#[serde(skip)]
pub json: String,
+ #[serde(skip)]
+ pub source_url: String,
}
impl WebSocketEvent for GuildRoleUpdate {}
+#[cfg(feature = "client")]
impl UpdateMessage for GuildRoleUpdate {
fn id(&self) -> Option {
Some(self.role.id)
diff --git a/src/types/events/mod.rs b/src/types/events/mod.rs
index e440c05..f4e926c 100644
--- a/src/types/events/mod.rs
+++ b/src/types/events/mod.rs
@@ -1,12 +1,5 @@
-use std::sync::{Arc, RwLock};
-
-use std::collections::HashMap;
-
-use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
-use serde_json::{from_str, from_value, to_value, Value};
-
pub use application::*;
pub use auto_moderation::*;
pub use call::*;
@@ -34,9 +27,24 @@ pub use voice::*;
pub use webhooks::*;
pub use webrtc::*;
+#[cfg(feature = "client")]
+use super::Snowflake;
+
+#[cfg(feature = "client")]
use crate::gateway::Updateable;
-use super::Snowflake;
+#[cfg(feature = "client")]
+use serde_json::{from_str, from_value, to_value, Value};
+
+#[cfg(feature = "client")]
+use std::collections::HashMap;
+
+use std::fmt::Debug;
+#[cfg(feature = "client")]
+use std::sync::{Arc, RwLock};
+
+#[cfg(feature = "client")]
+use serde::de::DeserializeOwned;
mod application;
mod auto_moderation;
@@ -66,7 +74,7 @@ mod webhooks;
mod webrtc;
-pub trait WebSocketEvent {}
+pub trait WebSocketEvent: Send + Sync + Debug {}
#[derive(Debug, Default, Serialize, Clone)]
/// The payload used for sending events to the gateway
@@ -107,6 +115,7 @@ pub struct GatewayReceivePayload<'a> {
impl<'a> WebSocketEvent for GatewayReceivePayload<'a> {}
+#[cfg(feature = "client")]
/// An [`UpdateMessage`] represents a received Gateway Message which contains updated
/// information for an [`Updateable`] of Type T.
/// # Example:
@@ -119,7 +128,7 @@ impl<'a> WebSocketEvent for GatewayReceivePayload<'a> {}
/// 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
/// a [`Channel`] object.
-pub(crate) trait UpdateMessage: Clone + JsonField
+pub(crate) trait UpdateMessage: Clone + JsonField + SourceUrlField
where
T: Updateable + Serialize + DeserializeOwned + Clone,
{
@@ -134,6 +143,12 @@ pub(crate) trait JsonField: Clone {
fn get_json(&self) -> String;
}
+pub trait SourceUrlField: Clone {
+ fn set_source_url(&mut self, url: String);
+ fn get_source_url(&self) -> String;
+}
+
+#[cfg(feature = "client")]
/// Only applicable for events where the Update struct is the same as the Entity struct
pub(crate) fn update_object(
value: String,
diff --git a/src/types/events/thread.rs b/src/types/events/thread.rs
index 19f1cde..cff5f6f 100644
--- a/src/types/events/thread.rs
+++ b/src/types/events/thread.rs
@@ -1,10 +1,11 @@
-use chorus_macros::JsonField;
+use chorus_macros::{JsonField, SourceUrlField};
use serde::{Deserialize, Serialize};
use crate::types::entities::{Channel, ThreadMember};
use crate::types::events::WebSocketEvent;
-use crate::types::{JsonField, Snowflake};
+use crate::types::{JsonField, Snowflake, SourceUrlField};
+#[cfg(feature = "client")]
use super::UpdateMessage;
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
@@ -16,17 +17,20 @@ pub struct ThreadCreate {
impl WebSocketEvent for ThreadCreate {}
-#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)]
+#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)]
/// See
pub struct ThreadUpdate {
#[serde(flatten)]
pub thread: Channel,
#[serde(skip)]
pub json: String,
+ #[serde(skip)]
+ pub source_url: String,
}
impl WebSocketEvent for ThreadUpdate {}
+#[cfg(feature = "client")]
impl UpdateMessage for ThreadUpdate {
fn id(&self) -> Option {
Some(self.thread.id)
diff --git a/src/types/interfaces/guild_welcome_screen.rs b/src/types/interfaces/guild_welcome_screen.rs
index 4912a78..dbeef0f 100644
--- a/src/types/interfaces/guild_welcome_screen.rs
+++ b/src/types/interfaces/guild_welcome_screen.rs
@@ -2,14 +2,14 @@ use serde::{Deserialize, Serialize};
use crate::types::utils::Snowflake;
-#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
+#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Hash)]
pub struct WelcomeScreenObject {
pub enabled: bool,
pub description: Option,
pub welcome_channels: Vec,
}
-#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
+#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Hash)]
pub struct WelcomeScreenChannel {
pub channel_id: Snowflake,
pub description: String,
diff --git a/src/types/schema/auth.rs b/src/types/schema/auth.rs
index 60e23a4..2159de9 100644
--- a/src/types/schema/auth.rs
+++ b/src/types/schema/auth.rs
@@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
-#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
+#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub struct RegisterSchema {
pub username: String,
@@ -15,7 +15,7 @@ pub struct RegisterSchema {
pub promotional_email_opt_in: Option,
}
-#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
+#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub struct LoginSchema {
/// For Discord, usernames must be between 2 and 32 characters,
diff --git a/tests/auth.rs b/tests/auth.rs
index c26552f..f89e5e4 100644
--- a/tests/auth.rs
+++ b/tests/auth.rs
@@ -4,13 +4,13 @@ mod common;
#[tokio::test]
async fn test_registration() {
- let mut bundle = common::setup().await;
+ let bundle = common::setup().await;
let reg = RegisterSchema {
username: "Hiiii".into(),
date_of_birth: Some("2000-01-01".to_string()),
consent: true,
..Default::default()
};
- bundle.instance.register_account(®).await.unwrap();
+ bundle.instance.clone().register_account(reg).await.unwrap();
common::teardown(bundle).await;
}
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index 19c6509..ce42578 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -31,7 +31,8 @@ impl TestBundle {
..Default::default()
};
self.instance
- .register_account(®ister_schema)
+ .clone()
+ .register_account(register_schema)
.await
.unwrap()
}
@@ -42,7 +43,7 @@ impl TestBundle {
limits: self.user.limits.clone(),
settings: self.user.settings.clone(),
object: self.user.object.clone(),
- gateway: Arc::new(Gateway::new(self.instance.urls.wss.clone()).await.unwrap()),
+ gateway: Gateway::new(self.instance.urls.wss.clone()).await.unwrap(),
}
}
}
@@ -54,7 +55,7 @@ pub(crate) async fn setup() -> TestBundle {
"ws://localhost:3001".to_string(),
"http://localhost:3001".to_string(),
);
- let mut instance = Instance::new(urls.clone(), true).await.unwrap();
+ let instance = Instance::new(urls.clone(), true).await.unwrap();
// Requires the existance of the below user.
let reg = RegisterSchema {
username: "integrationtestuser".into(),
@@ -91,7 +92,7 @@ pub(crate) async fn setup() -> TestBundle {
default_thread_rate_limit_per_user: Some(0),
video_quality_mode: None,
};
- let mut user = instance.register_account(®).await.unwrap();
+ let mut user = instance.clone().register_account(reg).await.unwrap();
let guild = Guild::create(&mut user, guild_create_schema).await.unwrap();
let channel = Channel::create(&mut user, guild.id, None, channel_create_schema)
.await