1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
use crate::{
activity::events as activity_events,
lobby::{events as lobby_events, Lobby, LobbyId},
overlay::events as overlay_events,
relations::events as relation_events,
types::ErrorPayload,
user::events as user_events,
voice::events::VoiceSettingsUpdateEvent,
};
use serde::{Deserialize, Serialize};
/// Events sent from Discord when some action occurs
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub(crate) enum EventKind {
Ready,
Error,
CurrentUserUpdate,
ActivityJoinRequest,
ActivityJoin,
ActivitySpectate,
ActivityInvite,
LobbyUpdate,
LobbyDelete,
LobbyMemberConnect,
LobbyMemberUpdate,
LobbyMemberDisconnect,
LobbyMessage,
SpeakingStart,
SpeakingStop,
OverlayUpdate,
RelationshipUpdate,
#[serde(rename = "VOICE_SETTINGS_UPDATE_2")]
VoiceSettingsUpdate,
}
/// An event sent from Discord to notify us of some kind of state change or
/// completed action.
///
/// ```json
/// { "evt": "ACTIVITY_JOIN", "data": { "secret": "super_sekret" } }
/// ```
#[derive(Deserialize, Debug)]
#[serde(tag = "evt", content = "data", rename_all = "SCREAMING_SNAKE_CASE")]
#[cfg_attr(test, derive(Serialize))]
pub enum Event {
/// Fires when we've done something naughty and Discord is telling us to stop.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/discord#error-handling)
Error(ErrorPayload),
/// Sent by Discord upon receipt of our `Handshake` message, the user is
/// the current user logged in to the Discord we connected to.
Ready(user_events::ConnectEvent),
/// Fired when the connection has been interrupted between us and Discord,
/// this is a synthesized event as there are can be numerous reasons on
/// the client side for this to happen, in addition to Discord itself being
/// closed, etc.
#[serde(skip)]
Disconnected { reason: crate::Error },
/// Fired when any details on the current logged in user are changed.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/users#oncurrentuserupdate)
CurrentUserUpdate(user_events::UpdateEvent),
/// Event fired when a user starts speaking in a lobby voice channel.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/lobbies#onspeaking)
SpeakingStart(lobby_events::SpeakingEvent),
/// Event fired when a user stops speaking in a lobby voice channel.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/lobbies#onspeaking)
SpeakingStop(lobby_events::SpeakingEvent),
/// Event fired when a user connects to a lobby.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/lobbies#onmemberconnect)
LobbyMemberConnect(lobby_events::MemberEvent),
/// Event fired when a user disconnects from a lobby.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/lobbies#onmemberdisconnect)
LobbyMemberDisconnect(lobby_events::MemberEvent),
/// Event fired when a lobby is deleted, or the user disconnects from the lobby.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/lobbies#onlobbydelete)
LobbyDelete { id: LobbyId },
/// Event fired when a lobby is updated. Note that this is only the metadata
/// on the lobby itself, not the `members`.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/lobbies#onlobbyupdate)
LobbyUpdate(Lobby),
/// Event fired when the metadata for a lobby member is changed.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/lobbies#onmemberupdate)
LobbyMemberUpdate(lobby_events::MemberEvent),
/// Event fired when a message is sent to the lobby.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/lobbies#onlobbymessage)
LobbyMessage(lobby_events::MessageEvent),
#[serde(skip)]
LobbyCreate(Lobby),
#[serde(skip)]
LobbyConnect(Lobby),
/// Sent by Discord when the local user has requested to join a game, and
/// the remote user has accepted their request.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/activities#onactivityjoin)
ActivityJoin(activity_events::SecretEvent),
/// Sent by Discord when the local user has chosen to spectate another user's
/// game session.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/activities#onactivityspectate)
ActivitySpectate(activity_events::SecretEvent),
/// Fires when a user asks to join the current user's game.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/activities#onactivityjoinrequest)
ActivityJoinRequest(activity_events::JoinRequestEvent),
/// Fires when the current user is invited by another user to their game.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/activities#onactivityinvite)
ActivityInvite(activity_events::InviteEvent),
/// Event fired when the overlay state changes.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/overlay#ontoggle)
OverlayUpdate(overlay_events::UpdateEvent),
/// Event fired when a relationship with another user changes.
///
/// [API docs](https://discord.com/developers/docs/game-sdk/relationships#onrelationshipupdate)
RelationshipUpdate(std::sync::Arc<crate::relations::Relationship>),
/// Event fired when any voice settings are changed
#[serde(rename = "VOICE_SETTINGS_UPDATE_2")]
VoiceSettingsUpdate(VoiceSettingsUpdateEvent),
}
/// An event sent from Discord as JSON.
///
/// ```json
/// {
/// "cmd": "DISPATCH",
/// "evt": "ACTIVITY_JOIN",
/// "data": { "secret": "super_sekret" },
/// "nonce": null,
/// }
/// ```
#[derive(Deserialize, Debug)]
#[cfg_attr(test, derive(Serialize))]
pub(crate) struct EventFrame {
/// The actual data payload, we don't care about "cmd" or "nonce" since
/// nonce is not set for events and cmd is always `DISPATCH`.
#[serde(flatten)]
pub(crate) inner: Event,
}
pub enum ClassifiedEvent {
Lobby(lobby_events::LobbyEvent),
User(user_events::UserEvent),
Activity(activity_events::ActivityEvent),
Overlay(overlay_events::OverlayEvent),
Relations(relation_events::RelationshipEvent),
Voice(VoiceSettingsUpdateEvent),
}
impl From<Event> for ClassifiedEvent {
fn from(eve: Event) -> Self {
use activity_events::ActivityEvent as AE;
use lobby_events::LobbyEvent as LE;
use user_events::UserEvent as UE;
match eve {
// User/connection
Event::Ready(ce) => Self::User(UE::Connect(ce)),
Event::Disconnected { reason } => {
Self::User(UE::Disconnect(user_events::DisconnectEvent { reason }))
}
Event::CurrentUserUpdate(user) => Self::User(UE::Update(user)),
// Lobby
Event::SpeakingStart(se) => Self::Lobby(LE::SpeakingStart(se)),
Event::SpeakingStop(se) => Self::Lobby(LE::SpeakingStop(se)),
Event::LobbyDelete { id } => Self::Lobby(LE::Delete { id }),
Event::LobbyUpdate(lob) => Self::Lobby(LE::Update(lob)),
Event::LobbyMemberConnect(me) => Self::Lobby(LE::MemberConnect(me)),
Event::LobbyMemberDisconnect(me) => Self::Lobby(LE::MemberDisconnect(me)),
Event::LobbyMemberUpdate(me) => Self::Lobby(LE::MemberUpdate(me)),
Event::LobbyMessage(msg) => Self::Lobby(LE::Message(msg)),
Event::LobbyCreate(lobby) => Self::Lobby(LE::Create(lobby)),
Event::LobbyConnect(lobby) => Self::Lobby(LE::Connect(lobby)),
// Activity
Event::ActivityJoin(secret) => Self::Activity(AE::Join(secret)),
Event::ActivitySpectate(secret) => Self::Activity(AE::Spectate(secret)),
Event::ActivityJoinRequest(jr) => Self::Activity(AE::JoinRequest(jr)),
Event::ActivityInvite(inv) => Self::Activity(AE::Invite(inv)),
// Overlay
Event::OverlayUpdate(update) => {
Self::Overlay(overlay_events::OverlayEvent::Update(update))
}
// Relationships
Event::RelationshipUpdate(relationship) => {
Self::Relations(relation_events::RelationshipEvent::Update(relationship))
}
// Voice
Event::VoiceSettingsUpdate(voice) => Self::Voice(voice),
// Errors get converted before this path
Event::Error(_) => unreachable!(),
}
}
}