Error observer (also merge perpetual/gateway-dev) (#425)
* Add Webrtc Identify & Ready * Test error observer * Minor updates * More derives * Even more derives * Small types update * e
This commit is contained in:
parent
8c45355620
commit
141dc32819
|
@ -2,6 +2,8 @@
|
||||||
use custom_error::custom_error;
|
use custom_error::custom_error;
|
||||||
use reqwest::Error;
|
use reqwest::Error;
|
||||||
|
|
||||||
|
use crate::types::WebSocketEvent;
|
||||||
|
|
||||||
custom_error! {
|
custom_error! {
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub RegistrationError
|
pub RegistrationError
|
||||||
|
@ -54,9 +56,10 @@ custom_error! {
|
||||||
/// Supposed to be sent as numbers, though they are sent as string most of the time?
|
/// Supposed to be sent as numbers, though they are sent as string most of the time?
|
||||||
///
|
///
|
||||||
/// Also includes errors when initiating a connection and unexpected opcodes
|
/// Also includes errors when initiating a connection and unexpected opcodes
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq, Default, Clone)]
|
||||||
pub GatewayError
|
pub GatewayError
|
||||||
// Errors we have received from the gateway
|
// Errors we have received from the gateway
|
||||||
|
#[default]
|
||||||
Unknown = "We're not sure what went wrong. Try reconnecting?",
|
Unknown = "We're not sure what went wrong. Try reconnecting?",
|
||||||
UnknownOpcode = "You sent an invalid Gateway opcode or an invalid payload for an opcode",
|
UnknownOpcode = "You sent an invalid Gateway opcode or an invalid payload for an opcode",
|
||||||
Decode = "Gateway server couldn't decode payload",
|
Decode = "Gateway server couldn't decode payload",
|
||||||
|
@ -79,3 +82,5 @@ custom_error! {
|
||||||
// Other misc errors
|
// Other misc errors
|
||||||
UnexpectedOpcodeReceived{opcode: u8} = "Received an opcode we weren't expecting to receive: {opcode}",
|
UnexpectedOpcodeReceived{opcode: u8} = "Received an opcode we weren't expecting to receive: {opcode}",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for GatewayError {}
|
||||||
|
|
|
@ -479,13 +479,15 @@ impl Gateway {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: handle errors in a good way, maybe observers like events?
|
|
||||||
if msg.is_error() {
|
if msg.is_error() {
|
||||||
warn!("GW: Received error, connection will close..");
|
let error = msg.error().unwrap();
|
||||||
|
|
||||||
let _error = msg.error();
|
warn!("GW: Received error {:?}, connection will close..", error);
|
||||||
|
|
||||||
self.close().await;
|
self.close().await;
|
||||||
|
|
||||||
|
self.events.lock().await.error.notify(error).await;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,6 +937,7 @@ mod events {
|
||||||
pub webhooks: Webhooks,
|
pub webhooks: Webhooks,
|
||||||
pub gateway_identify_payload: GatewayEvent<types::GatewayIdentifyPayload>,
|
pub gateway_identify_payload: GatewayEvent<types::GatewayIdentifyPayload>,
|
||||||
pub gateway_resume: GatewayEvent<types::GatewayResume>,
|
pub gateway_resume: GatewayEvent<types::GatewayResume>,
|
||||||
|
pub error: GatewayEvent<GatewayError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub struct CallCreate {
|
||||||
|
|
||||||
impl WebSocketEvent for CallCreate {}
|
impl WebSocketEvent for CallCreate {}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
|
||||||
/// Officially Undocumented;
|
/// Officially Undocumented;
|
||||||
/// Updates the client on which calls are ringing, along with a specific call?;
|
/// Updates the client on which calls are ringing, along with a specific call?;
|
||||||
///
|
///
|
||||||
|
@ -38,7 +38,7 @@ pub struct CallUpdate {
|
||||||
|
|
||||||
impl WebSocketEvent for CallUpdate {}
|
impl WebSocketEvent for CallUpdate {}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
|
||||||
/// Officially Undocumented;
|
/// Officially Undocumented;
|
||||||
/// Deletes a ringing call;
|
/// Deletes a ringing call;
|
||||||
/// Ex: {"t":"CALL_DELETE","s":8,"op":0,"d":{"channel_id":"837609115475771392"}}
|
/// Ex: {"t":"CALL_DELETE","s":8,"op":0,"d":{"channel_id":"837609115475771392"}}
|
||||||
|
@ -48,7 +48,7 @@ pub struct CallDelete {
|
||||||
|
|
||||||
impl WebSocketEvent for CallDelete {}
|
impl WebSocketEvent for CallDelete {}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
|
||||||
/// Officially Undocumented;
|
/// Officially Undocumented;
|
||||||
/// See <https://unofficial-discord-docs.vercel.app/gateway/op13>;
|
/// See <https://unofficial-discord-docs.vercel.app/gateway/op13>;
|
||||||
///
|
///
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::types::WebSocketEvent;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Received on gateway init, tells the client how often to send heartbeats;
|
/// Received on gateway init, tells the client how often to send heartbeats;
|
||||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
pub struct GatewayHello {
|
pub struct GatewayHello {
|
||||||
pub op: i32,
|
pub op: i32,
|
||||||
pub d: HelloData,
|
pub d: HelloData,
|
||||||
|
@ -10,7 +10,7 @@ pub struct GatewayHello {
|
||||||
|
|
||||||
impl WebSocketEvent for GatewayHello {}
|
impl WebSocketEvent for GatewayHello {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, Copy)]
|
||||||
/// Contains info on how often the client should send heartbeats to the server;
|
/// Contains info on how often the client should send heartbeats to the server;
|
||||||
pub struct HelloData {
|
pub struct HelloData {
|
||||||
/// How often a client should send heartbeats, in milliseconds
|
/// How often a client should send heartbeats, in milliseconds
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::types::events::{PresenceUpdate, WebSocketEvent};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::serde_as;
|
use serde_with::serde_as;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
|
||||||
pub struct GatewayIdentifyPayload {
|
pub struct GatewayIdentifyPayload {
|
||||||
pub token: String,
|
pub token: String,
|
||||||
pub properties: GatewayIdentifyConnectionProps,
|
pub properties: GatewayIdentifyConnectionProps,
|
||||||
|
@ -68,7 +68,7 @@ impl GatewayIdentifyPayload {
|
||||||
|
|
||||||
impl WebSocketEvent for GatewayIdentifyPayload {}
|
impl WebSocketEvent for GatewayIdentifyPayload {}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
pub struct GatewayIdentifyConnectionProps {
|
pub struct GatewayIdentifyConnectionProps {
|
||||||
/// Almost always sent
|
/// Almost always sent
|
||||||
|
@ -144,7 +144,7 @@ impl GatewayIdentifyConnectionProps {
|
||||||
referring_domain: None,
|
referring_domain: None,
|
||||||
referrer_current: None,
|
referrer_current: None,
|
||||||
release_channel: String::from("stable"),
|
release_channel: String::from("stable"),
|
||||||
client_build_number: 199933,
|
client_build_number: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ impl GatewayIdentifyConnectionProps {
|
||||||
system_locale: String::from("en-US"),
|
system_locale: String::from("en-US"),
|
||||||
os: String::from("Windows"),
|
os: String::from("Windows"),
|
||||||
os_version: Some(String::from("10")),
|
os_version: Some(String::from("10")),
|
||||||
client_build_number: 199933,
|
client_build_number: 222963,
|
||||||
release_channel: String::from("stable"),
|
release_channel: String::from("stable"),
|
||||||
..Self::minimal()
|
..Self::minimal()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ use std::collections::HashMap;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use serde_json::{from_str, from_value, to_value, Value};
|
||||||
|
|
||||||
pub use application::*;
|
pub use application::*;
|
||||||
pub use auto_moderation::*;
|
pub use auto_moderation::*;
|
||||||
pub use call::*;
|
pub use call::*;
|
||||||
|
@ -24,13 +26,13 @@ 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::*;
|
||||||
pub use user::*;
|
pub use user::*;
|
||||||
pub use voice::*;
|
pub use voice::*;
|
||||||
pub use webhooks::*;
|
pub use webhooks::*;
|
||||||
|
pub use webrtc::*;
|
||||||
|
|
||||||
use crate::gateway::Updateable;
|
use crate::gateway::Updateable;
|
||||||
|
|
||||||
|
@ -62,6 +64,8 @@ mod user;
|
||||||
mod voice;
|
mod voice;
|
||||||
mod webhooks;
|
mod webhooks;
|
||||||
|
|
||||||
|
mod webrtc;
|
||||||
|
|
||||||
pub trait WebSocketEvent {}
|
pub trait WebSocketEvent {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize, Clone)]
|
#[derive(Debug, Default, Serialize, Clone)]
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub struct UpdatePresence {
|
||||||
pub afk: bool,
|
pub afk: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq)]
|
||||||
/// Received to tell the client that a user updated their presence / status
|
/// Received to tell the client that a user updated their presence / status
|
||||||
/// See <https://discord.com/developers/docs/topics/gateway-events#presence-update-presence-update-event-fields>
|
/// See <https://discord.com/developers/docs/topics/gateway-events#presence-update-presence-update-event-fields>
|
||||||
pub struct PresenceUpdate {
|
pub struct PresenceUpdate {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::types::entities::PublicUser;
|
||||||
use crate::types::events::WebSocketEvent;
|
use crate::types::events::WebSocketEvent;
|
||||||
use crate::types::utils::Snowflake;
|
use crate::types::utils::Snowflake;
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
/// See <https://discord.com/developers/docs/topics/gateway-events#user-update>;
|
/// See <https://discord.com/developers/docs/topics/gateway-events#user-update>;
|
||||||
/// Sent to indicate updates to a user object; (name changes, discriminator changes, etc);
|
/// Sent to indicate updates to a user object; (name changes, discriminator changes, etc);
|
||||||
pub struct UserUpdate {
|
pub struct UserUpdate {
|
||||||
|
@ -14,7 +14,7 @@ pub struct UserUpdate {
|
||||||
|
|
||||||
impl WebSocketEvent for UserUpdate {}
|
impl WebSocketEvent for UserUpdate {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
/// Undocumented;
|
/// Undocumented;
|
||||||
///
|
///
|
||||||
/// Possibly an update for muted guild / channel settings for the current user;
|
/// Possibly an update for muted guild / channel settings for the current user;
|
||||||
|
@ -39,7 +39,7 @@ pub struct UserGuildSettingsUpdate {
|
||||||
|
|
||||||
impl WebSocketEvent for UserGuildSettingsUpdate {}
|
impl WebSocketEvent for UserGuildSettingsUpdate {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
/// Undocumented;
|
/// Undocumented;
|
||||||
///
|
///
|
||||||
/// Received in [UserGuildSettingsUpdate];
|
/// Received in [UserGuildSettingsUpdate];
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::types::{events::WebSocketEvent, Snowflake, VoiceState};
|
use crate::types::{events::WebSocketEvent, Snowflake, VoiceState};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default)]
|
#[derive(Debug, Deserialize, Serialize, Default, Clone, Copy, PartialEq, Eq)]
|
||||||
///
|
///
|
||||||
/// Sent to the server to indicate an update of the voice state (leave voice channel, join voice channel, mute, deafen);
|
/// Sent to the server to indicate an update of the voice state (leave voice channel, join voice channel, mute, deafen);
|
||||||
///
|
///
|
||||||
|
@ -28,7 +28,7 @@ pub struct VoiceStateUpdate {
|
||||||
|
|
||||||
impl WebSocketEvent for VoiceStateUpdate {}
|
impl WebSocketEvent for VoiceStateUpdate {}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
|
||||||
/// See <https://discord.com/developers/docs/topics/gateway-events#voice-server-update>;
|
/// See <https://discord.com/developers/docs/topics/gateway-events#voice-server-update>;
|
||||||
///
|
///
|
||||||
/// Received to indicate which voice endpoint, token and guild_id to use;
|
/// Received to indicate which voice endpoint, token and guild_id to use;
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
use crate::types::{Snowflake, WebSocketEvent};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
|
||||||
|
/// The identify payload for the webrtc stream;
|
||||||
|
/// Contains info to begin a webrtc connection;
|
||||||
|
/// See https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload;
|
||||||
|
pub struct VoiceIdentify {
|
||||||
|
server_id: Snowflake,
|
||||||
|
user_id: Snowflake,
|
||||||
|
session_id: String,
|
||||||
|
token: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// Undocumented field, but is also in discord client comms
|
||||||
|
video: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for VoiceIdentify {}
|
|
@ -0,0 +1,5 @@
|
||||||
|
pub use identify::*;
|
||||||
|
pub use ready::*;
|
||||||
|
|
||||||
|
mod identify;
|
||||||
|
mod ready;
|
|
@ -0,0 +1,29 @@
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
|
use crate::types::WebSocketEvent;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
|
/// The ready event for the webrtc stream;
|
||||||
|
/// Used to give info after the identify event;
|
||||||
|
/// See https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-ready-payload;
|
||||||
|
pub struct VoiceReady {
|
||||||
|
ssrc: i32,
|
||||||
|
ip: Ipv4Addr,
|
||||||
|
port: u32,
|
||||||
|
modes: Vec<String>,
|
||||||
|
// Heartbeat interval is also sent, but is "an erroneous field and should be ignored. The correct heartbeat_interval value comes from the Hello payload."
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for VoiceReady {
|
||||||
|
fn default() -> Self {
|
||||||
|
VoiceReady {
|
||||||
|
ssrc: 1,
|
||||||
|
ip: Ipv4Addr::UNSPECIFIED,
|
||||||
|
port: 0,
|
||||||
|
modes: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for VoiceReady {}
|
|
@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::{entities::Emoji, Snowflake};
|
use crate::types::{entities::Emoji, Snowflake};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
|
||||||
pub struct Activity {
|
pub struct Activity {
|
||||||
name: String,
|
name: String,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
|
@ -22,19 +22,19 @@ pub struct Activity {
|
||||||
buttons: Option<Vec<ActivityButton>>,
|
buttons: Option<Vec<ActivityButton>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
|
||||||
struct ActivityTimestamps {
|
struct ActivityTimestamps {
|
||||||
start: Option<i64>,
|
start: Option<i64>,
|
||||||
end: Option<i64>,
|
end: Option<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
struct ActivityParty {
|
struct ActivityParty {
|
||||||
id: Option<String>,
|
id: Option<String>,
|
||||||
size: Option<Vec<(i32, i32)>>,
|
size: Option<Vec<(i32, i32)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
struct ActivityAssets {
|
struct ActivityAssets {
|
||||||
large_image: Option<String>,
|
large_image: Option<String>,
|
||||||
large_text: Option<String>,
|
large_text: Option<String>,
|
||||||
|
@ -42,7 +42,7 @@ struct ActivityAssets {
|
||||||
small_text: Option<String>,
|
small_text: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
struct ActivitySecrets {
|
struct ActivitySecrets {
|
||||||
join: Option<String>,
|
join: Option<String>,
|
||||||
spectate: Option<String>,
|
spectate: Option<String>,
|
||||||
|
@ -50,7 +50,7 @@ struct ActivitySecrets {
|
||||||
match_string: Option<String>,
|
match_string: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
struct ActivityButton {
|
struct ActivityButton {
|
||||||
label: String,
|
label: String,
|
||||||
url: String,
|
url: String,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
|
||||||
/// See <https://discord.com/developers/docs/topics/gateway-events#client-status-object>
|
/// See <https://discord.com/developers/docs/topics/gateway-events#client-status-object>
|
||||||
pub struct ClientStatusObject {
|
pub struct ClientStatusObject {
|
||||||
pub desktop: Option<String>,
|
pub desktop: Option<String>,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::Snowflake;
|
use crate::types::Snowflake;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
/// A schema used to modify a user.
|
/// A schema used to modify a user.
|
||||||
pub struct UserModifySchema {
|
pub struct UserModifySchema {
|
||||||
|
@ -29,7 +29,7 @@ pub struct UserModifySchema {
|
||||||
///
|
///
|
||||||
/// # Reference:
|
/// # Reference:
|
||||||
/// Read: <https://discord-userdoccers.vercel.app/resources/channel#json-params>
|
/// Read: <https://discord-userdoccers.vercel.app/resources/channel#json-params>
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
pub struct PrivateChannelCreateSchema {
|
pub struct PrivateChannelCreateSchema {
|
||||||
pub recipients: Option<Vec<Snowflake>>,
|
pub recipients: Option<Vec<Snowflake>>,
|
||||||
pub access_tokens: Option<Vec<String>>,
|
pub access_tokens: Option<Vec<String>>,
|
||||||
|
|
Loading…
Reference in New Issue