2023-06-08 17:34:52 +02:00
use crate ::errors ::GatewayError ;
2023-04-28 18:18:32 +02:00
use crate ::errors ::ObserverError ;
use crate ::gateway ::events ::Events ;
2023-05-26 12:59:32 +02:00
use crate ::types ;
2023-06-10 12:43:07 +02:00
use crate ::types ::WebSocketEvent ;
2023-06-11 13:52:31 +02:00
use std ::sync ::Arc ;
2023-05-25 23:09:18 +02:00
use futures_util ::stream ::SplitSink ;
2023-06-08 18:24:11 +02:00
use futures_util ::stream ::SplitStream ;
2023-04-30 14:45:15 +02:00
use futures_util ::SinkExt ;
2023-04-28 23:21:55 +02:00
use futures_util ::StreamExt ;
2023-04-30 11:56:14 +02:00
use native_tls ::TlsConnector ;
2023-04-28 18:18:32 +02:00
use tokio ::net ::TcpStream ;
2023-05-07 11:58:12 +02:00
use tokio ::sync ::mpsc ::error ::TryRecvError ;
2023-05-13 16:35:42 +02:00
use tokio ::sync ::mpsc ::Sender ;
2023-04-30 11:56:14 +02:00
use tokio ::sync ::Mutex ;
2023-04-30 14:45:15 +02:00
use tokio ::task ;
2023-05-28 14:52:48 +02:00
use tokio ::task ::JoinHandle ;
2023-05-05 18:38:04 +02:00
use tokio ::time ;
use tokio ::time ::Instant ;
2023-05-07 11:58:12 +02:00
use tokio_tungstenite ::MaybeTlsStream ;
2023-05-25 23:09:18 +02:00
use tokio_tungstenite ::{ connect_async_tls_with_config , Connector , WebSocketStream } ;
2023-05-03 21:06:01 +02:00
2023-05-28 14:39:41 +02:00
// Gateway opcodes
/// Opcode received when the server dispatches a [crate::types::WebSocketEvent]
const GATEWAY_DISPATCH : u8 = 0 ;
/// Opcode sent when sending a heartbeat
const GATEWAY_HEARTBEAT : u8 = 1 ;
/// Opcode sent to initiate a session
2023-05-28 14:52:48 +02:00
///
2023-05-28 14:39:41 +02:00
/// See [types::GatewayIdentifyPayload]
const GATEWAY_IDENTIFY : u8 = 2 ;
/// Opcode sent to update our presence
2023-05-28 14:52:48 +02:00
///
2023-05-28 14:39:41 +02:00
/// See [types::GatewayUpdatePresence]
const GATEWAY_UPDATE_PRESENCE : u8 = 3 ;
/// Opcode sent to update our state in vc
2023-05-28 14:52:48 +02:00
///
2023-05-28 14:39:41 +02:00
/// Like muting, deafening, leaving, joining..
2023-05-28 14:52:48 +02:00
///
2023-05-28 14:39:41 +02:00
/// See [types::UpdateVoiceState]
const GATEWAY_UPDATE_VOICE_STATE : u8 = 4 ;
/// Opcode sent to resume a session
2023-05-28 14:52:48 +02:00
///
2023-05-28 14:39:41 +02:00
/// See [types::GatewayResume]
const GATEWAY_RESUME : u8 = 6 ;
/// Opcode received to tell the client to reconnect
const GATEWAY_RECONNECT : u8 = 7 ;
/// Opcode sent to request guild member data
2023-05-28 14:52:48 +02:00
///
2023-05-28 14:39:41 +02:00
/// See [types::GatewayRequestGuildMembers]
const GATEWAY_REQUEST_GUILD_MEMBERS : u8 = 8 ;
/// Opcode received to tell the client their token / session is invalid
const GATEWAY_INVALID_SESSION : u8 = 9 ;
/// Opcode received when initially connecting to the gateway, starts our heartbeat
2023-05-28 14:52:48 +02:00
///
2023-05-28 14:39:41 +02:00
/// See [types::HelloData]
const GATEWAY_HELLO : u8 = 10 ;
/// Opcode received to acknowledge a heartbeat
const GATEWAY_HEARTBEAT_ACK : u8 = 11 ;
/// Opcode sent to get the voice state of users in a given DM/group channel
2023-05-28 14:52:48 +02:00
///
2023-05-28 14:39:41 +02:00
/// See [types::CallSync]
const GATEWAY_CALL_SYNC : u8 = 13 ;
/// Opcode sent to get data for a server (Lazy Loading request)
2023-05-28 14:52:48 +02:00
///
2023-05-28 14:39:41 +02:00
/// Sent by the official client when switching to a server
2023-05-28 14:52:48 +02:00
///
2023-05-28 14:39:41 +02:00
/// See [types::LazyRequest]
const GATEWAY_LAZY_REQUEST : u8 = 14 ;
2023-06-02 10:57:47 +02:00
/// The amount of time we wait for a heartbeat ack before resending our heartbeat in ms
const HEARTBEAT_ACK_TIMEOUT : u128 = 2000 ;
2023-06-08 17:34:52 +02:00
#[ derive(Clone, Debug) ]
/**
Represents a messsage received from the gateway . This will be either a [ GatewayReceivePayload ] , containing events , or a [ GatewayError ] .
This struct is used internally when handling messages .
* /
pub struct GatewayMessage {
/// The message we received from the server
message : tokio_tungstenite ::tungstenite ::Message ,
}
impl GatewayMessage {
/// Creates self from a tungstenite message
pub fn from_tungstenite_message ( message : tokio_tungstenite ::tungstenite ::Message ) -> Self {
Self { message }
}
/// Parses the message as an error;
/// Returns the error if succesfully parsed, None if the message isn't an error
pub fn error ( & self ) -> Option < GatewayError > {
let content = self . message . to_string ( ) ;
// Some error strings have dots on the end, which we don't care about
let processed_content = content . clone ( ) . to_lowercase ( ) . replace ( " . " , " " ) ;
match processed_content . as_str ( ) {
" unknown error " | " 4000 " = > {
return Some ( GatewayError ::UnknownError ) ;
}
" unknown opcode " | " 4001 " = > {
return Some ( GatewayError ::UnknownOpcodeError ) ;
}
2023-06-09 20:22:59 +02:00
" decode error " | " error while decoding payload " | " 4002 " = > {
2023-06-08 17:34:52 +02:00
return Some ( GatewayError ::DecodeError ) ;
}
" not authenticated " | " 4003 " = > {
return Some ( GatewayError ::NotAuthenticatedError ) ;
}
" authentication failed " | " 4004 " = > {
return Some ( GatewayError ::AuthenticationFailedError ) ;
}
" already authenticated " | " 4005 " = > {
return Some ( GatewayError ::AlreadyAuthenticatedError ) ;
}
" invalid seq " | " 4007 " = > {
return Some ( GatewayError ::InvalidSequenceNumberError ) ;
}
" rate limited " | " 4008 " = > {
return Some ( GatewayError ::RateLimitedError ) ;
}
" session timed out " | " 4009 " = > {
return Some ( GatewayError ::SessionTimedOutError ) ;
}
" invalid shard " | " 4010 " = > {
return Some ( GatewayError ::InvalidShardError ) ;
}
" sharding required " | " 4011 " = > {
return Some ( GatewayError ::ShardingRequiredError ) ;
}
" invalid api version " | " 4012 " = > {
return Some ( GatewayError ::InvalidAPIVersionError ) ;
}
" invalid intent(s) " | " invalid intent " | " 4013 " = > {
return Some ( GatewayError ::InvalidIntentsError ) ;
}
" disallowed intent(s) " | " disallowed intents " | " 4014 " = > {
return Some ( GatewayError ::DisallowedIntentsError ) ;
}
_ = > {
return None ;
}
}
}
/// Returns whether or not the message is an error
pub fn is_error ( & self ) -> bool {
return self . error ( ) . is_some ( ) ;
}
/// Parses the message as a payload;
/// Returns a result of deserializing
pub fn payload ( & self ) -> Result < types ::GatewayReceivePayload , serde_json ::Error > {
return serde_json ::from_str ( self . message . to_text ( ) . unwrap ( ) ) ;
}
/// Returns whether or not the message is a payload
pub fn is_payload ( & self ) -> bool {
// close messages are never payloads, payloads are only text messages
if self . message . is_close ( ) | ! self . message . is_text ( ) {
return false ;
}
return self . payload ( ) . is_ok ( ) ;
}
/// Returns whether or not the message is empty
pub fn is_empty ( & self ) -> bool {
return self . message . is_empty ( ) ;
}
}
2023-05-11 22:47:31 +02:00
#[ derive(Debug) ]
2023-04-28 13:40:29 +02:00
/**
2023-05-11 22:47:31 +02:00
Represents a handle to a Gateway connection . A Gateway connection will create observable
2023-04-28 18:18:32 +02:00
[ ` GatewayEvents ` ] ( GatewayEvent ) , which you can subscribe to . Gateway events include all currently
implemented [ Types ] with the trait [ ` WebSocketEvent ` ]
2023-05-11 22:47:31 +02:00
Using this handle you can also send Gateway Events directly .
2023-06-11 13:52:31 +02:00
* /
2023-05-11 22:47:31 +02:00
pub struct GatewayHandle {
2023-04-28 18:18:32 +02:00
pub url : String ,
2023-05-11 22:47:31 +02:00
pub events : Arc < Mutex < Events > > ,
2023-05-28 14:39:41 +02:00
pub websocket_send : Arc <
2023-05-25 23:09:18 +02:00
Mutex <
SplitSink <
WebSocketStream < MaybeTlsStream < TcpStream > > ,
tokio_tungstenite ::tungstenite ::Message ,
> ,
> ,
> ,
2023-05-28 14:52:48 +02:00
pub handle : JoinHandle < ( ) > ,
2023-06-08 17:34:52 +02:00
/// Tells gateway tasks to close
kill_send : tokio ::sync ::broadcast ::Sender < ( ) > ,
2023-04-28 18:18:32 +02:00
}
2023-05-11 22:47:31 +02:00
impl GatewayHandle {
2023-05-05 19:23:57 +02:00
/// Sends json to the gateway with an opcode
2023-05-28 14:39:41 +02:00
async fn send_json_event ( & self , op_code : u8 , to_send : serde_json ::Value ) {
2023-05-26 19:36:41 +02:00
let gateway_payload = types ::GatewaySendPayload {
2023-05-28 14:39:41 +02:00
op_code ,
2023-05-28 14:52:08 +02:00
event_data : Some ( to_send ) ,
sequence_number : None ,
2023-05-25 23:09:18 +02:00
} ;
2023-05-05 19:23:57 +02:00
let payload_json = serde_json ::to_string ( & gateway_payload ) . unwrap ( ) ;
let message = tokio_tungstenite ::tungstenite ::Message ::text ( payload_json ) ;
2023-05-28 14:52:48 +02:00
self . websocket_send
. lock ( )
. await
. send ( message )
. await
. unwrap ( ) ;
2023-05-05 19:23:57 +02:00
}
/// Sends an identify event to the gateway
2023-05-26 12:59:32 +02:00
pub async fn send_identify ( & self , to_send : types ::GatewayIdentifyPayload ) {
2023-05-17 17:24:29 +02:00
let to_send_value = serde_json ::to_value ( & to_send ) . unwrap ( ) ;
2023-05-05 19:23:57 +02:00
2023-05-07 12:44:11 +02:00
println! ( " GW: Sending Identify.. " ) ;
2023-05-28 14:39:41 +02:00
self . send_json_event ( GATEWAY_IDENTIFY , to_send_value ) . await ;
2023-05-05 19:23:57 +02:00
}
/// Sends a resume event to the gateway
2023-05-26 12:59:32 +02:00
pub async fn send_resume ( & self , to_send : types ::GatewayResume ) {
2023-05-17 17:24:29 +02:00
let to_send_value = serde_json ::to_value ( & to_send ) . unwrap ( ) ;
2023-05-05 19:23:57 +02:00
2023-05-07 12:44:11 +02:00
println! ( " GW: Sending Resume.. " ) ;
2023-05-28 14:39:41 +02:00
self . send_json_event ( GATEWAY_RESUME , to_send_value ) . await ;
2023-05-05 19:23:57 +02:00
}
/// Sends an update presence event to the gateway
2023-06-10 16:32:42 +02:00
pub async fn send_update_presence ( & self , to_send : types ::UpdatePresence ) {
2023-05-17 17:24:29 +02:00
let to_send_value = serde_json ::to_value ( & to_send ) . unwrap ( ) ;
2023-05-05 19:23:57 +02:00
2023-06-10 16:32:42 +02:00
println! ( " GW: Sending Update Presence.. " ) ;
2023-05-13 15:59:46 +02:00
2023-05-28 14:52:48 +02:00
self . send_json_event ( GATEWAY_UPDATE_PRESENCE , to_send_value )
. await ;
2023-04-30 14:45:15 +02:00
}
2023-05-13 15:59:46 +02:00
2023-05-22 18:42:12 +02:00
/// Sends a request guild members to the server
2023-05-26 12:59:32 +02:00
pub async fn send_request_guild_members ( & self , to_send : types ::GatewayRequestGuildMembers ) {
2023-05-17 17:24:29 +02:00
let to_send_value = serde_json ::to_value ( & to_send ) . unwrap ( ) ;
2023-05-13 15:59:46 +02:00
println! ( " GW: Sending Request Guild Members.. " ) ;
2023-05-28 14:52:48 +02:00
self . send_json_event ( GATEWAY_REQUEST_GUILD_MEMBERS , to_send_value )
. await ;
2023-05-13 15:59:46 +02:00
}
2023-05-22 18:42:12 +02:00
/// Sends an update voice state to the server
2023-05-26 19:47:41 +02:00
pub async fn send_update_voice_state ( & self , to_send : types ::UpdateVoiceState ) {
2023-05-17 17:24:29 +02:00
let to_send_value = serde_json ::to_value ( & to_send ) . unwrap ( ) ;
2023-05-13 15:59:46 +02:00
2023-05-22 18:42:12 +02:00
println! ( " GW: Sending Update Voice State.. " ) ;
2023-05-13 15:59:46 +02:00
2023-05-28 14:52:48 +02:00
self . send_json_event ( GATEWAY_UPDATE_VOICE_STATE , to_send_value )
. await ;
2023-05-13 15:59:46 +02:00
}
2023-05-14 11:43:17 +02:00
2023-05-22 18:42:12 +02:00
/// Sends a call sync to the server
2023-05-26 19:36:41 +02:00
pub async fn send_call_sync ( & self , to_send : types ::CallSync ) {
2023-05-17 17:24:29 +02:00
let to_send_value = serde_json ::to_value ( & to_send ) . unwrap ( ) ;
2023-05-14 11:43:17 +02:00
println! ( " GW: Sending Call Sync.. " ) ;
2023-05-28 14:39:41 +02:00
self . send_json_event ( GATEWAY_CALL_SYNC , to_send_value ) . await ;
2023-05-14 11:43:17 +02:00
}
/// Sends a Lazy Request
2023-05-26 19:36:41 +02:00
pub async fn send_lazy_request ( & self , to_send : types ::LazyRequest ) {
2023-05-17 17:24:29 +02:00
let to_send_value = serde_json ::to_value ( & to_send ) . unwrap ( ) ;
2023-05-14 11:43:17 +02:00
println! ( " GW: Sending Lazy Request.. " ) ;
2023-05-28 14:52:48 +02:00
self . send_json_event ( GATEWAY_LAZY_REQUEST , to_send_value )
. await ;
2023-05-14 11:43:17 +02:00
}
2023-06-08 17:34:52 +02:00
2023-06-09 20:22:59 +02:00
/// Closes the websocket connection and stops all gateway tasks;
///
/// Esentially pulls the plug on the gateway, leaving it possible to resume;
pub async fn close ( & self ) {
2023-06-08 17:34:52 +02:00
self . kill_send . send ( ( ) ) . unwrap ( ) ;
self . websocket_send . lock ( ) . await . close ( ) . await . unwrap ( ) ;
}
2023-04-30 14:45:15 +02:00
}
2023-05-11 22:47:31 +02:00
pub struct Gateway {
pub events : Arc < Mutex < Events > > ,
2023-06-08 18:24:11 +02:00
heartbeat_handler : HeartbeatHandler ,
2023-05-28 14:39:41 +02:00
pub websocket_send : Arc <
2023-05-25 23:09:18 +02:00
Mutex <
SplitSink <
WebSocketStream < MaybeTlsStream < TcpStream > > ,
tokio_tungstenite ::tungstenite ::Message ,
> ,
> ,
> ,
2023-06-08 18:24:11 +02:00
pub websocket_receive : SplitStream < WebSocketStream < MaybeTlsStream < TcpStream > > > ,
2023-06-08 17:34:52 +02:00
kill_send : tokio ::sync ::broadcast ::Sender < ( ) > ,
2023-05-11 22:47:31 +02:00
}
2023-05-13 16:43:29 +02:00
impl Gateway {
2023-06-08 17:34:52 +02:00
pub async fn new ( websocket_url : String ) -> Result < GatewayHandle , GatewayError > {
2023-05-28 14:39:41 +02:00
let ( websocket_stream , _ ) = match connect_async_tls_with_config (
2023-05-11 22:47:31 +02:00
& websocket_url ,
None ,
2023-05-20 08:39:02 +02:00
false ,
2023-05-11 22:47:31 +02:00
Some ( Connector ::NativeTls (
TlsConnector ::builder ( ) . build ( ) . unwrap ( ) ,
) ) ,
)
. await
{
2023-05-28 14:39:41 +02:00
Ok ( websocket_stream ) = > websocket_stream ,
2023-06-08 17:34:52 +02:00
Err ( e ) = > {
return Err ( GatewayError ::CannotConnectError {
error : e . to_string ( ) ,
} )
}
2023-05-11 22:47:31 +02:00
} ;
2023-06-08 17:34:52 +02:00
let ( websocket_send , mut websocket_receive ) = websocket_stream . split ( ) ;
let shared_websocket_send = Arc ::new ( Mutex ::new ( websocket_send ) ) ;
2023-05-11 22:47:31 +02:00
2023-06-08 17:34:52 +02:00
// Create a shared broadcast channel for killing all gateway tasks
2023-06-08 18:24:11 +02:00
let ( kill_send , mut _kill_receive ) = tokio ::sync ::broadcast ::channel ::< ( ) > ( 16 ) ;
2023-05-11 22:47:31 +02:00
2023-05-13 09:47:12 +02:00
// Wait for the first hello and then spawn both tasks so we avoid nested tasks
// This automatically spawns the heartbeat task, but from the main thread
2023-06-08 17:34:52 +02:00
let msg = websocket_receive . next ( ) . await . unwrap ( ) . unwrap ( ) ;
2023-05-28 00:50:52 +02:00
let gateway_payload : types ::GatewayReceivePayload =
serde_json ::from_str ( msg . to_text ( ) . unwrap ( ) ) . unwrap ( ) ;
2023-05-13 09:47:12 +02:00
2023-05-28 14:39:41 +02:00
if gateway_payload . op_code ! = GATEWAY_HELLO {
2023-06-08 17:34:52 +02:00
return Err ( GatewayError ::NonHelloOnInitiateError {
opcode : gateway_payload . op_code ,
} ) ;
2023-05-13 09:47:12 +02:00
}
println! ( " GW: Received Hello " ) ;
2023-05-28 00:50:52 +02:00
let gateway_hello : types ::HelloData =
2023-05-28 14:52:08 +02:00
serde_json ::from_str ( gateway_payload . event_data . unwrap ( ) . get ( ) ) . unwrap ( ) ;
2023-05-13 09:47:12 +02:00
2023-06-10 15:37:02 +02:00
let events = Events ::default ( ) ;
let shared_events = Arc ::new ( Mutex ::new ( events ) ) ;
2023-06-08 18:24:11 +02:00
let mut gateway = Gateway {
2023-06-10 15:37:02 +02:00
events : shared_events . clone ( ) ,
2023-06-08 18:24:11 +02:00
heartbeat_handler : HeartbeatHandler ::new (
gateway_hello . heartbeat_interval ,
shared_websocket_send . clone ( ) ,
kill_send . subscribe ( ) ,
) ,
websocket_send : shared_websocket_send . clone ( ) ,
websocket_receive ,
kill_send : kill_send . clone ( ) ,
} ;
2023-06-08 17:34:52 +02:00
2023-06-08 18:24:11 +02:00
// 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 {
gateway . gateway_listen_task ( ) . await ;
2023-05-11 22:47:31 +02:00
} ) ;
return Ok ( GatewayHandle {
url : websocket_url . clone ( ) ,
events : shared_events ,
2023-06-08 17:34:52 +02:00
websocket_send : shared_websocket_send . clone ( ) ,
2023-05-28 14:39:41 +02:00
handle ,
2023-06-08 17:34:52 +02:00
kill_send : kill_send . clone ( ) ,
2023-05-11 22:47:31 +02:00
} ) ;
}
2023-06-08 18:24:11 +02:00
/// The main gateway listener task;
///
/// Can only be stopped by closing the websocket, cannot be made to listen for kill
pub async fn gateway_listen_task ( & mut self ) {
loop {
let msg = self . websocket_receive . next ( ) . await ;
// This if chain can be much better but if let is unstable on stable rust
if msg . as_ref ( ) . is_some ( ) {
if msg . as_ref ( ) . unwrap ( ) . is_ok ( ) {
let msg_unwrapped = msg . unwrap ( ) . unwrap ( ) ;
2023-06-10 12:43:07 +02:00
self . handle_message ( GatewayMessage ::from_tungstenite_message ( msg_unwrapped ) )
2023-06-08 18:24:11 +02:00
. await ;
continue ;
}
}
// We couldn't receive the next message or it was an error, something is wrong with the websocket, close
println! ( " GW: Websocket is broken, stopping gateway " ) ;
break ;
}
}
2023-06-08 17:34:52 +02:00
/// Closes the websocket connection and stops all tasks
async fn close ( & mut self ) {
self . kill_send . send ( ( ) ) . unwrap ( ) ;
self . websocket_send . lock ( ) . await . close ( ) . await . unwrap ( ) ;
}
2023-06-10 12:43:07 +02:00
/// Deserializes and updates a dispatched event, when we already know its type;
/// (Called for every event in handle_message)
async fn handle_event < ' a , T : WebSocketEvent + serde ::Deserialize < ' a > > (
data : & ' a str ,
event : & mut GatewayEvent < T > ,
) -> Result < ( ) , serde_json ::Error > {
let data_deserialize_result : Result < T , serde_json ::Error > = serde_json ::from_str ( data ) ;
if data_deserialize_result . is_err ( ) {
return Err ( data_deserialize_result . err ( ) . unwrap ( ) ) ;
}
event . update_data ( data_deserialize_result . unwrap ( ) ) . await ;
return Ok ( ( ) ) ;
}
2023-05-11 22:47:31 +02:00
/// This handles a message as a websocket event and updates its events along with the events' observers
2023-06-10 12:43:07 +02:00
pub async fn handle_message ( & mut self , msg : GatewayMessage ) {
2023-06-08 17:34:52 +02:00
if msg . is_empty ( ) {
2023-05-11 22:47:31 +02:00
return ;
}
2023-06-09 20:22:59 +02:00
if ! msg . is_error ( ) & & ! msg . is_payload ( ) {
println! (
" Message unrecognised: {:?}, please open an issue on the chorus github " ,
msg . message . to_string ( )
) ;
return ;
}
2023-06-08 17:34:52 +02:00
// To:do: handle errors in a good way, maybe observers like events?
if msg . is_error ( ) {
println! ( " GW: Received error, connection will close.. " ) ;
let error = msg . error ( ) ;
match error {
_ = > { }
}
self . close ( ) . await ;
return ;
}
let gateway_payload = msg . payload ( ) . unwrap ( ) ;
2023-05-11 22:47:31 +02:00
// See https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-opcodes
2023-05-28 14:39:41 +02:00
match gateway_payload . op_code {
2023-05-11 22:47:31 +02:00
// An event was dispatched, we need to look at the gateway event name t
2023-05-28 14:39:41 +02:00
GATEWAY_DISPATCH = > {
let gateway_payload_t = gateway_payload . clone ( ) . event_name . unwrap ( ) ;
2023-05-11 22:47:31 +02:00
println! ( " GW: Received {} .. " , gateway_payload_t ) ;
2023-05-17 16:24:04 +02:00
2023-05-27 17:33:19 +02:00
//println!("Event data dump: {}", gateway_payload.d.clone().unwrap().get());
2023-05-28 00:50:52 +02:00
2023-05-11 22:47:31 +02:00
// See https://discord.com/developers/docs/topics/gateway-events#receive-events
2023-05-28 14:39:41 +02:00
// "Some" of these are undocumented
2023-05-11 22:47:31 +02:00
match gateway_payload_t . as_str ( ) {
" READY " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . session . ready ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-28 00:50:52 +02:00
}
2023-05-14 14:03:18 +02:00
" READY_SUPPLEMENTAL " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . session . ready_supplemental ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-11 22:47:31 +02:00
}
2023-05-13 16:24:34 +02:00
" RESUMED " = > { }
2023-05-27 17:29:30 +02:00
" APPLICATION_COMMAND_PERMISSIONS_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self
. events
2023-05-28 00:50:52 +02:00
. lock ( )
. await
. application
2023-06-10 12:43:07 +02:00
. command_permissions_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 17:29:30 +02:00
}
2023-05-27 16:50:38 +02:00
" AUTO_MODERATION_RULE_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . auto_moderation . rule_create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 16:50:38 +02:00
}
" AUTO_MODERATION_RULE_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . auto_moderation . rule_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 16:50:38 +02:00
}
" AUTO_MODERATION_RULE_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . auto_moderation . rule_delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 16:50:38 +02:00
}
" AUTO_MODERATION_ACTION_EXECUTION " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . auto_moderation . action_execution ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 16:50:38 +02:00
}
2023-05-13 21:27:44 +02:00
" CHANNEL_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . channel . create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
" CHANNEL_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . channel . update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
2023-05-15 20:45:33 +02:00
" CHANNEL_UNREAD_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . channel . unread_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-15 20:45:33 +02:00
}
2023-05-13 21:27:44 +02:00
" CHANNEL_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . channel . delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
" CHANNEL_PINS_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . channel . pins_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
2023-05-14 08:20:25 +02:00
" CALL_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . call . create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-28 00:50:52 +02:00
}
2023-05-14 08:39:23 +02:00
" CALL_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . call . update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 08:39:23 +02:00
}
" CALL_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . call . delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 08:20:25 +02:00
}
2023-05-13 21:27:44 +02:00
" THREAD_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . thread . create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
" THREAD_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . thread . update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
" THREAD_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . thread . delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
" THREAD_LIST_SYNC " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . thread . list_sync ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
" THREAD_MEMBER_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . thread . member_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
" THREAD_MEMBERS_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . thread . members_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
" GUILD_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 21:27:44 +02:00
}
2023-05-14 08:20:25 +02:00
" GUILD_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 08:20:25 +02:00
}
2023-05-13 16:24:34 +02:00
" GUILD_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 16:24:34 +02:00
}
2023-05-20 13:03:44 +02:00
" GUILD_AUDIT_LOG_ENTRY_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . audit_log_entry_create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-20 13:03:44 +02:00
}
2023-05-13 16:24:34 +02:00
" GUILD_BAN_ADD " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . ban_add ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 16:24:34 +02:00
}
" GUILD_BAN_REMOVE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . ban_remove ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 08:20:25 +02:00
}
" GUILD_EMOJIS_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . emojis_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 16:24:34 +02:00
}
2023-05-14 15:55:20 +02:00
" GUILD_STICKERS_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . stickers_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
" GUILD_INTEGRATIONS_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . integrations_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
" GUILD_MEMBER_ADD " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . member_add ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
" GUILD_MEMBER_REMOVE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . member_remove ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
" GUILD_MEMBER_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . member_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
" GUILD_MEMBERS_CHUNK " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . members_chunk ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
" GUILD_ROLE_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . role_create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
" GUILD_ROLE_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . role_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
" GUILD_ROLE_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . role_delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
2023-05-22 16:46:49 +02:00
" GUILD_SCHEDULED_EVENT_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . role_scheduled_event_create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-22 16:46:49 +02:00
}
" GUILD_SCHEDULED_EVENT_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . role_scheduled_event_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-22 16:46:49 +02:00
}
" GUILD_SCHEDULED_EVENT_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . role_scheduled_event_delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-22 16:46:49 +02:00
}
" GUILD_SCHEDULED_EVENT_USER_ADD " = > {
2023-06-10 12:43:07 +02:00
let event =
& mut self . events . lock ( ) . await . guild . role_scheduled_event_user_add ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-22 16:46:49 +02:00
}
" GUILD_SCHEDULED_EVENT_USER_REMOVE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self
. events
2023-05-28 00:50:52 +02:00
. lock ( )
. await
. guild
2023-06-10 12:43:07 +02:00
. role_scheduled_event_user_remove ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-22 16:46:49 +02:00
}
2023-05-20 09:35:48 +02:00
" PASSIVE_UPDATE_V1 " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . guild . passive_update_v1 ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-20 09:35:48 +02:00
}
2023-05-14 15:55:20 +02:00
" INTEGRATION_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . integration . create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
" INTEGRATION_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . integration . update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
" INTEGRATION_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . integration . delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
2023-05-27 17:11:47 +02:00
" INTERACTION_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . interaction . create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 17:11:47 +02:00
}
2023-05-20 12:50:05 +02:00
" INVITE_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . invite . create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-20 12:50:05 +02:00
}
" INVITE_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . invite . delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-20 12:50:05 +02:00
}
2023-05-11 22:47:31 +02:00
" MESSAGE_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . message . create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-11 22:47:31 +02:00
}
" MESSAGE_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . message . update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-11 22:47:31 +02:00
}
" MESSAGE_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . message . delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-11 22:47:31 +02:00
}
" MESSAGE_DELETE_BULK " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . message . delete_bulk ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-11 22:47:31 +02:00
}
" MESSAGE_REACTION_ADD " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . message . reaction_add ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-11 22:47:31 +02:00
}
" MESSAGE_REACTION_REMOVE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . message . reaction_remove ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-11 22:47:31 +02:00
}
" MESSAGE_REACTION_REMOVE_ALL " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . message . reaction_remove_all ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-11 22:47:31 +02:00
}
" MESSAGE_REACTION_REMOVE_EMOJI " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . message . reaction_remove_emoji ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-28 00:50:52 +02:00
}
2023-05-14 11:43:17 +02:00
" MESSAGE_ACK " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . message . ack ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-11 22:47:31 +02:00
}
" PRESENCE_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . user . presence_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-11 22:47:31 +02:00
}
2023-05-27 16:03:23 +02:00
" RELATIONSHIP_ADD " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . relationship . add ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 16:03:23 +02:00
}
" RELATIONSHIP_REMOVE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . relationship . remove ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 16:03:23 +02:00
}
2023-05-27 17:05:25 +02:00
" STAGE_INSTANCE_CREATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . stage_instance . create ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 17:05:25 +02:00
}
" STAGE_INSTANCE_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . stage_instance . update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 17:05:25 +02:00
}
" STAGE_INSTANCE_DELETE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . stage_instance . delete ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-27 17:05:25 +02:00
}
2023-05-14 15:55:20 +02:00
" SESSIONS_REPLACE " = > {
2023-06-10 12:43:07 +02:00
let result : Result < Vec < types ::Session > , serde_json ::Error > =
serde_json ::from_str ( gateway_payload . event_data . unwrap ( ) . get ( ) ) ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
let data = types ::SessionsReplace {
sessions : result . unwrap ( ) ,
} ;
2023-05-28 00:50:52 +02:00
self . events
. lock ( )
. await
. session
. replace
2023-06-10 12:43:07 +02:00
. update_data ( data )
2023-05-28 00:50:52 +02:00
. await ;
2023-05-11 22:47:31 +02:00
}
2023-05-13 16:24:34 +02:00
" USER_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . user . update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-28 14:52:48 +02:00
}
2023-05-28 08:18:50 +02:00
" USER_GUILD_SETTINGS_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . user . guild_settings_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-13 16:24:34 +02:00
}
2023-05-22 18:42:12 +02:00
" VOICE_STATE_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . voice . state_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-22 18:42:12 +02:00
}
" VOICE_SERVER_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . voice . server_update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-22 18:42:12 +02:00
}
2023-05-14 15:55:20 +02:00
" WEBHOOKS_UPDATE " = > {
2023-06-10 12:43:07 +02:00
let event = & mut self . events . lock ( ) . await . webhooks . update ;
let result =
Gateway ::handle_event ( gateway_payload . event_data . unwrap ( ) . get ( ) , event )
. await ;
if result . is_err ( ) {
println! (
" Failed to parse gateway event {} ({}) " ,
gateway_payload_t ,
result . err ( ) . unwrap ( )
) ;
return ;
}
2023-05-14 15:55:20 +02:00
}
2023-05-14 19:55:43 +02:00
_ = > {
2023-05-28 14:39:41 +02:00
println! ( " Received unrecognized gateway event ( {} )! Please open an issue on the chorus github so we can implement it " , & gateway_payload_t ) ;
2023-05-14 19:55:43 +02:00
}
2023-05-11 22:47:31 +02:00
}
}
// We received a heartbeat from the server
2023-06-02 10:42:19 +02:00
// "Discord may send the app a Heartbeat (opcode 1) event, in which case the app should send a Heartbeat event immediately."
GATEWAY_HEARTBEAT = > {
println! ( " GW: Received Heartbeat // Heartbeat Request " ) ;
// Tell the heartbeat handler it should send a heartbeat right away
let heartbeat_communication = HeartbeatThreadCommunication {
sequence_number : gateway_payload . sequence_number ,
op_code : Some ( GATEWAY_HEARTBEAT ) ,
} ;
self . heartbeat_handler
. send
. send ( heartbeat_communication )
. await
. unwrap ( ) ;
}
2023-05-28 14:39:41 +02:00
GATEWAY_RECONNECT = > {
2023-05-25 23:09:18 +02:00
todo! ( )
}
2023-05-28 14:39:41 +02:00
GATEWAY_INVALID_SESSION = > {
2023-05-25 23:09:18 +02:00
todo! ( )
}
2023-05-11 22:47:31 +02:00
// Starts our heartbeat
2023-05-13 09:47:12 +02:00
// We should have already handled this in gateway init
2023-05-28 14:39:41 +02:00
GATEWAY_HELLO = > {
panic! ( " Received hello when it was unexpected " ) ;
2023-05-11 22:47:31 +02:00
}
2023-05-28 14:39:41 +02:00
GATEWAY_HEARTBEAT_ACK = > {
2023-05-11 22:47:31 +02:00
println! ( " GW: Received Heartbeat ACK " ) ;
2023-06-02 10:57:47 +02:00
// Tell the heartbeat handler we received an ack
let heartbeat_communication = HeartbeatThreadCommunication {
sequence_number : gateway_payload . sequence_number ,
op_code : Some ( GATEWAY_HEARTBEAT_ACK ) ,
} ;
self . heartbeat_handler
. send
. send ( heartbeat_communication )
. await
. unwrap ( ) ;
2023-05-11 22:47:31 +02:00
}
2023-05-28 14:52:48 +02:00
GATEWAY_IDENTIFY
| GATEWAY_UPDATE_PRESENCE
| GATEWAY_UPDATE_VOICE_STATE
| GATEWAY_RESUME
| GATEWAY_REQUEST_GUILD_MEMBERS
| GATEWAY_CALL_SYNC
| GATEWAY_LAZY_REQUEST = > {
2023-06-08 17:34:52 +02:00
let error = GatewayError ::UnexpectedOpcodeReceivedError {
opcode : gateway_payload . op_code ,
} ;
Err ::< ( ) , GatewayError > ( error ) . unwrap ( ) ;
2023-05-28 00:50:52 +02:00
}
_ = > {
2023-05-28 14:52:08 +02:00
println! ( " Received unrecognized gateway op code ( {} )! Please open an issue on the chorus github so we can implement it " , gateway_payload . op_code ) ;
2023-05-28 00:50:52 +02:00
}
2023-05-11 22:47:31 +02:00
}
2023-06-08 18:24:11 +02:00
// If we we received a seq number we should let it know
if gateway_payload . sequence_number . is_some ( ) {
2023-06-02 10:42:19 +02:00
let heartbeat_communication = HeartbeatThreadCommunication {
sequence_number : Some ( gateway_payload . sequence_number . unwrap ( ) ) ,
// Op code is irrelevant here
op_code : None ,
} ;
2023-05-11 22:47:31 +02:00
2023-06-02 10:42:19 +02:00
self . heartbeat_handler
. send
. send ( heartbeat_communication )
. await
. unwrap ( ) ;
2023-05-11 22:47:31 +02:00
}
}
}
2023-05-05 18:38:04 +02:00
/**
Handles sending heartbeats to the gateway in another thread
2023-06-11 13:52:31 +02:00
* /
2023-05-05 18:38:04 +02:00
struct HeartbeatHandler {
/// The heartbeat interval in milliseconds
2023-05-28 14:39:41 +02:00
pub heartbeat_interval : u128 ,
/// The send channel for the heartbeat thread
pub send : Sender < HeartbeatThreadCommunication > ,
/// The handle of the thread
2023-05-28 14:52:48 +02:00
handle : JoinHandle < ( ) > ,
2023-05-05 18:38:04 +02:00
}
impl HeartbeatHandler {
2023-05-25 23:09:18 +02:00
pub fn new (
heartbeat_interval : u128 ,
websocket_tx : Arc <
Mutex <
SplitSink <
WebSocketStream < MaybeTlsStream < TcpStream > > ,
tokio_tungstenite ::tungstenite ::Message ,
> ,
> ,
> ,
2023-06-08 17:34:52 +02:00
kill_rc : tokio ::sync ::broadcast ::Receiver < ( ) > ,
2023-05-25 23:09:18 +02:00
) -> HeartbeatHandler {
2023-06-08 18:24:11 +02:00
let ( send , receive ) = tokio ::sync ::mpsc ::channel ( 32 ) ;
let kill_receive = kill_rc . resubscribe ( ) ;
2023-05-28 14:39:41 +02:00
let handle : JoinHandle < ( ) > = task ::spawn ( async move {
2023-06-08 18:24:11 +02:00
HeartbeatHandler ::heartbeat_task (
websocket_tx ,
heartbeat_interval ,
receive ,
kill_receive ,
)
. await ;
} ) ;
2023-05-05 18:38:04 +02:00
2023-06-08 18:24:11 +02:00
Self {
heartbeat_interval ,
send ,
handle ,
}
}
2023-06-08 17:34:52 +02:00
2023-06-08 18:24:11 +02:00
/// The main heartbeat task;
///
/// Can be killed by the kill broadcast;
/// If the websocket is closed, will die out next time it tries to send a heartbeat;
pub async fn heartbeat_task (
websocket_tx : Arc <
Mutex <
SplitSink <
WebSocketStream < MaybeTlsStream < TcpStream > > ,
tokio_tungstenite ::tungstenite ::Message ,
> ,
> ,
> ,
heartbeat_interval : u128 ,
mut receive : tokio ::sync ::mpsc ::Receiver < HeartbeatThreadCommunication > ,
mut kill_receive : tokio ::sync ::broadcast ::Receiver < ( ) > ,
) {
let mut last_heartbeat_timestamp : Instant = time ::Instant ::now ( ) ;
let mut last_heartbeat_acknowledged = true ;
let mut last_seq_number : Option < u64 > = None ;
loop {
let should_shutdown = kill_receive . try_recv ( ) . is_ok ( ) ;
if should_shutdown {
break ;
}
2023-06-02 10:42:19 +02:00
2023-06-08 18:24:11 +02:00
let mut should_send ;
2023-06-02 10:42:19 +02:00
2023-06-08 18:24:11 +02:00
let time_to_send = last_heartbeat_timestamp . elapsed ( ) . as_millis ( ) > = heartbeat_interval ;
2023-06-02 10:42:19 +02:00
2023-06-08 18:24:11 +02:00
should_send = time_to_send ;
2023-05-05 18:38:04 +02:00
2023-06-08 18:24:11 +02:00
let received_communication : Result < HeartbeatThreadCommunication , TryRecvError > =
receive . try_recv ( ) ;
if received_communication . is_ok ( ) {
let communication = received_communication . unwrap ( ) ;
2023-06-02 10:42:19 +02:00
2023-06-08 18:24:11 +02:00
// If we received a seq number update, use that as the last seq number
if communication . sequence_number . is_some ( ) {
last_seq_number = Some ( communication . sequence_number . unwrap ( ) ) ;
2023-06-02 10:42:19 +02:00
}
2023-05-28 14:39:41 +02:00
2023-06-08 18:24:11 +02:00
if communication . op_code . is_some ( ) {
match communication . op_code . unwrap ( ) {
GATEWAY_HEARTBEAT = > {
// As per the api docs, if the server sends us a Heartbeat, that means we need to respond with a heartbeat immediately
should_send = true ;
}
GATEWAY_HEARTBEAT_ACK = > {
// The server received our heartbeat
last_heartbeat_acknowledged = true ;
}
_ = > { }
}
2023-06-02 10:57:47 +02:00
}
2023-06-08 18:24:11 +02:00
}
2023-06-02 10:57:47 +02:00
2023-06-08 18:24:11 +02:00
// If the server hasn't acknowledged our heartbeat we should resend it
if ! last_heartbeat_acknowledged
& & last_heartbeat_timestamp . elapsed ( ) . as_millis ( ) > HEARTBEAT_ACK_TIMEOUT
{
should_send = true ;
println! ( " GW: Timed out waiting for a heartbeat ack, resending " ) ;
}
2023-05-06 11:14:38 +02:00
2023-06-08 18:24:11 +02:00
if should_send {
println! ( " GW: Sending Heartbeat.. " ) ;
2023-05-05 18:38:04 +02:00
2023-06-08 18:24:11 +02:00
let heartbeat = types ::GatewayHeartbeat {
op : GATEWAY_HEARTBEAT ,
d : last_seq_number ,
} ;
2023-05-05 18:38:04 +02:00
2023-06-08 18:24:11 +02:00
let heartbeat_json = serde_json ::to_string ( & heartbeat ) . unwrap ( ) ;
2023-05-05 18:38:04 +02:00
2023-06-08 18:24:11 +02:00
let msg = tokio_tungstenite ::tungstenite ::Message ::text ( heartbeat_json ) ;
2023-05-05 18:38:04 +02:00
2023-06-08 18:24:11 +02:00
let send_result = websocket_tx . lock ( ) . await . send ( msg ) . await ;
if send_result . is_err ( ) {
// We couldn't send, the websocket is broken
println! ( " GW: Couldnt send heartbeat, websocket seems broken " ) ;
break ;
2023-05-05 18:38:04 +02:00
}
2023-06-08 18:24:11 +02:00
last_heartbeat_timestamp = time ::Instant ::now ( ) ;
last_heartbeat_acknowledged = false ;
}
2023-05-25 23:09:18 +02:00
}
2023-05-05 18:38:04 +02:00
}
}
/**
2023-06-02 10:42:19 +02:00
Used for communications between the heartbeat and gateway thread .
Either signifies a sequence number update , a heartbeat ACK or a Heartbeat request by the server
2023-05-05 18:38:04 +02:00
* /
#[ derive(Clone, Copy, Debug) ]
struct HeartbeatThreadCommunication {
2023-06-02 10:42:19 +02:00
/// The opcode for the communication we received, if relevant
op_code : Option < u8 > ,
/// The sequence number we got from discord, if any
sequence_number : Option < u64 > ,
2023-05-05 18:38:04 +02:00
}
2023-04-28 13:40:29 +02:00
/**
2023-05-28 14:39:41 +02:00
Trait which defines the behavior of an Observer . An Observer is an object which is subscribed to
2023-04-28 13:40:29 +02:00
an Observable . The Observer is notified when the Observable ' s data changes .
2023-04-28 18:18:32 +02:00
In this case , the Observable is a [ ` GatewayEvent ` ] , which is a wrapper around a WebSocketEvent .
2023-04-28 13:40:29 +02:00
* /
2023-05-26 12:59:32 +02:00
pub trait Observer < T : types ::WebSocketEvent > : std ::fmt ::Debug {
2023-06-10 15:37:02 +02:00
fn update ( & mut self , data : & T ) ;
2023-04-27 17:57:10 +02:00
}
2023-04-28 13:40:29 +02:00
/** GatewayEvent is a wrapper around a WebSocketEvent. It is used to notify the observers of a
2023-04-28 18:18:32 +02:00
change in the WebSocketEvent . GatewayEvents are observable .
2023-06-11 13:52:31 +02:00
* /
2023-05-11 22:47:31 +02:00
#[ derive(Default, Debug) ]
2023-05-26 12:59:32 +02:00
pub struct GatewayEvent < T : types ::WebSocketEvent > {
2023-05-11 22:47:31 +02:00
observers : Vec < Arc < Mutex < dyn Observer < T > + Sync + Send > > > ,
2023-04-28 12:31:59 +02:00
pub event_data : T ,
2023-04-27 22:29:07 +02:00
pub is_observed : bool ,
2023-04-27 17:57:10 +02:00
}
2023-05-26 12:59:32 +02:00
impl < T : types ::WebSocketEvent > GatewayEvent < T > {
2023-04-28 12:31:59 +02:00
fn new ( event_data : T ) -> Self {
2023-04-27 17:57:10 +02:00
Self {
2023-04-27 22:29:07 +02:00
is_observed : false ,
2023-04-27 17:57:10 +02:00
observers : Vec ::new ( ) ,
2023-04-28 12:31:59 +02:00
event_data ,
2023-04-27 17:57:10 +02:00
}
}
2023-04-28 13:40:29 +02:00
/**
Returns true if the GatewayEvent is observed by at least one Observer .
2023-06-11 13:52:31 +02:00
* /
2023-04-27 22:29:07 +02:00
pub fn is_observed ( & self ) -> bool {
self . is_observed
}
2023-04-28 13:40:29 +02:00
/**
Subscribes an Observer to the GatewayEvent . Returns an error if the GatewayEvent is already
observed .
# Errors
Returns an error if the GatewayEvent is already observed .
Error type : [ ` ObserverError ::AlreadySubscribedError ` ]
2023-06-11 13:52:31 +02:00
* /
2023-05-25 23:09:18 +02:00
pub fn subscribe (
& mut self ,
observable : Arc < Mutex < dyn Observer < T > + Sync + Send > > ,
2023-05-28 17:37:05 +02:00
) -> Result < ( ) , ObserverError > {
2023-04-27 22:29:07 +02:00
if self . is_observed {
2023-05-28 17:37:05 +02:00
return Err ( ObserverError ::AlreadySubscribedError ) ;
2023-04-27 22:29:07 +02:00
}
self . is_observed = true ;
2023-04-27 22:38:41 +02:00
self . observers . push ( observable ) ;
2023-05-28 17:37:05 +02:00
Ok ( ( ) )
2023-04-27 17:57:10 +02:00
}
2023-04-28 13:40:29 +02:00
/**
Unsubscribes an Observer from the GatewayEvent .
2023-06-11 13:52:31 +02:00
* /
2023-05-11 22:47:31 +02:00
pub fn unsubscribe ( & mut self , observable : Arc < Mutex < dyn Observer < T > + Sync + Send > > ) {
2023-04-28 12:31:59 +02:00
// .retain()'s closure retains only those elements of the vector, which have a different
// pointer value than observable.
2023-05-11 22:47:31 +02:00
// The usage of the debug format to compare the generic T of observers is quite stupid, but the only thing to compare between them is T and if T == T they are the same
// anddd there is no way to do that without using format
2023-05-25 23:09:18 +02:00
self . observers
. retain ( | obs | ! ( format! ( " {:?} " , obs ) = = format! ( " {:?} " , & observable ) ) ) ;
2023-04-28 12:31:59 +02:00
self . is_observed = ! self . observers . is_empty ( ) ;
2023-04-27 17:57:10 +02:00
}
2023-04-28 13:40:29 +02:00
/**
Updates the GatewayEvent ' s data and notifies the observers .
2023-06-11 13:52:31 +02:00
* /
2023-05-11 22:47:31 +02:00
async fn update_data ( & mut self , new_event_data : T ) {
2023-04-28 12:31:59 +02:00
self . event_data = new_event_data ;
2023-05-11 22:47:31 +02:00
self . notify ( ) . await ;
2023-04-27 17:57:10 +02:00
}
2023-04-28 13:40:29 +02:00
/**
Notifies the observers of the GatewayEvent .
2023-06-11 13:52:31 +02:00
* /
2023-05-11 22:47:31 +02:00
async fn notify ( & self ) {
2023-04-27 17:57:10 +02:00
for observer in & self . observers {
2023-06-10 15:37:02 +02:00
let mut observer_lock = observer . lock ( ) . await ;
observer_lock . update ( & self . event_data ) ;
drop ( observer_lock ) ;
2023-04-28 12:31:59 +02:00
}
}
}
2023-04-28 18:18:32 +02:00
mod events {
use super ::* ;
2023-06-11 13:52:31 +02:00
2023-05-11 22:47:31 +02:00
#[ derive(Default, Debug) ]
pub struct Events {
2023-05-27 17:29:30 +02:00
pub application : Application ,
2023-05-27 16:50:38 +02:00
pub auto_moderation : AutoModeration ,
2023-05-14 15:55:20 +02:00
pub session : Session ,
2023-05-11 22:47:31 +02:00
pub message : Message ,
pub user : User ,
2023-05-27 16:03:23 +02:00
pub relationship : Relationship ,
2023-05-13 21:27:44 +02:00
pub channel : Channel ,
pub thread : Thread ,
pub guild : Guild ,
2023-05-20 12:50:05 +02:00
pub invite : Invite ,
2023-05-14 15:55:20 +02:00
pub integration : Integration ,
2023-05-27 17:11:47 +02:00
pub interaction : Interaction ,
2023-05-27 17:05:25 +02:00
pub stage_instance : StageInstance ,
2023-05-14 08:20:25 +02:00
pub call : Call ,
2023-05-22 18:42:12 +02:00
pub voice : Voice ,
2023-05-14 15:55:20 +02:00
pub webhooks : Webhooks ,
2023-05-26 12:59:32 +02:00
pub gateway_identify_payload : GatewayEvent < types ::GatewayIdentifyPayload > ,
pub gateway_resume : GatewayEvent < types ::GatewayResume > ,
2023-04-28 18:18:32 +02:00
}
2023-05-27 17:29:30 +02:00
#[ derive(Default, Debug) ]
pub struct Application {
pub command_permissions_update : GatewayEvent < types ::ApplicationCommandPermissionsUpdate > ,
}
2023-05-27 16:50:38 +02:00
#[ derive(Default, Debug) ]
pub struct AutoModeration {
pub rule_create : GatewayEvent < types ::AutoModerationRuleCreate > ,
pub rule_update : GatewayEvent < types ::AutoModerationRuleUpdate > ,
pub rule_delete : GatewayEvent < types ::AutoModerationRuleDelete > ,
pub action_execution : GatewayEvent < types ::AutoModerationActionExecution > ,
}
2023-05-14 14:03:18 +02:00
#[ derive(Default, Debug) ]
2023-05-14 15:55:20 +02:00
pub struct Session {
2023-05-26 19:36:41 +02:00
pub ready : GatewayEvent < types ::GatewayReady > ,
2023-05-28 14:39:41 +02:00
pub ready_supplemental : GatewayEvent < types ::GatewayReadySupplemental > ,
2023-05-28 00:50:52 +02:00
pub replace : GatewayEvent < types ::SessionsReplace > ,
2023-05-14 14:03:18 +02:00
}
2023-05-27 17:05:25 +02:00
#[ derive(Default, Debug) ]
pub struct StageInstance {
pub create : GatewayEvent < types ::StageInstanceCreate > ,
pub update : GatewayEvent < types ::StageInstanceUpdate > ,
pub delete : GatewayEvent < types ::StageInstanceDelete > ,
}
2023-05-11 22:47:31 +02:00
#[ derive(Default, Debug) ]
pub struct Message {
2023-05-26 12:59:32 +02:00
pub create : GatewayEvent < types ::MessageCreate > ,
pub update : GatewayEvent < types ::MessageUpdate > ,
pub delete : GatewayEvent < types ::MessageDelete > ,
pub delete_bulk : GatewayEvent < types ::MessageDeleteBulk > ,
pub reaction_add : GatewayEvent < types ::MessageReactionAdd > ,
pub reaction_remove : GatewayEvent < types ::MessageReactionRemove > ,
pub reaction_remove_all : GatewayEvent < types ::MessageReactionRemoveAll > ,
pub reaction_remove_emoji : GatewayEvent < types ::MessageReactionRemoveEmoji > ,
2023-05-28 00:50:52 +02:00
pub ack : GatewayEvent < types ::MessageACK > ,
2023-04-28 18:18:32 +02:00
}
2023-05-11 22:47:31 +02:00
#[ derive(Default, Debug) ]
pub struct User {
2023-05-26 12:59:32 +02:00
pub update : GatewayEvent < types ::UserUpdate > ,
2023-05-28 08:18:50 +02:00
pub guild_settings_update : GatewayEvent < types ::UserGuildSettingsUpdate > ,
2023-05-26 12:59:32 +02:00
pub presence_update : GatewayEvent < types ::PresenceUpdate > ,
pub typing_start_event : GatewayEvent < types ::TypingStartEvent > ,
2023-04-28 18:18:32 +02:00
}
2023-05-13 21:27:44 +02:00
2023-05-27 16:03:23 +02:00
#[ derive(Default, Debug) ]
pub struct Relationship {
pub add : GatewayEvent < types ::RelationshipAdd > ,
pub remove : GatewayEvent < types ::RelationshipRemove > ,
}
2023-05-13 21:27:44 +02:00
#[ derive(Default, Debug) ]
pub struct Channel {
2023-05-26 12:59:32 +02:00
pub create : GatewayEvent < types ::ChannelCreate > ,
pub update : GatewayEvent < types ::ChannelUpdate > ,
2023-05-26 19:36:41 +02:00
pub unread_update : GatewayEvent < types ::ChannelUnreadUpdate > ,
2023-05-26 12:59:32 +02:00
pub delete : GatewayEvent < types ::ChannelDelete > ,
pub pins_update : GatewayEvent < types ::ChannelPinsUpdate > ,
2023-05-13 21:27:44 +02:00
}
#[ derive(Default, Debug) ]
pub struct Thread {
2023-05-26 12:59:32 +02:00
pub create : GatewayEvent < types ::ThreadCreate > ,
pub update : GatewayEvent < types ::ThreadUpdate > ,
pub delete : GatewayEvent < types ::ThreadDelete > ,
pub list_sync : GatewayEvent < types ::ThreadListSync > ,
pub member_update : GatewayEvent < types ::ThreadMemberUpdate > ,
pub members_update : GatewayEvent < types ::ThreadMembersUpdate > ,
2023-05-13 21:27:44 +02:00
}
#[ derive(Default, Debug) ]
pub struct Guild {
2023-05-26 12:59:32 +02:00
pub create : GatewayEvent < types ::GuildCreate > ,
2023-05-26 19:36:41 +02:00
pub update : GatewayEvent < types ::GuildUpdate > ,
pub delete : GatewayEvent < types ::GuildDelete > ,
pub audit_log_entry_create : GatewayEvent < types ::GuildAuditLogEntryCreate > ,
pub ban_add : GatewayEvent < types ::GuildBanAdd > ,
pub ban_remove : GatewayEvent < types ::GuildBanRemove > ,
pub emojis_update : GatewayEvent < types ::GuildEmojisUpdate > ,
pub stickers_update : GatewayEvent < types ::GuildStickersUpdate > ,
pub integrations_update : GatewayEvent < types ::GuildIntegrationsUpdate > ,
pub member_add : GatewayEvent < types ::GuildMemberAdd > ,
pub member_remove : GatewayEvent < types ::GuildMemberRemove > ,
pub member_update : GatewayEvent < types ::GuildMemberUpdate > ,
pub members_chunk : GatewayEvent < types ::GuildMembersChunk > ,
pub role_create : GatewayEvent < types ::GuildRoleCreate > ,
pub role_update : GatewayEvent < types ::GuildRoleUpdate > ,
pub role_delete : GatewayEvent < types ::GuildRoleDelete > ,
2023-05-26 19:47:41 +02:00
pub role_scheduled_event_create : GatewayEvent < types ::GuildScheduledEventCreate > ,
pub role_scheduled_event_update : GatewayEvent < types ::GuildScheduledEventUpdate > ,
pub role_scheduled_event_delete : GatewayEvent < types ::GuildScheduledEventDelete > ,
pub role_scheduled_event_user_add : GatewayEvent < types ::GuildScheduledEventUserAdd > ,
pub role_scheduled_event_user_remove : GatewayEvent < types ::GuildScheduledEventUserRemove > ,
2023-05-26 19:36:41 +02:00
pub passive_update_v1 : GatewayEvent < types ::PassiveUpdateV1 > ,
2023-05-13 21:27:44 +02:00
}
2023-05-14 08:20:25 +02:00
2023-05-20 12:50:05 +02:00
#[ derive(Default, Debug) ]
pub struct Invite {
2023-05-26 19:36:41 +02:00
pub create : GatewayEvent < types ::InviteCreate > ,
2023-05-28 00:50:52 +02:00
pub delete : GatewayEvent < types ::InviteDelete > ,
2023-05-20 12:50:05 +02:00
}
2023-05-14 15:55:20 +02:00
#[ derive(Default, Debug) ]
pub struct Integration {
2023-05-26 19:36:41 +02:00
pub create : GatewayEvent < types ::IntegrationCreate > ,
pub update : GatewayEvent < types ::IntegrationUpdate > ,
2023-05-28 00:50:52 +02:00
pub delete : GatewayEvent < types ::IntegrationDelete > ,
2023-05-14 15:55:20 +02:00
}
2023-05-27 17:11:47 +02:00
#[ derive(Default, Debug) ]
pub struct Interaction {
pub create : GatewayEvent < types ::InteractionCreate > ,
}
2023-05-14 08:20:25 +02:00
#[ derive(Default, Debug) ]
pub struct Call {
2023-05-26 19:36:41 +02:00
pub create : GatewayEvent < types ::CallCreate > ,
pub update : GatewayEvent < types ::CallUpdate > ,
2023-05-28 00:50:52 +02:00
pub delete : GatewayEvent < types ::CallDelete > ,
2023-05-14 08:20:25 +02:00
}
2023-05-14 15:55:20 +02:00
2023-05-22 18:42:12 +02:00
#[ derive(Default, Debug) ]
pub struct Voice {
2023-05-26 19:47:41 +02:00
pub state_update : GatewayEvent < types ::VoiceStateUpdate > ,
2023-05-28 00:50:52 +02:00
pub server_update : GatewayEvent < types ::VoiceServerUpdate > ,
2023-05-22 18:42:12 +02:00
}
2023-05-14 15:55:20 +02:00
#[ derive(Default, Debug) ]
pub struct Webhooks {
2023-05-26 19:36:41 +02:00
pub update : GatewayEvent < types ::WebhooksUpdate > ,
2023-05-14 15:55:20 +02:00
}
2023-04-28 18:18:32 +02:00
}
2023-04-28 12:31:59 +02:00
#[ cfg(test) ]
2023-04-28 12:39:58 +02:00
mod example {
2023-04-28 12:31:59 +02:00
use super ::* ;
2023-05-11 22:47:31 +02:00
#[ derive(Debug) ]
2023-04-28 12:31:59 +02:00
struct Consumer ;
2023-06-11 13:52:31 +02:00
2023-05-26 12:59:32 +02:00
impl Observer < types ::GatewayResume > for Consumer {
2023-06-10 15:37:02 +02:00
fn update ( & mut self , data : & types ::GatewayResume ) {
2023-04-28 12:31:59 +02:00
println! ( " {} " , data . token )
}
}
2023-05-11 22:47:31 +02:00
#[ tokio::test ]
2023-05-28 14:39:41 +02:00
async fn test_observer_behavior ( ) {
2023-05-26 12:59:32 +02:00
let mut event = GatewayEvent ::new ( types ::GatewayResume {
2023-04-28 12:31:59 +02:00
token : " start " . to_string ( ) ,
session_id : " start " . to_string ( ) ,
seq : " start " . to_string ( ) ,
} ) ;
2023-05-26 12:59:32 +02:00
let new_data = types ::GatewayResume {
2023-04-28 12:31:59 +02:00
token : " token_3276ha37am3 " . to_string ( ) ,
session_id : " 89346671230 " . to_string ( ) ,
seq : " 3 " . to_string ( ) ,
} ;
let consumer = Consumer ;
2023-05-13 15:36:29 +02:00
let arc_mut_consumer = Arc ::new ( Mutex ::new ( consumer ) ) ;
2023-04-28 12:31:59 +02:00
2023-06-10 12:43:07 +02:00
event . subscribe ( arc_mut_consumer . clone ( ) ) . unwrap ( ) ;
2023-04-28 12:31:59 +02:00
2023-05-11 22:47:31 +02:00
event . notify ( ) . await ;
2023-04-28 12:31:59 +02:00
2023-05-11 22:47:31 +02:00
event . update_data ( new_data ) . await ;
2023-04-28 12:31:59 +02:00
let second_consumer = Consumer ;
2023-05-13 15:36:29 +02:00
let arc_mut_second_consumer = Arc ::new ( Mutex ::new ( second_consumer ) ) ;
2023-04-28 12:31:59 +02:00
2023-05-29 17:11:08 +02:00
match event . subscribe ( arc_mut_second_consumer . clone ( ) ) . err ( ) {
2023-04-28 12:39:58 +02:00
None = > assert! ( false ) ,
2023-04-28 12:31:59 +02:00
Some ( err ) = > println! ( " You cannot subscribe twice: {} " , err ) ,
2023-04-27 17:57:10 +02:00
}
2023-05-13 15:36:29 +02:00
event . unsubscribe ( arc_mut_consumer . clone ( ) ) ;
2023-05-29 17:11:08 +02:00
event . subscribe ( arc_mut_second_consumer . clone ( ) ) . unwrap ( ) ;
2023-04-27 17:57:10 +02:00
}
2023-04-25 17:21:27 +02:00
}