Update to v7
This commit is contained in:
parent
ca6d629006
commit
6ecbda1550
|
@ -34,8 +34,10 @@ impl WebSocketEvent for VoiceStateUpdate {}
|
|||
/// Received to indicate which voice endpoint, token and guild_id to use;
|
||||
pub struct VoiceServerUpdate {
|
||||
pub token: String,
|
||||
/// Can be None in dm calls
|
||||
/// The guild this voice server update is for
|
||||
pub guild_id: Option<Snowflake>,
|
||||
/// The private channel this voice server update is for
|
||||
pub channel_id: Option<Snowflake>,
|
||||
pub endpoint: Option<String>,
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
use crate::types::{Snowflake, WebSocketEvent};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Copy)]
|
||||
/// Sent when another user connects to the voice server.
|
||||
///
|
||||
/// Contains the user id and "flags".
|
||||
///
|
||||
/// Not documented anywhere, if you know what this is, please reach out
|
||||
///
|
||||
/// {"op":18,"d":{"user_id":"1234567890","flags":2}}
|
||||
pub struct VoiceClientConnectFlags {
|
||||
pub user_id: Snowflake,
|
||||
// Likely some sort of bitflags
|
||||
pub flags: u8,
|
||||
}
|
||||
|
||||
impl WebSocketEvent for VoiceClientConnectFlags {}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Copy)]
|
||||
/// Sent when another user connects to the voice server.
|
||||
///
|
||||
/// Contains the user id and "platform".
|
||||
///
|
||||
/// Not documented anywhere, if you know what this is, please reach out
|
||||
///
|
||||
/// {"op":20,"d":{"user_id":"1234567890","platform":0}}
|
||||
pub struct VoiceClientConnectPlatform {
|
||||
pub user_id: Snowflake,
|
||||
// Likely an enum
|
||||
pub platform: u8,
|
||||
}
|
||||
|
||||
impl WebSocketEvent for VoiceClientConnectPlatform {}
|
|
@ -0,0 +1,14 @@
|
|||
use crate::types::{Snowflake, WebSocketEvent};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Copy)]
|
||||
/// Sent when another user disconnects from the voice server.
|
||||
///
|
||||
/// When received, the SSRC of the user should be discarded.
|
||||
///
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#other-client-disconnection>
|
||||
pub struct VoiceClientDisconnection {
|
||||
pub user_id: Snowflake,
|
||||
}
|
||||
|
||||
impl WebSocketEvent for VoiceClientDisconnection {}
|
|
@ -5,7 +5,14 @@ use serde::{Deserialize, Serialize};
|
|||
/// Contains info on how often the client should send heartbeats to the server;
|
||||
///
|
||||
/// Differs from the normal hello data in that discord sends heartbeat interval as a float.
|
||||
///
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#heartbeating>
|
||||
pub struct VoiceHelloData {
|
||||
/// The voice gateway version.
|
||||
///
|
||||
/// Note: no idea why this is sent, we already specify the version when establishing a connection.
|
||||
#[serde(rename = "v")]
|
||||
pub version: u8,
|
||||
/// How often a client should send heartbeats, in milliseconds
|
||||
pub heartbeat_interval: f64,
|
||||
}
|
||||
|
|
|
@ -6,16 +6,16 @@ use serde::{Deserialize, Serialize};
|
|||
///
|
||||
/// 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>
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#identify-structure>
|
||||
pub struct VoiceIdentify {
|
||||
/// Not needed when in a dm call
|
||||
pub server_id: Option<Snowflake>,
|
||||
/// The ID of the guild or the private channel being connected to
|
||||
pub server_id: Snowflake,
|
||||
pub user_id: Snowflake,
|
||||
pub session_id: String,
|
||||
pub token: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
/// Undocumented field, but is also in discord client comms
|
||||
pub video: Option<bool>,
|
||||
// TODO: Add video streams
|
||||
}
|
||||
|
||||
impl WebSocketEvent for VoiceIdentify {}
|
||||
|
|
|
@ -2,19 +2,25 @@ use super::WebSocketEvent;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{value::RawValue, Value};
|
||||
|
||||
pub use client_connect::*;
|
||||
pub use client_disconnect::*;
|
||||
pub use hello::*;
|
||||
pub use identify::*;
|
||||
pub use ready::*;
|
||||
pub use select_protocol::*;
|
||||
pub use session_description::*;
|
||||
pub use speaking::*;
|
||||
pub use voice_backend_version::*;
|
||||
|
||||
mod client_connect;
|
||||
mod client_disconnect;
|
||||
mod hello;
|
||||
mod identify;
|
||||
mod ready;
|
||||
mod select_protocol;
|
||||
mod session_description;
|
||||
mod speaking;
|
||||
mod voice_backend_version;
|
||||
|
||||
#[derive(Debug, Default, Serialize, Clone)]
|
||||
/// The payload used for sending events to the webrtc gateway.
|
||||
|
@ -48,22 +54,41 @@ pub struct VoiceGatewayReceivePayload<'a> {
|
|||
impl<'a> WebSocketEvent for VoiceGatewayReceivePayload<'a> {}
|
||||
|
||||
/// The modes of encryption available in webrtc connections;
|
||||
/// See <https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-encryption-modes>
|
||||
///
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#encryption-mode> and <https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-encryption-modes>
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum WebrtcEncryptionMode {
|
||||
pub enum VoiceEncryptionMode {
|
||||
#[default]
|
||||
// Documented
|
||||
// Officially Documented
|
||||
Xsalsa20Poly1305,
|
||||
Xsalsa20Poly1305Suffix,
|
||||
Xsalsa20Poly1305Lite,
|
||||
// Undocumented
|
||||
// Officially Undocumented
|
||||
Xsalsa20Poly1305LiteRtpsize,
|
||||
AeadAes256Gcm,
|
||||
AeadAes256GcmRtpsize,
|
||||
AeadXchacha20Poly1305Rtpsize,
|
||||
}
|
||||
|
||||
/// The possible audio codecs to use
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AudioCodec {
|
||||
#[default]
|
||||
Opus,
|
||||
}
|
||||
|
||||
/// The possible video codecs to use
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
pub enum VideoCodec {
|
||||
#[default]
|
||||
VP8,
|
||||
VP9,
|
||||
H264,
|
||||
}
|
||||
|
||||
// The various voice opcodes
|
||||
pub const VOICE_IDENTIFY: u8 = 0;
|
||||
pub const VOICE_SELECT_PROTOCOL: u8 = 1;
|
||||
|
@ -77,7 +102,12 @@ pub const VOICE_HELLO: u8 = 8;
|
|||
pub const VOICE_RESUMED: u8 = 9;
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/opcodes-and-status-codes#voice-opcodes>
|
||||
pub const VOICE_VIDEO: u8 = 12;
|
||||
pub const VOICE_CLIENT_DISCONENCT: u8 = 13;
|
||||
pub const VOICE_CLIENT_DISCONNECT: u8 = 13;
|
||||
pub const VOICE_SESSION_UPDATE: u8 = 14;
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/opcodes-and-status-codes#voice-opcodes>
|
||||
/// Sent with empty data from the client, the server responds with the voice backend version;
|
||||
pub const VOICE_BACKEND_VERSION: u8 = 16;
|
||||
|
||||
// These two get simultaenously fired when a user joins, one has flags and one has a platform
|
||||
pub const VOICE_CLIENT_CONNECT_FLAGS: u8 = 18;
|
||||
pub const VOICE_CLIENT_CONNECT_PLATFORM: u8 = 20;
|
||||
|
|
|
@ -3,21 +3,24 @@ use std::net::Ipv4Addr;
|
|||
use crate::types::WebSocketEvent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::WebrtcEncryptionMode;
|
||||
use super::VoiceEncryptionMode;
|
||||
|
||||
#[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>
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#ready-structure>
|
||||
pub struct VoiceReady {
|
||||
/// See <https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpStreamStats/ssrc>
|
||||
pub ssrc: i32,
|
||||
pub ip: Ipv4Addr,
|
||||
pub port: u32,
|
||||
/// The available encryption modes for the webrtc connection
|
||||
pub modes: Vec<WebrtcEncryptionMode>,
|
||||
pub modes: Vec<VoiceEncryptionMode>,
|
||||
#[serde(default)]
|
||||
pub experiments: Vec<String>,
|
||||
// TODO: Add video streams
|
||||
// Heartbeat interval is also sent, but is "an erroneous field and should be ignored. The correct heartbeat_interval value comes from the Hello payload."
|
||||
}
|
||||
|
||||
|
@ -28,6 +31,7 @@ impl Default for VoiceReady {
|
|||
ip: Ipv4Addr::UNSPECIFIED,
|
||||
port: 0,
|
||||
modes: Vec::new(),
|
||||
experiments: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,58 @@ use std::net::Ipv4Addr;
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::WebrtcEncryptionMode;
|
||||
use super::VoiceEncryptionMode;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
||||
/// An event sent by the client to the webrtc server, detailing what protocol, address and encryption to use;
|
||||
///
|
||||
/// See <https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-select-protocol-payload>
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#select-protocol-structure>
|
||||
pub struct SelectProtocol {
|
||||
/// The protocol to use. The only option detailed in discord docs is "udp"
|
||||
pub protocol: String,
|
||||
/// The protocol to use. The only option chorus supports is [VoiceProtocol::Udp].
|
||||
pub protocol: VoiceProtocol,
|
||||
pub data: SelectProtocolData,
|
||||
/// The UUID4 RTC connection ID, used for analytics.
|
||||
///
|
||||
/// Note: Not recommended to set this
|
||||
pub rtc_connection_id: Option<String>,
|
||||
// TODO: Add codecs, what is a codec object
|
||||
/// The possible experiments we want to enable
|
||||
#[serde(rename = "experiments")]
|
||||
pub enabled_experiments: Vec<String>,
|
||||
}
|
||||
|
||||
/// The possible protocol for sending a receiving voice data.
|
||||
///
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#select-protocol-structure>
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum VoiceProtocol {
|
||||
#[default]
|
||||
/// Sending data via UDP, documented and the only protocol chorus supports.
|
||||
Udp,
|
||||
// Possible value, yet NOT RECOMMENED, AS CHORUS DOES NOT SUPPORT WEBRTC
|
||||
//Webrtc,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
/// The data field of the SelectProtocol Event
|
||||
///
|
||||
/// See <https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-select-protocol-payload>
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#protocol-data-structure>
|
||||
pub struct SelectProtocolData {
|
||||
/// Our external ip
|
||||
pub address: Ipv4Addr,
|
||||
/// Our external udp port
|
||||
pub port: u32,
|
||||
/// The mode of encryption to use
|
||||
pub mode: WebrtcEncryptionMode,
|
||||
pub mode: VoiceEncryptionMode,
|
||||
}
|
||||
|
||||
impl Default for SelectProtocolData {
|
||||
fn default() -> Self {
|
||||
SelectProtocolData {
|
||||
address: Ipv4Addr::UNSPECIFIED,
|
||||
port: 0,
|
||||
mode: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,39 @@
|
|||
use super::WebrtcEncryptionMode;
|
||||
use super::{AudioCodec, VideoCodec, VoiceEncryptionMode};
|
||||
use crate::types::WebSocketEvent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
||||
/// Event that describes our encryption mode and secret key for encryption
|
||||
///
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#session-description-structure>
|
||||
pub struct SessionDescription {
|
||||
/// The encryption mode we're using in webrtc
|
||||
pub mode: WebrtcEncryptionMode,
|
||||
pub audio_codec: AudioCodec,
|
||||
pub video_codec: VideoCodec,
|
||||
pub media_session_id: String,
|
||||
/// The encryption mode to use
|
||||
#[serde(rename = "mode")]
|
||||
pub encryption_mode: VoiceEncryptionMode,
|
||||
/// The secret key we'll use for encryption
|
||||
pub secret_key: [u8; 32],
|
||||
/// The keyframe interval in milliseconds
|
||||
pub keyframe_interval: Option<u64>,
|
||||
}
|
||||
|
||||
impl WebSocketEvent for SessionDescription {}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
||||
/// Event that might be sent to update session parameters
|
||||
///
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#session-update-structure>
|
||||
pub struct SessionUpdate {
|
||||
#[serde(rename = "audio_codec")]
|
||||
pub new_audio_codec: Option<AudioCodec>,
|
||||
|
||||
#[serde(rename = "video_codec")]
|
||||
pub new_video_codec: Option<VideoCodec>,
|
||||
|
||||
#[serde(rename = "media_session_id")]
|
||||
pub new_media_session_id: Option<String>,
|
||||
}
|
||||
|
||||
impl WebSocketEvent for SessionUpdate {}
|
||||
|
|
|
@ -1,20 +1,28 @@
|
|||
use bitflags::bitflags;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Snowflake, WebSocketEvent};
|
||||
|
||||
/// Event that tells the server we are speaking;
|
||||
///
|
||||
/// Essentially, what allows us to send udp data and lights up the green circle around your avatar.
|
||||
///
|
||||
/// See <https://discord.com/developers/docs/topics/voice-connections#speaking-example-speaking-payload>
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#speaking-structure>
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
||||
pub struct Speaking {
|
||||
/// Data about the audio we're transmitting, its type
|
||||
pub speaking: SpeakingBitflags,
|
||||
/// Assuming delay in milliseconds for the audio, should be 0 most of the time
|
||||
pub delay: u64,
|
||||
pub ssrc: i32,
|
||||
/// The user id of the speaking user, only sent by the server
|
||||
#[serde(skip_serializing)]
|
||||
pub user_id: Option<Snowflake>,
|
||||
/// Delay in milliseconds, not sent by the server
|
||||
#[serde(default)]
|
||||
pub delay: u64,
|
||||
}
|
||||
|
||||
impl WebSocketEvent for Speaking {}
|
||||
|
||||
bitflags! {
|
||||
/// Bitflags of speaking types;
|
||||
///
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
use crate::types::WebSocketEvent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq)]
|
||||
/// Received from the server to describe the backend version.
|
||||
///
|
||||
/// See <https://discord-userdoccers.vercel.app/topics/voice-connections#voice-backend-version>
|
||||
pub struct VoiceBackendVersion {
|
||||
/// The voice backend's version
|
||||
#[serde(rename = "voice")]
|
||||
pub voice_version: String,
|
||||
/// The WebRTC worker's version
|
||||
#[serde(rename = "rtc_worker")]
|
||||
pub rtc_worker_version: String,
|
||||
}
|
||||
|
||||
impl WebSocketEvent for VoiceBackendVersion {}
|
96
src/voice.rs
96
src/voice.rs
|
@ -19,9 +19,10 @@ use crate::errors::VoiceGatewayError;
|
|||
use crate::gateway::{GatewayEvent, HEARTBEAT_ACK_TIMEOUT};
|
||||
use crate::types::{
|
||||
self, SelectProtocol, Speaking, VoiceGatewayReceivePayload, VoiceGatewaySendPayload,
|
||||
VoiceIdentify, WebSocketEvent, VOICE_BACKEND_VERSION, VOICE_HEARTBEAT, VOICE_HEARTBEAT_ACK,
|
||||
VoiceIdentify, WebSocketEvent, VOICE_BACKEND_VERSION, VOICE_CLIENT_CONNECT_FLAGS,
|
||||
VOICE_CLIENT_CONNECT_PLATFORM, VOICE_CLIENT_DISCONNECT, VOICE_HEARTBEAT, VOICE_HEARTBEAT_ACK,
|
||||
VOICE_HELLO, VOICE_IDENTIFY, VOICE_READY, VOICE_RESUME, VOICE_SELECT_PROTOCOL,
|
||||
VOICE_SESSION_DESCRIPTION, VOICE_SPEAKING,
|
||||
VOICE_SESSION_DESCRIPTION, VOICE_SESSION_UPDATE, VOICE_SPEAKING,
|
||||
};
|
||||
|
||||
use self::voice_events::VoiceEvents;
|
||||
|
@ -199,7 +200,7 @@ impl VoiceGateway {
|
|||
#[allow(clippy::new_ret_no_self)]
|
||||
pub async fn new(websocket_url: String) -> Result<VoiceGatewayHandle, VoiceGatewayError> {
|
||||
// Append the needed things to the websocket url
|
||||
let processed_url = format!("wss://{}/?v=4", websocket_url);
|
||||
let processed_url = format!("wss://{}/?v=7", websocket_url);
|
||||
trace!("Created voice socket url: {}", processed_url.clone());
|
||||
|
||||
let (websocket_stream, _) = match connect_async_tls_with_config(
|
||||
|
@ -357,6 +358,19 @@ impl VoiceGateway {
|
|||
return;
|
||||
}
|
||||
}
|
||||
VOICE_BACKEND_VERSION => {
|
||||
trace!("VGW: Received Backend Version");
|
||||
|
||||
let event = &mut self.events.lock().await.backend_version;
|
||||
let result = VoiceGateway::handle_event(gateway_payload.data.get(), event).await;
|
||||
if result.is_err() {
|
||||
warn!(
|
||||
"Failed to parse VOICE_BACKEND_VERSION ({})",
|
||||
result.err().unwrap()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
VOICE_SESSION_DESCRIPTION => {
|
||||
trace!("VGW: Received Session Description");
|
||||
|
||||
|
@ -364,12 +378,75 @@ impl VoiceGateway {
|
|||
let result = VoiceGateway::handle_event(gateway_payload.data.get(), event).await;
|
||||
if result.is_err() {
|
||||
warn!(
|
||||
"Failed to parse VOICE_SELECT_PROTOCOL ({})",
|
||||
"Failed to parse VOICE_SESSION_DESCRIPTION ({})",
|
||||
result.err().unwrap()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
VOICE_SESSION_UPDATE => {
|
||||
trace!("VGW: Received Session Update");
|
||||
|
||||
let event = &mut self.events.lock().await.session_update;
|
||||
let result = VoiceGateway::handle_event(gateway_payload.data.get(), event).await;
|
||||
if result.is_err() {
|
||||
warn!(
|
||||
"Failed to parse VOICE_SESSION_UPDATE ({})",
|
||||
result.err().unwrap()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
VOICE_SPEAKING => {
|
||||
trace!("VGW: Received Speaking");
|
||||
|
||||
let event = &mut self.events.lock().await.speaking;
|
||||
let result = VoiceGateway::handle_event(gateway_payload.data.get(), event).await;
|
||||
if result.is_err() {
|
||||
warn!("Failed to parse VOICE_SPEAKING ({})", result.err().unwrap());
|
||||
return;
|
||||
}
|
||||
}
|
||||
VOICE_CLIENT_DISCONNECT => {
|
||||
trace!("VGW: Received Client Disconnect");
|
||||
|
||||
let event = &mut self.events.lock().await.client_disconnect;
|
||||
let result = VoiceGateway::handle_event(gateway_payload.data.get(), event).await;
|
||||
if result.is_err() {
|
||||
warn!(
|
||||
"Failed to parse VOICE_CLIENT_DISCONNECT ({})",
|
||||
result.err().unwrap()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
VOICE_CLIENT_CONNECT_FLAGS => {
|
||||
trace!("VGW: Received Client Connect Flags");
|
||||
|
||||
let event = &mut self.events.lock().await.client_connect_flags;
|
||||
let result = VoiceGateway::handle_event(gateway_payload.data.get(), event).await;
|
||||
if result.is_err() {
|
||||
warn!(
|
||||
"Failed to parse VOICE_CLIENT_CONNECT_FLAGS ({})",
|
||||
result.err().unwrap()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
VOICE_CLIENT_CONNECT_PLATFORM => {
|
||||
trace!("VGW: Received Client Connect Platform");
|
||||
|
||||
let event = &mut self.events.lock().await.client_connect_platform;
|
||||
let result = VoiceGateway::handle_event(gateway_payload.data.get(), event).await;
|
||||
if result.is_err() {
|
||||
warn!(
|
||||
"Failed to parse VOICE_CLIENT_CONNECT_PLATFORM ({})",
|
||||
result.err().unwrap()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We received a heartbeat from the server
|
||||
// "Discord may send the app a Heartbeat (opcode 1) event, in which case the app should send a Heartbeat event immediately."
|
||||
VOICE_HEARTBEAT => {
|
||||
|
@ -563,14 +640,23 @@ struct VoiceHeartbeatThreadCommunication {
|
|||
}
|
||||
|
||||
pub mod voice_events {
|
||||
use crate::types::{SessionDescription, VoiceReady};
|
||||
use crate::types::{
|
||||
SessionDescription, SessionUpdate, VoiceBackendVersion, VoiceClientConnectFlags,
|
||||
VoiceClientConnectPlatform, VoiceClientDisconnection, VoiceReady,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct VoiceEvents {
|
||||
pub voice_ready: GatewayEvent<VoiceReady>,
|
||||
pub backend_version: GatewayEvent<VoiceBackendVersion>,
|
||||
pub session_description: GatewayEvent<SessionDescription>,
|
||||
pub session_update: GatewayEvent<SessionUpdate>,
|
||||
pub speaking: GatewayEvent<Speaking>,
|
||||
pub client_disconnect: GatewayEvent<VoiceClientDisconnection>,
|
||||
pub client_connect_flags: GatewayEvent<VoiceClientConnectFlags>,
|
||||
pub client_connect_platform: GatewayEvent<VoiceClientConnectPlatform>,
|
||||
pub error: GatewayEvent<VoiceGatewayError>,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue