lavalink_rs/model/
events.rs

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
use crate::client::LavalinkClient;
use crate::model::*;

#[derive(Debug, Clone, Default)]
#[cfg_attr(not(feature = "python"), derive(Hash))]
pub struct Events {
    /// Every single event will trigger this event with the raw data received.
    pub raw: Option<fn(LavalinkClient, session_id: String, &serde_json::Value) -> BoxFuture<()>>,
    /// Dispatched by Lavalink upon successful connection and authorization.
    pub ready: Option<fn(LavalinkClient, session_id: String, &Ready) -> BoxFuture<()>>,
    /// Dispatched periodically with the current state of a player.
    pub player_update:
        Option<fn(LavalinkClient, session_id: String, &PlayerUpdate) -> BoxFuture<()>>,
    /// A collection of statistics sent every minute.
    pub stats: Option<fn(LavalinkClient, session_id: String, &Stats) -> BoxFuture<()>>,
    /// Dispatched when a track starts playing.
    pub track_start: Option<fn(LavalinkClient, session_id: String, &TrackStart) -> BoxFuture<()>>,
    /// Dispatched when a track ends.
    /// track_exception and track_stuck will also trigger this event.
    pub track_end: Option<fn(LavalinkClient, session_id: String, &TrackEnd) -> BoxFuture<()>>,
    /// Dispatched when a track throws an exception.
    pub track_exception:
        Option<fn(LavalinkClient, session_id: String, &TrackException) -> BoxFuture<()>>,
    /// Dispatched when a track gets stuck while playing.
    pub track_stuck: Option<fn(LavalinkClient, session_id: String, &TrackStuck) -> BoxFuture<()>>,
    /// Dispatched when an audio WebSocket to Discord is closed.
    pub websocket_closed:
        Option<fn(LavalinkClient, session_id: String, &WebSocketClosed) -> BoxFuture<()>>,

    #[cfg(feature = "python")]
    pub(crate) event_handler: Option<crate::python::event::EventHandler>,
}

#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Dispatched by Lavalink upon successful connection and authorization.
pub struct Ready {
    pub op: String,
    /// The lavalink session ID, used for some REST requests and resuming.
    pub session_id: String,
    /// Whether this session was resumed.
    pub resumed: bool,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Dispatched periodically with the current state of a player.
pub struct PlayerUpdate {
    pub op: String,
    #[serde(deserialize_with = "deserialize_number_from_string")]
    pub guild_id: GuildId,
    /// The player state.
    pub state: player::State,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// A collection of statistics sent every minute.
pub struct Stats {
    #[serde(default)]
    pub op: String,
    /// The amount of players connected to the node.
    pub players: u64,
    /// The amount of players playing a track.
    pub playing_players: u64,
    /// The uptime of the node in milliseconds.
    pub uptime: u64,
    /// Memory statistics of the node.
    pub memory: Memory,
    /// CPU statistics of the node.
    pub cpu: Cpu,
    /// The frame stats of the node.
    ///
    /// This field is None if there's no players, or it was requested via the REST API.
    pub frame_stats: Option<FrameStats>,
}

#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
pub struct Cpu {
    pub cores: u64,
    pub system_load: f64,
    pub lavalink_load: f64,
}

#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
pub struct Memory {
    pub free: u64,
    pub used: u64,
    pub allocated: u64,
    pub reservable: u64,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
pub struct FrameStats {
    /// The amount of frames sent to Discord.
    pub sent: u64,
    /// The amount of frames that were nulled.
    pub nulled: u64,
    /// The difference between sent frames and the expected amount of frames.
    ///
    /// The expected amount of frames is 3000 (1 every 20 ms) per player.
    /// If the deficit is negative, too many frames were sent, and if it's positive, not enough frames got sent.
    pub deficit: i64,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Dispatched when a track starts playing.
pub struct TrackStart {
    pub op: String,
    #[serde(rename = "type")]
    pub event_type: String,
    #[serde(deserialize_with = "deserialize_number_from_string")]
    pub guild_id: GuildId,
    /// The track that started playing.
    pub track: track::TrackData,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Dispatched when a track ends.
/// track_exception and track_stuck will also trigger this event.
pub struct TrackEnd {
    pub op: String,
    #[serde(rename = "type")]
    pub event_type: String,
    #[serde(deserialize_with = "deserialize_number_from_string")]
    pub guild_id: GuildId,
    /// The track that finished playing.
    pub track: track::TrackData,
    /// The reason the track finished.
    pub reason: TrackEndReason,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all, eq, eq_int))]
/// The reason the track finished.
pub enum TrackEndReason {
    Finished,
    LoadFailed,
    Stopped,
    Replaced,
    Cleanup,
}

impl From<TrackEndReason> for bool {
    /// If the player should continue playing with the next track on the queue or not.
    fn from(value: TrackEndReason) -> Self {
        match value {
            TrackEndReason::Finished => true,
            TrackEndReason::LoadFailed => true,
            TrackEndReason::Stopped => false,
            TrackEndReason::Replaced => false,
            TrackEndReason::Cleanup => false,
        }
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Dispatched when a track throws an exception.
pub struct TrackException {
    pub op: String,
    #[serde(rename = "type")]
    pub event_type: String,
    #[serde(deserialize_with = "deserialize_number_from_string")]
    pub guild_id: GuildId,
    /// The track that threw the exception
    pub track: track::TrackData,
    /// The exception itself.
    pub exception: track::TrackError,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Dispatched when a track gets stuck while playing.
pub struct TrackStuck {
    pub op: String,
    #[serde(rename = "type")]
    pub event_type: String,
    #[serde(deserialize_with = "deserialize_number_from_string")]
    pub guild_id: GuildId,
    /// The track that got stuck.
    pub track: track::TrackData,
    /// The threshold in milliseconds that was exceeded.
    pub threshold_ms: u64,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Dispatched when an audio WebSocket to Discord is closed.
pub struct WebSocketClosed {
    pub op: String,
    #[serde(rename = "type")]
    pub event_type: String,
    #[serde(deserialize_with = "deserialize_number_from_string")]
    pub guild_id: GuildId,
    /// Status code returned by discord.
    ///
    /// See the [discord docs](https://discord.com/developers/docs/topics/opcodes-and-status-codes#voice-voice-close-event-codes)
    /// for a list of them.
    pub code: u16,
    /// The reason the socket was closed.
    pub reason: String,
    /// Whether the connection was closed by Discord or not.
    pub by_remote: bool,
}