Error observer (also merge perpetual/gateway-dev) (#425)

* Add Webrtc Identify & Ready

* Test error observer

* Minor updates

* More derives

* Even more derives

* Small types update

* e
This commit is contained in:
kozabrada123 2023-08-29 16:38:26 +00:00 committed by GitHub
parent 8c45355620
commit 141dc32819
15 changed files with 93 additions and 29 deletions

View File

@ -2,6 +2,8 @@
use custom_error::custom_error;
use reqwest::Error;
use crate::types::WebSocketEvent;
custom_error! {
#[derive(PartialEq, Eq)]
pub RegistrationError
@ -54,9 +56,10 @@ custom_error! {
/// Supposed to be sent as numbers, though they are sent as string most of the time?
///
/// Also includes errors when initiating a connection and unexpected opcodes
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Default, Clone)]
pub GatewayError
// Errors we have received from the gateway
#[default]
Unknown = "We're not sure what went wrong. Try reconnecting?",
UnknownOpcode = "You sent an invalid Gateway opcode or an invalid payload for an opcode",
Decode = "Gateway server couldn't decode payload",
@ -79,3 +82,5 @@ custom_error! {
// Other misc errors
UnexpectedOpcodeReceived{opcode: u8} = "Received an opcode we weren't expecting to receive: {opcode}",
}
impl WebSocketEvent for GatewayError {}

View File

@ -479,13 +479,15 @@ impl Gateway {
return;
}
// Todo: handle errors in a good way, maybe observers like events?
if msg.is_error() {
warn!("GW: Received error, connection will close..");
let error = msg.error().unwrap();
let _error = msg.error();
warn!("GW: Received error {:?}, connection will close..", error);
self.close().await;
self.events.lock().await.error.notify(error).await;
return;
}
@ -935,6 +937,7 @@ mod events {
pub webhooks: Webhooks,
pub gateway_identify_payload: GatewayEvent<types::GatewayIdentifyPayload>,
pub gateway_resume: GatewayEvent<types::GatewayResume>,
pub error: GatewayEvent<GatewayError>,
}
#[derive(Default, Debug)]

View File

@ -21,7 +21,7 @@ pub struct CallCreate {
impl WebSocketEvent for CallCreate {}
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
/// Officially Undocumented;
/// Updates the client on which calls are ringing, along with a specific call?;
///
@ -38,7 +38,7 @@ pub struct CallUpdate {
impl WebSocketEvent for CallUpdate {}
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
/// Officially Undocumented;
/// Deletes a ringing call;
/// Ex: {"t":"CALL_DELETE","s":8,"op":0,"d":{"channel_id":"837609115475771392"}}
@ -48,7 +48,7 @@ pub struct CallDelete {
impl WebSocketEvent for CallDelete {}
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
/// Officially Undocumented;
/// See <https://unofficial-discord-docs.vercel.app/gateway/op13>;
///

View File

@ -2,7 +2,7 @@ use crate::types::WebSocketEvent;
use serde::{Deserialize, Serialize};
/// Received on gateway init, tells the client how often to send heartbeats;
#[derive(Debug, Default, Deserialize, Serialize)]
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct GatewayHello {
pub op: i32,
pub d: HelloData,
@ -10,7 +10,7 @@ pub struct GatewayHello {
impl WebSocketEvent for GatewayHello {}
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, Copy)]
/// Contains info on how often the client should send heartbeats to the server;
pub struct HelloData {
/// How often a client should send heartbeats, in milliseconds

View File

@ -2,7 +2,7 @@ use crate::types::events::{PresenceUpdate, WebSocketEvent};
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
pub struct GatewayIdentifyPayload {
pub token: String,
pub properties: GatewayIdentifyConnectionProps,
@ -68,7 +68,7 @@ impl GatewayIdentifyPayload {
impl WebSocketEvent for GatewayIdentifyPayload {}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
#[serde_as]
pub struct GatewayIdentifyConnectionProps {
/// Almost always sent
@ -144,7 +144,7 @@ impl GatewayIdentifyConnectionProps {
referring_domain: None,
referrer_current: None,
release_channel: String::from("stable"),
client_build_number: 199933,
client_build_number: 0,
}
}
@ -159,7 +159,7 @@ impl GatewayIdentifyConnectionProps {
system_locale: String::from("en-US"),
os: String::from("Windows"),
os_version: Some(String::from("10")),
client_build_number: 199933,
client_build_number: 222963,
release_channel: String::from("stable"),
..Self::minimal()
}

View File

@ -5,6 +5,8 @@ use std::collections::HashMap;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde_json::{from_str, from_value, to_value, Value};
pub use application::*;
pub use auto_moderation::*;
pub use call::*;
@ -24,13 +26,13 @@ pub use ready::*;
pub use relationship::*;
pub use request_members::*;
pub use resume::*;
use serde_json::{from_str, from_value, to_value, Value};
pub use session::*;
pub use stage_instance::*;
pub use thread::*;
pub use user::*;
pub use voice::*;
pub use webhooks::*;
pub use webrtc::*;
use crate::gateway::Updateable;
@ -62,6 +64,8 @@ mod user;
mod voice;
mod webhooks;
mod webrtc;
pub trait WebSocketEvent {}
#[derive(Debug, Default, Serialize, Clone)]

View File

@ -14,7 +14,7 @@ pub struct UpdatePresence {
pub afk: bool,
}
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq)]
/// Received to tell the client that a user updated their presence / status
/// See <https://discord.com/developers/docs/topics/gateway-events#presence-update-presence-update-event-fields>
pub struct PresenceUpdate {

View File

@ -4,7 +4,7 @@ use crate::types::entities::PublicUser;
use crate::types::events::WebSocketEvent;
use crate::types::utils::Snowflake;
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
/// See <https://discord.com/developers/docs/topics/gateway-events#user-update>;
/// Sent to indicate updates to a user object; (name changes, discriminator changes, etc);
pub struct UserUpdate {
@ -14,7 +14,7 @@ pub struct UserUpdate {
impl WebSocketEvent for UserUpdate {}
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
/// Undocumented;
///
/// Possibly an update for muted guild / channel settings for the current user;
@ -39,7 +39,7 @@ pub struct UserGuildSettingsUpdate {
impl WebSocketEvent for UserGuildSettingsUpdate {}
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
/// Undocumented;
///
/// Received in [UserGuildSettingsUpdate];

View File

@ -1,7 +1,7 @@
use crate::types::{events::WebSocketEvent, Snowflake, VoiceState};
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Default)]
#[derive(Debug, Deserialize, Serialize, Default, Clone, Copy, PartialEq, Eq)]
///
/// Sent to the server to indicate an update of the voice state (leave voice channel, join voice channel, mute, deafen);
///
@ -28,7 +28,7 @@ pub struct VoiceStateUpdate {
impl WebSocketEvent for VoiceStateUpdate {}
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
/// See <https://discord.com/developers/docs/topics/gateway-events#voice-server-update>;
///
/// Received to indicate which voice endpoint, token and guild_id to use;

View File

@ -0,0 +1,18 @@
use crate::types::{Snowflake, WebSocketEvent};
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
/// The identify payload for the webrtc stream;
/// Contains info to begin a webrtc connection;
/// See https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload;
pub struct VoiceIdentify {
server_id: Snowflake,
user_id: Snowflake,
session_id: String,
token: String,
#[serde(skip_serializing_if = "Option::is_none")]
/// Undocumented field, but is also in discord client comms
video: Option<bool>,
}
impl WebSocketEvent for VoiceIdentify {}

View File

@ -0,0 +1,5 @@
pub use identify::*;
pub use ready::*;
mod identify;
mod ready;

View File

@ -0,0 +1,29 @@
use std::net::Ipv4Addr;
use crate::types::WebSocketEvent;
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
/// The ready event for the webrtc stream;
/// Used to give info after the identify event;
/// See https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-ready-payload;
pub struct VoiceReady {
ssrc: i32,
ip: Ipv4Addr,
port: u32,
modes: Vec<String>,
// Heartbeat interval is also sent, but is "an erroneous field and should be ignored. The correct heartbeat_interval value comes from the Hello payload."
}
impl Default for VoiceReady {
fn default() -> Self {
VoiceReady {
ssrc: 1,
ip: Ipv4Addr::UNSPECIFIED,
port: 0,
modes: Vec::new(),
}
}
}
impl WebSocketEvent for VoiceReady {}

View File

@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use crate::types::{entities::Emoji, Snowflake};
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
pub struct Activity {
name: String,
#[serde(rename = "type")]
@ -22,19 +22,19 @@ pub struct Activity {
buttons: Option<Vec<ActivityButton>>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
struct ActivityTimestamps {
start: Option<i64>,
end: Option<i64>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
struct ActivityParty {
id: Option<String>,
size: Option<Vec<(i32, i32)>>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
struct ActivityAssets {
large_image: Option<String>,
large_text: Option<String>,
@ -42,7 +42,7 @@ struct ActivityAssets {
small_text: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
struct ActivitySecrets {
join: Option<String>,
spectate: Option<String>,
@ -50,7 +50,7 @@ struct ActivitySecrets {
match_string: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
struct ActivityButton {
label: String,
url: String,

View File

@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)]
/// See <https://discord.com/developers/docs/topics/gateway-events#client-status-object>
pub struct ClientStatusObject {
pub desktop: Option<String>,

View File

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use crate::types::Snowflake;
#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
/// A schema used to modify a user.
pub struct UserModifySchema {
@ -29,7 +29,7 @@ pub struct UserModifySchema {
///
/// # Reference:
/// Read: <https://discord-userdoccers.vercel.app/resources/channel#json-params>
#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct PrivateChannelCreateSchema {
pub recipients: Option<Vec<Snowflake>>,
pub access_tokens: Option<Vec<String>>,